mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
Compare commits
17 Commits
main
...
klkvr/benc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
450713e79d | ||
|
|
699a26ea1e | ||
|
|
955976dd63 | ||
|
|
b37151c6a2 | ||
|
|
47b59e8ebc | ||
|
|
9af31bc2c4 | ||
|
|
2c8a66ef29 | ||
|
|
ecf640d33e | ||
|
|
245b499b19 | ||
|
|
170d0a5e52 | ||
|
|
bba57395c6 | ||
|
|
ca62b86733 | ||
|
|
102acb7bf0 | ||
|
|
0119a880b1 | ||
|
|
e0ed7e0d4b | ||
|
|
4d3ed18a9e | ||
|
|
f215ab39a2 |
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -6239,8 +6239,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nybbles"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210"
|
||||
source = "git+https://github.com/alloy-rs/nybbles?rev=8df38fb#8df38fb3f9c897090771a56a639eaf161327109e"
|
||||
dependencies = [
|
||||
"alloy-rlp",
|
||||
"arbitrary",
|
||||
|
||||
@@ -760,3 +760,5 @@ ipnet = "2.11"
|
||||
|
||||
# alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "072c248" }
|
||||
# alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "072c248" }
|
||||
|
||||
nybbles = { git = "https://github.com/alloy-rs/nybbles", rev = "8df38fb" }
|
||||
@@ -466,49 +466,36 @@ where
|
||||
if new { &mut self.new_storage_updates } else { &mut self.storage_updates };
|
||||
|
||||
// Process all storage updates in parallel, skipping tries with no pending updates.
|
||||
let span = tracing::Span::current();
|
||||
let storage_results = storage_updates
|
||||
.iter_mut()
|
||||
.filter(|(_, updates)| !updates.is_empty())
|
||||
.map(|(address, updates)| {
|
||||
let trie = self.trie.take_or_create_storage_trie(address);
|
||||
let fetched = self.fetched_storage_targets.remove(address).unwrap_or_default();
|
||||
let span = debug_span!("process_storage_leaf_updates").entered();
|
||||
for (address, updates) in storage_updates {
|
||||
if updates.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
(address, updates, fetched, trie)
|
||||
})
|
||||
.par_bridge_buffered()
|
||||
.map(|(address, updates, mut fetched, mut trie)| {
|
||||
let _enter = debug_span!(target: "engine::tree::payload_processor::sparse_trie", parent: &span, "storage_trie_leaf_updates", a=%address).entered();
|
||||
let mut targets = Vec::new();
|
||||
let trie = self.trie.get_or_create_storage_trie_mut(*address);
|
||||
let fetched = self.fetched_storage_targets.entry(*address).or_default();
|
||||
let mut targets = Vec::new();
|
||||
|
||||
trie.update_leaves(updates, |path, min_len| match fetched.entry(path) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
if min_len < *entry.get() {
|
||||
entry.insert(min_len);
|
||||
targets.push(Target::new(path).with_min_len(min_len));
|
||||
}
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
trie.update_leaves(updates, |path, min_len| match fetched.entry(path) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
if min_len < *entry.get() {
|
||||
entry.insert(min_len);
|
||||
targets.push(Target::new(path).with_min_len(min_len));
|
||||
}
|
||||
})?;
|
||||
|
||||
SparseTrieResult::Ok((address, targets, fetched, trie))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
drop(span);
|
||||
|
||||
for (address, targets, fetched, trie) in storage_results {
|
||||
self.fetched_storage_targets.insert(*address, fetched);
|
||||
self.trie.insert_storage_trie(*address, trie);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(min_len);
|
||||
targets.push(Target::new(path).with_min_len(min_len));
|
||||
}
|
||||
})?;
|
||||
|
||||
if !targets.is_empty() {
|
||||
self.pending_targets.storage_targets.entry(*address).or_default().extend(targets);
|
||||
}
|
||||
}
|
||||
|
||||
drop(span);
|
||||
|
||||
// Process account trie updates and fill the account targets.
|
||||
self.process_account_leaf_updates(new)?;
|
||||
|
||||
@@ -577,7 +564,7 @@ where
|
||||
})
|
||||
.par_bridge_buffered()
|
||||
.for_each(|(address, trie)| {
|
||||
let _enter = debug_span!(target: "engine::tree::payload_processor::sparse_trie", parent: &span, "storage_root", ?address).entered();
|
||||
let _enter = debug_span!(target: "engine::tree::payload_processor::sparse_trie", parent: &span, "storage_root", ?address, prefix_set_len = trie.prefix_set_len()).entered();
|
||||
trie.root().expect("updates are drained, trie should be revealed by now");
|
||||
});
|
||||
drop(span);
|
||||
|
||||
@@ -931,6 +931,10 @@ impl SparseTrie for ParallelSparseTrie {
|
||||
.is_some_and(|node| node.cached_rlp_node().is_some())
|
||||
}
|
||||
|
||||
fn prefix_set_len(&self) -> usize {
|
||||
self.prefix_set.len()
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", target = "trie::sparse::parallel", skip(self))]
|
||||
fn update_subtrie_hashes(&mut self) {
|
||||
trace!(target: "trie::parallel_sparse", "Updating subtrie hashes");
|
||||
@@ -1099,25 +1103,48 @@ impl SparseTrie for ParallelSparseTrie {
|
||||
loop {
|
||||
let curr_node = curr_subtrie.nodes.get(&curr_path).unwrap();
|
||||
|
||||
match Self::find_next_to_leaf(&curr_path, curr_node, full_path) {
|
||||
FindNextToLeafOutcome::NotFound => return Ok(LeafLookup::NonExistent),
|
||||
FindNextToLeafOutcome::BlindedNode { path, hash } => {
|
||||
return Err(LeafLookupError::BlindedNode { path, hash });
|
||||
match curr_node {
|
||||
SparseNode::Empty => return Ok(LeafLookup::NonExistent),
|
||||
SparseNode::Leaf { key, .. } => {
|
||||
let mut found_full_path = curr_path;
|
||||
found_full_path.extend(key);
|
||||
assert!(&found_full_path != full_path, "target leaf {full_path:?} found, even though value wasn't in values hashmap");
|
||||
return Ok(LeafLookup::NonExistent)
|
||||
}
|
||||
FindNextToLeafOutcome::Found => {
|
||||
panic!("target leaf {full_path:?} found at path {curr_path:?}, even though value wasn't in values hashmap");
|
||||
}
|
||||
FindNextToLeafOutcome::ContinueFrom(next_path) => {
|
||||
curr_path = next_path;
|
||||
// If we were previously looking at the upper trie, and the new path is in the
|
||||
// lower trie, we need to pull out a ref to the lower trie.
|
||||
if curr_subtrie_is_upper &&
|
||||
let Some(lower_subtrie) = self.lower_subtrie_for_path(&curr_path)
|
||||
{
|
||||
curr_subtrie = lower_subtrie;
|
||||
curr_subtrie_is_upper = false;
|
||||
SparseNode::Extension { key, .. } => {
|
||||
if full_path.len() == curr_path.len() {
|
||||
return Ok(LeafLookup::NonExistent)
|
||||
}
|
||||
curr_path.extend(key);
|
||||
if !full_path.starts_with(&curr_path) {
|
||||
return Ok(LeafLookup::NonExistent)
|
||||
}
|
||||
}
|
||||
SparseNode::Branch { state_mask, blinded_mask, blinded_hashes, .. } => {
|
||||
if full_path.len() == curr_path.len() {
|
||||
return Ok(LeafLookup::NonExistent)
|
||||
}
|
||||
let nibble = full_path.get_unchecked(curr_path.len());
|
||||
if !state_mask.is_bit_set(nibble) {
|
||||
return Ok(LeafLookup::NonExistent)
|
||||
}
|
||||
curr_path.push_unchecked(nibble);
|
||||
if blinded_mask.is_bit_set(nibble) {
|
||||
return Err(LeafLookupError::BlindedNode {
|
||||
path: curr_path,
|
||||
hash: blinded_hashes[nibble as usize],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we were previously looking at the upper trie, and the new path is in the
|
||||
// lower trie, we need to pull out a ref to the lower trie.
|
||||
if curr_subtrie_is_upper &&
|
||||
let Some(lower_subtrie) = self.lower_subtrie_for_path(&curr_path)
|
||||
{
|
||||
curr_subtrie = lower_subtrie;
|
||||
curr_subtrie_is_upper = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use reth_trie_common::{
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use tracing::debug;
|
||||
use tracing::{instrument, trace};
|
||||
use tracing::{debug_span, instrument, trace};
|
||||
|
||||
/// Holds data that should be dropped after any locks are released.
|
||||
///
|
||||
@@ -323,6 +323,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let _span = debug_span!("reveal_storage_v2_proof_nodes").entered();
|
||||
#[cfg(feature = "std")]
|
||||
// If std then reveal storage proofs in parallel
|
||||
{
|
||||
@@ -389,6 +390,7 @@ where
|
||||
///
|
||||
/// V2 proofs already include the masks in the `ProofTrieNode` structure,
|
||||
/// so no separate masks map is needed.
|
||||
#[instrument(level = "debug", target = "trie::sparse", skip_all)]
|
||||
pub fn reveal_account_v2_proof_nodes(
|
||||
&mut self,
|
||||
mut nodes: Vec<ProofTrieNodeV2>,
|
||||
|
||||
@@ -193,6 +193,9 @@ pub trait SparseTrie: Sized + Debug + Send + Sync {
|
||||
/// Returns true if the root node is cached and does not need any recomputation.
|
||||
fn is_root_cached(&self) -> bool;
|
||||
|
||||
/// Returns the length of the prefix set of the trie.
|
||||
fn prefix_set_len(&self) -> usize;
|
||||
|
||||
/// Recalculates and updates the RLP hashes of subtries deeper than a certain level. The level
|
||||
/// is defined in the implementation.
|
||||
///
|
||||
|
||||
@@ -169,6 +169,11 @@ impl<T: SparseTrieTrait> RevealableSparseTrie<T> {
|
||||
self.as_revealed_ref().is_some_and(|trie| trie.is_root_cached())
|
||||
}
|
||||
|
||||
/// Returns the length of the prefix set of the trie.
|
||||
pub fn prefix_set_len(&self) -> usize {
|
||||
self.as_revealed_ref().map(|trie| trie.prefix_set_len()).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Returns the root hash along with any accumulated update information.
|
||||
///
|
||||
/// This is useful for when you need both the root hash and information about
|
||||
|
||||
Reference in New Issue
Block a user