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.
This commit is contained in:
Dave Collins 2016-10-19 14:24:42 -05:00
parent bfbaff9fae
commit 9cdc1b8afd
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
4 changed files with 38 additions and 143 deletions

View file

@ -654,35 +654,6 @@ func (b *BlockChain) removeBlockNode(node *blockNode) error {
return nil 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 // calcPastMedianTime calculates the median time of the previous few blocks
// prior to, and including, the passed block node. It is primarily used to // prior to, and including, the passed block node. It is primarily used to
// validate new blocks have sane timestamps. // validate new blocks have sane timestamps.

View file

@ -103,6 +103,9 @@ var regressionNetParams = &chaincfg.Params{
PowLimit: regressionPowLimit, PowLimit: regressionPowLimit,
PowLimitBits: 0x207fffff, PowLimitBits: 0x207fffff,
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
BIP0034Height: 100000000, // Not active - Permit ver 1 blocks
BIP0065Height: 1351, // Used by regression tests
BIP0066Height: 1251, // Used by regression tests
SubsidyReductionInterval: 150, SubsidyReductionInterval: 150,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
TargetTimePerBlock: time.Minute * 10, // 10 minutes TargetTimePerBlock: time.Minute * 10, // 10 minutes
@ -114,16 +117,6 @@ var regressionNetParams = &chaincfg.Params{
// Checkpoints ordered from oldest to newest. // Checkpoints ordered from oldest to newest.
Checkpoints: nil, 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 // Mempool parameters
RelayNonStdTxs: true, RelayNonStdTxs: true,

View file

@ -710,36 +710,17 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode
return ruleError(ErrForkTooOld, str) return ruleError(ErrForkTooOld, str)
} }
if !fastAdd { // Reject outdated block versions once a majority of the network
// Reject version 3 blocks once a majority of the network has // has upgraded. These were originally voted on by BIP0034,
// upgraded. This is part of BIP0065. // BIP0065, and BIP0066.
if header.Version < 4 && b.isMajorityVersion(4, prevNode, params := b.chainParams
b.chainParams.BlockRejectNumRequired) { 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 := "new blocks with version %d are no longer valid"
str = fmt.Sprintf(str, header.Version) str = fmt.Sprintf(str, header.Version)
return ruleError(ErrBlockVersionTooOld, str) 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)
}
} }
return nil 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 // once a majority of the network has upgraded. This is part of
// BIP0034. // BIP0034.
if ShouldHaveSerializedBlockHeight(header) && if ShouldHaveSerializedBlockHeight(header) &&
b.isMajorityVersion(serializedHeightVersion, prevNode, blockHeight >= b.chainParams.BIP0034Height {
b.chainParams.BlockEnforceNumRequired) {
coinbaseTx := block.Transactions()[0] coinbaseTx := block.Transactions()[0]
err := checkSerializedHeight(coinbaseTx, blockHeight) err := checkSerializedHeight(coinbaseTx, blockHeight)
@ -1126,16 +1106,6 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi
runScripts = false 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 // Blocks created after the BIP0016 activation time need to have the
// pay-to-script-hash checks enabled. // pay-to-script-hash checks enabled.
var scriptFlags txscript.ScriptFlags var scriptFlags txscript.ScriptFlags
@ -1143,22 +1113,16 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi
scriptFlags |= txscript.ScriptBip16 scriptFlags |= txscript.ScriptBip16
} }
// Enforce DER signatures for block versions 3+ once the majority of the // Enforce DER signatures for block versions 3+ once the historical
// network has upgraded to the enforcement threshold. This is part of // activation threshold has been reached. This is part of BIP0066.
// BIP0066.
blockHeader := &block.MsgBlock().Header blockHeader := &block.MsgBlock().Header
if blockHeader.Version >= 3 && b.isMajorityVersion(3, prevNode, if blockHeader.Version >= 3 && node.height >= b.chainParams.BIP0066Height {
b.chainParams.BlockEnforceNumRequired) {
scriptFlags |= txscript.ScriptVerifyDERSignatures scriptFlags |= txscript.ScriptVerifyDERSignatures
} }
// Enforce CHECKLOCKTIMEVERIFY for block versions 4+ once the majority // Enforce CHECKLOCKTIMEVERIFY for block versions 4+ once the historical
// of the network has upgraded to the enforcement threshold. This is // activation threshold has been reached. This is part of BIP0065.
// part of BIP0065. if blockHeader.Version >= 4 && node.height >= b.chainParams.BIP0065Height {
if blockHeader.Version >= 4 && b.isMajorityVersion(4, prevNode,
b.chainParams.BlockEnforceNumRequired) {
scriptFlags |= txscript.ScriptVerifyCheckLockTimeVerify scriptFlags |= txscript.ScriptVerifyCheckLockTimeVerify
} }

View file

@ -123,6 +123,12 @@ type Params struct {
// block in compact form. // block in compact form.
PowLimitBits uint32 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 // CoinbaseMaturity is the number of blocks required before newly mined
// coins (coinbase transactions) can be spent. // coins (coinbase transactions) can be spent.
CoinbaseMaturity uint16 CoinbaseMaturity uint16
@ -164,17 +170,6 @@ type Params struct {
// Checkpoints ordered from oldest to newest. // Checkpoints ordered from oldest to newest.
Checkpoints []Checkpoint 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 // These fields are related to voting on consensus rule changes as
// defined by BIP0009. // defined by BIP0009.
// //
@ -229,6 +224,9 @@ var MainNetParams = Params{
GenesisHash: &genesisHash, GenesisHash: &genesisHash,
PowLimit: mainPowLimit, PowLimit: mainPowLimit,
PowLimitBits: 0x1d00ffff, PowLimitBits: 0x1d00ffff,
BIP0034Height: 227931, // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8
BIP0065Height: 388381, // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
BIP0066Height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000, SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
@ -260,16 +258,6 @@ var MainNetParams = Params{
{382320, newHashFromStr("00000000000000000a8dc6ed5b133d0eb2fd6af56203e4159789b092defd8ab2")}, {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. // Consensus rule change deployments.
// //
// The miner confirmation window is defined as: // The miner confirmation window is defined as:
@ -316,6 +304,9 @@ var RegressionNetParams = Params{
PowLimit: regressionPowLimit, PowLimit: regressionPowLimit,
PowLimitBits: 0x207fffff, PowLimitBits: 0x207fffff,
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
BIP0034Height: 100000000, // Not active - Permit ver 1 blocks
BIP0065Height: 1351, // Used by regression tests
BIP0066Height: 1251, // Used by regression tests
SubsidyReductionInterval: 150, SubsidyReductionInterval: 150,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
TargetTimePerBlock: time.Minute * 10, // 10 minutes TargetTimePerBlock: time.Minute * 10, // 10 minutes
@ -327,16 +318,6 @@ var RegressionNetParams = Params{
// Checkpoints ordered from oldest to newest. // Checkpoints ordered from oldest to newest.
Checkpoints: nil, 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. // Consensus rule change deployments.
// //
// The miner confirmation window is defined as: // The miner confirmation window is defined as:
@ -387,6 +368,9 @@ var TestNet3Params = Params{
GenesisHash: &testNet3GenesisHash, GenesisHash: &testNet3GenesisHash,
PowLimit: testNet3PowLimit, PowLimit: testNet3PowLimit,
PowLimitBits: 0x1d00ffff, PowLimitBits: 0x1d00ffff,
BIP0034Height: 21111, // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8
BIP0065Height: 581885, // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
BIP0066Height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000, SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
@ -401,16 +385,6 @@ var TestNet3Params = Params{
{546, newHashFromStr("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, {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. // Consensus rule change deployments.
// //
// The miner confirmation window is defined as: // The miner confirmation window is defined as:
@ -460,6 +434,9 @@ var SimNetParams = Params{
GenesisHash: &simNetGenesisHash, GenesisHash: &simNetGenesisHash,
PowLimit: simNetPowLimit, PowLimit: simNetPowLimit,
PowLimitBits: 0x207fffff, PowLimitBits: 0x207fffff,
BIP0034Height: 0, // Always active on simnet
BIP0065Height: 0, // Always active on simnet
BIP0066Height: 0, // Always active on simnet
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000, SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
@ -472,16 +449,6 @@ var SimNetParams = Params{
// Checkpoints ordered from oldest to newest. // Checkpoints ordered from oldest to newest.
Checkpoints: nil, 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. // Consensus rule change deployments.
// //
// The miner confirmation window is defined as: // The miner confirmation window is defined as: