Block Validation Pipeline
When a new block arrives, it goes through a multi-stage validation pipeline. Each stage is progressively more expensive:
Cheap checks come first. Verifying PoW is nearly free and rejects most spam. Storing to disk happens before full validation so blocks can be validated later without re-downloading. This design made headers-first sync possible.
ProcessNewBlock()
The entry point for all incoming blocks. Located in validation.cpp:
What It Does
- Check PoW: reject immediately if the block doesn't meet the difficulty target
- AcceptBlock(): validate header chain, check body, write block to disk (
blk*.datfiles) - ActivateBestChain(): if this block creates a chain with more work, switch to it
Chainstate Manager
The ChainstateManager coordinates potentially two chainstates:
- Active chainstate: the normal chain with fully validated blocks
- Snapshot chainstate: used during AssumeUTXO bootstrapping (a UTXO snapshot is loaded, then background validation catches up)
ConnectBlock()
This is the most critical function in all of Bitcoin Core. It applies a block to the UTXO set:
Step by Step
- Check BIP30: ensure no duplicate transaction IDs
- Determine script flags: which consensus rules apply at this height (soft forks)
- For each transaction:
- Look up all input UTXOs from the CCoinsView
- Check input values (no negative, no overflow)
- Verify sequence locks (relative timelocks)
- Add script checks to the verification queue
- Spend inputs: mark UTXOs as spent
- Create outputs: add new UTXOs to the set
- Run all script checks: verify signatures (parallelized)
- Verify block reward: coinbase output ≤ subsidy + total fees
- Update the UTXO database: flush changes
If ConnectBlock fails after partially updating the UTXO set, the changes are rolled back using the CCoinsViewCache undo mechanism. Failed blocks never corrupt the UTXO database.
The UTXO Set
The UTXO set is the most important state in Bitcoin; it represents who owns what:
CCoinsView Hierarchy
Bitcoin Core uses a layered caching system for UTXO access:
Coin Structure
Each UTXO is stored as a Coin object:
CTxOut out, the output itself (amount + scriptPubKey)uint32_t nHeight, block height at which this output was createdbool fCoinBase, whether it's from a coinbase transaction (100-block maturity rule)
The key for lookup is the COutPoint (txid + output index). The UTXO set currently holds ~180 million entries.
Proof of Work
A block's proof of work is verified by CheckProofOfWork():
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) {
// 1. Decode compact target from nBits
arith_uint256 bnTarget;
bnTarget.SetCompact(nBits);
// 2. Target must be positive and below powLimit
if (bnTarget <= 0 || bnTarget > UintToArith256(params.powLimit))
return false;
// 3. Block hash must be below target
if (UintToArith256(hash) > bnTarget)
return false;
return true;
}
The core idea: the block header hash (double SHA-256) must be numerically less than the target value encoded in nBits. A lower target = higher difficulty = more computational work required.
Difficulty Adjustment
Every 2,016 blocks (~2 weeks), the difficulty adjusts to maintain ~10-minute block times:
The Algorithm
- Measure how long the last 2,016 blocks actually took (
actualTimespan) - Compare to the target: 2,016 × 10 minutes = 20,160 minutes (
targetTimespan) - Calculate:
newTarget = oldTarget × (actualTimespan / targetTimespan) - Clamp: timespan is limited to range [3.5 days, 8 weeks] to prevent extreme swings
If blocks came faster than 10 minutes → target decreases (harder). If slower → target increases (easier).
The target is stored as a 4-byte compact representation. The first byte is the exponent (number of bytes), and the remaining 3 bytes are the mantissa. For example, 0x1d00ffff means a target that starts with 00ffff shifted left by (0x1d - 3) = 26 bytes.
Consensus Parameters
Key constants that define Bitcoin's rules:
Block Template & Mining
Mining is the process of creating new blocks. Bitcoin Core's BlockAssembler creates block templates:
CreateNewBlock() Flow
- Create coinbase transaction with subsidy + fees
- Sort mempool by ancestor fee rate (highest first)
- Greedily add transactions until the 4 MWU weight limit is reached
- Respect package (ancestor) relationships, a child can't be included without its parent
- Calculate Merkle root from final transaction list
- Fill in block header (prev hash, timestamp, nBits)
- Return the template for the miner to search for a valid nonce
Mining Loop (External)
The actual mining (finding a nonce that produces a valid PoW) is done externally, either by generateblock RPC for testing, or by specialized mining hardware (ASICs) via the Stratum protocol or getblocktemplate RPC.
Chain Reorganizations
When a competing chain has more total work, Bitcoin Core performs a reorganization:
Each block stores an "undo" file (rev*.dat) containing the data needed to reverse its UTXO changes. This makes disconnection efficient.