/ src / test / versionbits_tests.cpp
versionbits_tests.cpp
  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  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      explicit(false) TestConditionChecker(const Consensus::BIP9Deployment& dep) : VersionBitsConditionChecker{dep} { }
 28      ~TestConditionChecker() override = default;
 29  
 30      ThresholdState StateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, cache); }
 31      int StateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, cache); }
 32      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      Deployments()
 48      {
 49          delayed = normal; delayed.min_activation_height = 15000;
 50          always = normal; always.nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
 51          never = normal; never.nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
 52      }
 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      explicit VersionBitsTester(FastRandomContext& rng, int32_t nVersionBase=0) : m_rng{rng}, nVersionBase{nVersionBase} { }
 86  
 87      VersionBitsTester& Reset() {
 88          // Have each group of tests be counted by the 1000s part, starting at 1000
 89          num = num - (num % 1000) + 1000;
 90  
 91          for (unsigned int i = 0; i < vpblock.size(); i++) {
 92              delete vpblock[i];
 93          }
 94          for (unsigned int  i = 0; i < CHECKERS; i++) {
 95              checker[i].clear();
 96              checker_delayed[i].clear();
 97              checker_always[i].clear();
 98              checker_never[i].clear();
 99          }
100          vpblock.clear();
101          return *this;
102      }
103  
104      ~VersionBitsTester() {
105           Reset();
106      }
107  
108      VersionBitsTester& Mine(unsigned int height, int32_t nTime, int32_t nVersion) {
109          while (vpblock.size() < height) {
110              CBlockIndex* pindex = new CBlockIndex();
111              pindex->nHeight = vpblock.size();
112              pindex->pprev = Tip();
113              pindex->nTime = nTime;
114              pindex->nVersion = (nVersionBase | nVersion);
115              pindex->BuildSkip();
116              vpblock.push_back(pindex);
117          }
118          return *this;
119      }
120  
121      VersionBitsTester& TestStateSinceHeight(int height)
122      {
123          return TestStateSinceHeight(height, height);
124      }
125  
126      VersionBitsTester& TestStateSinceHeight(int height, int height_delayed)
127      {
128          const CBlockIndex* tip = Tip();
129          for (int i = 0; i < CHECKERS; i++) {
130              if (m_rng.randbits(i) == 0) {
131                  BOOST_CHECK_MESSAGE(checker[i].StateSinceHeightFor(tip) == height, strprintf("Test %i for StateSinceHeight", num));
132                  BOOST_CHECK_MESSAGE(checker_delayed[i].StateSinceHeightFor(tip) == height_delayed, strprintf("Test %i for StateSinceHeight (delayed)", num));
133                  BOOST_CHECK_MESSAGE(checker_always[i].StateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
134                  BOOST_CHECK_MESSAGE(checker_never[i].StateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (never active)", num));
135              }
136          }
137          num++;
138          return *this;
139      }
140  
141      VersionBitsTester& TestState(ThresholdState exp)
142      {
143          return TestState(exp, exp);
144      }
145  
146      VersionBitsTester& TestState(ThresholdState exp, ThresholdState exp_delayed)
147      {
148          if (exp != exp_delayed) {
149              // only expected differences are that delayed stays in locked_in longer
150              BOOST_CHECK_EQUAL(exp, ThresholdState::ACTIVE);
151              BOOST_CHECK_EQUAL(exp_delayed, ThresholdState::LOCKED_IN);
152          }
153  
154          const CBlockIndex* pindex = Tip();
155          for (int i = 0; i < CHECKERS; i++) {
156              if (m_rng.randbits(i) == 0) {
157                  ThresholdState got = checker[i].StateFor(pindex);
158                  ThresholdState got_delayed = checker_delayed[i].StateFor(pindex);
159                  ThresholdState got_always = checker_always[i].StateFor(pindex);
160                  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                  int height = pindex == nullptr ? 0 : pindex->nHeight + 1;
164                  BOOST_CHECK_MESSAGE(got == exp, strprintf("Test %i for %s height %d (got %s)", num, StateName(exp), height, StateName(got)));
165                  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                  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                  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          num++;
171          return *this;
172      }
173  
174      VersionBitsTester& TestDefined() { return TestState(ThresholdState::DEFINED); }
175      VersionBitsTester& TestStarted() { return TestState(ThresholdState::STARTED); }
176      VersionBitsTester& TestLockedIn() { return TestState(ThresholdState::LOCKED_IN); }
177      VersionBitsTester& TestActive() { return TestState(ThresholdState::ACTIVE); }
178      VersionBitsTester& TestFailed() { return TestState(ThresholdState::FAILED); }
179  
180      // non-delayed should be active; delayed should still be locked in
181      VersionBitsTester& TestActiveDelayed() { return TestState(ThresholdState::ACTIVE, ThresholdState::LOCKED_IN); }
182  
183      CBlockIndex* Tip() { return vpblock.empty() ? nullptr : vpblock.back(); }
184  };
185  
186  BOOST_FIXTURE_TEST_SUITE(versionbits_tests, BasicTestingSetup)
187  
188  BOOST_AUTO_TEST_CASE(versionbits_test)
189  {
190      for (int i = 0; i < 64; i++) {
191          // DEFINED -> STARTED after timeout reached -> FAILED
192          VersionBitsTester(m_rng, VERSIONBITS_TOP_BITS).TestDefined().TestStateSinceHeight(0)
193                             .Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0)
194                             .Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0)
195                             .Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0)
196                             .Mine(999, TestTime(20000), 0x100).TestDefined().TestStateSinceHeight(0) // Timeout and start time reached simultaneously
197                             .Mine(1000, TestTime(20000), 0).TestStarted().TestStateSinceHeight(1000) // Hit started, stop signalling
198                             .Mine(1999, TestTime(30001), 0).TestStarted().TestStateSinceHeight(1000)
199                             .Mine(2000, TestTime(30002), 0x100).TestFailed().TestStateSinceHeight(2000) // Hit failed, start signalling again
200                             .Mine(2001, TestTime(30003), 0x100).TestFailed().TestStateSinceHeight(2000)
201                             .Mine(2999, TestTime(30004), 0x100).TestFailed().TestStateSinceHeight(2000)
202                             .Mine(3000, TestTime(30005), 0x100).TestFailed().TestStateSinceHeight(2000)
203                             .Mine(4000, TestTime(30006), 0x100).TestFailed().TestStateSinceHeight(2000)
204  
205          // DEFINED -> STARTED -> FAILED
206                             .Reset().TestDefined().TestStateSinceHeight(0)
207                             .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
208                             .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
209                             .Mine(2000, TestTime(10000), 0x100).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
210                             .Mine(2051, TestTime(10010), 0).TestStarted().TestStateSinceHeight(2000) // 51 old blocks
211                             .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 899 new blocks
212                             .Mine(3000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(3000) // 50 old blocks (so 899 out of the past 1000)
213                             .Mine(4000, TestTime(20010), 0x100).TestFailed().TestStateSinceHeight(3000)
214  
215          // DEFINED -> STARTED -> LOCKEDIN after timeout reached -> ACTIVE
216                             .Reset().TestDefined().TestStateSinceHeight(0)
217                             .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
218                             .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
219                             .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
220                             .Mine(2999, TestTime(30000), 0x100).TestStarted().TestStateSinceHeight(2000) // 999 new blocks
221                             .Mine(3000, TestTime(30000), 0x100).TestLockedIn().TestStateSinceHeight(3000) // 1 new block (so 1000 out of the past 1000 are new)
222                             .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
223                             .Mine(4000, TestTime(30002), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
224                             .Mine(14333, TestTime(30003), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
225                             .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
226  
227          // DEFINED -> STARTED -> LOCKEDIN before timeout -> ACTIVE
228                             .Reset().TestDefined()
229                             .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
230                             .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
231                             .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
232                             .Mine(2050, TestTime(10010), 0x200).TestStarted().TestStateSinceHeight(2000) // 50 old blocks
233                             .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 900 new blocks
234                             .Mine(2999, TestTime(19999), 0x200).TestStarted().TestStateSinceHeight(2000) // 49 old blocks
235                             .Mine(3000, TestTime(29999), 0x200).TestLockedIn().TestStateSinceHeight(3000) // 1 old block (so 900 out of the past 1000)
236                             .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
237                             .Mine(4000, TestTime(30002), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000) // delayed will not become active until height=15000
238                             .Mine(14333, TestTime(30003), 0).TestActiveDelayed().TestStateSinceHeight(4000, 3000)
239                             .Mine(15000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
240                             .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000, 15000)
241  
242          // DEFINED multiple periods -> STARTED multiple periods -> FAILED
243                             .Reset().TestDefined().TestStateSinceHeight(0)
244                             .Mine(999, TestTime(999), 0).TestDefined().TestStateSinceHeight(0)
245                             .Mine(1000, TestTime(1000), 0).TestDefined().TestStateSinceHeight(0)
246                             .Mine(2000, TestTime(2000), 0).TestDefined().TestStateSinceHeight(0)
247                             .Mine(3000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
248                             .Mine(4000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
249                             .Mine(5000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
250                             .Mine(5999, TestTime(20000), 0).TestStarted().TestStateSinceHeight(3000)
251                             .Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000)
252                             .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000)
253                             .Mine(24000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000) // stay in FAILED no matter how much we signal
254          ;
255      }
256  }
257  
258  struct BlockVersionTest : BasicTestingSetup {
259  /** Check that ComputeBlockVersion will set the appropriate bit correctly
260   * Also checks IsActiveAfter() behaviour */
261  void check_computeblockversion(VersionBitsCache& versionbitscache, const Consensus::Params& params, Consensus::DeploymentPos dep)
262  {
263      // Clear the cache every time
264      versionbitscache.Clear();
265  
266      int64_t bit = params.vDeployments[dep].bit;
267      int64_t nStartTime = params.vDeployments[dep].nStartTime;
268      int64_t nTimeout = params.vDeployments[dep].nTimeout;
269      int min_activation_height = params.vDeployments[dep].min_activation_height;
270      uint32_t period = params.vDeployments[dep].period;
271      uint32_t threshold = params.vDeployments[dep].threshold;
272  
273      BOOST_REQUIRE(period > 0); // no division by zero, thankyou
274      BOOST_REQUIRE(0 < threshold); // must be able to have a window that doesn't activate
275      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      BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
279  
280      // always/never active deployments shouldn't need to be tested further
281      if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE ||
282          nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE)
283      {
284          if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
285              BOOST_CHECK(versionbitscache.IsActiveAfter(nullptr, params, dep));
286          } else {
287              BOOST_CHECK(!versionbitscache.IsActiveAfter(nullptr, params, dep));
288          }
289          BOOST_CHECK_EQUAL(min_activation_height, 0);
290          BOOST_CHECK_EQUAL(nTimeout, Consensus::BIP9Deployment::NO_TIMEOUT);
291          return;
292      }
293  
294      BOOST_REQUIRE(nStartTime < nTimeout);
295      BOOST_REQUIRE(nStartTime >= 0);
296      BOOST_REQUIRE(nTimeout <= std::numeric_limits<uint32_t>::max() || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
297      BOOST_REQUIRE(0 <= bit && bit < 32);
298      // Make sure that no deployment tries to set an invalid bit.
299      BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
300      BOOST_REQUIRE(min_activation_height >= 0);
301      // Check min_activation_height is on a retarget boundary
302      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      VersionBitsTester firstChain{m_rng}, secondChain{m_rng};
308  
309      int64_t nTime = nStartTime;
310  
311      const CBlockIndex *lastBlock = nullptr;
312  
313      // Before MedianTimePast of the chain has crossed nStartTime, the bit
314      // should not be set.
315      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          lastBlock = firstChain.Mine(period - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
320          BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
321          BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
322          lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
323          BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
324          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          --nTime;
329  
330          // Start generating blocks before nStartTime
331          lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
332          BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
333          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          for (uint32_t i = 1; i < period - 4; i++) {
337              lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
338              BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
339              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          nTime = nStartTime;
344          for (uint32_t i = period - 4; i <= period; i++) {
345              lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
346              BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
347              BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
348          }
349          // Next we will advance to the next period and transition to STARTED,
350      }
351  
352      lastBlock = firstChain.Mine(period * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
353      // so ComputeBlockVersion should now set the bit,
354      BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
355      // and should also be using the VERSIONBITS_TOP_BITS.
356      BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
357      BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
358  
359      // Check that ComputeBlockVersion will set the bit until nTimeout
360      nTime += 600;
361      uint32_t blocksToMine = period * 2; // test blocks for up to 2 time periods
362      uint32_t nHeight = period * 3;
363      // These blocks are all before nTimeout is reached.
364      while (nTime < nTimeout && blocksToMine > 0) {
365          lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
366          BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
367          BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
368          BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
369          blocksToMine--;
370          nTime += 600;
371          nHeight += 1;
372      }
373  
374      if (nTimeout != Consensus::BIP9Deployment::NO_TIMEOUT) {
375          // can reach any nTimeout other than NO_TIMEOUT due to earlier BOOST_REQUIRE
376  
377          nTime = nTimeout;
378  
379          // finish the last period before we start timing out
380          while (nHeight % period != 0) {
381              lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
382              BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
383              BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
384              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          for (uint32_t i = 0; i < period - 1; i++) {
390              lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
391              BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
392              BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
393              nHeight += 1;
394          }
395          // The next block should trigger no longer setting the bit.
396          lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
397          BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
398          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      nTime = nStartTime;
405  
406      // Mine one period worth of blocks, and check that the bit will be on for the
407      // next period.
408      lastBlock = secondChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
409      BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
410      BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
411  
412      // Mine another period worth of blocks, signaling the new bit.
413      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      BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
417      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      lastBlock = secondChain.Mine((period * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
422      BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
423      BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
424      lastBlock = secondChain.Mine(period * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
425  
426      if (lastBlock->nHeight + 1 < min_activation_height) {
427          // check signalling continues while min_activation_height is not reached
428          lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
429          BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
430          BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));
431          // then reach min_activation_height, which was already REQUIRE'd to start a new period
432          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      BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
437      BOOST_CHECK(versionbitscache.IsActiveAfter(lastBlock, params, dep));
438  }
439  }; // struct BlockVersionTest
440  
441  BOOST_FIXTURE_TEST_CASE(versionbits_computeblockversion, BlockVersionTest)
442  {
443      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      for (const auto& chain_type: {ChainType::MAIN, ChainType::TESTNET, ChainType::TESTNET4, ChainType::SIGNET, ChainType::REGTEST}) {
448          const auto chainParams = CreateChainParams(*m_node.args, chain_type);
449          uint32_t chain_all_vbits{0};
450          for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
451              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              const uint32_t dep_mask{uint32_t{1} << chainParams->GetConsensus().vDeployments[dep].bit};
458              BOOST_CHECK(!(chain_all_vbits & dep_mask));
459              chain_all_vbits |= dep_mask;
460              check_computeblockversion(vbcache, chainParams->GetConsensus(), dep);
461          }
462      }
463  
464      {
465          // Use regtest/testdummy to ensure we always exercise some
466          // deployment that's not always/never active
467          ArgsManager args;
468          args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999"); // January 1, 2008 - December 31, 2008
469          const auto chainParams = CreateChainParams(args, ChainType::REGTEST);
470          check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
471      }
472  
473      {
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          ArgsManager args;
478          args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200
479          const auto chainParams = CreateChainParams(args, ChainType::REGTEST);
480          check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
481      }
482  }
483  
484  BOOST_AUTO_TEST_SUITE_END()