From a679040ec19ef17f3f03988a52207f1c03af701e Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 7 Dec 2023 12:16:22 +1000 Subject: [PATCH] consensus/params: Move version bits period/threshold to bip9 param Rather than having the rule change period/threshold be constant for all potential deployments on a chain, have it be specific to the deployment itself. This both matches history (BIP 9 specified a 2016 block period and 1916 block threshold; BIP 91 specified a 336 block period and 269 block threshold; and BIP 341 specified a 2016 block period and 1815 block threshold), and allows the code to be simplified, as only the BIP9Deployment structure is needed, not the full Consensus::Params structure. --- src/consensus/params.h | 15 +++++++------ src/kernel/chainparams.cpp | 31 +++++++++++++++++--------- src/test/versionbits_tests.cpp | 40 +++++++++++++++++++--------------- src/validation.cpp | 16 ++++++++++++-- src/versionbits.cpp | 19 ++++++++-------- 5 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index 32f14c25e84..6344349b866 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -53,6 +53,14 @@ struct BIP9Deployment { * boundary. */ int min_activation_height{0}; + /** Period of blocks to check signalling in (usually retarget period, ie params.DifficultyAdjustmentInterval()) */ + uint32_t period{2016}; + /** + * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, + * which is also used for BIP9 deployments. + * Examples: 1916 for 95%, 1512 for testchains. + */ + uint32_t threshold{1916}; /** Constant for nTimeout very far in the future. */ static constexpr int64_t NO_TIMEOUT = std::numeric_limits::max(); @@ -98,13 +106,6 @@ struct Params { /** Don't warn about unknown BIP 9 activations below this height. * This prevents us from warning about the CSV and segwit activations. */ int MinBIP9WarningHeight; - /** - * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, - * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. - * Examples: 1916 for 95%, 1512 for testchains. - */ - uint32_t nRuleChangeActivationThreshold; - uint32_t nMinerConfirmationWindow; std::array vDeployments; /** Proof of work parameters */ uint256 powLimit; diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index 349e14a5d6e..7e1c31b1b50 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -104,18 +104,20 @@ public: consensus.fPowAllowMinDifficultyBlocks = false; consensus.enforce_BIP94 = false; consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016 - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90% + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; // Deployment of Taproot (BIPs 340-342) consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021 consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021 consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 709632; // Approximately November 12th, 2021 + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90% + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016; consensus.nMinimumChainWork = uint256{"000000000000000000000000000000000000000088e186b70e0862c193ec44d6"}; consensus.defaultAssumeValid = uint256{"000000000000000000011c5890365bdbe5d25b97ce0057589acaef4f1a57263f"}; // 856760 @@ -228,18 +230,20 @@ public: consensus.fPowAllowMinDifficultyBlocks = true; consensus.enforce_BIP94 = false; consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; // Deployment of Taproot (BIPs 340-342) consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021 consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021 consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016; consensus.nMinimumChainWork = uint256{"000000000000000000000000000000000000000000000f209695166be8b61fa9"}; consensus.defaultAssumeValid = uint256{"000000000000000465b1a66c9f386308e8c75acef9201f3f577811da09fc90ad"}; // 2873500 @@ -327,18 +331,21 @@ public: consensus.fPowAllowMinDifficultyBlocks = true; consensus.enforce_BIP94 = true; consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; // Deployment of Taproot (BIPs 340-342) consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016; consensus.nMinimumChainWork = uint256{"00000000000000000000000000000000000000000000005faa15d02e6202f3ba"}; consensus.defaultAssumeValid = uint256{"000000005be348057db991fa5d89fe7c4695b667cfb311391a8db374b6f681fd"}; // 39550 @@ -465,20 +472,22 @@ public: consensus.fPowAllowMinDifficultyBlocks = false; consensus.enforce_BIP94 = false; consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016 - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.MinBIP9WarningHeight = 0; consensus.powLimit = uint256{"00000377ae000000000000000000000000000000000000000000000000000000"}; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90% + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; // Activation of Taproot (BIPs 340-342) consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90% + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016; // message start is defined as the first 4 bytes of the sha256d of the block script HashWriter h{}; @@ -544,18 +553,20 @@ public: consensus.fPowAllowMinDifficultyBlocks = true; consensus.enforce_BIP94 = opts.enforce_bip94; consensus.fPowNoRetargeting = true; - consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains - consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 108; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 144; // Faster than normal for regtest (144 instead of 2016) consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 108; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 144; consensus.nMinimumChainWork = uint256{}; consensus.defaultAssumeValid = uint256{}; diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index a59dfdad40f..19f75c57bb0 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -268,6 +268,12 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens int64_t nStartTime = params.vDeployments[dep].nStartTime; int64_t nTimeout = params.vDeployments[dep].nTimeout; int min_activation_height = params.vDeployments[dep].min_activation_height; + uint32_t period = params.vDeployments[dep].period; + uint32_t threshold = params.vDeployments[dep].threshold; + + BOOST_REQUIRE(period > 0); // no division by zero, thankyou + BOOST_REQUIRE(0 < threshold); // must be able to have a window that doesn't activate + BOOST_REQUIRE(threshold < period); // must be able to have a window that does activate // should not be any signalling for first block BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS); @@ -289,7 +295,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0); BOOST_REQUIRE(min_activation_height >= 0); // Check min_activation_height is on a retarget boundary - BOOST_REQUIRE_EQUAL(min_activation_height % params.nMinerConfirmationWindow, 0U); + BOOST_REQUIRE_EQUAL(min_activation_height % period, 0U); const uint32_t bitmask{versionbitscache.Mask(params, dep)}; BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit); @@ -309,9 +315,9 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens // since CBlockIndex::nTime is uint32_t we can't represent any // earlier time, so will transition from DEFINED to STARTED at the // end of the first period by mining blocks at nTime == 0 - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + lastBlock = firstChain.Mine(period - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0); - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0); // then we'll keep mining at nStartTime... } else { @@ -319,25 +325,25 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens --nTime; // Start generating blocks before nStartTime - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0); // Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet. - for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) { - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + for (uint32_t i = 1; i < period - 4; i++) { + lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0); } // Now mine 5 more blocks at the start time -- MTP should not have passed yet, so // CBV should still not yet set the bit. nTime = nStartTime; - for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) { - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + for (uint32_t i = period - 4; i <= period; i++) { + lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0); } // Next we will advance to the next period and transition to STARTED, } - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + lastBlock = firstChain.Mine(period * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); // so ComputeBlockVersion should now set the bit, BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0); // and should also be using the VERSIONBITS_TOP_BITS. @@ -345,8 +351,8 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens // Check that ComputeBlockVersion will set the bit until nTimeout nTime += 600; - uint32_t blocksToMine = params.nMinerConfirmationWindow * 2; // test blocks for up to 2 time periods - uint32_t nHeight = params.nMinerConfirmationWindow * 3; + uint32_t blocksToMine = period * 2; // test blocks for up to 2 time periods + uint32_t nHeight = period * 3; // These blocks are all before nTimeout is reached. while (nTime < nTimeout && blocksToMine > 0) { lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); @@ -363,7 +369,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens nTime = nTimeout; // finish the last period before we start timing out - while (nHeight % params.nMinerConfirmationWindow != 0) { + while (nHeight % period != 0) { lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0); nHeight += 1; @@ -371,7 +377,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens // FAILED is only triggered at the end of a period, so CBV should be setting // the bit until the period transition. - for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) { + for (uint32_t i = 0; i < period - 1; i++) { lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0); nHeight += 1; @@ -388,20 +394,20 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens // Mine one period worth of blocks, and check that the bit will be on for the // next period. - lastBlock = secondChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + lastBlock = secondChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0); // Mine another period worth of blocks, signaling the new bit. - lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 2, nTime, VERSIONBITS_TOP_BITS | (1<nHeight + 1 < min_activation_height) { // check signalling continues while min_activation_height is not reached diff --git a/src/validation.cpp b/src/validation.cpp index c9d5e866866..95bffd15a82 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2378,8 +2378,20 @@ public: int64_t BeginTime() const override { return 0; } int64_t EndTime() const override { return std::numeric_limits::max(); } - int Period() const override { return m_chainman.GetConsensus().nMinerConfirmationWindow; } - int Threshold() const override { return m_chainman.GetConsensus().nRuleChangeActivationThreshold; } + int Period() const override { + if (m_chainman.GetParams().IsTestChain()) { + return m_chainman.GetConsensus().DifficultyAdjustmentInterval(); + } else { + return 2016; + } + } + int Threshold() const override { + if (m_chainman.GetParams().IsTestChain()) { + return m_chainman.GetConsensus().DifficultyAdjustmentInterval() * 3 / 4; // 75% for test nets per BIP9 suggestion + } else { + return 1815; // 90% threshold used in BIP 341 + } + } bool Condition(const CBlockIndex* pindex) const override { diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 958bb76abbb..e986427bd65 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -179,15 +179,14 @@ namespace */ class VersionBitsConditionChecker : public AbstractThresholdConditionChecker { private: - const Consensus::Params& params; - const Consensus::DeploymentPos id; + const Consensus::BIP9Deployment& dep; protected: - int64_t BeginTime() const override { return params.vDeployments[id].nStartTime; } - int64_t EndTime() const override { return params.vDeployments[id].nTimeout; } - int MinActivationHeight() const override { return params.vDeployments[id].min_activation_height; } - int Period() const override { return params.nMinerConfirmationWindow; } - int Threshold() const override { return params.nRuleChangeActivationThreshold; } + int64_t BeginTime() const override { return dep.nStartTime; } + int64_t EndTime() const override { return dep.nTimeout; } + int MinActivationHeight() const override { return dep.min_activation_height; } + int Period() const override { return dep.period; } + int Threshold() const override { return dep.threshold; } bool Condition(const CBlockIndex* pindex) const override { @@ -195,8 +194,10 @@ protected: } public: - explicit VersionBitsConditionChecker(const Consensus::Params& params, Consensus::DeploymentPos id) : params{params}, id{id} {} - uint32_t Mask() const { return (uint32_t{1}) << params.vDeployments[id].bit; } + explicit VersionBitsConditionChecker(const Consensus::BIP9Deployment& dep) : dep{dep} {} + explicit VersionBitsConditionChecker(const Consensus::Params& params, Consensus::DeploymentPos id) : VersionBitsConditionChecker{params.vDeployments[id]} {} + + uint32_t Mask() const { return (uint32_t{1}) << dep.bit; } }; } // namespace