The Blockchain Chief Bitcoin Book / Part III: Validation & Consensus
Chapter 06

Transaction Validation & Mempool

How Bitcoin Core decides whether a transaction is valid: AcceptToMemoryPool, script verification, fee policies, RBF, package relay, and the CTxMemPool data structure.

The Gatekeeper

Before a transaction can enter the mempool (and eventually a block), it must pass through Bitcoin Core's validation engine. This is the most critical code path in the codebase; it determines what's valid and what's not.

Transaction validation happens in two contexts:

⚠️ Consensus vs. Policy

Consensus rules are things every node must agree on - violating them means the block is invalid. Policy rules are stricter local rules for the mempool - a transaction can be policy-invalid but still end up in a block.

AcceptToMemoryPool (ATMP)

The main entry point for transaction validation is AcceptToMemoryPool() in validation.cpp. It uses the MemPoolAccept workhorse class:

AcceptToMemoryPool()Entry point, creates MemPoolAccept workspace
PreChecks()Fast structural checks, size, version, fee, duplicates
PolicyScriptChecks()Run scripts with policy flags (strict)
ConsensusScriptChecks()Run scripts with consensus flags (permissive)
Finalize()Add to mempool, update fee estimator, notify wallet

If any step fails, the transaction is rejected with a specific error code (like TX_MISSING_INPUTS, TX_MEMPOOL_POLICY, etc.).

PreChecks: The Fast Path

PreChecks are lightweight validations that can quickly reject obviously invalid transactions:

What Gets Checked

  1. Already in mempool?: Reject duplicates (by txid or wtxid)
  2. Coinbase?: Coinbase transactions can't enter the mempool
  3. Standard size?: Transaction weight must be under 400,000 WU
  4. Version check: Transaction version must be 1 or 2
  5. Script standardness: Only accept known script types
  6. Input existence: All inputs must reference existing UTXOs (orphan handling if not)
  7. No double-spends: Inputs must not conflict with existing mempool transactions (unless RBF applies)
  8. Sequence lock checks: Relative timelocks must be satisfied
  9. Fee rate: Must meet minimum relay fee and mempool min fee
  10. Dust check: Outputs must be above the dust threshold
  11. Ancestor/descendant limits: Can't create overly long chains of unconfirmed transactions
💡 Orphan Transactions

If a transaction references inputs that don't exist yet (they might be in a transaction we haven't received), it becomes an orphan. Bitcoin Core stores a limited number of orphans and re-evaluates them when new transactions arrive.

Script Verification

If PreChecks pass, the real work begins: verifying every input's script.

PolicyScriptChecks

Runs scripts with policy flags, the strictest set of rules:

ConsensusScriptChecks

Runs scripts with consensus flags, the minimum rules required for validity:

Parallel Verification

Script checks for different inputs are independent and can run in parallel. Bitcoin Core uses a CCheckQueue with multiple threads to verify scripts concurrently during block validation, significantly speeding up block connection.

CTxMemPool: The Transaction Pool

The mempool is implemented as CTxMemPool in txmempool.cpp. It's a complex multi-indexed data structure:

by txidHash map for O(1) lookup by transaction ID
by wtxidHash map for witness transaction ID lookup
by descendant fee rateSorted for mining (highest fee rate first)
by ancestor fee rateSorted for CPFP evaluation
by entry timeSorted for expiration (oldest first)

CTxMemPoolEntry

Each transaction in the mempool is wrapped in a CTxMemPoolEntry that tracks:

Fee Policies

Bitcoin Core enforces several fee-related policies:

Minimum Relay Fee

minRelayTxFee, the absolute minimum fee rate to relay a transaction (default: 1 sat/vB). Transactions below this are dropped.

Incremental Relay Fee

For RBF replacements, the new transaction must pay at least incrementalRelayFee more per virtual byte than the transaction it's replacing.

Mempool Minimum Fee

When the mempool is full (default 300 MB), a dynamic minimum fee rate kicks in. Transactions must pay more than the lowest-fee-rate transaction currently in the pool.

Dust Threshold

An output is "dust" if it would cost more in fees to spend than it's worth. The dust threshold is calculated based on the output type and the dust relay fee rate.

Replace-By-Fee (RBF)

BIP 125 allows unconfirmed transactions to be replaced by higher-fee versions:

Rules for Replacement

  1. The original transaction must signal replaceability (any input's nSequence < 0xFFFFFFFE)
  2. The replacement must pay a higher absolute fee
  3. The replacement must pay a higher fee rate
  4. The replacement must not introduce new unconfirmed inputs
  5. The number of original transactions being evicted must be limited (≤ 100)
  6. The replacement must pay for the bandwidth of all evicted transactions
✅ Full RBF

As of Bitcoin Core 28.0, full RBF is enabled by default (-mempoolfullrbf=1). This means all transactions are replaceable, regardless of their sequence number signaling. This improves mempool convergence and fee bumping reliability.

Package Relay

Package relay (BIP 331) allows submitting a group of related transactions together. This solves the "stuck transaction" problem:

CPFP (Child Pays for Parent)

CPFP is the mechanism miners use to evaluate packages: a high-fee child transaction makes its low-fee parent attractive to mine. The mempool tracks "ancestor fee rate" specifically for this purpose.

Mempool Eviction

When the mempool reaches its size limit (default 300 MB):

  1. Transactions are sorted by descendant fee rate
  2. The lowest fee rate transactions are evicted first
  3. The minimum mempool fee rate rises to match the evicted transactions
  4. Transactions also expire after a configurable timeout (default 336 hours / 14 days)