SPV Client (Simplified Payment Verification)
A lightweight Bitcoin client that verifies transactions using block headers and Merkle proofs without downloading the full blockchain.
Key Takeaways
- SPV clients verify Bitcoin transactions by downloading only block headers (80 bytes each) and requesting Merkle proofs from full nodes, rather than storing the entire blockchain.
- Two filtering approaches exist: BIP-37 bloom filters (largely deprecated due to privacy and denial-of-service concerns) and BIP-157/158 compact block filters, which preserve client privacy by performing all address matching locally.
- SPV enables Bitcoin on mobile devices and resource-constrained environments, making self-custody accessible to users who cannot run a full Bitcoin node.
What Is an SPV Client?
An SPV client (Simplified Payment Verification client) is a lightweight Bitcoin client that can verify whether a transaction has been included in a block without downloading and validating the entire blockchain. Introduced in Section 8 of the Bitcoin whitepaper, SPV was Satoshi Nakamoto's original solution for scaling Bitcoin to devices that cannot store hundreds of gigabytes of blockchain data.
Instead of processing every transaction in every block, an SPV client stores only the chain of block headers: a compact summary of each block that is just 80 bytes. When the client needs to confirm a payment, it requests a Merkle proof from a full node, which cryptographically demonstrates that a specific transaction is included in a specific block. The entire header chain from Bitcoin's genesis block to the present occupies roughly 72 MB of storage and grows by only about 4 MB per year.
SPV clients trust that the longest proof-of-work chain contains only valid transactions. They cannot independently verify transaction validity (correct signatures, no double spends, proper amounts) the way a full node can. This tradeoff between security and resource requirements is what makes Bitcoin usable on smartphones and embedded devices. For a deeper technical analysis, see the Bitcoin light clients and SPV explained research article.
How It Works
SPV verification relies on two core data structures: block headers and Merkle trees. Together, they allow a client to confirm transaction inclusion with minimal data.
Block Header Verification
Every Bitcoin block header is exactly 80 bytes and contains six fields:
| Field | Size | Purpose |
|---|---|---|
| Version | 4 bytes | Block validation rules version |
| Previous Block Hash | 32 bytes | Links to the prior block, forming the chain |
| Merkle Root | 32 bytes | Root hash of all transactions in the block |
| Timestamp | 4 bytes | Approximate block creation time |
| Difficulty Target | 4 bytes | Compact encoding of the proof-of-work target |
| Nonce | 4 bytes | Value adjusted by miners to satisfy proof-of-work |
An SPV client downloads every block header and verifies that each one references the previous header's hash, forming an unbroken chain back to the genesis block. It also checks that each header meets its stated difficulty target, confirming that real computational work was performed.
Merkle Proof Validation
To verify that a transaction exists in a given block, the SPV client requests a Merkle proof (also called a Merkle branch or Merkle path) from a full node. The verification process works as follows:
- The client identifies the block containing the transaction using a filter or direct query
- A full node returns the minimum set of sibling hashes needed to reconstruct the path from the transaction up to the Merkle root
- The client hashes the transaction, pairs it with its sibling, hashes the result with the next sibling, and repeats up the tree
- The client compares the computed root against the Merkle root stored in the block header it already possesses
- If they match, the transaction is cryptographically proven to be included in that block
For a block containing N transactions, a Merkle proof requires only log2(N) hashes. A block with 4,096 transactions needs just 12 hashes (roughly 384 bytes) to prove inclusion: a dramatic reduction compared to downloading the full block.
# Merkle proof verification (pseudocode)
def verify_merkle_proof(tx_hash, proof_hashes, merkle_root, index):
current = tx_hash
for i, sibling in enumerate(proof_hashes):
if index & (1 << i):
current = sha256d(sibling + current)
else:
current = sha256d(current + sibling)
return current == merkle_rootTransaction Discovery: Bloom Filters vs. Compact Block Filters
Merkle proofs can verify that a transaction exists in a block, but the SPV client first needs to know which blocks contain its transactions. Two approaches have been developed for this discovery step, with very different privacy and performance characteristics.
BIP-37 Bloom Filters
The original approach, defined in BIP-37, has the client construct a probabilistic bloom filter encoding its addresses and send it to a connected full node. The node then returns only the transactions and Merkle proofs matching the filter. This is bandwidth-efficient because the client downloads only relevant data.
However, BIP-37 has two critical problems. First, the bloom filter reveals the client's addresses to the serving node. Research has shown that even with configured false positive rates, techniques like filter intersection (collecting multiple filters from the same client across reconnections) and transaction graph analysis can identify the client's exact address set. Second, serving bloom filter requests is computationally expensive for full nodes because each client gets a unique filter, creating a denial-of-service vector.
Bitcoin Core disabled bloom filter support by default in version 0.19.0 (November 2019), making BIP-37 largely impractical for new SPV implementations.
BIP-157/158 Compact Block Filters (Neutrino)
The modern approach, proposed by Olaoluwa Osuntokun, Alex Akselrod, and Jim Posen, inverts the filtering model. Instead of the client sending its filter to the server, the server generates a deterministic compact filter for each block using Golomb-Rice Coded Sets. Every client receives the same filter, and all address matching happens locally on the client.
The process works as follows:
- The SPV client downloads compact block filters from one or more full nodes
- For each filter, the client checks locally whether any of its addresses match
- If a filter matches, the client downloads the full block to find the relevant transaction
- The client can cross-validate filters across multiple peers: if peers disagree, it downloads the disputed block and computes the correct filter locally
Because the server sends identical filters to all clients, it learns nothing about which addresses any particular client cares about. The filters are computed once per block and cached, eliminating the per-client computational burden that plagued BIP-37.
Comparing the Two Approaches
| Aspect | BIP-37 Bloom Filters | BIP-157/158 Compact Filters |
|---|---|---|
| Privacy | Server learns client addresses | Server learns nothing |
| Server load | High (unique computation per client) | Low (same filter for all clients) |
| Bandwidth | Lower (only matching data sent) | Higher (all filters downloaded) |
| Omission resistance | Server can lie about matches | Cross-peer verification detects omissions |
| Status | Deprecated by default in Bitcoin Core | Supported in Bitcoin Core since v0.21.0 |
Use Cases
Mobile Bitcoin Wallets
The primary use case for SPV is enabling Bitcoin wallets on smartphones. The full Bitcoin blockchain exceeds 740 GB, far beyond what a mobile device can store or sync. SPV clients reduce storage to roughly 72 MB of headers (plus approximately 4 GB if using compact block filters), making self-custodial Bitcoin wallets feasible on phones.
Wallets like Blixt and Breez run full Lightning Network nodes with Neutrino (BIP-157/158) as their Bitcoin backend, enabling users to send and receive Lightning payments without trusting a centralized server for transaction data. This architecture demonstrates how SPV enables layer-2 protocols on constrained devices.
Lightning Network Light Clients
LND, one of the major Lightning Network implementations, supports Neutrino as a backend. This means a user can operate a full Lightning node: opening channels, routing payments, and monitoring for force closes: using only SPV-level blockchain access. The compact block filter approach is particularly well-suited for Lightning because the node needs to monitor the chain for specific UTXOs related to its channels.
Embedded and IoT Devices
Point-of-sale terminals, hardware wallets, and Internet of Things devices can use SPV to verify Bitcoin payments with minimal hardware requirements. An 80-byte-per-block header chain is small enough for devices with limited storage and intermittent connectivity.
Developer Tools and SDKs
Bitcoin development kits like BDK (Bitcoin Development Kit) provide compact block filter support, allowing developers to build HD wallet applications that verify transactions without requiring users to run full nodes. These SDKs make SPV accessible to application developers building on Bitcoin.
Risks and Considerations
Security Assumptions
SPV clients cannot verify that transactions within a block are actually valid. They trust that miners have performed this validation correctly. This means SPV security depends on an honest majority of hashrate: if an attacker controls more than 50% of mining power, they could create blocks containing invalid transactions (such as spending coins that do not exist) that SPV clients would accept. Full nodes would reject these blocks, but SPV clients have no way to detect the invalidity.
For the specific case of double-spend resistance (the probability that a confirmed transaction gets reversed), SPV clients and full nodes have equivalent security. The risk depends on hashrate distribution, not the verification method.
Eclipse Attacks
An eclipse attack occurs when an adversary controls all of an SPV client's peer connections, isolating it from the honest network. The attacker can then feed the client a fabricated chain containing fraudulent transactions. Connecting to multiple diverse peers and using compact block filter cross-validation (where disagreement triggers full block download) mitigates this risk but does not eliminate it entirely.
Privacy Tradeoffs
Even with BIP-157/158 compact block filters, SPV clients reveal some information. Downloading a full block after a filter match tells the serving node that the client has a transaction in that block. Over time, this pattern of block requests can leak information about the client's activity. Running a personal full node as the SPV client's peer (or using Tor for network-level privacy) provides stronger guarantees.
Bandwidth and Sync Time
While dramatically lighter than a full node, SPV clients using compact block filters still need to download approximately 4 GB of filter data for the full chain history. Initial sync on a mobile connection can take considerable time. Header-only sync is fast (roughly 72 MB), but adding filters for comprehensive transaction discovery increases the requirements significantly.
SPV in the Modern Bitcoin Stack
SPV remains essential for making Bitcoin accessible on everyday devices. As layer-2 solutions like the Lightning Network and Spark expand Bitcoin's capabilities, SPV clients provide the foundation for lightweight nodes that can participate in these protocols without the resource overhead of a full node. The evolution from BIP-37 to BIP-157/158 reflects a broader trend in Bitcoin development: finding better tradeoffs between efficiency, privacy, and trust minimization.
For a comprehensive comparison of light client approaches and their role in Bitcoin's scaling strategy, see the research article on Bitcoin light clients and SPV. Related concepts include compact blocks (a separate optimization for block relay between full nodes) and SegWit (which affects how transaction data is structured and verified).
This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.