@@ -44,6 +44,12 @@ class TestConditionChecker : public AbstractThresholdConditionChecker
4444 int GetStateSinceHeightFor (const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor (pindexPrev, paramsDummy, cache); }
4545};
4646
47+ class TestDelayedActivationConditionChecker : public TestConditionChecker
48+ {
49+ public:
50+ int MinActivationHeight (const Consensus::Params& params) const override { return 15000 ; }
51+ };
52+
4753class TestAlwaysActiveConditionChecker : public TestConditionChecker
4854{
4955public:
@@ -68,6 +74,8 @@ class VersionBitsTester
6874 // The first one performs all checks, the second only 50%, the third only 25%, etc...
6975 // This is to test whether lack of cached information leads to the same results.
7076 TestConditionChecker checker[CHECKERS];
77+ // Another 6 that assume delayed activation
78+ TestDelayedActivationConditionChecker checker_delayed[CHECKERS];
7179 // Another 6 that assume always active activation
7280 TestAlwaysActiveConditionChecker checker_always[CHECKERS];
7381 // Another 6 that assume never active activation
@@ -77,14 +85,18 @@ class VersionBitsTester
7785 int num;
7886
7987public:
80- VersionBitsTester () : num(0 ) {}
88+ VersionBitsTester () : num(1000 ) {}
8189
8290 VersionBitsTester& Reset () {
91+ // Have each group of tests be counted by the 1000s part, starting at 1000
92+ num = num - (num % 1000 ) + 1000 ;
93+
8394 for (unsigned int i = 0 ; i < vpblock.size (); i++) {
8495 delete vpblock[i];
8596 }
8697 for (unsigned int i = 0 ; i < CHECKERS; i++) {
8798 checker[i] = TestConditionChecker ();
99+ checker_delayed[i] = TestDelayedActivationConditionChecker ();
88100 checker_always[i] = TestAlwaysActiveConditionChecker ();
89101 checker_never[i] = TestNeverActiveConditionChecker ();
90102 }
@@ -109,11 +121,18 @@ class VersionBitsTester
109121 return *this ;
110122 }
111123
112- VersionBitsTester& TestStateSinceHeight (int height) {
124+ VersionBitsTester& TestStateSinceHeight (int height)
125+ {
126+ return TestStateSinceHeight (height, height);
127+ }
128+
129+ VersionBitsTester& TestStateSinceHeight (int height, int height_delayed)
130+ {
113131 const CBlockIndex* tip = Tip ();
114132 for (int i = 0 ; i < CHECKERS; i++) {
115133 if (InsecureRandBits (i) == 0 ) {
116134 BOOST_CHECK_MESSAGE (checker[i].GetStateSinceHeightFor (tip) == height, strprintf (" Test %i for StateSinceHeight" , num));
135+ BOOST_CHECK_MESSAGE (checker_delayed[i].GetStateSinceHeightFor (tip) == height_delayed, strprintf (" Test %i for StateSinceHeight (delayed)" , num));
117136 BOOST_CHECK_MESSAGE (checker_always[i].GetStateSinceHeightFor (tip) == 0 , strprintf (" Test %i for StateSinceHeight (always active)" , num));
118137
119138 // never active may go from DEFINED -> FAILED at the first period
@@ -125,17 +144,31 @@ class VersionBitsTester
125144 return *this ;
126145 }
127146
128- VersionBitsTester& TestState (ThresholdState exp) {
147+ VersionBitsTester& TestState (ThresholdState exp)
148+ {
149+ return TestState (exp, exp);
150+ }
151+
152+ VersionBitsTester& TestState (ThresholdState exp, ThresholdState exp_delayed)
153+ {
154+ if (exp != exp_delayed) {
155+ // only expected differences are that delayed stays in locked_in longer
156+ BOOST_CHECK_EQUAL (exp, ThresholdState::ACTIVE);
157+ BOOST_CHECK_EQUAL (exp_delayed, ThresholdState::LOCKED_IN);
158+ }
159+
129160 const CBlockIndex* pindex = Tip ();
130161 for (int i = 0 ; i < CHECKERS; i++) {
131162 if (InsecureRandBits (i) == 0 ) {
132163 ThresholdState got = checker[i].GetStateFor (pindex);
164+ ThresholdState got_delayed = checker_delayed[i].GetStateFor (pindex);
133165 ThresholdState got_always = checker_always[i].GetStateFor (pindex);
134166 ThresholdState got_never = checker_never[i].GetStateFor (pindex);
135167 // nHeight of the next block. If vpblock is empty, the next (ie first)
136168 // block should be the genesis block with nHeight == 0.
137169 int height = pindex == nullptr ? 0 : pindex->nHeight + 1 ;
138170 BOOST_CHECK_MESSAGE (got == exp, strprintf (" Test %i for %s height %d (got %s)" , num, StateName (exp), height, StateName (got)));
171+ 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)));
139172 BOOST_CHECK_MESSAGE (got_always == ThresholdState::ACTIVE, strprintf (" Test %i for ACTIVE height %d (got %s; always active case)" , num, height, StateName (got_always)));
140173 BOOST_CHECK_MESSAGE (got_never == ThresholdState::DEFINED|| got_never == ThresholdState::FAILED, strprintf (" Test %i for DEFINED/FAILED height %d (got %s; never active case)" , num, height, StateName (got_never)));
141174 }
@@ -150,6 +183,9 @@ class VersionBitsTester
150183 VersionBitsTester& TestActive () { return TestState (ThresholdState::ACTIVE); }
151184 VersionBitsTester& TestFailed () { return TestState (ThresholdState::FAILED); }
152185
186+ // non-delayed should be active; delayed should still be locked in
187+ VersionBitsTester& TestActiveDelayed () { return TestState (ThresholdState::ACTIVE, ThresholdState::LOCKED_IN); }
188+
153189 CBlockIndex* Tip () { return vpblock.empty () ? nullptr : vpblock.back (); }
154190};
155191
@@ -170,7 +206,6 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
170206 .Mine (2001 , TestTime (30003 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
171207 .Mine (2999 , TestTime (30004 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
172208 .Mine (3000 , TestTime (30005 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
173-
174209 // DEFINED -> STARTED -> FAILED
175210 .Reset ().TestDefined ().TestStateSinceHeight (0 )
176211 .Mine (1 , TestTime (1 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
@@ -203,9 +238,10 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
203238 .Mine (2999 , TestTime (19999 ), 0x200 ).TestStarted ().TestStateSinceHeight (2000 ) // 49 old blocks
204239 .Mine (3000 , TestTime (29999 ), 0x200 ).TestLockedIn ().TestStateSinceHeight (3000 ) // 1 old block (so 900 out of the past 1000)
205240 .Mine (3999 , TestTime (30001 ), 0 ).TestLockedIn ().TestStateSinceHeight (3000 )
206- .Mine (4000 , TestTime (30002 ), 0 ).TestActive ().TestStateSinceHeight (4000 )
207- .Mine (14333 , TestTime (30003 ), 0 ).TestActive ().TestStateSinceHeight (4000 )
208- .Mine (24000 , TestTime (40000 ), 0 ).TestActive ().TestStateSinceHeight (4000 )
241+ .Mine (4000 , TestTime (30002 ), 0 ).TestActiveDelayed ().TestStateSinceHeight (4000 , 3000 ) // delayed will not become active until height=15000
242+ .Mine (14333 , TestTime (30003 ), 0 ).TestActiveDelayed ().TestStateSinceHeight (4000 , 3000 )
243+ .Mine (15000 , TestTime (40000 ), 0 ).TestActive ().TestStateSinceHeight (4000 , 15000 )
244+ .Mine (24000 , TestTime (40000 ), 0 ).TestActive ().TestStateSinceHeight (4000 , 15000 )
209245
210246 // DEFINED multiple periods -> STARTED multiple periods -> FAILED
211247 .Reset ().TestDefined ().TestStateSinceHeight (0 )
@@ -216,7 +252,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
216252 .Mine (4000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
217253 .Mine (5000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
218254 .Mine (6000 , TestTime (20000 ), 0 ).TestFailed ().TestStateSinceHeight (6000 )
219- .Mine (7000 , TestTime (20000 ), 0x100 ).TestFailed ().TestStateSinceHeight (6000 );
255+ .Mine (7000 , TestTime (20000 ), 0x100 ).TestFailed ().TestStateSinceHeight (6000 )
256+ ;
220257 }
221258}
222259
@@ -230,6 +267,13 @@ BOOST_AUTO_TEST_CASE(versionbits_sanity)
230267 // Make sure that no deployment tries to set an invalid bit.
231268 BOOST_CHECK_EQUAL (bitmask & ~(uint32_t )VERSIONBITS_TOP_MASK, bitmask);
232269
270+ // Check min_activation_height is on a retarget boundary
271+ BOOST_CHECK_EQUAL (mainnetParams.vDeployments [i].min_activation_height % mainnetParams.nMinerConfirmationWindow , 0U );
272+ // Check min_activation_height is 0 for ALWAYS_ACTIVE and never active deployments
273+ if (mainnetParams.vDeployments [i].nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE || mainnetParams.vDeployments [i].nTimeout <= 1230768000 ) {
274+ BOOST_CHECK_EQUAL (mainnetParams.vDeployments [i].min_activation_height , 0 );
275+ }
276+
233277 // Verify that the deployment windows of different deployment using the
234278 // same bit are disjoint.
235279 // This test may need modification at such time as a new deployment
@@ -268,7 +312,8 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
268312 BOOST_REQUIRE (nTimeout <= std::numeric_limits<uint32_t >::max () || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
269313 BOOST_REQUIRE (0 <= bit && bit < 32 );
270314 BOOST_REQUIRE (((1 << bit) & VERSIONBITS_TOP_MASK) == 0 );
271- BOOST_REQUIRE (min_activation_height == 0 );
315+ BOOST_REQUIRE (min_activation_height >= 0 );
316+ BOOST_REQUIRE_EQUAL (min_activation_height % params.nMinerConfirmationWindow , 0U );
272317
273318 // In the first chain, test that the bit is set by CBV until it has failed.
274319 // In the second chain, test the bit is set by CBV while STARTED and
@@ -378,6 +423,16 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
378423 lastBlock = secondChain.Mine ((params.nMinerConfirmationWindow * 3 ) - 1 , nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
379424 BOOST_CHECK ((ComputeBlockVersion (lastBlock, params) & (1 << bit)) != 0 );
380425 lastBlock = secondChain.Mine (params.nMinerConfirmationWindow * 3 , nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
426+
427+ if (lastBlock->nHeight + 1 < min_activation_height) {
428+ // check signalling continues while min_activation_height is not reached
429+ lastBlock = secondChain.Mine (min_activation_height - 1 , nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
430+ BOOST_CHECK ((ComputeBlockVersion (lastBlock, params) & (1 << bit)) != 0 );
431+ // then reach min_activation_height, which was already REQUIRE'd to start a new period
432+ lastBlock = secondChain.Mine (min_activation_height, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
433+ }
434+
435+ // Check that we don't signal after activation
381436 BOOST_CHECK_EQUAL (ComputeBlockVersion (lastBlock, params) & (1 <<bit), 0 );
382437}
383438
@@ -391,6 +446,16 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
391446 check_computeblockversion (chainParams->GetConsensus (), static_cast <Consensus::DeploymentPos>(i));
392447 }
393448 }
449+
450+ {
451+ // Use regtest/testdummy to ensure we always exercise the
452+ // min_activation_height test, even if we're not using that in a
453+ // live deployment
454+ ArgsManager args;
455+ args.ForceSetArg (" -vbparams" , " testdummy:1199145601:1230767999:403200" ); // January 1, 2008 - December 31, 2008, min act height 403200
456+ const auto chainParams = CreateChainParams (args, CBaseChainParams::REGTEST);
457+ check_computeblockversion (chainParams->GetConsensus (), Consensus::DEPLOYMENT_TESTDUMMY);
458+ }
394459}
395460
396461BOOST_AUTO_TEST_SUITE_END ()
0 commit comments