BIP8 test fixes

pull/751/head
David Burkett 3 years ago
parent 3865f76a97
commit 133e84880e

@ -29,16 +29,16 @@ public:
const int64_t m_end;
const int m_period;
const int m_threshold;
const int m_min_activation_height;
const int64_t m_begin_height;
const int64_t m_end_height;
const int m_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}
TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int64_t begin_height, int64_t end_height, int bit)
: m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_begin_height{begin_height}, m_end_height{end_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); }
@ -46,7 +46,8 @@ 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; }
int64_t BeginHeight(const Consensus::Params& params) const override { return m_begin_height; }
int64_t EndHeight(const Consensus::Params& params) const override { return m_end_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); }
@ -144,6 +145,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
bool never_active_test = false;
int64_t start_time;
int64_t timeout;
int64_t start_height = 0;
int64_t end_height = 0;
if (fuzzed_data_provider.ConsumeBool()) {
// pick the timestamp to switch based on a block
// note states will change *after* these blocks because mediantime lags
@ -166,9 +169,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
timeout = fuzzed_data_provider.ConsumeBool() ? Consensus::BIP9Deployment::NO_TIMEOUT : fuzzed_data_provider.ConsumeIntegral<int64_t>();
}
int min_activation = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, period * max_periods);
TestConditionChecker checker(start_time, timeout, period, threshold, min_activation, bit);
TestConditionChecker checker(start_time, timeout, period, threshold, start_height, end_height, bit);
// Early exit if the versions don't signal sensibly for the deployment
if (!checker.Condition(ver_signal)) return;
@ -304,15 +306,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
break;
case ThresholdState::LOCKED_IN:
if (exp_state == ThresholdState::LOCKED_IN) {
assert(current_block->nHeight + 1 < min_activation);
} else {
if (exp_state != ThresholdState::LOCKED_IN) {
assert(exp_state == ThresholdState::STARTED);
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:

@ -312,6 +312,93 @@ BOOST_AUTO_TEST_CASE(versionbits_sanity)
}
}
/** Check that ComputeBlockVersion will set the appropriate bit correctly for BIP8 (height-based) activation */
static void check_computeblockversion_bip8(const Consensus::Params& params, Consensus::DeploymentPos dep)
{
// nStartTime and nTimeout must be set to 0 to use BIP8
BOOST_CHECK(params.vDeployments[dep].nStartTime == 0 && params.vDeployments[dep].nTimeout == 0);
int64_t bit = params.vDeployments[dep].bit;
int64_t nStartHeight = params.vDeployments[dep].nStartHeight;
int64_t nTimeoutHeight = params.vDeployments[dep].nTimeoutHeight;
uint32_t nMinerConfirmationWindow = params.nMinerConfirmationWindow;
// should not be any signalling for first block
BOOST_CHECK_EQUAL(ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
BOOST_CHECK(nStartHeight >= 0);
BOOST_CHECK_EQUAL(nStartHeight % nMinerConfirmationWindow, 0U);
BOOST_CHECK(nTimeoutHeight <= std::numeric_limits<uint32_t>::max());
BOOST_CHECK_EQUAL(nTimeoutHeight % nMinerConfirmationWindow, 0U);
BOOST_CHECK(0 <= bit && bit < 32);
BOOST_CHECK(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
int64_t nTime = 100000;
const CBlockIndex* lastBlock = nullptr;
{
// In the first chain, we don't set the bit, and wait for forced activation via timeout.
// The bit should be set by CBV during range [nStartHeight, nTimeoutHeight + nMinerConfirmationWindow)
VersionBitsTester chain;
// Bit should not be set before nStartHeight
lastBlock = chain.Mine(nStartHeight - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
// Once we hit nStartHeight, the feature switches to STARTED, we should be able to signal for activation.
for (uint32_t i = nStartHeight; i < nTimeoutHeight; i++) {
lastBlock = chain.Mine(i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
}
// Once the time height is hit, the feature switches to LOCKED_IN for 1 full miner confirmation window
for (uint32_t i = 0; i < nMinerConfirmationWindow; i++) {
lastBlock = chain.Mine(nTimeoutHeight + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
}
// After 1 full confirmation window, the feature should be ACTIVE, so we should stop setting the bit.
lastBlock = chain.Mine(nTimeoutHeight + nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
}
{
// In the second chain, we set the bit to activate before forced activation at nTimeoutHeight.
// We will signal for the feature during the first confirmation window.
// It should be LOCKED-IN for the 2nd window, after which it switches to ACTIVE.
// The bit should be set by CBV while STARTED and LOCKED-IN, and then no longer set while ACTIVE.
// That is, it should be set by CBV during range [nStartHeight, nStartHeight + 2 * nMinerConfirmationWindow)
VersionBitsTester chain;
// Bit should not be set before nStartHeight
lastBlock = chain.Mine(nStartHeight - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
// Once we hit nStartHeight, the feature switches to STARTED, and we start signaling for activation.
for (uint32_t i = 0; i < nMinerConfirmationWindow; i++) {
lastBlock = chain.Mine(nStartHeight + i, nTime, VERSIONBITS_TOP_BITS | (1 << bit)).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
}
// After the first confirmation window, the feature switches to LOCKED-IN for 1 full miner confirmation window.
for (uint32_t i = 0; i < nMinerConfirmationWindow; i++) {
lastBlock = chain.Mine(nStartHeight + nMinerConfirmationWindow + i, nTime, VERSIONBITS_TOP_BITS | (1 << bit)).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
}
// After 1 full LOCKED-IN confirmation window, the feature should be ACTIVE, so we should stop setting the bit.
lastBlock = chain.Mine(nStartHeight + (2 * nMinerConfirmationWindow), nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);
}
}
/** Check that ComputeBlockVersion will set the appropriate bit correctly */
static void check_computeblockversion(const Consensus::Params& params, Consensus::DeploymentPos dep)
{
@ -321,8 +408,10 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
int64_t bit = params.vDeployments[dep].bit;
int64_t nStartTime = params.vDeployments[dep].nStartTime;
int64_t nTimeout = params.vDeployments[dep].nTimeout;
int64_t nStartHeight = params.vDeployments[dep].nStartHeight;
int64_t nTimeoutHeight = params.vDeployments[dep].nTimeoutHeight;
if (nStartTime == 0 && nTimeout == 0) {
return check_computeblockversion_bip8(params, dep);
}
// should not be any signalling for first block
BOOST_CHECK_EQUAL(ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
@ -336,9 +425,6 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
BOOST_CHECK(nTimeout <= std::numeric_limits<uint32_t>::max() || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
BOOST_CHECK(0 <= bit && bit < 32);
BOOST_CHECK(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
BOOST_CHECK(nStartHeight >= 0);
BOOST_CHECK_EQUAL(nStartHeight % params.nMinerConfirmationWindow, 0U);
BOOST_CHECK(nTimeoutHeight <= std::numeric_limits<uint32_t>::max());
// In the first chain, test that the bit is set by CBV until it has failed.
// In the second chain, test the bit is set by CBV while STARTED and
@ -457,7 +543,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
{
// check that any deployment on any chain can conceivably reach both
// ACTIVE and FAILED states in roughly the way we expect
for (const auto& chain_name : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST}) {
for (const auto& chain_name : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST}) {
const auto chainParams = CreateChainParams(*m_node.args, chain_name);
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
check_computeblockversion(chainParams->GetConsensus(), static_cast<Consensus::DeploymentPos>(i));
@ -473,15 +559,6 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
}
{
// Use regtest/testdummy to ensure we always exercise the
// min_activation_height test, even if we're not using that in a
// live deployment
ArgsManager args;
args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200
const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
}
}
BOOST_AUTO_TEST_SUITE_END()

@ -59,7 +59,6 @@ protected:
virtual int64_t EndTime(const Consensus::Params& params) const = 0;
virtual int64_t BeginHeight(const Consensus::Params& params) const = 0;
virtual int64_t EndHeight(const Consensus::Params& params) const = 0;
virtual int MinActivationHeight(const Consensus::Params& params) const { return 0; }
virtual int Period(const Consensus::Params& params) const =0;
virtual int Threshold(const Consensus::Params& params) const =0;

Loading…
Cancel
Save