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.
251EXCLUSIVE_LOCKS_REQUIRED(::cs_main)252{253AssertLockHeld(::cs_main);254assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.255if (nStatus & BLOCK_FAILED_VALID)256return false;257return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);258}260//! Raise the validity level of this block index entry.261//! Returns true if the validity was changed.262bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)263{264AssertLockHeld(::cs_main);265assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.266if (nStatus & BLOCK_FAILED_VALID) return false;268if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {269nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;270return true;271}272return false;273}275//! Build the skiplist pointer for this entry.276void BuildSkip();278//! Efficiently find an ancestor of this block.279CBlockIndex* GetAncestor(int height);280const CBlockIndex* GetAncestor(int height) const;282CBlockIndex() = default;283~CBlockIndex() = default;285protected:286//! CBlockIndex should not allow public copy construction because equality287//! comparison via pointer is very common throughout the codebase, making288//! use of copy a footgun. Also, use of copies do not have the benefit289//! of simplifying lifetime considerations due to attributes like pprev and290//! pskip, which are at risk of becoming dangling pointers in a copied291//! instance.292//!293//! We declare these protected instead of simply deleting them so that294//! CDiskBlockIndex can reuse copy construction.295CBlockIndex(const CBlockIndex&) = default;296CBlockIndex& operator=(const CBlockIndex&) = delete;297CBlockIndex(CBlockIndex&&) = delete;298CBlockIndex& operator=(CBlockIndex&&) = delete;299};301/** Compute how much work an nBits value corresponds to. */302arith_uint256 GetBitsProof(uint32_t bits);304/** Compute how much work a block index entry corresponds to. */305inline arith_uint256 GetBlockProof(const CBlockIndex& block) { return GetBitsProof(block.nBits); }307/** Compute how much work a block header corresponds to. */308inline arith_uint256 GetBlockProof(const CBlockHeader& header) { return GetBitsProof(header.nBits); }310/** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */311int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);312/** Find the forking point between two chain tips. */313const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);316/** Used to marshal pointers into hashes for db storage. */317class CDiskBlockIndex : public CBlockIndex318{319/** Historically CBlockLocator's version field has been written to disk320* streams as the client version, but the value has never been used.321*322* Hard-code to the highest client version ever written.323* SerParams can be used if the field requires any meaning in the future.324**/325static constexpr int DUMMY_VERSION = 259900;327public:328uint256 hashPrev;330CDiskBlockIndex()331{332hashPrev = uint256();333}335explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)336{337hashPrev = (pprev ? pprev->GetBlockHash() : uint256());338}340SERIALIZE_METHODS(CDiskBlockIndex, obj)341{342LOCK(::cs_main);343int _nVersion = DUMMY_VERSION;344READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));346READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));347READWRITE(VARINT(obj.nStatus));348READWRITE(VARINT(obj.nTx));349if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));350if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));351if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));353// block header354READWRITE(obj.nVersion);355READWRITE(obj.hashPrev);356READWRITE(obj.hashMerkleRoot);357READWRITE(obj.nTime);358READWRITE(obj.nBits);359READWRITE(obj.nNonce);360}362uint256 ConstructBlockHash() const363{364CBlockHeader block;365block.nVersion = nVersion;366block.hashPrevBlock = hashPrev;367block.hashMerkleRoot = hashMerkleRoot;368block.nTime = nTime;369block.nBits = nBits;370block.nNonce = nNonce;371return block.GetHash();372}374uint256 GetBlockHash() = delete;375std::string ToString() = delete;376};378/** An in-memory indexed chain of blocks. */379class CChain380{381private:382std::vector<CBlockIndex*> vChain;384public:385CChain() = default;386CChain(const CChain&) = delete;387CChain& operator=(const CChain&) = delete;389/** Returns the index entry for the genesis block of this chain, or nullptr if none. */390CBlockIndex* Genesis() const391{392return vChain.size() > 0 ? vChain[0] : nullptr;393}395/** Returns the index entry for the tip of this chain, or nullptr if none. */396CBlockIndex* Tip() const397{398return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;399}401/** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */402CBlockIndex* operator[](int nHeight) const403{404if (nHeight < 0 || nHeight >= (int)vChain.size())405return nullptr;406return vChain[nHeight];407}409/** Efficiently check whether a block is present in this chain. */410bool Contains(const CBlockIndex& index) const411{412return (*this)[index.nHeight] == &index;413}415/** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */416CBlockIndex* Next(const CBlockIndex& index) const417{418if (Contains(index))419return (*this)[index.nHeight + 1];420else421return nullptr;422}424/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */425int Height() const426{427return int(vChain.size()) - 1;428}430/** Check whether this chain's tip exists, has enough work, and is recent. */431bool IsTipRecent(const arith_uint256& min_chain_work, std::chrono::seconds max_tip_age) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)432{433const auto tip{Tip()};434return tip &&435tip->nChainWork >= min_chain_work &&436tip->Time() >= Now<NodeSeconds>() - max_tip_age;437}439/** Set/initialize a chain with a given tip. */440void SetTip(CBlockIndex& block);442/** Find the last common block between this chain and a block index entry. */443const CBlockIndex* FindFork(const CBlockIndex& index) const;445/** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */446CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;447};449/** Get a locator for a block index entry. */450CBlockLocator GetLocator(const CBlockIndex* index);452/** Construct a list of hash entries to put in a locator. */453std::vector<uint256> LocatorEntries(const CBlockIndex* index);455#endif // BITCOIN_CHAIN_H
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.