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