From 9cdc1b8afdda8b6ea7c83575f35cc0b344908386 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 19 Oct 2016 14:24:42 -0500 Subject: [PATCH] blockchain: Remove isMajorityVersion code. Now that all softforking is done via BIP0009 versionbits, replace the old isMajorityVersion deployment mechanism with hard coded historical block heights at which they became active. Since the activation heights vary per network, this adds new parameters to the chaincfg.Params struct for them and sets the correct heights at which each softfork became active on each chain. It should be noted that this is a technically hard fork since the behavior of alternate chain history is different with these hard-coded activation heights as opposed to the old isMajorityVersion code. In particular, an alternate chain history could activate one of the soft forks earlier than these hard-coded heights which means the old code would reject blocks which violate the new soft fork rules whereas this new code would not. However, all of the soft forks this refers to were activated so far in the chain history there is there is no way a reorg that long could happen and checkpoints reject alternate chains before the most recent checkpoint anyways. Furthermore, the same change was made in Bitcoin Core so this needs to be changed to be consistent anyways. --- blockchain/chain.go | 29 ------------ blockchain/fullblocktests/params.go | 13 ++---- blockchain/validate.go | 70 +++++++---------------------- chaincfg/params.go | 69 ++++++++-------------------- 4 files changed, 38 insertions(+), 143 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 7e76c390..b55876df 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -654,35 +654,6 @@ func (b *BlockChain) removeBlockNode(node *blockNode) error { return nil } -// isMajorityVersion determines if a previous number of blocks in the chain -// starting with startNode are at least the minimum passed version. -// -// This function MUST be called with the chain state lock held (for writes). -func (b *BlockChain) isMajorityVersion(minVer int32, startNode *blockNode, numRequired uint64) bool { - numFound := uint64(0) - iterNode := startNode - for i := uint64(0); i < b.chainParams.BlockUpgradeNumToCheck && - numFound < numRequired && iterNode != nil; i++ { - // This node has a version that is at least the minimum version. - if iterNode.version >= minVer { - numFound++ - } - - // Get the previous block node. This function is used over - // simply accessing iterNode.parent directly as it will - // dynamically create previous block nodes as needed. This - // helps allow only the pieces of the chain that are needed - // to remain in memory. - var err error - iterNode, err = b.getPrevNodeFromNode(iterNode) - if err != nil { - break - } - } - - return numFound >= numRequired -} - // calcPastMedianTime calculates the median time of the previous few blocks // prior to, and including, the passed block node. It is primarily used to // validate new blocks have sane timestamps. diff --git a/blockchain/fullblocktests/params.go b/blockchain/fullblocktests/params.go index 05a3ab38..4679036f 100644 --- a/blockchain/fullblocktests/params.go +++ b/blockchain/fullblocktests/params.go @@ -103,6 +103,9 @@ var regressionNetParams = &chaincfg.Params{ PowLimit: regressionPowLimit, PowLimitBits: 0x207fffff, CoinbaseMaturity: 100, + BIP0034Height: 100000000, // Not active - Permit ver 1 blocks + BIP0065Height: 1351, // Used by regression tests + BIP0066Height: 1251, // Used by regression tests SubsidyReductionInterval: 150, TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimePerBlock: time.Minute * 10, // 10 minutes @@ -114,16 +117,6 @@ var regressionNetParams = &chaincfg.Params{ // Checkpoints ordered from oldest to newest. Checkpoints: nil, - // Enforce current block version once majority of the network has - // upgraded. - // 75% (750 / 1000) - // Reject previous block versions once a majority of the network has - // upgraded. - // 95% (950 / 1000) - BlockEnforceNumRequired: 750, - BlockRejectNumRequired: 950, - BlockUpgradeNumToCheck: 1000, - // Mempool parameters RelayNonStdTxs: true, diff --git a/blockchain/validate.go b/blockchain/validate.go index 7b85b602..1745f4ea 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -710,36 +710,17 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode return ruleError(ErrForkTooOld, str) } - if !fastAdd { - // Reject version 3 blocks once a majority of the network has - // upgraded. This is part of BIP0065. - if header.Version < 4 && b.isMajorityVersion(4, prevNode, - b.chainParams.BlockRejectNumRequired) { + // Reject outdated block versions once a majority of the network + // has upgraded. These were originally voted on by BIP0034, + // BIP0065, and BIP0066. + params := b.chainParams + if header.Version < 2 && blockHeight >= params.BIP0034Height || + header.Version < 3 && blockHeight >= params.BIP0066Height || + header.Version < 4 && blockHeight >= params.BIP0065Height { - str := "new blocks with version %d are no longer valid" - str = fmt.Sprintf(str, header.Version) - return ruleError(ErrBlockVersionTooOld, str) - } - - // Reject version 2 blocks once a majority of the network has - // upgraded. This is part of BIP0066. - if header.Version < 3 && b.isMajorityVersion(3, prevNode, - b.chainParams.BlockRejectNumRequired) { - - str := "new blocks with version %d are no longer valid" - str = fmt.Sprintf(str, header.Version) - return ruleError(ErrBlockVersionTooOld, str) - } - - // Reject version 1 blocks once a majority of the network has - // upgraded. This is part of BIP0034. - if header.Version < 2 && b.isMajorityVersion(2, prevNode, - b.chainParams.BlockRejectNumRequired) { - - str := "new blocks with version %d are no longer valid" - str = fmt.Sprintf(str, header.Version) - return ruleError(ErrBlockVersionTooOld, str) - } + str := "new blocks with version %d are no longer valid" + str = fmt.Sprintf(str, header.Version) + return ruleError(ErrBlockVersionTooOld, str) } return nil @@ -791,8 +772,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode // once a majority of the network has upgraded. This is part of // BIP0034. if ShouldHaveSerializedBlockHeight(header) && - b.isMajorityVersion(serializedHeightVersion, prevNode, - b.chainParams.BlockEnforceNumRequired) { + blockHeight >= b.chainParams.BIP0034Height { coinbaseTx := block.Transactions()[0] err := checkSerializedHeight(coinbaseTx, blockHeight) @@ -1126,16 +1106,6 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi runScripts = false } - // Get the previous block node. This function is used over simply - // accessing node.parent directly as it will dynamically create previous - // block nodes as needed. This helps allow only the pieces of the chain - // that are needed to remain in memory. - prevNode, err := b.getPrevNodeFromNode(node) - if err != nil { - log.Errorf("getPrevNodeFromNode: %v", err) - return err - } - // Blocks created after the BIP0016 activation time need to have the // pay-to-script-hash checks enabled. var scriptFlags txscript.ScriptFlags @@ -1143,22 +1113,16 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi scriptFlags |= txscript.ScriptBip16 } - // Enforce DER signatures for block versions 3+ once the majority of the - // network has upgraded to the enforcement threshold. This is part of - // BIP0066. + // Enforce DER signatures for block versions 3+ once the historical + // activation threshold has been reached. This is part of BIP0066. blockHeader := &block.MsgBlock().Header - if blockHeader.Version >= 3 && b.isMajorityVersion(3, prevNode, - b.chainParams.BlockEnforceNumRequired) { - + if blockHeader.Version >= 3 && node.height >= b.chainParams.BIP0066Height { scriptFlags |= txscript.ScriptVerifyDERSignatures } - // Enforce CHECKLOCKTIMEVERIFY for block versions 4+ once the majority - // of the network has upgraded to the enforcement threshold. This is - // part of BIP0065. - if blockHeader.Version >= 4 && b.isMajorityVersion(4, prevNode, - b.chainParams.BlockEnforceNumRequired) { - + // Enforce CHECKLOCKTIMEVERIFY for block versions 4+ once the historical + // activation threshold has been reached. This is part of BIP0065. + if blockHeader.Version >= 4 && node.height >= b.chainParams.BIP0065Height { scriptFlags |= txscript.ScriptVerifyCheckLockTimeVerify } diff --git a/chaincfg/params.go b/chaincfg/params.go index da2959bf..59d61fcb 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -123,6 +123,12 @@ type Params struct { // block in compact form. PowLimitBits uint32 + // These fields define the block heights at which the specified softfork + // BIP became active. + BIP0034Height int32 + BIP0065Height int32 + BIP0066Height int32 + // CoinbaseMaturity is the number of blocks required before newly mined // coins (coinbase transactions) can be spent. CoinbaseMaturity uint16 @@ -164,17 +170,6 @@ type Params struct { // Checkpoints ordered from oldest to newest. Checkpoints []Checkpoint - // Enforce current block version once network has - // upgraded. This is part of BIP0034. - BlockEnforceNumRequired uint64 - - // Reject previous block versions once network has - // upgraded. This is part of BIP0034. - BlockRejectNumRequired uint64 - - // The number of nodes to check. This is part of BIP0034. - BlockUpgradeNumToCheck uint64 - // These fields are related to voting on consensus rule changes as // defined by BIP0009. // @@ -229,6 +224,9 @@ var MainNetParams = Params{ GenesisHash: &genesisHash, PowLimit: mainPowLimit, PowLimitBits: 0x1d00ffff, + BIP0034Height: 227931, // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8 + BIP0065Height: 388381, // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 + BIP0066Height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -260,16 +258,6 @@ var MainNetParams = Params{ {382320, newHashFromStr("00000000000000000a8dc6ed5b133d0eb2fd6af56203e4159789b092defd8ab2")}, }, - // Enforce current block version once majority of the network has - // upgraded. - // 75% (750 / 1000) - // Reject previous block versions once a majority of the network has - // upgraded. - // 95% (950 / 1000) - BlockEnforceNumRequired: 750, - BlockRejectNumRequired: 950, - BlockUpgradeNumToCheck: 1000, - // Consensus rule change deployments. // // The miner confirmation window is defined as: @@ -316,6 +304,9 @@ var RegressionNetParams = Params{ PowLimit: regressionPowLimit, PowLimitBits: 0x207fffff, CoinbaseMaturity: 100, + BIP0034Height: 100000000, // Not active - Permit ver 1 blocks + BIP0065Height: 1351, // Used by regression tests + BIP0066Height: 1251, // Used by regression tests SubsidyReductionInterval: 150, TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimePerBlock: time.Minute * 10, // 10 minutes @@ -327,16 +318,6 @@ var RegressionNetParams = Params{ // Checkpoints ordered from oldest to newest. Checkpoints: nil, - // Enforce current block version once majority of the network has - // upgraded. - // 75% (750 / 1000) - // Reject previous block versions once a majority of the network has - // upgraded. - // 95% (950 / 1000) - BlockEnforceNumRequired: 750, - BlockRejectNumRequired: 950, - BlockUpgradeNumToCheck: 1000, - // Consensus rule change deployments. // // The miner confirmation window is defined as: @@ -387,6 +368,9 @@ var TestNet3Params = Params{ GenesisHash: &testNet3GenesisHash, PowLimit: testNet3PowLimit, PowLimitBits: 0x1d00ffff, + BIP0034Height: 21111, // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8 + BIP0065Height: 581885, // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 + BIP0066Height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -401,16 +385,6 @@ var TestNet3Params = Params{ {546, newHashFromStr("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, }, - // Enforce current block version once majority of the network has - // upgraded. - // 51% (51 / 100) - // Reject previous block versions once a majority of the network has - // upgraded. - // 75% (75 / 100) - BlockEnforceNumRequired: 51, - BlockRejectNumRequired: 75, - BlockUpgradeNumToCheck: 100, - // Consensus rule change deployments. // // The miner confirmation window is defined as: @@ -460,6 +434,9 @@ var SimNetParams = Params{ GenesisHash: &simNetGenesisHash, PowLimit: simNetPowLimit, PowLimitBits: 0x207fffff, + BIP0034Height: 0, // Always active on simnet + BIP0065Height: 0, // Always active on simnet + BIP0066Height: 0, // Always active on simnet CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -472,16 +449,6 @@ var SimNetParams = Params{ // Checkpoints ordered from oldest to newest. Checkpoints: nil, - // Enforce current block version once majority of the network has - // upgraded. - // 51% (51 / 100) - // Reject previous block versions once a majority of the network has - // upgraded. - // 75% (75 / 100) - BlockEnforceNumRequired: 51, - BlockRejectNumRequired: 75, - BlockUpgradeNumToCheck: 100, - // Consensus rule change deployments. // // The miner confirmation window is defined as: