1 // Copyright (c) 2014-2016 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.
6 #include "versionbits.h"
7 #include "test/test_bitcoin.h"
8 #include "chainparams.h"
9 #include "validation.h"
10 #include "consensus/params.h"
12 #include <boost/test/unit_test.hpp>
14 /* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
15 int32_t TestTime(int nHeight
) { return 1415926536 + 600 * nHeight
; }
17 static const Consensus::Params paramsDummy
= Consensus::Params();
19 class TestConditionChecker
: public AbstractThresholdConditionChecker
22 mutable ThresholdConditionCache cache
;
25 int64_t BeginTime(const Consensus::Params
& params
) const override
{ return TestTime(10000); }
26 int64_t EndTime(const Consensus::Params
& params
) const override
{ return TestTime(20000); }
27 int Period(const Consensus::Params
& params
) const override
{ return 1000; }
28 int Threshold(const Consensus::Params
& params
) const override
{ return 900; }
29 bool Condition(const CBlockIndex
* pindex
, const Consensus::Params
& params
) const override
{ return (pindex
->nVersion
& 0x100); }
31 ThresholdState
GetStateFor(const CBlockIndex
* pindexPrev
) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev
, paramsDummy
, cache
); }
32 int GetStateSinceHeightFor(const CBlockIndex
* pindexPrev
) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev
, paramsDummy
, cache
); }
37 class VersionBitsTester
40 std::vector
<CBlockIndex
*> vpblock
;
42 // 6 independent checkers for the same bit.
43 // The first one performs all checks, the second only 50%, the third only 25%, etc...
44 // This is to test whether lack of cached information leads to the same results.
45 TestConditionChecker checker
[CHECKERS
];
47 // Test counter (to identify failures)
51 VersionBitsTester() : num(0) {}
53 VersionBitsTester
& Reset() {
54 for (unsigned int i
= 0; i
< vpblock
.size(); i
++) {
57 for (unsigned int i
= 0; i
< CHECKERS
; i
++) {
58 checker
[i
] = TestConditionChecker();
64 ~VersionBitsTester() {
68 VersionBitsTester
& Mine(unsigned int height
, int32_t nTime
, int32_t nVersion
) {
69 while (vpblock
.size() < height
) {
70 CBlockIndex
* pindex
= new CBlockIndex();
71 pindex
->nHeight
= vpblock
.size();
72 pindex
->pprev
= vpblock
.size() > 0 ? vpblock
.back() : nullptr;
73 pindex
->nTime
= nTime
;
74 pindex
->nVersion
= nVersion
;
76 vpblock
.push_back(pindex
);
81 VersionBitsTester
& TestStateSinceHeight(int height
) {
82 for (int i
= 0; i
< CHECKERS
; i
++) {
83 if (InsecureRandBits(i
) == 0) {
84 BOOST_CHECK_MESSAGE(checker
[i
].GetStateSinceHeightFor(vpblock
.empty() ? nullptr : vpblock
.back()) == height
, strprintf("Test %i for StateSinceHeight", num
));
91 VersionBitsTester
& TestDefined() {
92 for (int i
= 0; i
< CHECKERS
; i
++) {
93 if (InsecureRandBits(i
) == 0) {
94 BOOST_CHECK_MESSAGE(checker
[i
].GetStateFor(vpblock
.empty() ? nullptr : vpblock
.back()) == THRESHOLD_DEFINED
, strprintf("Test %i for DEFINED", num
));
101 VersionBitsTester
& TestStarted() {
102 for (int i
= 0; i
< CHECKERS
; i
++) {
103 if (InsecureRandBits(i
) == 0) {
104 BOOST_CHECK_MESSAGE(checker
[i
].GetStateFor(vpblock
.empty() ? nullptr : vpblock
.back()) == THRESHOLD_STARTED
, strprintf("Test %i for STARTED", num
));
111 VersionBitsTester
& TestLockedIn() {
112 for (int i
= 0; i
< CHECKERS
; i
++) {
113 if (InsecureRandBits(i
) == 0) {
114 BOOST_CHECK_MESSAGE(checker
[i
].GetStateFor(vpblock
.empty() ? nullptr : vpblock
.back()) == THRESHOLD_LOCKED_IN
, strprintf("Test %i for LOCKED_IN", num
));
121 VersionBitsTester
& TestActive() {
122 for (int i
= 0; i
< CHECKERS
; i
++) {
123 if (InsecureRandBits(i
) == 0) {
124 BOOST_CHECK_MESSAGE(checker
[i
].GetStateFor(vpblock
.empty() ? nullptr : vpblock
.back()) == THRESHOLD_ACTIVE
, strprintf("Test %i for ACTIVE", num
));
131 VersionBitsTester
& TestFailed() {
132 for (int i
= 0; i
< CHECKERS
; i
++) {
133 if (InsecureRandBits(i
) == 0) {
134 BOOST_CHECK_MESSAGE(checker
[i
].GetStateFor(vpblock
.empty() ? nullptr : vpblock
.back()) == THRESHOLD_FAILED
, strprintf("Test %i for FAILED", num
));
141 CBlockIndex
* Tip() { return vpblock
.size() ? vpblock
.back() : nullptr; }
144 BOOST_FIXTURE_TEST_SUITE(versionbits_tests
, TestingSetup
)
146 BOOST_AUTO_TEST_CASE(versionbits_test
)
148 for (int i
= 0; i
< 64; i
++) {
150 VersionBitsTester().TestDefined().TestStateSinceHeight(0)
151 .Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0)
152 .Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0)
153 .Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0)
154 .Mine(999, TestTime(20000), 0x100).TestDefined().TestStateSinceHeight(0)
155 .Mine(1000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(1000)
156 .Mine(1999, TestTime(30001), 0x100).TestFailed().TestStateSinceHeight(1000)
157 .Mine(2000, TestTime(30002), 0x100).TestFailed().TestStateSinceHeight(1000)
158 .Mine(2001, TestTime(30003), 0x100).TestFailed().TestStateSinceHeight(1000)
159 .Mine(2999, TestTime(30004), 0x100).TestFailed().TestStateSinceHeight(1000)
160 .Mine(3000, TestTime(30005), 0x100).TestFailed().TestStateSinceHeight(1000)
162 // DEFINED -> STARTED -> FAILED
163 .Reset().TestDefined().TestStateSinceHeight(0)
164 .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
165 .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
166 .Mine(2000, TestTime(10000), 0x100).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
167 .Mine(2051, TestTime(10010), 0).TestStarted().TestStateSinceHeight(2000) // 51 old blocks
168 .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 899 new blocks
169 .Mine(3000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(3000) // 50 old blocks (so 899 out of the past 1000)
170 .Mine(4000, TestTime(20010), 0x100).TestFailed().TestStateSinceHeight(3000)
172 // DEFINED -> STARTED -> FAILED while threshold reached
173 .Reset().TestDefined().TestStateSinceHeight(0)
174 .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
175 .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
176 .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
177 .Mine(2999, TestTime(30000), 0x100).TestStarted().TestStateSinceHeight(2000) // 999 new blocks
178 .Mine(3000, TestTime(30000), 0x100).TestFailed().TestStateSinceHeight(3000) // 1 new block (so 1000 out of the past 1000 are new)
179 .Mine(3999, TestTime(30001), 0).TestFailed().TestStateSinceHeight(3000)
180 .Mine(4000, TestTime(30002), 0).TestFailed().TestStateSinceHeight(3000)
181 .Mine(14333, TestTime(30003), 0).TestFailed().TestStateSinceHeight(3000)
182 .Mine(24000, TestTime(40000), 0).TestFailed().TestStateSinceHeight(3000)
184 // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE
185 .Reset().TestDefined()
186 .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
187 .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
188 .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
189 .Mine(2050, TestTime(10010), 0x200).TestStarted().TestStateSinceHeight(2000) // 50 old blocks
190 .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 900 new blocks
191 .Mine(2999, TestTime(19999), 0x200).TestStarted().TestStateSinceHeight(2000) // 49 old blocks
192 .Mine(3000, TestTime(29999), 0x200).TestLockedIn().TestStateSinceHeight(3000) // 1 old block (so 900 out of the past 1000)
193 .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
194 .Mine(4000, TestTime(30002), 0).TestActive().TestStateSinceHeight(4000)
195 .Mine(14333, TestTime(30003), 0).TestActive().TestStateSinceHeight(4000)
196 .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000)
198 // DEFINED multiple periods -> STARTED multiple periods -> FAILED
199 .Reset().TestDefined().TestStateSinceHeight(0)
200 .Mine(999, TestTime(999), 0).TestDefined().TestStateSinceHeight(0)
201 .Mine(1000, TestTime(1000), 0).TestDefined().TestStateSinceHeight(0)
202 .Mine(2000, TestTime(2000), 0).TestDefined().TestStateSinceHeight(0)
203 .Mine(3000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
204 .Mine(4000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
205 .Mine(5000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
206 .Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000)
207 .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000);
210 // Sanity checks of version bit deployments
211 const auto chainParams
= CreateChainParams(CBaseChainParams::MAIN
);
212 const Consensus::Params
&mainnetParams
= chainParams
->GetConsensus();
213 for (int i
=0; i
<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS
; i
++) {
214 uint32_t bitmask
= VersionBitsMask(mainnetParams
, (Consensus::DeploymentPos
)i
);
215 // Make sure that no deployment tries to set an invalid bit.
216 BOOST_CHECK_EQUAL(bitmask
& ~(uint32_t)VERSIONBITS_TOP_MASK
, bitmask
);
218 // Verify that the deployment windows of different deployment using the
219 // same bit are disjoint.
220 // This test may need modification at such time as a new deployment
221 // is proposed that reuses the bit of an activated soft fork, before the
222 // end time of that soft fork. (Alternatively, the end time of that
223 // activated soft fork could be later changed to be earlier to avoid
225 for (int j
=i
+1; j
<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS
; j
++) {
226 if (VersionBitsMask(mainnetParams
, (Consensus::DeploymentPos
)j
) == bitmask
) {
227 BOOST_CHECK(mainnetParams
.vDeployments
[j
].nStartTime
> mainnetParams
.vDeployments
[i
].nTimeout
||
228 mainnetParams
.vDeployments
[i
].nStartTime
> mainnetParams
.vDeployments
[j
].nTimeout
);
234 BOOST_AUTO_TEST_CASE(versionbits_computeblockversion
)
236 // Check that ComputeBlockVersion will set the appropriate bit correctly
238 const auto chainParams
= CreateChainParams(CBaseChainParams::MAIN
);
239 const Consensus::Params
&mainnetParams
= chainParams
->GetConsensus();
241 // Use the TESTDUMMY deployment for testing purposes.
242 int64_t bit
= mainnetParams
.vDeployments
[Consensus::DEPLOYMENT_TESTDUMMY
].bit
;
243 int64_t nStartTime
= mainnetParams
.vDeployments
[Consensus::DEPLOYMENT_TESTDUMMY
].nStartTime
;
244 int64_t nTimeout
= mainnetParams
.vDeployments
[Consensus::DEPLOYMENT_TESTDUMMY
].nTimeout
;
246 assert(nStartTime
< nTimeout
);
248 // In the first chain, test that the bit is set by CBV until it has failed.
249 // In the second chain, test the bit is set by CBV while STARTED and
250 // LOCKED-IN, and then no longer set while ACTIVE.
251 VersionBitsTester firstChain
, secondChain
;
253 // Start generating blocks before nStartTime
254 int64_t nTime
= nStartTime
- 1;
256 // Before MedianTimePast of the chain has crossed nStartTime, the bit
257 // should not be set.
258 CBlockIndex
*lastBlock
= nullptr;
259 lastBlock
= firstChain
.Mine(2016, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
260 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
), 0);
262 // Mine 2011 more blocks at the old time, and check that CBV isn't setting the bit yet.
263 for (int i
=1; i
<2012; i
++) {
264 lastBlock
= firstChain
.Mine(2016+i
, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
265 // This works because VERSIONBITS_LAST_OLD_BLOCK_VERSION happens
266 // to be 4, and the bit we're testing happens to be bit 28.
267 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
), 0);
269 // Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
270 // CBV should still not yet set the bit.
272 for (int i
=2012; i
<=2016; i
++) {
273 lastBlock
= firstChain
.Mine(2016+i
, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
274 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
), 0);
277 // Advance to the next period and transition to STARTED,
278 lastBlock
= firstChain
.Mine(6048, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
279 // so ComputeBlockVersion should now set the bit,
280 BOOST_CHECK((ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
)) != 0);
281 // and should also be using the VERSIONBITS_TOP_BITS.
282 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & VERSIONBITS_TOP_MASK
, VERSIONBITS_TOP_BITS
);
284 // Check that ComputeBlockVersion will set the bit until nTimeout
286 int blocksToMine
= 4032; // test blocks for up to 2 time periods
288 // These blocks are all before nTimeout is reached.
289 while (nTime
< nTimeout
&& blocksToMine
> 0) {
290 lastBlock
= firstChain
.Mine(nHeight
+1, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
291 BOOST_CHECK((ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
)) != 0);
292 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & VERSIONBITS_TOP_MASK
, VERSIONBITS_TOP_BITS
);
299 // FAILED is only triggered at the end of a period, so CBV should be setting
300 // the bit until the period transition.
301 for (int i
=0; i
<2015; i
++) {
302 lastBlock
= firstChain
.Mine(nHeight
+1, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
303 BOOST_CHECK((ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
)) != 0);
306 // The next block should trigger no longer setting the bit.
307 lastBlock
= firstChain
.Mine(nHeight
+1, nTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
308 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
), 0);
311 // verify that the bit will be set after lock-in, and then stop being set
315 // Mine one period worth of blocks, and check that the bit will be on for the
317 lastBlock
= secondChain
.Mine(2016, nStartTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
318 BOOST_CHECK((ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
)) != 0);
320 // Mine another period worth of blocks, signaling the new bit.
321 lastBlock
= secondChain
.Mine(4032, nStartTime
, VERSIONBITS_TOP_BITS
| (1<<bit
)).Tip();
322 // After one period of setting the bit on each block, it should have locked in.
323 // We keep setting the bit for one more period though, until activation.
324 BOOST_CHECK((ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
)) != 0);
326 // Now check that we keep mining the block until the end of this period, and
327 // then stop at the beginning of the next period.
328 lastBlock
= secondChain
.Mine(6047, nStartTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
329 BOOST_CHECK((ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
)) != 0);
330 lastBlock
= secondChain
.Mine(6048, nStartTime
, VERSIONBITS_LAST_OLD_BLOCK_VERSION
).Tip();
331 BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock
, mainnetParams
) & (1<<bit
), 0);
333 // Finally, verify that after a soft fork has activated, CBV no longer uses
334 // VERSIONBITS_LAST_OLD_BLOCK_VERSION.
335 //BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
339 BOOST_AUTO_TEST_SUITE_END()