-
Notifications
You must be signed in to change notification settings - Fork 105
chore(l2): cache precaculated hashes for an in memory trie #4648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR optimizes trie construction by caching pre-calculated hashes to avoid redundant hash computations during trie rebuilding from RLP-encoded nodes.
- Introduces a
with_hash
method toNodeRef
that allows setting pre-calculated hashes - Updates
from_nodes
method to use cached hashes when available instead of recomputing them - Reduces hash computation overhead by approximately half according to flamegraph analysis
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
crates/common/trie/node.rs | Adds with_hash method to NodeRef for setting pre-calculated hashes |
crates/common/trie/trie.rs | Updates trie construction to use cached hashes via the new with_hash method |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Benchmark for f9320f6Click to view benchmark
|
Lines of code reportTotal lines added: Detailed view
|
/// # Warning | ||
/// will lead to errors if setting the wrong hash, use only | ||
/// when the hash was correctly precalculated | ||
pub fn with_hash(self, hash: NodeHash) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have an indication in its name that it doesn't check the validity of the hash, and the warning comment should be a SAFETY
one, so it's easier to grep for.
/// # Warning | |
/// will lead to errors if setting the wrong hash, use only | |
/// when the hash was correctly precalculated | |
pub fn with_hash(self, hash: NodeHash) -> Self { | |
/// # SAFETY: caller must ensure the hash is correct for the node. | |
/// Otherwise, the `Trie` will silently produce incorrect results and may | |
/// fail to query other nodes from the `TrieDB`. | |
pub fn with_hash_unchecked(self, hash: NodeHash) -> Self { |
Some(rlp) => { | ||
let node_ref: NodeRef = | ||
get_embedded_node(all_nodes, rlp)?.into(); | ||
node_ref.with_hash(hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is safe to use it here since we passed the hash.is_valid()
check, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hash.is_valid()
only checks that the hash is not empty, there isn't a way to check that a hash corresponds to a preimage without hashing again
Motivation
The prover's guest program takes as input a list of RLP encoded nodes, hashes them and later rebuilds the trie using
from_nodes()
, but this function does not cache the hashes already calculated, leading to double hashing.This cuts calls of
compute_hash
by half (some remain because of new nodes that appear when modifying the state trie after block execution).flamegraphs:


before:
after:
Proving time diffs:
