Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251.Mine(5999, TestTime(20000), 0).TestStarted().TestStateSinceHeight(3000)252.Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000)253.Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000)254.Mine(24000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000) // stay in FAILED no matter how much we signal255;256}257}259struct BlockVersionTest : BasicTestingSetup {260/** Check that ComputeBlockVersion will set the appropriate bit correctly261* Also checks IsActiveAfter() behaviour */262void check_computeblockversion(VersionBitsCache& versionbitscache, const Consensus::Params& params, Consensus::DeploymentPos dep)263{264// Clear the cache every time265versionbitscache.Clear();267int64_t bit = params.vDeployments[dep].bit;268int64_t nStartTime = params.vDeployments[dep].nStartTime;269int64_t nTimeout = params.vDeployments[dep].nTimeout;270int min_activation_height = params.vDeployments[dep].min_activation_height;271uint32_t period = params.vDeployments[dep].period;272uint32_t threshold = params.vDeployments[dep].threshold;274BOOST_REQUIRE(period > 0); // no division by zero, thankyou275BOOST_REQUIRE(0 < threshold); // must be able to have a window that doesn't activate276BOOST_REQUIRE(threshold < period); // must be able to have a window that does activate278// should not be any signalling for first block279BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(nullptr, params), VERSIONBITS_TOP_BITS);281// always/never active deployments shouldn't need to be tested further282if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE ||283nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE)284{285if (nStartTime == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {286BOOST_CHECK(versionbitscache.IsActiveAfter(nullptr, params, dep));287} else {288BOOST_CHECK(!versionbitscache.IsActiveAfter(nullptr, params, dep));289}290BOOST_CHECK_EQUAL(min_activation_height, 0);291BOOST_CHECK_EQUAL(nTimeout, Consensus::BIP9Deployment::NO_TIMEOUT);292return;293}295BOOST_REQUIRE(nStartTime < nTimeout);296BOOST_REQUIRE(nStartTime >= 0);297BOOST_REQUIRE(nTimeout <= std::numeric_limits<uint32_t>::max() || nTimeout == Consensus::BIP9Deployment::NO_TIMEOUT);298BOOST_REQUIRE(0 <= bit);299BOOST_REQUIRE(bit < 32);300// Make sure that no deployment tries to set an invalid bit.301BOOST_REQUIRE(((1 << bit) & VERSIONBITS_TOP_MASK) == 0);302BOOST_REQUIRE(min_activation_height >= 0);303// Check min_activation_height is on a retarget boundary304BOOST_REQUIRE_EQUAL(min_activation_height % period, 0U);306// In the first chain, test that the bit is set by CBV until it has failed.307// In the second chain, test the bit is set by CBV while STARTED and308// LOCKED-IN, and then no longer set while ACTIVE.309VersionBitsTester firstChain{m_rng}, secondChain{m_rng};311int64_t nTime = nStartTime;313const CBlockIndex *lastBlock = nullptr;315// Before MedianTimePast of the chain has crossed nStartTime, the bit316// should not be set.317if (nTime == 0) {318// since CBlockIndex::nTime is uint32_t we can't represent any319// earlier time, so will transition from DEFINED to STARTED at the320// end of the first period by mining blocks at nTime == 0321lastBlock = firstChain.Mine(period - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();322BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);323BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));324lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();325BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);326BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));327// then we'll keep mining at nStartTime...328} else {329// use a time 1s earlier than start time to check we stay DEFINED330--nTime;332// Start generating blocks before nStartTime333lastBlock = firstChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();334BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);335BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));337// Mine more blocks (4 less than the adjustment period) at the old time, and check that CBV isn't setting the bit yet.338for (uint32_t i = 1; i < period - 4; i++) {339lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();340BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);341BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));342}343// Now mine 5 more blocks at the start time -- MTP should not have passed yet, so344// CBV should still not yet set the bit.345nTime = nStartTime;346for (uint32_t i = period - 4; i <= period; i++) {347lastBlock = firstChain.Mine(period + i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();348BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);349BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));350}351// Next we will advance to the next period and transition to STARTED,352}354lastBlock = firstChain.Mine(period * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();355// so ComputeBlockVersion should now set the bit,356BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);357// and should also be using the VERSIONBITS_TOP_BITS.358BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);359BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));361// Check that ComputeBlockVersion will set the bit until nTimeout362nTime += 600;363uint32_t blocksToMine = period * 2; // test blocks for up to 2 time periods364uint32_t nHeight = period * 3;365// These blocks are all before nTimeout is reached.366while (nTime < nTimeout && blocksToMine > 0) {367lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();368BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);369BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);370BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));371blocksToMine--;372nTime += 600;373nHeight += 1;374}376if (nTimeout != Consensus::BIP9Deployment::NO_TIMEOUT) {377// can reach any nTimeout other than NO_TIMEOUT due to earlier BOOST_REQUIRE379nTime = nTimeout;381// finish the last period before we start timing out382while (nHeight % period != 0) {383lastBlock = firstChain.Mine(nHeight+1, nTime - 1, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();384BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);385BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));386nHeight += 1;387}389// FAILED is only triggered at the end of a period, so CBV should be setting390// the bit until the period transition.391for (uint32_t i = 0; i < period - 1; i++) {392lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();393BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);394BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));395nHeight += 1;396}397// The next block should trigger no longer setting the bit.398lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();399BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);400BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));401}403// On a new chain:404// verify that the bit will be set after lock-in, and then stop being set405// after activation.406nTime = nStartTime;408// Mine one period worth of blocks, and check that the bit will be on for the409// next period.410lastBlock = secondChain.Mine(period, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();411BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);412BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));414// Mine another period worth of blocks, signaling the new bit.415lastBlock = secondChain.Mine(period * 2, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();416// After one period of setting the bit on each block, it should have locked in.417// We keep setting the bit for one more period though, until activation.418BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);419BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));421// Now check that we keep mining the block until the end of this period, and422// then stop at the beginning of the next period.423lastBlock = secondChain.Mine((period * 3) - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();424BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);425BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));426lastBlock = secondChain.Mine(period * 3, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();428if (lastBlock->nHeight + 1 < min_activation_height) {429// check signalling continues while min_activation_height is not reached430lastBlock = secondChain.Mine(min_activation_height - 1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();431BOOST_CHECK((versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit)) != 0);432BOOST_CHECK(!versionbitscache.IsActiveAfter(lastBlock, params, dep));433// then reach min_activation_height, which was already REQUIRE'd to start a new period434lastBlock = secondChain.Mine(min_activation_height, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();435}437// Check that we don't signal after activation438BOOST_CHECK_EQUAL(versionbitscache.ComputeBlockVersion(lastBlock, params) & (1 << bit), 0);439BOOST_CHECK(versionbitscache.IsActiveAfter(lastBlock, params, dep));440}441}; // struct BlockVersionTest443BOOST_FIXTURE_TEST_CASE(versionbits_computeblockversion, BlockVersionTest)444{445VersionBitsCache vbcache;447// check that any deployment on any chain can conceivably reach both448// ACTIVE and FAILED states in roughly the way we expect449for (const auto& chain_type: {ChainType::MAIN, ChainType::TESTNET, ChainType::TESTNET4, ChainType::SIGNET, ChainType::REGTEST}) {450const auto chainParams = CreateChainParams(*m_node.args, chain_type);451uint32_t chain_all_vbits{0};452for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {453const auto dep = static_cast<Consensus::DeploymentPos>(i);454// Check that no bits are reused (within the same chain). This is455// disallowed because the transition to FAILED (on timeout) does456// not take precedence over STARTED/LOCKED_IN. So all softforks on457// the same bit might overlap, even when non-overlapping start-end458// times are picked.459const auto& dep_info = chainParams->GetConsensus().vDeployments[dep];460const uint32_t dep_mask{uint32_t{1} << dep_info.bit};461BOOST_CHECK(!(chain_all_vbits & dep_mask));462chain_all_vbits |= dep_mask;463BOOST_CHECK(0 <= dep_info.bit);464BOOST_CHECK(dep_info.bit < VERSIONBITS_MAX_NUM_BITS);465if (chain_type != ChainType::REGTEST) {466if (dep == Consensus::DEPLOYMENT_TESTDUMMY) {467BOOST_CHECK_EQUAL(dep_info.nStartTime, Consensus::BIP9Deployment::NEVER_ACTIVE);468BOOST_CHECK_EQUAL(dep_info.nTimeout, Consensus::BIP9Deployment::NO_TIMEOUT);469} else {470BOOST_CHECK(dep_info.bit < VERSIONBITS_NUM_BITS);471}472}473check_computeblockversion(vbcache, chainParams->GetConsensus(), dep);474}475}477{478// Use regtest/testdummy to ensure we always exercise some479// deployment that's not always/never active480ArgsManager args;481args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999"); // January 1, 2008 - December 31, 2008482const auto chainParams = CreateChainParams(args, ChainType::REGTEST);483check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);484}486{487// Use regtest/testdummy to ensure we always exercise the488// min_activation_height test, even if we're not using that in a489// live deployment490ArgsManager args;491args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200492const auto chainParams = CreateChainParams(args, ChainType::REGTEST);493check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);494}495}497BOOST_AUTO_TEST_SUITE_END()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.