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: