message: fuzz: test versionbits delayed activation
diff: @@ -29,14 +29,16 @@ public:
  const int64_t m_end;
  const int m_period;
  const int m_threshold;
  + const int m_min_activation_height;
  const int m_bit;
  - TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int bit)
  - : m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_bit{bit}
  + TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int min_activation_height, int bit)
  + : m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_min_activation_height{min_activation_height}, m_bit{bit}
  {
  assert(m_period > 0);
  assert(0 <= m_threshold && m_threshold <= m_period);
  assert(0 <= m_bit && m_bit < 32 && m_bit < VERSIONBITS_NUM_BITS);
  + assert(0 <= m_min_activation_height);
  }
  bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return Condition(pindex->nVersion); }
  @@ -44,6 +46,7 @@ public:
  int64_t EndTime(const Consensus::Params& params) const override { return m_end; }
  int Period(const Consensus::Params& params) const override { return m_period; }
  int Threshold(const Consensus::Params& params) const override { return m_threshold; }
  + int MinActivationHeight(const Consensus::Params& params) const override { return m_min_activation_height; }
  ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, dummy_params, m_cache); }
  int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
  @@ -168,8 +171,9 @@ FUZZ_TARGET_INIT(versionbits, initialize)
  never_active_test = true;
  }
  }
  + int min_activation = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, period * max_periods);
  - TestConditionChecker checker(start_time, timeout, period, threshold, bit);
  + TestConditionChecker checker(start_time, timeout, period, threshold, min_activation, bit);
  // Early exit if the versions don't signal sensibly for the deployment
  if (!checker.Condition(ver_signal)) return;
  @@ -306,11 +310,16 @@ FUZZ_TARGET_INIT(versionbits, initialize)
  }
  break;
  case ThresholdState::LOCKED_IN:
  + if (exp_state == ThresholdState::LOCKED_IN) {
  + assert(current_block->nHeight + 1 < min_activation);
  + } else {
  assert(exp_state == ThresholdState::STARTED);
  assert(current_block->GetMedianTimePast() < checker.m_end);
  assert(blocks_sig >= threshold);
  + }
  break;
  case ThresholdState::ACTIVE:
  + assert(always_active_test || min_activation <= current_block->nHeight + 1);
  assert(exp_state == ThresholdState::ACTIVE || exp_state == ThresholdState::LOCKED_IN);
  break;
  case ThresholdState::FAILED:
  