diff options
author | Anthony Towns <aj@erisian.com.au> | 2021-03-28 03:10:48 +1000 |
---|---|---|
committer | Anthony Towns <aj@erisian.com.au> | 2021-04-12 10:47:42 +1000 |
commit | 593274445004506c921d5d851361aefb3434d744 (patch) | |
tree | 2fca71183f72b5303dea2358ad35bf97dcfedc04 | |
parent | 63879f0a4760c0c0f784029849cb5d21ee088abb (diff) |
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.
-rw-r--r-- | src/test/versionbits_tests.cpp | 106 |
1 files changed, 71 insertions, 35 deletions
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index b09827ffe5..7e96ef923e 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -252,38 +252,61 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus int64_t nStartTime = params.vDeployments[dep].nStartTime; 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 second chain, test the bit is set by CBV while STARTED and // LOCKED-IN, and then no longer set while ACTIVE. VersionBitsTester firstChain, secondChain; - // Start generating blocks before nStartTime - int64_t nTime = nStartTime - 1; + int64_t nTime = nStartTime; - // Before MedianTimePast of the chain has crossed nStartTime, the bit - // should not be set. 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. - for (uint32_t i = 1; i < params.nMinerConfirmationWindow - 4; i++) { - lastBlock = firstChain.Mine(params.nMinerConfirmationWindow + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); - // This works because VERSIONBITS_LAST_OLD_BLOCK_VERSION happens - // to be 4, and the bit we're testing happens to be bit 28. + // Before MedianTimePast of the chain has crossed nStartTime, the bit + // should not be set. + if (nTime == 0) { + // since CBlockIndex::nTime is uint32_t we can't represent any + // 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); - } - // 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(); + lastBlock = firstChain.Mine(params.nMinerConfirmationWindow, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0); + // then we'll keep mining at nStartTime... + } else { + // use a time 1s earlier than start time to check we stay DEFINED + --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); + + // 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(); // so ComputeBlockVersion should now set the bit, BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0); @@ -304,17 +327,29 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus nHeight += 1; } - nTime = nTimeout; - // 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++) { + if (nTimeout != Consensus::BIP9Deployment::NO_TIMEOUT) { + // can reach any nTimeout other than NO_TIMEOUT due to earlier BOOST_REQUIRE + + 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(); - BOOST_CHECK((ComputeBlockVersion(lastBlock, params) & (1<<bit)) != 0); - nHeight += 1; + BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, params) & (1<<bit), 0); } - // 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: // 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); lastBlock = secondChain.Mine(params.nMinerConfirmationWindow * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); 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) { - // Use the TESTDUMMY deployment for testing purposes. - const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN); - check_computeblockversion(chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY); + // 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::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() |