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()
|