tests: test ComputeBlockVersion for all deployments

This generalises the ComputeBlockVersion test so that it can apply to
any activation parameters we might set, and checks all the parameters
set for each deployment on each chain, to simultaneously ensure that the
deployments we have configured work sensibly, and that the test code
does not suffer bitrot in the event that all interesting deployments
are buried.
pull/826/head
Anthony Towns 4 years ago
parent 63879f0a47
commit 5932744450

@ -252,38 +252,61 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
int64_t nStartTime = params.vDeployments[dep].nStartTime; int64_t nStartTime = params.vDeployments[dep].nStartTime;
int64_t nTimeout = params.vDeployments[dep].nTimeout; int64_t nTimeout = params.vDeployments[dep].nTimeout;
assert(nStartTime < nTimeout); // should not be any signalling for first block
BOOST_CHECK_EQUAL(ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);
// always active deployments shouldn't need to be tested further
if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE) return;
BOOST_REQUIRE(nStartTime < nTimeout);
BOOST_REQUIRE(nStartTime >= 0);
BOOST_REQUIRE(nTimeout <= std::numeric_limits<uint32_t>::max() || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);
BOOST_REQUIRE(0 <= bit && bit < 32);
BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);
// In the first chain, test that the bit is set by CBV until it has failed. // 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 // In the second chain, test the bit is set by CBV while STARTED and
// LOCKED-IN, and then no longer set while ACTIVE. // LOCKED-IN, and then no longer set while ACTIVE.
VersionBitsTester firstChain, secondChain; VersionBitsTester firstChain, secondChain;
// Start generating blocks before nStartTime int64_t nTime = nStartTime;
int64_t nTime = nStartTime - 1;
// Before MedianTimePast of the chain has crossed nStartTime, the bit
// should not be set.
CBlockIndex *lastBlock = nullptr; CBlockIndex *lastBlock = nullptr;
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
// Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet. // Before MedianTimePast of the chain has crossed nStartTime, the bit
for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) { // should not be set.
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); if (nTime == 0) {
// This works because VERSIONBITS_LAST_OLD_BLOCK_VERSION happens // since CBlockIndex::nTime is uint32_t we can't represent any
// to be 4, and the bit we're testing happens to be bit 28. // earlier time, so will transition from DEFINED to STARTED at the
// end of the first period by mining blocks at nTime == 0
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0); BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
} lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
// CBV should still not yet set the bit. // then we'll keep mining at nStartTime...
nTime = nStartTime; } else {
for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) { // use a time 1s earlier than start time to check we stay DEFINED
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); --nTime;
// Start generating blocks before nStartTime
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0); BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
// Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet.
for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) {
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
}
// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
// CBV should still not yet set the bit.
nTime = nStartTime;
for (uint32_t i = params.nMinerConfirmationWindow - 4; i <= params.nMinerConfirmationWindow; i++) {
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
}
// Next we will advance to the next period and transition to STARTED,
} }
// Advance to the next period and transition to STARTED,
lastBlock = firstChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); lastBlock = firstChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
// so ComputeBlockVersion should now set the bit, // so ComputeBlockVersion should now set the bit,
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0); BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
@ -304,17 +327,29 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
nHeight += 1; nHeight += 1;
} }
nTime = nTimeout; if (nTimeout != Consensus::BIP9Deployment::NO_TIMEOUT) {
// FAILED is only triggered at the end of a period, so CBV should be setting // can reach any nTimeout other than NO_TIMEOUT due to earlier BOOST_REQUIRE
// the bit until the period transition.
for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) { nTime = nTimeout;
// finish the last period before we start timing out
while (nHeight % params.nMinerConfirmationWindow != 0) {
lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
nHeight += 1;
}
// FAILED is only triggered at the end of a period, so CBV should be setting
// the bit until the period transition.
for (uint32_t i = 0; i < params.nMinerConfirmationWindow - 1; i++) {
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0);
nHeight += 1;
}
// The next block should trigger no longer setting the bit.
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0); BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
nHeight += 1;
} }
// The next block should trigger no longer setting the bit.
lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
// On a new chain: // On a new chain:
// verify that the bit will be set after lock-in, and then stop being set // verify that the bit will be set after lock-in, and then stop being set
@ -338,17 +373,18 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0); BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);
lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0); BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0);
// Finally, verify that after a soft fork has activated, CBV no longer uses
// VERSIONBITS_LAST_OLD_BLOCK_VERSION.
//BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
} }
BOOST_AUTO_TEST_CASE(versionbits_computeblockversion) BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
{ {
// Use the TESTDUMMY deployment for testing purposes. // check that any deployment on any chain can conceivably reach both
const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN); // ACTIVE and FAILED states in roughly the way we expect
check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY); for (const auto& chain_name : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::SIGNET, 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));
}
}
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

Loading…
Cancel
Save