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