LCOV - code coverage report
Current view: top level - src/test - versionbits_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 261 268 97.4 %
Date: 2026-06-25 07:23:43 Functions: 68 68 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2014-2021 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <chain.h>
       6             : #include <chainparams.h>
       7             : #include <consensus/params.h>
       8             : #include <test/util/random.h>
       9             : #include <test/util/setup_common.h>
      10             : #include <validation.h>
      11             : #include <versionbits.h>
      12             : 
      13             : #include <boost/test/unit_test.hpp>
      14             : 
      15             : /* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
      16      144028 : static int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
      17             : 
      18       40416 : static std::string StateName(ThresholdState state)
      19             : {
      20       40416 :     switch (state) {
      21        8932 :     case ThresholdState::DEFINED:   return "DEFINED";
      22        7560 :     case ThresholdState::STARTED:   return "STARTED";
      23        2968 :     case ThresholdState::LOCKED_IN: return "LOCKED_IN";
      24        9224 :     case ThresholdState::ACTIVE:    return "ACTIVE";
      25       11732 :     case ThresholdState::FAILED:    return "FAILED";
      26             :     } // no default case, so the compiler can warn about missing cases
      27           0 :     return "";
      28       40416 : }
      29             : 
      30             : static const Consensus::Params paramsDummy = Consensus::Params();
      31             : 
      32             : class TestConditionChecker : public AbstractThresholdConditionChecker
      33             : {
      34             : private:
      35             :     mutable ThresholdConditionCache cache;
      36             : 
      37             : public:
      38       70440 :     int64_t BeginTime(const Consensus::Params& params) const override { return TestTime(10000); }
      39       70452 :     int64_t EndTime(const Consensus::Params& params) const override { return TestTime(20000); }
      40       70452 :     int SignalHeight(const CBlockIndex* const pindex, const Consensus::Params& params) const override { return 0; }
      41       79476 :     int Period(const Consensus::Params& params) const override { return 1000; }
      42        3764 :     int Threshold(const Consensus::Params& params, int nAttempt) const override { return 900; }
      43     1804758 :     bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return (pindex->nVersion & 0x100); }
      44             : 
      45       26944 :     ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); }
      46       26920 :     int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); }
      47             : };
      48             : 
      49             : class TestDelayedActivationConditionChecker : public TestConditionChecker
      50             : {
      51             : public:
      52       26680 :     int MinActivationHeight(const Consensus::Params& params) const override { return 15000; }
      53             : };
      54             : 
      55             : class TestAlwaysActiveConditionChecker : public TestConditionChecker
      56             : {
      57             : public:
      58       13466 :     int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; }
      59             : };
      60             : 
      61             : class TestNeverActiveConditionChecker : public TestConditionChecker
      62             : {
      63             : public:
      64       13466 :     int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::NEVER_ACTIVE; }
      65             : };
      66             : 
      67             : #define CHECKERS 6
      68             : 
      69          70 : class VersionBitsTester
      70             : {
      71             :     // A fake blockchain
      72             :     std::vector<CBlockIndex*> vpblock;
      73             : 
      74             :     // 6 independent checkers for the same bit.
      75             :     // The first one performs all checks, the second only 50%, the third only 25%, etc...
      76             :     // This is to test whether lack of cached information leads to the same results.
      77             :     TestConditionChecker checker[CHECKERS];
      78             :     // Another 6 that assume delayed activation
      79             :     TestDelayedActivationConditionChecker checker_delayed[CHECKERS];
      80             :     // Another 6 that assume always active activation
      81             :     TestAlwaysActiveConditionChecker checker_always[CHECKERS];
      82             :     // Another 6 that assume never active activation
      83             :     TestNeverActiveConditionChecker checker_never[CHECKERS];
      84             : 
      85             :     // Test counter (to identify failures)
      86          70 :     int num{1000};
      87             : 
      88             : public:
      89         326 :     VersionBitsTester& Reset() {
      90             :         // Have each group of tests be counted by the 1000s part, starting at 1000
      91         326 :         num = num - (num % 1000) + 1000;
      92             : 
      93     5526838 :         for (unsigned int i = 0; i < vpblock.size(); i++) {
      94     5526512 :             delete vpblock[i];
      95     5526512 :         }
      96        2282 :         for (unsigned int  i = 0; i < CHECKERS; i++) {
      97        1956 :             checker[i] = TestConditionChecker();
      98        1956 :             checker_delayed[i] = TestDelayedActivationConditionChecker();
      99        1956 :             checker_always[i] = TestAlwaysActiveConditionChecker();
     100        1956 :             checker_never[i] = TestNeverActiveConditionChecker();
     101        1956 :         }
     102         326 :         vpblock.clear();
     103         326 :         return *this;
     104             :     }
     105             : 
     106         140 :     ~VersionBitsTester() {
     107          70 :          Reset();
     108         140 :     }
     109             : 
     110        4597 :     VersionBitsTester& Mine(unsigned int height, int32_t nTime, int32_t nVersion) {
     111     5531109 :         while (vpblock.size() < height) {
     112     5526512 :             CBlockIndex* pindex = new CBlockIndex();
     113     5526512 :             pindex->nHeight = vpblock.size();
     114     5526512 :             pindex->pprev = Tip();
     115     5526512 :             pindex->nTime = nTime;
     116     5526512 :             pindex->nVersion = nVersion;
     117     5526512 :             pindex->BuildSkip();
     118     5526512 :             vpblock.push_back(pindex);
     119             :         }
     120        4597 :         return *this;
     121           0 :     }
     122             : 
     123        2944 :     VersionBitsTester& TestStateSinceHeight(int height)
     124             :     {
     125        2944 :         return TestStateSinceHeight(height, height);
     126             :     }
     127             : 
     128        3392 :     VersionBitsTester& TestStateSinceHeight(int height, int height_delayed)
     129             :     {
     130        3392 :         const CBlockIndex* tip = Tip();
     131       23744 :         for (int i = 0; i < CHECKERS; i++) {
     132       20352 :             if (InsecureRandBits(i) == 0) {
     133        6730 :                 BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(tip) == height, strprintf("Test %i for StateSinceHeight", num));
     134        6730 :                 BOOST_CHECK_MESSAGE(checker_delayed[i].GetStateSinceHeightFor(tip) == height_delayed, strprintf("Test %i for StateSinceHeight (delayed)", num));
     135        6730 :                 BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
     136        6730 :                 BOOST_CHECK_MESSAGE(checker_never[i].GetStateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (never active)", num));
     137        6730 :             }
     138       20352 :         }
     139        3392 :         num++;
     140        3392 :         return *this;
     141           0 :     }
     142             : 
     143        3200 :     VersionBitsTester& TestState(ThresholdState exp)
     144             :     {
     145        3200 :         return TestState(exp, exp);
     146             :     }
     147             : 
     148        3456 :     VersionBitsTester& TestState(ThresholdState exp, ThresholdState exp_delayed)
     149             :     {
     150        3456 :         if (exp != exp_delayed) {
     151             :             // only expected differences are that delayed stays in locked_in longer
     152         256 :             BOOST_CHECK_EQUAL(exp, ThresholdState::ACTIVE);
     153         256 :             BOOST_CHECK_EQUAL(exp_delayed, ThresholdState::LOCKED_IN);
     154         256 :         }
     155             : 
     156        3456 :         const CBlockIndex* pindex = Tip();
     157       24192 :         for (int i = 0; i < CHECKERS; i++) {
     158       20736 :             if (InsecureRandBits(i) == 0) {
     159        6736 :                 ThresholdState got = checker[i].GetStateFor(pindex);
     160        6736 :                 ThresholdState got_delayed = checker_delayed[i].GetStateFor(pindex);
     161        6736 :                 ThresholdState got_always = checker_always[i].GetStateFor(pindex);
     162        6736 :                 ThresholdState got_never = checker_never[i].GetStateFor(pindex);
     163             :                 // nHeight of the next block. If vpblock is empty, the next (ie first)
     164             :                 // block should be the genesis block with nHeight == 0.
     165        6736 :                 int height = pindex == nullptr ? 0 : pindex->nHeight + 1;
     166        6736 :                 BOOST_CHECK_MESSAGE(got == exp, strprintf("Test %i for %s height %d (got %s)", num, StateName(exp), height, StateName(got)));
     167        6736 :                 BOOST_CHECK_MESSAGE(got_delayed == exp_delayed, strprintf("Test %i for %s height %d (got %s; delayed case)", num, StateName(exp_delayed), height, StateName(got_delayed)));
     168        6736 :                 BOOST_CHECK_MESSAGE(got_always == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE height %d (got %s; always active case)", num, height, StateName(got_always)));
     169        6736 :                 BOOST_CHECK_MESSAGE(got_never == ThresholdState::FAILED, strprintf("Test %i for FAILED height %d (got %s; never active case)", num, height, StateName(got_never)));
     170        6736 :             }
     171       20736 :         }
     172        3456 :         num++;
     173        3456 :         return *this;
     174           0 :     }
     175             : 
     176        1152 :     VersionBitsTester& TestDefined() { return TestState(ThresholdState::DEFINED); }
     177         960 :     VersionBitsTester& TestStarted() { return TestState(ThresholdState::STARTED); }
     178         256 :     VersionBitsTester& TestLockedIn() { return TestState(ThresholdState::LOCKED_IN); }
     179         192 :     VersionBitsTester& TestActive() { return TestState(ThresholdState::ACTIVE); }
     180         640 :     VersionBitsTester& TestFailed() { return TestState(ThresholdState::FAILED); }
     181             : 
     182             :     // non-delayed should be active; delayed should still be locked in
     183         256 :     VersionBitsTester& TestActiveDelayed() { return TestState(ThresholdState::ACTIVE, ThresholdState::LOCKED_IN); }
     184             : 
     185     5534821 :     CBlockIndex* Tip() { return vpblock.empty() ? nullptr : vpblock.back(); }
     186             : };
     187             : 
     188         146 : BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup)
     189             : 
     190         149 : BOOST_AUTO_TEST_CASE(versionbits_test)
     191             : {
     192          65 :     for (int i = 0; i < 64; i++) {
     193             :         // DEFINED -> STARTED after timeout reached -> FAILED
     194         128 :         VersionBitsTester().TestDefined().TestStateSinceHeight(0)
     195          64 :                            .Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0)
     196          64 :                            .Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0)
     197          64 :                            .Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0)
     198          64 :                            .Mine(999, TestTime(20000), 0x100).TestDefined().TestStateSinceHeight(0) // Timeout and start time reached simultaneously
     199          64 :                            .Mine(1000, TestTime(20000), 0).TestStarted().TestStateSinceHeight(1000) // Hit started, stop signalling
     200          64 :                            .Mine(1999, TestTime(30001), 0).TestStarted().TestStateSinceHeight(1000)
     201          64 :                            .Mine(2000, TestTime(30002), 0x100).TestFailed().TestStateSinceHeight(2000) // Hit failed, start signalling again
     202          64 :                            .Mine(2001, TestTime(30003), 0x100).TestFailed().TestStateSinceHeight(2000)
     203          64 :                            .Mine(2999, TestTime(30004), 0x100).TestFailed().TestStateSinceHeight(2000)
     204          64 :                            .Mine(3000, TestTime(30005), 0x100).TestFailed().TestStateSinceHeight(2000)
     205          64 :                            .Mine(4000, TestTime(30006), 0x100).TestFailed().TestStateSinceHeight(2000)
     206             : 
     207             :         // DEFINED -> STARTED -> FAILED
     208          64 :                            .Reset().TestDefined().TestStateSinceHeight(0)
     209          64 :                            .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
     210          64 :                            .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
     211          64 :                            .Mine(2000, TestTime(10000), 0x100).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
     212          64 :                            .Mine(2051, TestTime(10010), 0).TestStarted().TestStateSinceHeight(2000) // 51 old blocks
     213          64 :                            .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 899 new blocks
     214          64 :                            .Mine(3000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(3000) // 50 old blocks (so 899 out of the past 1000)
     215          64 :                            .Mine(4000, TestTime(20010), 0x100).TestFailed().TestStateSinceHeight(3000)
     216             : 
     217             :         // DEFINED -> STARTED -> LOCKEDIN after timeout reached -> ACTIVE
     218          64 :                            .Reset().TestDefined().TestStateSinceHeight(0)
     219          64 :                            .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
     220          64 :                            .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
     221          64 :                            .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
     222          64 :                            .Mine(2999, TestTime(30000), 0x100).TestStarted().TestStateSinceHeight(2000) // 999 new blocks
     223          64 :                            .Mine(3000, TestTime(30000), 0x100).TestLockedIn().TestStateSinceHeight(3000) // 1 new block (so 1000 out of the past 1000 are new)
     224          64 :                            .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
     225          64 :                            .Mine(4000, TestTime(30002), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
     226          64 :                            .Mine(14333, TestTime(30003), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
     227          64 :                            .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
     228             : 
     229             :         // DEFINED -> STARTED -> LOCKEDIN before timeout -> ACTIVE
     230          64 :                            .Reset().TestDefined()
     231          64 :                            .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
     232          64 :                            .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
     233          64 :                            .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
     234          64 :                            .Mine(2050, TestTime(10010), 0x200).TestStarted().TestStateSinceHeight(2000) // 50 old blocks
     235          64 :                            .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 900 new blocks
     236          64 :                            .Mine(2999, TestTime(19999), 0x200).TestStarted().TestStateSinceHeight(2000) // 49 old blocks
     237          64 :                            .Mine(3000, TestTime(29999), 0x200).TestLockedIn().TestStateSinceHeight(3000) // 1 old block (so 900 out of the past 1000)
     238          64 :                            .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
     239          64 :                            .Mine(4000, TestTime(30002), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000) // delayed will not become active until height=15000
     240          64 :                            .Mine(14333, TestTime(30003), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
     241          64 :                            .Mine(15000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
     242          64 :                            .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
     243             : 
     244             :         // DEFINED multiple periods -> STARTED multiple periods -> FAILED
     245          64 :                            .Reset().TestDefined().TestStateSinceHeight(0)
     246          64 :                            .Mine(999, TestTime(999), 0).TestDefined().TestStateSinceHeight(0)
     247          64 :                            .Mine(1000, TestTime(1000), 0).TestDefined().TestStateSinceHeight(0)
     248          64 :                            .Mine(2000, TestTime(2000), 0).TestDefined().TestStateSinceHeight(0)
     249          64 :                            .Mine(3000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
     250          64 :                            .Mine(4000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
     251          64 :                            .Mine(5000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
     252          64 :                            .Mine(5999, TestTime(20000), 0).TestStarted().TestStateSinceHeight(3000)
     253          64 :                            .Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000)
     254          64 :                            .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000)
     255          64 :                            .Mine(24000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000) // stay in FAILED no matter how much we signal
     256             :         ;
     257          64 :     }
     258           1 : }
     259             : 
     260             : /** Check that ComputeBlockVersion will set the appropriate bit correctly */
     261          10 : static void check_computeblockversion(VersionBitsCache& versionbitscache, const Consensus::Params& params, Consensus::DeploymentPos dep)
     262             : {
     263             :     // Clear the cache everytime
     264          10 :     versionbitscache.Clear();
     265             : 
     266          10 :     int64_t bit = params.vDeployments[dep].bit;
     267          10 :     int64_t nStartTime = params.vDeployments[dep].nStartTime;
     268          10 :     int64_t nTimeout = params.vDeployments[dep].nTimeout;
     269          10 :     int min_activation_height = params.vDeployments[dep].min_activation_height;
     270          10 :     uint32_t window_size = params.vDeployments[dep].nWindowSize;
     271          10 :     if (window_size == 0) window_size = params.nMinerConfirmationWindow;
     272             : 
     273             :     // TODO: make these unit tests to works with EHF too
     274          10 :     bool useEHF = params.vDeployments[dep].useEHF;
     275          10 :     if (useEHF) return;
     276             : 
     277             :     // should not be any signalling for first block
     278           6 :     BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
     279             : 
     280             :     // always/never active deployments shouldn't need to be tested further
     281           6 :     if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE ||
     282           6 :         nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE)
     283             :     {
     284           3 :         BOOST_CHECK_EQUAL(min_activation_height, 0);
     285           3 :         BOOST_CHECK_EQUAL(nTimeout, Consensus::BIP9Deployment::NO_TIMEOUT);
     286           3 :         return;
     287             :     }
     288             : 
     289           3 :     BOOST_REQUIRE(nStartTime < nTimeout);
     290           3 :     BOOST_REQUIRE(nStartTime >= 0);
     291           3 :     BOOST_REQUIRE(nTimeout <= std::numeric_limits<uint32_t>::max() || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
     292           3 :     BOOST_REQUIRE(0 <= bit && bit < 32);
     293             :     // Make sure that no deployment tries to set an invalid bit.
     294           3 :     BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
     295           3 :     BOOST_REQUIRE(min_activation_height >= 0);
     296             :     // Check min_activation_height is on a retarget boundary
     297           3 :     BOOST_REQUIRE_EQUAL(min_activation_height % window_size, 0U);
     298             : 
     299           3 :     const uint32_t bitmask{versionbitscache.Mask(params, dep)};
     300           3 :     BOOST_CHECK_EQUAL(bitmask, uint32_t{1} << bit);
     301             : 
     302             :     // In the first chain, test that the bit is set by CBV until it has failed.
     303             :     // In the second chain, test the bit is set by CBV while STARTED and
     304             :     // LOCKED-IN, and then no longer set while ACTIVE.
     305           3 :     VersionBitsTester firstChain, secondChain;
     306             : 
     307           3 :     int64_t nTime = nStartTime;
     308             : 
     309           3 :     const CBlockIndex *lastBlock = nullptr;
     310             : 
     311             :     // Before MedianTimePast of the chain has crossed nStartTime, the bit
     312             :     // should not be set.
     313           3 :     if (nTime == 0) {
     314             :         // since CBlockIndex::nTime is uint32_t we can't represent any
     315             :         // earlier time, so will transition from DEFINED to STARTED at the
     316             :         // end of the first period by mining blocks at nTime == 0
     317           1 :         lastBlock = firstChain.Mine(window_size - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     318           1 :         BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
     319           1 :         lastBlock = firstChain.Mine(window_size, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     320           1 :         BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     321             :         // then we'll keep mining at nStartTime...
     322           1 :     } else {
     323             :         // use a time 1s earlier than start time to check we stay DEFINED
     324           2 :         --nTime;
     325             : 
     326             :         // Start generating blocks before nStartTime
     327           2 :         lastBlock = firstChain.Mine(window_size, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     328           2 :         BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
     329             : 
     330             :         // Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet.
     331         280 :         for (uint32_t i = 1; i < window_size - 4; i++) {
     332         278 :             lastBlock = firstChain.Mine(window_size + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     333         278 :             BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
     334         278 :         }
     335             :         // Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
     336             :         // CBV should still not yet set the bit.
     337           2 :         nTime = nStartTime;
     338          12 :         for (uint32_t i = window_size - 4; i <= window_size; i++) {
     339          10 :             lastBlock = firstChain.Mine(window_size + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     340          10 :             BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
     341          10 :         }
     342             :         // Next we will advance to the next period and transition to STARTED,
     343             :     }
     344             : 
     345           3 :     lastBlock = firstChain.Mine(window_size * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     346             :     // so ComputeBlockVersion should now set the bit,
     347           3 :     BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     348             :     // and should also be using the VERSIONBITS_TOP_BITS.
     349           3 :     BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
     350             : 
     351             :     // Check that ComputeBlockVersion will set the bit until nTimeout
     352           3 :     nTime += 600;
     353           3 :     uint32_t blocksToMine = window_size * 2; // test blocks for up to 2 time periods
     354           3 :     uint32_t nHeight = window_size * 3;
     355             :     // These blocks are all before nTimeout is reached.
     356         867 :     while (nTime < nTimeout && blocksToMine > 0) {
     357         864 :         lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     358         864 :         BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     359         864 :         BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
     360         864 :         blocksToMine--;
     361         864 :         nTime += 600;
     362         864 :         nHeight += 1;
     363             :     }
     364             : 
     365           3 :     if (nTimeout != Consensus::BIP9Deployment::NO_TIMEOUT) {
     366             :         // can reach any nTimeout other than NO_TIMEOUT due to earlier BOOST_REQUIRE
     367             : 
     368           2 :         nTime = nTimeout;
     369             : 
     370             :         // finish the last period before we start timing out
     371           2 :         while (nHeight % window_size != 0) {
     372           0 :             lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     373           0 :             BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     374           0 :             nHeight += 1;
     375             :         }
     376             : 
     377             :         // FAILED is only triggered at the end of a period, so CBV should be setting
     378             :         // the bit until the period transition.
     379         288 :         for (uint32_t i = 0; i < window_size - 1; i++) {
     380         286 :             lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     381         286 :             BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     382         286 :             nHeight += 1;
     383         286 :         }
     384             :         // The next block should trigger no longer setting the bit.
     385           2 :         lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     386           2 :         BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
     387           2 :     }
     388             : 
     389             :     // On a new chain:
     390             :     // verify that the bit will be set after lock-in, and then stop being set
     391             :     // after activation.
     392           3 :     nTime = nStartTime;
     393             : 
     394             :     // Mine one period worth of blocks, and check that the bit will be on for the
     395             :     // next period.
     396           3 :     lastBlock = secondChain.Mine(window_size, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     397           3 :     BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     398             : 
     399             :     // Mine another period worth of blocks, signaling the new bit.
     400           3 :     lastBlock = secondChain.Mine(window_size * 2, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
     401             :     // After one period of setting the bit on each block, it should have locked in.
     402             :     // We keep setting the bit for one more period though, until activation.
     403           3 :     BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
     404             : 
     405             :     // Now check that we keep mining the block until the end of this period, and
     406             :     // then stop at the beginning of the next period.
     407           3 :     lastBlock = secondChain.Mine((window_size * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     408           3 :     BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
     409           3 :     lastBlock = secondChain.Mine(window_size * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     410             : 
     411           3 :     if (lastBlock->nHeight + 1 < min_activation_height) {
     412             :         // check signalling continues while min_activation_height is not reached
     413           1 :         lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     414           1 :         BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
     415             :         // then reach min_activation_height, which was already REQUIRE'd to start a new period
     416           1 :         lastBlock = secondChain.Mine(min_activation_height, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
     417           1 :     }
     418             : 
     419             :     // Check that we don't signal after activation
     420           3 :     BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
     421          10 : }
     422             : 
     423         149 : BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
     424             : {
     425           1 :     VersionBitsCache vbcache; // don't use chainman versionbitscache since we want custom chain params
     426             : 
     427             :     // check that any deployment on any chain can conceivably reach both
     428             :     // ACTIVE and FAILED states in roughly the way we expect
     429           5 :     for (const auto& chain_name : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, /*CBaseChainParams::DEVNET,=*/CBaseChainParams::DEVNET, CBaseChainParams::REGTEST}) {
     430           4 :         const auto chainParams = CreateChainParams(*m_node.args, chain_name);
     431             : 
     432           4 :         uint32_t chain_all_vbits{0};
     433          12 :         for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
     434           8 :             const auto dep = static_cast<Consensus::DeploymentPos>(i);
     435             :             // Check that no bits are reused (within the same chain). This is
     436             :             // disallowed because the transition to FAILED (on timeout) does
     437             :             // not take precedence over STARTED/LOCKED_IN. So all softforks on
     438             :             // the same bit might overlap, even when non-overlapping start-end
     439             :             // times are picked.
     440           8 :             const uint32_t dep_mask{vbcache.Mask(chainParams->GetConsensus(), dep)};
     441           8 :             BOOST_CHECK(!(chain_all_vbits & dep_mask));
     442           8 :             chain_all_vbits |= dep_mask;
     443           8 :             check_computeblockversion(vbcache, chainParams->GetConsensus(), dep);
     444           8 :         }
     445           4 :     }
     446             : 
     447             :     {
     448             :         // Use regtest/testdummy to ensure we always exercise some
     449             :         // deployment that's not always/never active
     450           1 :         ArgsManager args;
     451           1 :         args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999"); // January 1, 2008 - December 31, 2008
     452           1 :         const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
     453           1 :         check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
     454           1 :     }
     455             : 
     456             :     {
     457             :         // Use regtest/testdummy to ensure we always exercise the
     458             :         // min_activation_height test, even if we're not using that in a
     459             :         // live deployment
     460           1 :         ArgsManager args;
     461           1 :         args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200
     462           1 :         const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
     463           1 :         check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
     464           1 :     }
     465           1 : }
     466             : 
     467         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16