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