BIP34(Block v2, Height in Coinbase)
1 BIP地址
BIP: 34 Layer: Consensus (soft fork) Title: Block v2, Height in Coinbase Author: Gavin Andresen <gavinandresen@gmail.com> Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0034 Status: Final Type: Standards Track Created: 2012-07-06
2 原因和目的
BIP34提出和实践了一种升级机制,使得网络上的参与者可以就交易或者区块的结构、规则和行为变更达成共识。 另外还通过在coinbase里包含区块高度,保证了交易和区块的唯一性,来帮助区块验证。
3 细节
- 将version大于1的交易视为"non-standard"
- 将区块高度以"serialized CScript"的格式添加到coinbase交易的scriptSig中,block version提高到2
- 75%原则:如果过去1000个区块都有750个区块的block version比2大,那么拒绝无效的version=2的Block
- 95%原则:如果过去1000个区块都有950个区块的block version比2大,那么拒绝version=1的区块
4 相关实现
判断一个block是否应该在coinbase包含区块高度
// serializedHeightVersion is the block version which changed block // coinbases to start with the serialized block height. serializedHeightVersion = 2 // ShouldHaveSerializedBlockHeight determines if a block should have a // serialized block height embedded within the scriptSig of its // coinbase transaction. Judgement is based on the block version in the block // header. Blocks with version 2 and above satisfy this criteria. See BIP0034 // for further information. func ShouldHaveSerializedBlockHeight(header *wire.BlockHeader) bool { return header.Version >= serializedHeightVersion }
提取出coinbase中的区块高度
// ExtractCoinbaseHeight attempts to extract the height of the block from the // scriptSig of a coinbase transaction. Coinbase heights are only present in // blocks of version 2 or later. This was added as part of BIP0034. func ExtractCoinbaseHeight(coinbaseTx *btcutil.Tx) (int32, error) { sigScript := coinbaseTx.MsgTx().TxIn[0].SignatureScript if len(sigScript) < 1 { str := "the coinbase signature script for blocks of " + "version %d or greater must start with the " + "length of the serialized block height" str = fmt.Sprintf(str, serializedHeightVersion) return 0, ruleError(ErrMissingCoinbaseHeight, str) } // Detect the case when the block height is a small integer encoded with // as single byte. opcode := int(sigScript[0]) if opcode == txscript.OP_0 { return 0, nil } if opcode >= txscript.OP_1 && opcode <= txscript.OP_16 { return int32(opcode - (txscript.OP_1 - 1)), nil } // Otherwise, the opcode is the length of the following bytes which // encode in the block height. serializedLen := int(sigScript[0]) if len(sigScript[1:]) < serializedLen { str := "the coinbase signature script for blocks of " + "version %d or greater must start with the " + "serialized block height" str = fmt.Sprintf(str, serializedLen) return 0, ruleError(ErrMissingCoinbaseHeight, str) } serializedHeightBytes := make([]byte, 8) copy(serializedHeightBytes, sigScript[1:serializedLen+1]) serializedHeight := binary.LittleEndian.Uint64(serializedHeightBytes) return int32(serializedHeight), nil }