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