Skip to content

test(net): add first snap e2e tests#26368

Merged
mattsse merged 26 commits into
paradigmxyz:mainfrom
lean-apple:snap-e2e-tests
Jul 20, 2026
Merged

test(net): add first snap e2e tests#26368
mattsse merged 26 commits into
paradigmxyz:mainfrom
lean-apple:snap-e2e-tests

Conversation

@lean-apple

@lean-apple lean-apple commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Adds e2e tests that spin up real connected peers negotiating eth/71 + snap/2 and drive GetAccountRange /GetStorageRanges requests through the full RLPx path.

cargo +nightly nextest run -p reth-network --test it -E 'test(snap::)'

@github-project-automation github-project-automation Bot moved this to Backlog in Reth Tracker Jul 12, 2026
@lean-apple lean-apple changed the title Snap e2e tests test: add first snap e2e tests Jul 12, 2026
@lean-apple
lean-apple marked this pull request as ready for review July 15, 2026 04:11

@mattsse mattsse left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two issues currently prevent these tests from establishing interoperable, root-correct snap/2 behavior. The inline comments include concrete fixes and a minimal geth-compatible counterexample.

Comment thread crates/net/network/tests/it/snap.rs Outdated
Comment thread crates/net/network/tests/it/snap.rs Outdated
@github-project-automation github-project-automation Bot moved this from Backlog to In Progress in Reth Tracker Jul 16, 2026
Covers the same wire path as the account/storage range tests: an
empty-code hash resolved without a lookup, a missing hash skipped, and
found codes returned in request order rather than storage order.
lean-apple and others added 2 commits July 16, 2026 21:31
A zero-origin GetAccountRange request that exhausts the trie no
longer carries a boundary proof; snap/2 requires no proof when the
entire account range is returned.

Co-Authored-By: Matthias Seitz <matthias.seitz@outlook.de>
response_bytes is a soft limit; snap/2 requires at least one slot
be served when one exists, so only stop once a non-empty range has
already been accumulated, letting leading accounts with empty
storage still be traversed.

Co-Authored-By: Matthias Seitz <matthias.seitz@outlook.de>
@lean-apple lean-apple changed the title test: add first snap e2e tests test(net): add first snap e2e tests Jul 16, 2026
lean-apple and others added 4 commits July 16, 2026 21:58
geth's GetStorageRangesPacket types Origin/Limit as raw byte
strings and sends them empty for the common unbounded multi-account
request, rather than as 32-byte zero/max-value hashes. Reth's fixed
B256 fields required exactly 32 bytes, so a real geth peer's
request would fail to decode with UnexpectedLength.

Introduce RangeBound, a wrapper that RLP-encodes as either an empty
byte string or a 32-byte hash, and use it for
GetStorageRangesMessage's starting_hash/limit_hash. An empty
encoding resolves to B256::ZERO for the origin and
B256::repeat_byte(0xff) for the limit.

Co-Authored-By: Matthias Seitz <matthias.seitz@outlook.de>
…test

account_range_roundtrip_carries_slim_encoding_and_proof inserted
accounts directly into the hashed-state tables after persisting a
genesis header whose root was EMPTY_ROOT_HASH, computed the
resulting non-empty state_root, but still requested EMPTY_ROOT_HASH
and only checked the returned proof against the separately computed
state_root. The test passed even if the server ignored root_hash
and served whatever the current state happened to be.

Persist a block whose header carries the computed state_root,
advance the retained range to it, and request that root instead.

Co-Authored-By: Matthias Seitz <matthias.seitz@outlook.de>
snap_account_range_response_encodes_accounts_and_proof mocked an
exhausted, zero-origin range while still expecting a boundary
proof back. That combination is no longer proven per the
skip-proof-for-complete-ranges fix, so the test would otherwise
fail. Switch the mocked end reason to a hash-limit stop, which
still requires a proof and keeps the test's original intent of
covering proof-carrying responses.
GetStorageRangesMessage's starting_hash/limit_hash grew from B256 to
RangeBound to accept geth's empty-byte-string bounds, pushing
PollAction::Ready(FetchAction) (nested through
BlockRequest::GetSnap(SnapProtocolMessage)) over clippy's
too-large-for-stack threshold. Box the variant instead of inlining it.
@lean-apple
lean-apple requested a review from mattsse July 16, 2026 20:34
get_account_range_response omits the boundary proof when
starting_hash == B256::ZERO && end == RangeEnd::Exhausted. The one
test that exercised this combination was changed to RangeEnd::HashLimit
to keep asserting a non-empty proof, so nothing actually asserted
proof.is_empty() for a full, zero-origin, exhausted range. A
regression toward "always prove" or "never prove" could land
unnoticed in either direction.
The zero-byte-budget fix (only bail once a non-empty range has been
served) trades a bounded worst case for correctness: a peer
requesting MAX_STORAGE_RANGE_ACCOUNTS_SERVE storage-empty accounts
with response_bytes: 0 now costs a storage_range lookup per account
instead of bailing after the first. Record that explicitly rather
than leaving it an implicit side effect.
…/2 retention test

retained_and_expired_state_roots_respond_without_hanging duplicated
SNAPSHOT_STATE_RETENTION as a hardcoded 128, which would silently
stop reflecting reality if the real constant ever changed. Export
it from reth_provider::providers and reference it directly instead.
Replaces fake historical roots and dummy BAL bytes in the snap/2 e2e
fixtures with genuinely computed trie roots and valid EIP-7928 BAL
encodings, verified against the requested root and header hash. Adds
a bounded account-range case and a capability test covering eth +
snap/2 + a third negotiated protocol. Moves the snap/2 protocol
handler test fixture into its own module.
Adds a provider-level test proving the retained-root path actually
reverts a later account and storage change via AccountChangeSets/
StorageChangeSets, rather than coincidentally matching live state.
Mirrors state_range_provider_reverts_database_advancement_past_anchor,
using append_blocks_with_state to persist a real changeset.
The later block in the changeset-revert test carried an arbitrary
state root instead of the trie root state B actually produces,
leaving the fixture's own header inconsistent with its state.
zepter flagged the new alloy-eip7928 dev-dependency as missing serde
propagation from reth-network's serde feature.
@mattsse
mattsse added this pull request to the merge queue Jul 20, 2026
Merged via the queue into paradigmxyz:main with commit 9d56213 Jul 20, 2026
34 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Reth Tracker Jul 20, 2026
pull Bot pushed a commit to Dustin4444/tempo that referenced this pull request Jul 21, 2026
Automated nightly update of reth dependencies from `paradigmxyz/reth`
main branch.

## Upstream reth changes


[`1bf2384...01d3400`](paradigmxyz/reth@1bf2384...01d3400)

🔗 Amp thread:
https://ampcode.com/threads/T-019f82db-9b08-71f2-9518-e78daad00565
**Engine**
- Added SSZ containers for payloads, forkchoice status, proxy
communication, and REST-SSZ blob body witnesses
([#26133](paradigmxyz/reth#26133),
[#26271](paradigmxyz/reth#26271),
[#26335](paradigmxyz/reth#26335),
[#26328](paradigmxyz/reth#26328)).
- Improved sparse-trie proof handling with stalled-proof errors and
diagnostics, correct prune retention, preserved anchors, and reduced
cursor overlays
([#26325](paradigmxyz/reth#26325),
[#26327](paradigmxyz/reth#26327),
[#26332](paradigmxyz/reth#26332),
[#26422](paradigmxyz/reth#26422),
[#25952](paradigmxyz/reth#25952)).
- Extended post-execution hooks with parent state and header context,
passing state updates by value
([#26330](paradigmxyz/reth#26330),
[#26420](paradigmxyz/reth#26420),
[#26398](paradigmxyz/reth#26398)).
- Made state-root update stream ownership explicit and exposed the
payload state-root receiver
([#26329](paradigmxyz/reth#26329),
[#26431](paradigmxyz/reth#26431)).
- Added configurable development finality depth
([#26451](paradigmxyz/reth#26451)).

**Trie**
- Simplified state-root execution by removing `ParallelStateRoot`,
renaming its error type, and refactoring strategy selection and defaults
([#26121](paradigmxyz/reth#26121),
[#26132](paradigmxyz/reth#26132),
[#26085](paradigmxyz/reth#26085),
[#26355](paradigmxyz/reth#26355),
[#26358](paradigmxyz/reth#26358)).
- Fixed sparse-trie correctness and concurrency issues involving late
hints, branch-child pruning, and exact-subtrie proof target grouping
([#26356](paradigmxyz/reth#26356),
[#26376](paradigmxyz/reth#26376),
[#26357](paradigmxyz/reth#26357)).
- Simplified trie internals by consolidating lazy data, splitting
multiproof logic, removing changed-path tracking, and eliding empty new
accounts from hashed state
([#26139](paradigmxyz/reth#26139),
[#26353](paradigmxyz/reth#26353),
[#26403](paradigmxyz/reth#26403),
[#26367](paradigmxyz/reth#26367)).
- Improved tracing and span propagation for parallel sparse-trie work
and pruning ([#26273](paradigmxyz/reth#26273),
[#26331](paradigmxyz/reth#26331)).

**Network**
- Added a Snap client, inbound `snap/2` serving, real account/storage
range responses, and initial end-to-end coverage
([#26049](paradigmxyz/reth#26049),
[#26324](paradigmxyz/reth#26324),
[#26339](paradigmxyz/reth#26339),
[#26368](paradigmxyz/reth#26368)).
- Reduced ECIES allocation and copying, cached AES key schedules, and
raised the write flush boundary to 64 KiB
([#26120](paradigmxyz/reth#26120),
[#26119](paradigmxyz/reth#26119),
[#26346](paradigmxyz/reth#26346),
[#26348](paradigmxyz/reth#26348)).
- Reduced session and stream overhead through static ping/pong encoding,
less idle polling, timer change tracking, batched flushing, and reusable
Snappy buffers
([#26122](paradigmxyz/reth#26122),
[#26123](paradigmxyz/reth#26123),
[#26124](paradigmxyz/reth#26124),
[#26125](paradigmxyz/reth#26125),
[#26349](paradigmxyz/reth#26349),
[#26347](paradigmxyz/reth#26347)).
- Optimized pooled transaction recovery and preallocated pooled hash
metadata decoding
([#26304](paradigmxyz/reth#26304),
[#26145](paradigmxyz/reth#26145)).
- Fixed discovery advertisement and peer management: advertise the bound
RLPx port, share one UDP port across discv4/discv5, publish fork ENR
data for custom chains, and reset reputation after admin unban
([#26265](paradigmxyz/reth#26265),
[#26089](paradigmxyz/reth#26089),
[#26449](paradigmxyz/reth#26449),
[#26334](paradigmxyz/reth#26334)).

**RPC**
- Added the `EthSubscriptions` trait for log and header streams
([#22155](paradigmxyz/reth#22155)).
- Improved testing RPC behavior by accepting positional block parameters
and rejecting invalid block transactions by default
([#25750](paradigmxyz/reth#25750),
[#26372](paradigmxyz/reth#26372)).
- Aligned BAL lookup errors with the specification and added a BAL debug
method ([#26441](paradigmxyz/reth#26441),
[#26438](paradigmxyz/reth#26438)).

**Pruning & Storage**
- Added row-budgeted dupsort pruning and optimized pruning with
static-file transaction hash ranges
([#26287](paradigmxyz/reth#26287),
[#26312](paradigmxyz/reth#26312)).
- Corrected receipts static-file sizing to derive it from prune distance
([#26108](paradigmxyz/reth#26108)).
- Removed the unused prune database crate
([#26391](paradigmxyz/reth#26391)).

**Transaction Pool**
- Reduced validator allocations, forwarded same-origin validation
batches, specialized small discard lookups, and deduplicated blob
fallback reads
([#26343](paradigmxyz/reth#26343),
[#26341](paradigmxyz/reth#26341),
[#26345](paradigmxyz/reth#26345),
[#26255](paradigmxyz/reth#26255)).

**Wire & Metrics Performance**
- Preallocated Ethereum wire transaction-list decoding
([#26164](paradigmxyz/reth#26164)).
- Moved metric rendering off the main execution path
([#26180](paradigmxyz/reth#26180)).

**Download & Import**
- Added file-archive support for modular snapshots and exposed snapshot
environment access
([#26078](paradigmxyz/reth#26078),
[#25285](paradigmxyz/reth#25285)).
- Rejected incomplete blocks encountered at end-of-file during import
([#26363](paradigmxyz/reth#26363)).

**Builder & Stages**
- Refactored builder resource ownership around leases and paused JIT
execution while constructing payloads
([#26427](paradigmxyz/reth#26427),
[#26429](paradigmxyz/reth#26429)).
- Added a partial-persistence finish checkpoint for stages
([#26447](paradigmxyz/reth#26447)).

## Migrations

🔗 Amp thread:
https://ampcode.com/threads/T-019f82dc-2079-7249-9940-8e00022f9c94
- Bumped all Reth git dependencies from `1bf2384` to `01d3400`.
- Added handling for the new `IncomingEthRequest::GetSnap` variant by
dropping its response sender because the P2P proxy does not support snap
sync.
- Implemented the newly required `EthSubscriptions` helper trait for
`TempoEthApi`.
- Renamed payload-builder `trie_handle` usage to `state_root_handle` and
migrated state hooks to the consuming `take_state_hook()` API.
- Migrated hashed-state retrieval to `try_take_hashed_state_rx()`,
preserving the new shared `Arc<HashedPostState>` representation and
cloning only when fallback root computation requires ownership.
- Removed `changed_paths` from payload state-root handling and
`BuiltPayloadExecutedBlock` construction because the updated Reth
payload API no longer exposes that field.

[GitHub
Workflow](https://github.com/tempoxyz/tempo/actions/runs/29800127526)

---------

Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
@lean-apple
lean-apple deleted the snap-e2e-tests branch July 22, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants