@@ -44,6 +44,12 @@ class TestConditionChecker : public AbstractThresholdConditionChecker
44
44
int GetStateSinceHeightFor (const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor (pindexPrev, paramsDummy, cache); }
45
45
};
46
46
47
+ class TestDelayedActivationConditionChecker : public TestConditionChecker
48
+ {
49
+ public:
50
+ int MinActivationHeight (const Consensus::Params& params) const override { return 15000 ; }
51
+ };
52
+
47
53
class TestAlwaysActiveConditionChecker : public TestConditionChecker
48
54
{
49
55
public:
@@ -68,6 +74,8 @@ class VersionBitsTester
68
74
// The first one performs all checks, the second only 50%, the third only 25%, etc...
69
75
// This is to test whether lack of cached information leads to the same results.
70
76
TestConditionChecker checker[CHECKERS];
77
+ // Another 6 that assume delayed activation
78
+ TestDelayedActivationConditionChecker checker_delayed[CHECKERS];
71
79
// Another 6 that assume always active activation
72
80
TestAlwaysActiveConditionChecker checker_always[CHECKERS];
73
81
// Another 6 that assume never active activation
@@ -77,14 +85,18 @@ class VersionBitsTester
77
85
int num;
78
86
79
87
public:
80
- VersionBitsTester () : num(0 ) {}
88
+ VersionBitsTester () : num(1000 ) {}
81
89
82
90
VersionBitsTester& Reset () {
91
+ // Have each group of tests be counted by the 1000s part, starting at 1000
92
+ num = num - (num % 1000 ) + 1000 ;
93
+
83
94
for (unsigned int i = 0 ; i < vpblock.size (); i++) {
84
95
delete vpblock[i];
85
96
}
86
97
for (unsigned int i = 0 ; i < CHECKERS; i++) {
87
98
checker[i] = TestConditionChecker ();
99
+ checker_delayed[i] = TestDelayedActivationConditionChecker ();
88
100
checker_always[i] = TestAlwaysActiveConditionChecker ();
89
101
checker_never[i] = TestNeverActiveConditionChecker ();
90
102
}
@@ -109,11 +121,18 @@ class VersionBitsTester
109
121
return *this ;
110
122
}
111
123
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
+ {
113
131
const CBlockIndex* tip = Tip ();
114
132
for (int i = 0 ; i < CHECKERS; i++) {
115
133
if (InsecureRandBits (i) == 0 ) {
116
134
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));
117
136
BOOST_CHECK_MESSAGE (checker_always[i].GetStateSinceHeightFor (tip) == 0 , strprintf (" Test %i for StateSinceHeight (always active)" , num));
118
137
119
138
// never active may go from DEFINED -> FAILED at the first period
@@ -125,17 +144,31 @@ class VersionBitsTester
125
144
return *this ;
126
145
}
127
146
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
+
129
160
const CBlockIndex* pindex = Tip ();
130
161
for (int i = 0 ; i < CHECKERS; i++) {
131
162
if (InsecureRandBits (i) == 0 ) {
132
163
ThresholdState got = checker[i].GetStateFor (pindex);
164
+ ThresholdState got_delayed = checker_delayed[i].GetStateFor (pindex);
133
165
ThresholdState got_always = checker_always[i].GetStateFor (pindex);
134
166
ThresholdState got_never = checker_never[i].GetStateFor (pindex);
135
167
// nHeight of the next block. If vpblock is empty, the next (ie first)
136
168
// block should be the genesis block with nHeight == 0.
137
169
int height = pindex == nullptr ? 0 : pindex->nHeight + 1 ;
138
170
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)));
139
172
BOOST_CHECK_MESSAGE (got_always == ThresholdState::ACTIVE, strprintf (" Test %i for ACTIVE height %d (got %s; always active case)" , num, height, StateName (got_always)));
140
173
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)));
141
174
}
@@ -150,6 +183,9 @@ class VersionBitsTester
150
183
VersionBitsTester& TestActive () { return TestState (ThresholdState::ACTIVE); }
151
184
VersionBitsTester& TestFailed () { return TestState (ThresholdState::FAILED); }
152
185
186
+ // non-delayed should be active; delayed should still be locked in
187
+ VersionBitsTester& TestActiveDelayed () { return TestState (ThresholdState::ACTIVE, ThresholdState::LOCKED_IN); }
188
+
153
189
CBlockIndex* Tip () { return vpblock.empty () ? nullptr : vpblock.back (); }
154
190
};
155
191
@@ -170,7 +206,6 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
170
206
.Mine (2001 , TestTime (30003 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
171
207
.Mine (2999 , TestTime (30004 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
172
208
.Mine (3000 , TestTime (30005 ), 0x100 ).TestFailed ().TestStateSinceHeight (1000 )
173
-
174
209
// DEFINED -> STARTED -> FAILED
175
210
.Reset ().TestDefined ().TestStateSinceHeight (0 )
176
211
.Mine (1 , TestTime (1 ), 0 ).TestDefined ().TestStateSinceHeight (0 )
@@ -203,9 +238,10 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
203
238
.Mine (2999 , TestTime (19999 ), 0x200 ).TestStarted ().TestStateSinceHeight (2000 ) // 49 old blocks
204
239
.Mine (3000 , TestTime (29999 ), 0x200 ).TestLockedIn ().TestStateSinceHeight (3000 ) // 1 old block (so 900 out of the past 1000)
205
240
.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 )
209
245
210
246
// DEFINED multiple periods -> STARTED multiple periods -> FAILED
211
247
.Reset ().TestDefined ().TestStateSinceHeight (0 )
@@ -216,7 +252,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
216
252
.Mine (4000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
217
253
.Mine (5000 , TestTime (10000 ), 0 ).TestStarted ().TestStateSinceHeight (3000 )
218
254
.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
+ ;
220
257
}
221
258
}
222
259
@@ -230,6 +267,13 @@ BOOST_AUTO_TEST_CASE(versionbits_sanity)
230
267
// Make sure that no deployment tries to set an invalid bit.
231
268
BOOST_CHECK_EQUAL (bitmask & ~(uint32_t )VERSIONBITS_TOP_MASK, bitmask);
232
269
270
+ // Check min_activation_height is on a retarget boundary
271
+ BOOST_CHECK_EQUAL (mainnetParams.vDeployments [i].min_activation_height % mainnetParams.nMinerConfirmationWindow , 0 );
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
+
233
277
// Verify that the deployment windows of different deployment using the
234
278
// same bit are disjoint.
235
279
// 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
268
312
BOOST_REQUIRE (nTimeout <= std::numeric_limits<uint32_t >::max () || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
269
313
BOOST_REQUIRE (0 <= bit && bit < 32 );
270
314
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 , 0 );
272
317
273
318
// In the first chain, test that the bit is set by CBV until it has failed.
274
319
// 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
378
423
lastBlock = secondChain.Mine ((params.nMinerConfirmationWindow * 3 ) - 1 , nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip ();
379
424
BOOST_CHECK ((ComputeBlockVersion (lastBlock, params) & (1 << bit)) != 0 );
380
425
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
381
436
BOOST_CHECK_EQUAL (ComputeBlockVersion (lastBlock, params) & (1 <<bit), 0 );
382
437
}
383
438
@@ -391,6 +446,16 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
391
446
check_computeblockversion (chainParams->GetConsensus (), static_cast <Consensus::DeploymentPos>(i));
392
447
}
393
448
}
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
+ }
394
459
}
395
460
396
461
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments