Inside Bitcoin
Opening the selected file…
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.
1// Copyright (c) 2016-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <consensus/params.h>6#include <deploymentinfo.h>7#include <kernel/chainparams.h>8#include <util/check.h>9#include <versionbits.h>10#include <versionbits_impl.h>12using enum ThresholdState;14std::string StateName(ThresholdState state)15{16switch (state) {17case DEFINED: return "defined";18case STARTED: return "started";19case LOCKED_IN: return "locked_in";20case ACTIVE: return "active";21case FAILED: return "failed";22}23return "invalid";24}26ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const27{28int nPeriod = Period();29int nThreshold = Threshold();30int min_activation_height = MinActivationHeight();31int64_t nTimeStart = BeginTime();32int64_t nTimeTimeout = EndTime();34// Check if this deployment is always active.35if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {36return ThresholdState::ACTIVE;37}39// Check if this deployment is never active.40if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) {41return ThresholdState::FAILED;42}44// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.45if (pindexPrev != nullptr) {46pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));47}49// Walk backwards in steps of nPeriod to find a pindexPrev whose information is known50std::vector<const CBlockIndex*> vToCompute;51while (!cache.contains(pindexPrev)) {52if (pindexPrev == nullptr) {53// The genesis block is by definition defined.54cache[pindexPrev] = ThresholdState::DEFINED;55break;56}57if (pindexPrev->GetMedianTimePast() < nTimeStart) {58// Optimization: don't recompute down further, as we know every earlier block will be before the start time59cache[pindexPrev] = ThresholdState::DEFINED;60break;61}62vToCompute.push_back(pindexPrev);63pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);64}66// At this point, cache[pindexPrev] is known67assert(cache.contains(pindexPrev));68ThresholdState state = cache[pindexPrev];70// Now walk forward and compute the state of descendants of pindexPrev71while (!vToCompute.empty()) {72ThresholdState stateNext = state;73pindexPrev = vToCompute.back();74vToCompute.pop_back();76switch (state) {77case ThresholdState::DEFINED: {78if (pindexPrev->GetMedianTimePast() >= nTimeStart) {79stateNext = ThresholdState::STARTED;80}81break;82}83case ThresholdState::STARTED: {84// We need to count85const CBlockIndex* pindexCount = pindexPrev;86int count = 0;87for (int i = 0; i < nPeriod; i++) {88if (Condition(pindexCount)) {89count++;90}91pindexCount = pindexCount->pprev;92}93if (count >= nThreshold) {94stateNext = ThresholdState::LOCKED_IN;95} else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {96stateNext = ThresholdState::FAILED;97}98break;99}100case ThresholdState::LOCKED_IN: {101// Progresses into ACTIVE provided activation height will have been reached.102if (pindexPrev->nHeight + 1 >= min_activation_height) {103stateNext = ThresholdState::ACTIVE;104}105break;106}107case ThresholdState::FAILED:108case ThresholdState::ACTIVE: {109// Nothing happens, these are terminal states.110break;111}112}113cache[pindexPrev] = state = stateNext;114}116return state;117}119BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, std::vector<bool>* signalling_blocks) const120{121BIP9Stats stats = {};123stats.period = Period();124stats.threshold = Threshold();126if (pindex == nullptr) return stats;128// Find how many blocks are in the current period129int blocks_in_period = 1 + (pindex->nHeight % stats.period);131// Reset signalling_blocks132if (signalling_blocks) {133signalling_blocks->assign(blocks_in_period, false);134}136// Count from current block to beginning of period137int elapsed = 0;138int count = 0;139const CBlockIndex* currentIndex = pindex;140do {141++elapsed;142--blocks_in_period;143if (Condition(currentIndex)) {144++count;145if (signalling_blocks) signalling_blocks->at(blocks_in_period) = true;146}147currentIndex = currentIndex->pprev;148} while(blocks_in_period > 0);150stats.elapsed = elapsed;151stats.count = count;152stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);154return stats;155}157int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const158{159int64_t start_time = BeginTime();160if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE || start_time == Consensus::BIP9Deployment::NEVER_ACTIVE) {161return 0;162}164const ThresholdState initialState = GetStateFor(pindexPrev, cache);166// BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."167if (initialState == ThresholdState::DEFINED) {168return 0;169}171const int nPeriod = Period();173// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.174// To ease understanding of the following height calculation, it helps to remember that175// right now pindexPrev points to the block prior to the block that we are computing for, thus:176// if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and177// if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.178// The parent of the genesis block is represented by nullptr.179pindexPrev = Assert(pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)));181const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);183while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, cache) == initialState) {184pindexPrev = previousPeriodParent;185previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);186}188// Adjust the result because right now we point to the parent block.189return pindexPrev->nHeight + 1;190}192BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id)193{194BIP9Info result;196VersionBitsConditionChecker checker(params, id);198ThresholdState current_state, next_state;200{201LOCK(m_mutex);202current_state = checker.GetStateFor(block_index.pprev, m_caches[id]);203next_state = checker.GetStateFor(&block_index, m_caches[id]);204result.since = checker.GetStateSinceHeightFor(block_index.pprev, m_caches[id]);205}207result.current_state = StateName(current_state);208result.next_state = StateName(next_state);210const bool has_signal = (STARTED == current_state || LOCKED_IN == current_state);211if (has_signal) {212result.stats.emplace(checker.GetStateStatisticsFor(&block_index, &result.signalling_blocks));213if (LOCKED_IN == current_state) {214result.stats->threshold = 0;215result.stats->possible = false;216}217}219if (current_state == ACTIVE) {220result.active_since = result.since;221} else if (next_state == ACTIVE) {222result.active_since = block_index.nHeight + 1;223}225return result;226}228BIP9GBTStatus VersionBitsCache::GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params)229{230BIP9GBTStatus result;232LOCK(m_mutex);233for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {234auto pos = static_cast<Consensus::DeploymentPos>(i);235VersionBitsConditionChecker checker(params, pos);236ThresholdState state = checker.GetStateFor(&block_index, m_caches[pos]);237const VBDeploymentInfo& vbdepinfo = VersionBitsDeploymentInfo[pos];238BIP9GBTStatus::Info gbtinfo{.bit=params.vDeployments[pos].bit, .mask=checker.Mask(), .gbt_optional_rule=vbdepinfo.gbt_optional_rule};240switch (state) {241case DEFINED:242case FAILED:243// Not exposed to GBT244break;245case STARTED:246result.signalling.try_emplace(vbdepinfo.name, gbtinfo);247break;248case LOCKED_IN:249result.locked_in.try_emplace(vbdepinfo.name, gbtinfo);250break;
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.