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