feat(pxe): anchor-scoped node read cache#24969
Draft
nchamo wants to merge 2 commits into
Draft
Conversation
nchamo
marked this pull request as ready for review
July 24, 2026 17:21
nchamo
marked this pull request as draft
July 24, 2026 17:23
nchamo
commented
Jul 24, 2026
| keyStore: this.keyStore, | ||
| addressStore: this.addressStore, | ||
| aztecNode: BenchmarkedNodeFactory.create(this.node), | ||
| aztecNode: withReadCache(BenchmarkedNodeFactory.create(this.node), this.nodeReadCache), |
Contributor
Author
There was a problem hiding this comment.
FYI: cache hits are not counted for benchmarks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why we are doing this
Client flows repeat identical node reads within a single anchor block window: simulation and witness generation fetch the same membership witnesses, leaf indexes, receipts and public storage, and separate services re-fetch what a simulator just read. Every duplicate is a serial RPC round trip on the critical path of proving.
Our fix
AztecNodeReadCache: a PXE-wide store of node read promises keyed by method and arguments. In-flight promises are shared (concurrent identical reads collapse into one request) and rejected reads are evicted so callers can retry.withReadCache(node, cache): a transparentAztecNodewrapper that serves repeated immutable reads (witnesses, leaf indexes, public storage, blocks, tx receipts) from the store and passes everything else through.findLeavesIndexesis cached per leaf: only the leaves without a cached result are fetched, in a single batched node call.ContractSyncService,TxResolverService) get the wrapped node. Chain observers (BlockSynchronizer, tx submission,isValidTx) keep the raw node, since they must see live chain state.BlockSynchronizerwipes the store whenever the anchor block advances, so entries whose results can change as the chain grows (receipt statuses, block-number-keyed lookups) never outlive the anchor they were read at.Node calls per method across all client-flow benchmarks (whole run):
findLeavesIndexesgetTxReceiptgetPublicStorageAtgetPublicDataWitnessgetNullifierMembershipWitnessgetNoteHashMembershipWitnessProfiled flows: RPC calls and node round trips. RPC calls count every individual node request (server load). Round trips count how many times the flow blocks waiting on the network: requests issued concurrently count as many RPC calls but a single round trip, so client-perceived latency scales with round trips, not calls.
The benchmarks advance the anchor on every interaction, wiping the cache at the fastest possible cadence, so these numbers are a lower bound: production sessions doing repeated operations against one anchor reuse strictly more.