From 2b0d291da8f479739ff394dd92801da8c40b9f8e Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Tue, 16 Jun 2020 18:58:56 +1000 Subject: [refactor] Add deploymentstatus.h Provides DeploymentEnabled, DeploymentActiveAt, and DeploymentActiveAfter helpers for checking the status of buried deployments. Can be overloaded so the same syntax works for non-buried deployments, allowing future soft forks to be changed from signalled to buried deployments without having to touch the implementation code. Replaces IsWitnessEnabled and IsScriptWitnessEnabled. --- src/validation.cpp | 67 +++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 41 deletions(-) (limited to 'src/validation.cpp') diff --git a/src/validation.cpp b/src/validation.cpp index 1b0f881d14..b69faa54eb 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1649,15 +1650,6 @@ public: static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main); -// 0.13.0 was shipped with a segwit deployment defined for testnet, but not for -// mainnet. We no longer need to support disabling the segwit deployment -// except for testing purposes, due to limitations of the functional test -// environment. See test/functional/p2p-segwit.py. -static bool IsScriptWitnessEnabled(const Consensus::Params& params) -{ - return params.SegwitHeight != std::numeric_limits::max(); -} - static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) { unsigned int flags = SCRIPT_VERIFY_NONE; @@ -1676,22 +1668,22 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens // Enforce WITNESS rules whenever P2SH is in effect (and the segwit // deployment is defined). - if (flags & SCRIPT_VERIFY_P2SH && IsScriptWitnessEnabled(consensusparams)) { + if (flags & SCRIPT_VERIFY_P2SH && DeploymentEnabled(consensusparams, Consensus::DEPLOYMENT_SEGWIT)) { flags |= SCRIPT_VERIFY_WITNESS; } - // Start enforcing the DERSIG (BIP66) rule - if (pindex->nHeight >= consensusparams.BIP66Height) { + // Enforce the DERSIG (BIP66) rule + if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_DERSIG)) { flags |= SCRIPT_VERIFY_DERSIG; } - // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule - if (pindex->nHeight >= consensusparams.BIP65Height) { + // Enforce CHECKLOCKTIMEVERIFY (BIP65) + if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CLTV)) { flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; } - // Start enforcing BIP112 (CHECKSEQUENCEVERIFY) - if (pindex->nHeight >= consensusparams.CSVHeight) { + // Enforce CHECKSEQUENCEVERIFY (BIP112) + if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CSV)) { flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; } @@ -1700,8 +1692,8 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens flags |= SCRIPT_VERIFY_TAPROOT; } - // Start enforcing BIP147 NULLDUMMY (activated simultaneously with segwit) - if (IsWitnessEnabled(pindex->pprev, consensusparams)) { + // Enforce BIP147 NULLDUMMY (activated simultaneously with segwit) + if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_SEGWIT)) { flags |= SCRIPT_VERIFY_NULLDUMMY; } @@ -1891,9 +1883,9 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, } } - // Start enforcing BIP68 (sequence locks) + // Enforce BIP68 (sequence locks) int nLockTimeFlags = 0; - if (pindex->nHeight >= m_params.GetConsensus().CSVHeight) { + if (DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_CSV)) { nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; } @@ -2986,7 +2978,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi pindexNew->nDataPos = pos.nPos; pindexNew->nUndoPos = 0; pindexNew->nStatus |= BLOCK_HAVE_DATA; - if (IsWitnessEnabled(pindexNew->pprev, m_params.GetConsensus())) { + if (DeploymentActiveAt(*pindexNew, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) { pindexNew->nStatus |= BLOCK_OPT_WITNESS; } pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS); @@ -3107,17 +3099,11 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu return true; } -bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params) -{ - int height = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; - return (height >= params.SegwitHeight); -} - void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams) { int commitpos = GetWitnessCommitmentIndex(block); static const std::vector nonce(32, 0x00); - if (commitpos != NO_WITNESS_COMMITMENT && IsWitnessEnabled(pindexPrev, consensusParams) && !block.vtx[0]->HasWitness()) { + if (commitpos != NO_WITNESS_COMMITMENT && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT) && !block.vtx[0]->HasWitness()) { CMutableTransaction tx(*block.vtx[0]); tx.vin[0].scriptWitness.stack.resize(1); tx.vin[0].scriptWitness.stack[0] = nonce; @@ -3130,7 +3116,7 @@ std::vector GenerateCoinbaseCommitment(CBlock& block, const CBloc std::vector commitment; int commitpos = GetWitnessCommitmentIndex(block); std::vector ret(32, 0x00); - if (consensusParams.SegwitHeight != std::numeric_limits::max()) { + if (DeploymentEnabled(consensusParams, Consensus::DEPLOYMENT_SEGWIT)) { if (commitpos == NO_WITNESS_COMMITMENT) { uint256 witnessroot = BlockWitnessMerkleRoot(block, nullptr); CHash256().Write(witnessroot).Write(ret).Finalize(witnessroot); @@ -3208,13 +3194,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME) return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", "block timestamp too far in the future"); - // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: - // check for version 2, 3 and 4 upgrades - if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) || - (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) || - (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height)) + // Reject blocks with outdated version + if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) || + (block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DERSIG)) || + (block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CLTV))) { return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion), strprintf("rejected nVersion=0x%08x block", block.nVersion)); + } return true; } @@ -3229,9 +3215,9 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat { const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; - // Start enforcing BIP113 (Median Time Past). + // Enforce BIP113 (Median Time Past). int nLockTimeFlags = 0; - if (nHeight >= consensusParams.CSVHeight) { + if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV)) { assert(pindexPrev != nullptr); nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST; } @@ -3248,7 +3234,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat } // Enforce rule that the coinbase starts with serialized block height - if (nHeight >= consensusParams.BIP34Height) + if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) { CScript expect = CScript() << nHeight; if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() || @@ -3266,7 +3252,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are // multiple, the last one is used. bool fHaveWitness = false; - if (nHeight >= consensusParams.SegwitHeight) { + if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT)) { int commitpos = GetWitnessCommitmentIndex(block); if (commitpos != NO_WITNESS_COMMITMENT) { bool malleated = false; @@ -4096,9 +4082,8 @@ bool CChainState::NeedsRedownload() const // At and above m_params.SegwitHeight, segwit consensus rules must be validated CBlockIndex* block{m_chain.Tip()}; - const int segwit_height{m_params.GetConsensus().SegwitHeight}; - while (block != nullptr && block->nHeight >= segwit_height) { + while (block != nullptr && DeploymentActiveAt(*block, m_params.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) { if (!(block->nStatus & BLOCK_OPT_WITNESS)) { // block is insufficiently validated for a segwit client return true; @@ -5000,7 +4985,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot( // Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload() // won't ask to rewind the entire assumed-valid chain on startup. - if (index->pprev && ::IsWitnessEnabled(index->pprev, ::Params().GetConsensus())) { + if (index->pprev && DeploymentActiveAt(*index, ::Params().GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) { index->nStatus |= BLOCK_OPT_WITNESS; } } -- cgit v1.2.3