Overview
The validation engine is the core component responsible for verifying that blocks and transactions conform to Bitcoin’s consensus rules. It ensures the integrity and security of the blockchain by rejecting invalid data and maintaining the UTXO (Unspent Transaction Output) set. The validation code primarily lives in:src/validation.cpp- Main validation logicsrc/consensus/- Consensus-critical componentssrc/script/interpreter.cpp- Script verificationsrc/kernel/- Kernel library (consensus engine)
Validation Architecture
ChainstateManager
TheChainstateManager is the top-level coordinator for validation:
- Manages one or two
Chainstateobjects - Coordinates assumeutxo snapshot loading
- Provides unified interface for validation
- Manages block storage and indexing
Chainstate
AChainstate represents a view of the blockchain:
- Maintains UTXO set in LevelDB
- Tracks active chain (best chain)
- Can operate independently (for assumeutxo)
Block Validation Flow
Block validation occurs in multiple stages, each with increasing levels of verification:Stage 1: CheckBlock (Context-Free)
Performs validation that doesn’t require chain context:- Block size within limits (≤ 4MB weight)
- Valid proof-of-work (hash meets difficulty target)
- Valid timestamp (not too far in future)
- First transaction is coinbase, others are not
- All transactions are syntactically valid
- Merkle root matches transaction list
- No duplicate transactions
BLOCK_VALID_TREE
Stage 2: ContextualCheckBlock
Validation requiring chain context but not UTXO set: Checks:- Block timestamp ≥ median of last 11 blocks
- Coinbase height matches (BIP34)
- Witness commitment present if SegWit active (BIP141)
- Coinbase transaction structure
- Transaction finality (locktime)
Stage 3: AcceptBlock
Accepts block header and stores block data:- Verify header connects to known chain
- Check proof-of-work difficulty
- Store block to disk (blk*.dat files)
- Add to block index
- Update block status to
BLOCK_HAVE_DATA
BLOCK_VALID_TRANSACTIONS
Stage 4: ConnectBlock (Full Validation)
The most intensive validation - verifies all consensus rules:- Transaction inputs exist in UTXO set
- No double-spends
- Coinbase amount ≤ subsidy + fees
- BIP30: No duplicate transaction IDs
- Script verification (signatures, timelocks, etc.)
- SegWit rules (witness commitment, weight limits)
- Taproot rules (BIP340-342) if active
- Update UTXO set (remove inputs, add outputs)
- Generate undo data (for reorgs)
- Calculate block subsidy and fees
- Verify witness commitment
BLOCK_VALID_SCRIPTS
Transaction Validation
Mempool Acceptance
Transactions entering the mempool go throughAcceptToMemoryPool():
Validation Stages
1. PreChecks (Policy)
Checks:- Transaction size limits
- Minimum relay fee
- Non-standard transaction checks
- Inputs available in UTXO + mempool
- No conflicts (unless RBF)
- Locktime/sequence validation
2. Policy Script Checks
Checks:- Standard script types
- Script size limits
- Signature operation counts (sigops)
- Witness program validation
3. Consensus Script Checks
Full script execution and signature verification:- Execute scripts in parallel using
CCheckQueue - Verify ECDSA/Schnorr signatures
- Check script semantics (OP codes, stack operations)
- Validate witness data
4. Finalize
Actions:- Calculate modified fees (with prioritization)
- Determine transaction dependencies
- Check mempool limits and eviction
- Replace-by-fee (RBF) processing if applicable
Transaction Validation Result
Script Validation
Script validation is the most complex part of transaction validation.Script Interpreter
The script interpreter (src/script/interpreter.cpp) executes Bitcoin Script:
Verification Flags
Script verification behavior is controlled by flags:- Block height (soft fork activation)
- Network (mainnet vs testnet)
- Validation context (mempool vs block)
Signature Verification
Signature verification varies by script type:Legacy (P2PKH/P2SH)
- ECDSA signatures using secp256k1
- DER encoding enforced (BIP66)
- Low-S values required (BIP146)
SegWit v0 (P2WPKH/P2WSH)
- ECDSA with BIP143 signature hash
- Witness data separate from transaction
- Quadratic hashing fix
SegWit v1 (Taproot/P2TR)
- Schnorr signatures (BIP340)
- BIP342 signature hash (Tapscript)
- Batch verification possible
- Key path spending or script path spending
Signature Cache
To avoid redundant verification, valid signatures are cached:- Blocks contain transactions already in mempool
- Reorgs may re-validate same transactions
- Cache hit rate typically >95% for blocks
Parallel Validation
Script Verification Queue
Bitcoin Core uses a thread pool for parallel script verification:- Default: Use all available CPU cores
- Maximum: 15 threads (
MAX_SCRIPTCHECK_THREADS) - Command line:
-par=<n>
- Main thread queues all transaction checks
- Worker threads process checks in parallel
- Main thread waits for completion
- Any failure aborts entire block validation
CheckQueue Design
UTXO Set Management
Coins View Hierarchy
The UTXO set is accessed through a view hierarchy:CCoinsViewCache
Provides efficient UTXO access and modification:- Batch writes to LevelDB
- Dirty flag tracking
- Lazy deletion (flag as spent, flush later)
- Cache size limits with LRU eviction
Reorg Handling
Blockchain reorganizations require disconnecting and reconnecting blocks:Disconnect Process
- Load undo data (rev*.dat)
- Remove transaction outputs from UTXO
- Restore spent outputs from undo data
- Return transactions to mempool (if policy-valid)
Undo Data Format
Each block stores undo information:Assumeutxo
Assumeutxo allows fast sync using UTXO snapshots:Dual Chainstate Mode
Snapshot Validation
- Load snapshot: Deserialize UTXO set at specific height
- Sync to tip: Snapshot chainstate becomes active
- Background validation: Original chainstate validates from genesis
- Merge: When background reaches snapshot height, compare UTXO hash
- Finalize: Keep snapshot chainstate as fully validated
Performance Considerations
Validation Caching
- Signature cache: Avoid re-verifying signatures
- Script cache: Cache entire script execution results
- UTXO cache: Keep hot UTXOs in memory (default: 450MB)
Parallel Processing
- Script verification across multiple threads
- Block download and validation can overlap
- Assumes scripts are independent (no global state)
Database Tuning
- LevelDB block cache: 8MB default
- UTXO cache: Configurable via
-dbcache - Batch writes: Flush periodically, not per transaction
Validation Interface
Components register for validation events:- Wallet: Update balances and transactions
- ZMQ: Publish notifications
- Indexes: Update transaction/block indexes
Error Handling
Validation States
- BLOCK_CONSENSUS: Ban peer
- BLOCK_INVALID_HEADER: Disconnect peer
- BLOCK_MISSING_PREV: Request missing blocks