Skip to content

Commit dd85d54

Browse files
committed
tests: test versionbits delayed activation
1 parent 73d4a70 commit dd85d54

File tree

1 file changed

+74
-9
lines changed

1 file changed

+74
-9
lines changed

src/test/versionbits_tests.cpp

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4753
class TestAlwaysActiveConditionChecker : public TestConditionChecker
4854
{
4955
public:
@@ -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

7987
public:
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, 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+
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, 0);
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

396461
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)