Skip to content

refactor(store): pull storage map entries from account state forest#2012

Merged
kkovaacs merged 20 commits intomainfrom
krisztian/improve-get-account-storage-maps
Apr 30, 2026
Merged

refactor(store): pull storage map entries from account state forest#2012
kkovaacs merged 20 commits intomainfrom
krisztian/improve-get-account-storage-maps

Conversation

@kkovaacs
Copy link
Copy Markdown
Contributor

@kkovaacs kkovaacs commented Apr 28, 2026

As outlined in #1978 in some cases we can use the account state forest to pull storage map entries instead of the database.

The issue with storage state in account state forest is that storage keys are hashed before being stored in the forest, so querying all entries for a storage map requires an ability to reverse the hash.

This is not generally possible, but we can maintain an LRU cache of hashed_key -> key mappings. If all hashed keys for a storage map are present in the cache we don't need to query the database at all and can just use the cache to reverse the hashes.

If some hashes are missing from the cache, we fall back to querying the database and then make sure to update the LRU cache with the missing mappings.

This PR also adds some improvements to the stress-test tool:

  • seed-store can now generate a configurable number of vault assets and storage map entries for the accounts it is creating.
  • seed-store now optionally generates blocks with transactions that update the storage map entries for the accounts it has previously generated.
  • A new get-account benchmark that is querying account state, including vault assets and generated storage map values.

Using the new get-account benchmark we get the following results (on a DB with ~50k public accounts, each with 2 vault assets and 64 storage map entries).

Before:

➤ RUST_LOG=warn target/release/miden-node-stress-test benchmark-store -d /tmp/data --iterations 100000 --concurrency 16 get-account
Average request latency: 1.812924ms
P50 request latency: 789.342µs
P95 request latency: 1.093589ms
P99 request latency: 41.30199ms
P99.9 request latency: 41.981872ms
GetAccount statistics:
  Total runs: 100000
  Storage map limit exceeded responses: 0
  Average returned storage map entries: 64.00
  Vault limit exceeded responses: 0
  Average returned vault assets: 2.00

After:

➤ miden-node-stress-test benchmark-store -d /tmp/data --iterations 100000 --concurrency 16 get-account
Average request latency: 829.417µs
P50 request latency: 698.052µs
P95 request latency: 934.949µs
P99 request latency: 1.090607ms
P99.9 request latency: 41.353863ms
GetAccount statistics:
  Total runs: 100000
  Storage map limit exceeded responses: 0
  Average returned storage map entries: 64.00
  Vault limit exceeded responses: 0
  Average returned vault assets: 2.00

Note that there's also a change on how many storage map entries we're returning for all_entries slots. Previously, the code was using QueryParamStorageMapKeyTotalLimit as the limit, but that limit is supposed to be the maximum number of individual keys for any map in the request. The current value for that limit is 64, which makes sense for the case where we're returning proofs but all_entries query responses are just a list of (key, value) pairs. This PR changes the limit the maximum number of entries returned to AccountStorageMapDetails::MAX_RETURN_ENTRIES (1000 currently) so that the limit is consistent across the code base.

kkovaacs added 13 commits April 28, 2026 13:47
Use the account state forest to pull storage map entries instead of the database.

The issue with storage state in account state forest is that storage keys are _hashed_
before being stored in the forest, so querying _all_ entries for a storage map
requires an ability to reverse the hash.

This is not generally possible, but we can maintain an LRU cache of
`hashed_key` -> `key` mappings. If _all_ hashed keys for a storage map are present
in the cache we don't need to query the database at all and can just use the cache
to reverse the hashes.

If some hashes are missing from the cache, we fall back to querying the database
and then make sure to update the LRU cache with the missing mappings.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors GetAccount storage-map loading to prefer AccountStateForest (when raw keys can be reconstructed from a reverse-key cache) and expands the stress-test tool to seed/benchmark realistic account detail queries.

Changes:

  • Add an LRU reverse-key cache (hashed_key -> raw_key) to enable enumerating storage map entries from the forest without hitting SQLite when possible.
  • Update GetAccount all-entries storage map requests to use the forest when the cache is complete, otherwise fall back to DB reconstruction and backfill the cache.
  • Extend miden-node-stress-test with configurable seeding (vault assets + storage map entries + update blocks) and a new get-account benchmark.

Reviewed changes

Copilot reviewed 9 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/store/src/state/mod.rs Adds forest-first + DB-fallback path for AllEntries storage map details; backfills reverse-key cache after DB reconstruction.
crates/store/src/account_state_forest/mod.rs Introduces LRU cache and new API to fetch all storage map entries from forest when keys can be reversed.
crates/store/src/account_state_forest/tests.rs Adds a unit test asserting all-entries returns raw keys after an update.
crates/store/Cargo.toml Adds lru dependency.
bin/stress-test/src/store/mod.rs Adds get-account benchmark implementation and request builder.
bin/stress-test/src/seeding/mod.rs Adds configurable seeding for vault/storage-map sizing and optional post-init update blocks.
bin/stress-test/src/seeding/tests.rs Adds tests for new seeding behaviors (storage map sizing, vault assets, update logic).
bin/stress-test/src/main.rs Wires new seed/benchmark CLI options and new get-account endpoint.
bin/stress-test/README.md Documents new seeding knobs and the get-account benchmark usage/results.
Cargo.lock Records lru dependency resolution.
CHANGELOG.md Notes the GetAccount optimization for all-entries requests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/store/src/state/mod.rs Outdated
Comment thread crates/store/src/account_state_forest/mod.rs Outdated
Comment thread crates/store/src/state/mod.rs
Comment thread crates/store/src/account_state_forest/mod.rs
@kkovaacs kkovaacs marked this pull request as ready for review April 28, 2026 15:03
The `.get()` operation of the cache requires a mutable reference to update
the internal LRU state. We avoided that using `.peek()`, but that meant we
don't keep track of usage and the cache was not effective.
Comment thread crates/store/src/account_state_forest/mod.rs Outdated
@kkovaacs kkovaacs merged commit 1468f8e into main Apr 30, 2026
19 checks passed
@kkovaacs kkovaacs deleted the krisztian/improve-get-account-storage-maps branch April 30, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants