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