Skip to main content
netspecsEthereum networking

3.4.snap

Stage
Current
Validity
Active non-fork protocol.
Sources
1 pinned source

snap/1 is an optional RLPx capability for state synchronization. A peer that offers snap/1 must also offer eth. The eth session supplies chain negotiation and head updates. snap/1 supplies verifiable account, storage, code, and trie-node data.

Wire inventory

All messages use RLP. Each request and response starts with the same request ID.

ID Message Payload
0x00 GetAccountRange [request_id, root_hash, start_hash, limit_hash, response_bytes]
0x01 AccountRange [request_id, accounts, proof]
0x02 GetStorageRanges [request_id, root_hash, account_hashes, start_hash, limit_hash, response_bytes]
0x03 StorageRanges [request_id, slots, proof]
0x04 GetByteCodes [request_id, hashes, response_bytes]
0x05 ByteCodes [request_id, codes]
0x06 GetTrieNodes [request_id, root_hash, paths, response_bytes]
0x07 TrieNodes [request_id, nodes]

GetAccountRange requests a consecutive account range in trie-key order.

AccountRange returns slim account bodies and boundary proofs.

GetStorageRanges requests slots from one or more storage tries.

StorageRanges returns slot ranges and, when needed, boundary proofs.

GetByteCodes requests contract code by code hash.

ByteCodes returns available code in request order.

GetTrieNodes requests account or storage trie nodes by compact path.

TrieNodes returns available trie nodes in request order.

Range transfer

Accounts follow trie-key order. Their wire form omits the standard empty code hash and empty storage root. The receiver restores those values before it rebuilds the state trie.

A range response must cover the requested start and the last returned item with Merkle boundary proofs. If a whole trie fits in one response, the response omits the proof. A server may stop at its byte or service limit. It must return at least one item when one exists at or after the requested start, including the first item after limit_hash when the requested interval is empty.

Storage requests may cover several accounts. A response contains full storage tries until the size limit, then at most one partial trie with a proof.

Code and trie healing

Code and trie-node responses preserve request order but omit unavailable items. They do not insert placeholders. A requester compares returned hashes or paths with its request to find gaps.

The initial download may combine ranges from several recent state roots. The client rebuilds a near-complete trie, finds inconsistent paths, and uses GetTrieNodes to heal them. It accepts the result only when the rebuilt state root matches a trusted block header.

Validation and failure handling

  • A server always sends a response, even when the result is empty.
  • A server returns an empty response when it cannot serve the requested root.
  • A receiver rejects a range with an invalid proof, an out-of-order key, or a root mismatch.
  • A receiver checks each bytecode against its requested code hash.
  • A receiver checks each returned trie node against the requested path and root.
  • A requester must tolerate a short response and retry missing work with this peer or another peer.

Design rationale

Range transfer avoids sending every internal trie node. Boundary proofs let the receiver detect gaps without trusting the server. The protocol remains separate from eth because state sync needs an indexed snapshot and not every full node chooses to maintain one.

History

snap/1 introduced range-based state sync in 2020. snap/2 is a separate, in-progress capability that replaces trie-node healing with block access lists.