State Proof
A state proof is a cryptographic proof that verifies a specific piece of blockchain state without requiring the full chain history.
Key Takeaways
- A state proof is a compact cryptographic proof that a particular account balance, contract storage value, or other on-chain state exists at a given block height, verifiable against a trusted root hash in a block header without downloading the full dataset.
- State proofs power light clients, cross-chain bridges, and L2 withdrawal mechanisms by enabling trustless verification of on-chain data with minimal bandwidth and storage.
- Bitcoin and Ethereum take fundamentally different approaches: Ethereum maintains a persistent Merkle-Patricia trie of all account state, while Bitcoin's UTXO model has no cumulative state structure, relying on per-block transaction Merkle proofs instead.
What Is a State Proof?
A state proof is a cryptographic proof that demonstrates a specific piece of blockchain state exists at a given block height. Rather than requiring a verifier to replay every transaction from genesis, a state proof provides a short chain of hashes linking a particular data point (an account balance, a storage slot value, or a UTXO) to a trusted root hash published in a block header. The verifier only needs the block header and the proof to confirm the data is authentic.
State proofs are the mechanism that makes trustless lightweight verification possible. Without them, every participant in a blockchain network would need to store and process the entire chain history to confirm even a single balance. By compressing verification into a short proof, state proofs enable mobile wallets, embedded devices, and cross-chain protocols to interact with blockchains without running a full node.
How It Works
The core idea behind a state proof is a Merkle tree: a data structure where every leaf contains a hash of some data, and every internal node contains a hash of its children. The root hash at the top commits to every piece of data in the tree. To prove that a specific leaf exists, you provide the leaf data along with the sibling hashes at each level of the tree (the "Merkle path"). The verifier recomputes the root hash from this path and checks it against the known root.
The process follows a consistent pattern across blockchains:
- The blockchain commits all state into a hash-based data structure (a Merkle tree or variant) and publishes the root hash in each block header
- A prover extracts the target data and the corresponding Merkle path from the full dataset
- The verifier receives the proof, recomputes hashes along the path, and checks that the result matches the root hash in the block header
- If the hashes match, the verifier has cryptographic assurance that the data was included in that block's state without downloading anything else
Ethereum State Proofs
Ethereum maintains three Merkle-Patricia tries per block: a state trie (mapping every account address to its nonce, balance, storage hash, and code hash), a transaction trie, and a receipt trie. Each block header contains the corresponding root hashes: stateRoot, transactionsRoot, and receiptsRoot.
To prove an account's balance at a specific block, a prover traverses the state trie from the stateRoot down to the account's leaf node, collecting the encoded trie nodes along the way. EIP-1186 standardized this through the eth_getProof RPC method, which returns Merkle proofs for both account state and individual contract storage slots:
// Request a state proof for an account and storage slot
const proof = await provider.send("eth_getProof", [
"0xContractAddress", // target account
["0x0"], // storage slot keys
"0x1234567" // block number
]);
// proof.accountProof: Merkle path from stateRoot to account
// proof.storageProof: Merkle path from storageHash to slot valueThe verifier takes the account proof (a list of RLP-encoded trie nodes), recomputes hashes from the leaf up, and confirms the result matches the stateRoot in the block header. For storage proofs, a second verification step walks the account's storage trie using the storageHash from the account data.
Bitcoin UTXO Proofs
Bitcoin takes a fundamentally different approach. There is no persistent state trie that accumulates across blocks. Each block header contains a Merkle root of that block's transactions only. You can prove a transaction was included in a specific block by providing a Merkle inclusion proof against that block's transaction root, but there is no built-in structure for proving the current UTXO set.
This means proving a UTXO exists requires showing both that the creating transaction was included in a block and that the output has not been spent. The second part is the hard problem: proving a negative (that something was not spent) requires knowledge of all subsequent blocks, which is why Bitcoin's SPV light clients have historically relied on trusted full nodes for balance information rather than independently verifying state.
Verkle Trees and Future Improvements
Ethereum's Merkle-Patricia trie produces relatively large proofs because each trie node can have up to 16 children, requiring many sibling hashes at each level. Verkle trees use polynomial commitments instead of hash-based commitments, reducing proof sizes by an order of magnitude. This makes stateless clients practical: nodes that verify blocks using state proofs attached to each block rather than maintaining a local copy of the state.
Use Cases
Light Client Verification
Light clients download only block headers and request state proofs on demand. To verify an account balance, a light client obtains the relevant block header (with the stateRoot), requests a proof via eth_getProof, and locally verifies the Merkle path from root to leaf. This enables mobile wallets and browser-based applications to interact with Ethereum trustlessly without syncing hundreds of gigabytes of state data.
Cross-Chain Bridges
Cross-chain bridges use state proofs to verify events on a source chain from a smart contract on a destination chain. Rather than relying on a trusted set of validators or oracles to attest that something happened, a bridge contract can directly verify a Merkle proof against a known block header.
Projects like Herodotus use STARK proofs combined with Merkle Mountain Ranges to maintain on-chain commitments covering every Ethereum block hash back to genesis. This extends verification beyond the EVM's native 256-block BLOCKHASH opcode limit, allowing smart contracts on Starknet or other chains to verify historical Ethereum storage proofs. Lagrange's ZK Big Data Stack takes a different approach, proving computations over multi-chain datasets using ZK MapReduce. Both approaches eliminate reliance on trusted oracle or attestation layers.
L2 Withdrawal Proofs
Layer 2 networks use state proofs for their withdrawal mechanisms, though the approach differs between optimistic and ZK rollups:
- Optimistic rollups (such as Optimism Bedrock) require users to submit a Merkle-Patricia trie proof of their withdrawal message against the L2 OutputRoot posted to L1. The OutputRoot includes the L2 state root and an elevated withdrawal storage root from the L2-to-L1 message passer contract, reducing proof depth and gas cost. A 7-day challenge period follows before the withdrawal finalizes.
- ZK rollups (such as zkSync and Scroll) attach a validity proof (SNARK or STARK) to each state transition. Once the L1 verifier contract confirms the proof, the new state root is finalized immediately and withdrawals can execute without a challenge delay.
Efficient Bitcoin State Verification
Two innovations address Bitcoin's lack of a persistent state structure:
- Utreexo (proposed by Tadge Dryja) replaces the full UTXO set with a compact Merkle forest accumulator that can be represented in just a few hundred bytes regardless of UTXO set size. Spenders attach inclusion proofs against the Utreexo roots when broadcasting transactions, letting nodes verify without storing the complete UTXO set. Read more in our Utreexo deep dive.
- AssumeUTXO (shipped in Bitcoin Core 28.0) takes a snapshot-based approach: nodes load a pre-built UTXO set snapshot whose hash is hardcoded in the source code, becoming usable in around 90 minutes versus 10+ hours for full initial block download. The node validates the full chain history in the background while already serving requests. See our AssumeUTXO analysis for details.
Why It Matters
State proofs are foundational to blockchain scalability and interoperability. As ecosystems grow across multiple chains and layers, the ability to verify state without trusting intermediaries becomes increasingly critical. Light clients, bridges, rollups, and even Bitcoin's own node bootstrapping all depend on some form of state proof to reduce the resources needed for trustless verification.
For Bitcoin Layer 2 networks like Spark, state proofs and their underlying Merkle structures are part of the broader toolkit for efficient off-chain state management. Any system that moves computation or state off the base layer needs a mechanism to prove that off-chain state is valid when settling back to L1.
Risks and Considerations
Proof Size and Verification Cost
Merkle-Patricia trie proofs can be large: a single Ethereum account proof may require transmitting multiple kilobytes of encoded trie nodes. When verifying proofs on-chain (as bridges and rollup contracts must do), the gas cost of hashing and verifying each node adds up. This is a key motivation behind the move to Verkle trees and ZK-based proof compression.
Header Trust Assumptions
A state proof is only as trustworthy as the block header it verifies against. Light clients must still obtain block headers from honest sources and verify their validity (checking proof-of-work, following the longest chain, or tracking validator signatures). A state proof verified against a forged or orphaned block header provides no security guarantees.
State Availability
Generating a state proof requires access to the full state at the target block height. As blockchain state grows, fewer nodes retain historical state (most prune old data). If no node retains the state for a particular historical block, generating a proof against that block's state root becomes impossible. Archive nodes address this but are expensive to operate.
Proof Freshness
State proofs are snapshots: they prove state at a specific block, not the current state. A proof that an account held 100 ETH at block N says nothing about block N+1. Applications must consider how quickly state can change and whether a proof's block height is recent enough for their security requirements.
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.