Skip to content

Commit c57792c

Browse files
feat(trie): Implement skeleton of proof_v2 (paradigmxyz#19687)
1 parent e58aa09 commit c57792c

File tree

10 files changed

+432
-108
lines changed

10 files changed

+432
-108
lines changed

crates/engine/tree/src/tree/payload_processor/configured_sparse_trie.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! Configured sparse trie enum for switching between serial and parallel implementations.
22
33
use alloy_primitives::B256;
4-
use reth_trie::{Nibbles, TrieNode};
4+
use reth_trie::{Nibbles, ProofTrieNode, TrieMasks, TrieNode};
55
use reth_trie_sparse::{
66
errors::SparseTrieResult, provider::TrieNodeProvider, LeafLookup, LeafLookupError,
7-
RevealedSparseNode, SerialSparseTrie, SparseTrieInterface, SparseTrieUpdates, TrieMasks,
7+
SerialSparseTrie, SparseTrieInterface, SparseTrieUpdates,
88
};
99
use reth_trie_sparse_parallel::ParallelSparseTrie;
1010
use std::borrow::Cow;
@@ -83,7 +83,7 @@ impl SparseTrieInterface for ConfiguredSparseTrie {
8383
}
8484
}
8585

86-
fn reveal_nodes(&mut self, nodes: Vec<RevealedSparseNode>) -> SparseTrieResult<()> {
86+
fn reveal_nodes(&mut self, nodes: Vec<ProofTrieNode>) -> SparseTrieResult<()> {
8787
match self {
8888
Self::Serial(trie) => trie.reveal_nodes(nodes),
8989
Self::Parallel(trie) => trie.reveal_nodes(nodes),

crates/trie/common/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub use storage::{StorageTrieEntry, TrieChangeSetsEntry};
4141
mod subnode;
4242
pub use subnode::StoredSubNode;
4343

44+
mod trie;
45+
pub use trie::{ProofTrieNode, TrieMasks};
46+
4447
/// The implementation of a container for storing intermediate changes to a trie.
4548
/// The container indicates when the trie has been modified.
4649
pub mod prefix_set;

crates/trie/common/src/trie.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//! Types related to sparse trie nodes and masks.
2+
3+
use crate::Nibbles;
4+
use alloy_trie::{nodes::TrieNode, TrieMask};
5+
6+
/// Struct for passing around branch node mask information.
7+
///
8+
/// Branch nodes can have up to 16 children (one for each nibble).
9+
/// The masks represent which children are stored in different ways:
10+
/// - `hash_mask`: Indicates which children are stored as hashes in the database
11+
/// - `tree_mask`: Indicates which children are complete subtrees stored in the database
12+
///
13+
/// These masks are essential for efficient trie traversal and serialization, as they
14+
/// determine how nodes should be encoded and stored on disk.
15+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
16+
pub struct TrieMasks {
17+
/// Branch node hash mask, if any.
18+
///
19+
/// When a bit is set, the corresponding child node's hash is stored in the trie.
20+
///
21+
/// This mask enables selective hashing of child nodes.
22+
pub hash_mask: Option<TrieMask>,
23+
/// Branch node tree mask, if any.
24+
///
25+
/// When a bit is set, the corresponding child subtree is stored in the database.
26+
pub tree_mask: Option<TrieMask>,
27+
}
28+
29+
impl TrieMasks {
30+
/// Helper function, returns both fields `hash_mask` and `tree_mask` as [`None`]
31+
pub const fn none() -> Self {
32+
Self { hash_mask: None, tree_mask: None }
33+
}
34+
}
35+
36+
/// Carries all information needed by a sparse trie to reveal a particular node.
37+
#[derive(Debug, Clone, PartialEq, Eq)]
38+
pub struct ProofTrieNode {
39+
/// Path of the node.
40+
pub path: Nibbles,
41+
/// The node itself.
42+
pub node: TrieNode,
43+
/// Tree and hash masks for the node, if known.
44+
pub masks: TrieMasks,
45+
}

crates/trie/sparse-parallel/src/trie.rs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ use alloy_trie::{BranchNodeCompact, TrieMask, EMPTY_ROOT_HASH};
99
use reth_execution_errors::{SparseTrieErrorKind, SparseTrieResult};
1010
use reth_trie_common::{
1111
prefix_set::{PrefixSet, PrefixSetMut},
12-
BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, RlpNode, TrieNode, CHILD_INDEX_RANGE,
12+
BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, ProofTrieNode, RlpNode, TrieMasks,
13+
TrieNode, CHILD_INDEX_RANGE,
1314
};
1415
use reth_trie_sparse::{
1516
provider::{RevealedNode, TrieNodeProvider},
16-
LeafLookup, LeafLookupError, RevealedSparseNode, RlpNodeStackItem, SparseNode, SparseNodeType,
17-
SparseTrieInterface, SparseTrieUpdates, TrieMasks,
17+
LeafLookup, LeafLookupError, RlpNodeStackItem, SparseNode, SparseNodeType, SparseTrieInterface,
18+
SparseTrieUpdates,
1819
};
1920
use smallvec::SmallVec;
2021
use std::{
@@ -172,23 +173,23 @@ impl SparseTrieInterface for ParallelSparseTrie {
172173
self
173174
}
174175

175-
fn reveal_nodes(&mut self, mut nodes: Vec<RevealedSparseNode>) -> SparseTrieResult<()> {
176+
fn reveal_nodes(&mut self, mut nodes: Vec<ProofTrieNode>) -> SparseTrieResult<()> {
176177
if nodes.is_empty() {
177178
return Ok(())
178179
}
179180

180181
// Sort nodes first by their subtrie, and secondarily by their path. This allows for
181182
// grouping nodes by their subtrie using `chunk_by`.
182183
nodes.sort_unstable_by(
183-
|RevealedSparseNode { path: path_a, .. }, RevealedSparseNode { path: path_b, .. }| {
184+
|ProofTrieNode { path: path_a, .. }, ProofTrieNode { path: path_b, .. }| {
184185
let subtrie_type_a = SparseSubtrieType::from_path(path_a);
185186
let subtrie_type_b = SparseSubtrieType::from_path(path_b);
186187
subtrie_type_a.cmp(&subtrie_type_b).then(path_a.cmp(path_b))
187188
},
188189
);
189190

190191
// Update the top-level branch node masks. This is simple and can't be done in parallel.
191-
for RevealedSparseNode { path, masks, .. } in &nodes {
192+
for ProofTrieNode { path, masks, .. } in &nodes {
192193
if let Some(tree_mask) = masks.tree_mask {
193194
self.branch_node_tree_masks.insert(*path, tree_mask);
194195
}
@@ -2688,14 +2689,14 @@ mod tests {
26882689
prefix_set::PrefixSetMut,
26892690
proof::{ProofNodes, ProofRetainer},
26902691
updates::TrieUpdates,
2691-
BranchNode, ExtensionNode, HashBuilder, LeafNode, RlpNode, TrieMask, TrieNode,
2692-
EMPTY_ROOT_HASH,
2692+
BranchNode, ExtensionNode, HashBuilder, LeafNode, ProofTrieNode, RlpNode, TrieMask,
2693+
TrieMasks, TrieNode, EMPTY_ROOT_HASH,
26932694
};
26942695
use reth_trie_db::DatabaseTrieCursorFactory;
26952696
use reth_trie_sparse::{
26962697
provider::{DefaultTrieNodeProvider, RevealedNode, TrieNodeProvider},
2697-
LeafLookup, LeafLookupError, RevealedSparseNode, SerialSparseTrie, SparseNode,
2698-
SparseTrieInterface, SparseTrieUpdates, TrieMasks,
2698+
LeafLookup, LeafLookupError, SerialSparseTrie, SparseNode, SparseTrieInterface,
2699+
SparseTrieUpdates,
26992700
};
27002701
use std::collections::{BTreeMap, BTreeSet};
27012702

@@ -3277,7 +3278,7 @@ mod tests {
32773278
let node = create_leaf_node([0x2, 0x3], 42);
32783279
let masks = TrieMasks::none();
32793280

3280-
trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3281+
trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
32813282

32823283
assert_matches!(
32833284
trie.upper_subtrie.nodes.get(&path),
@@ -3298,7 +3299,7 @@ mod tests {
32983299
let node = create_leaf_node([0x3, 0x4], 42);
32993300
let masks = TrieMasks::none();
33003301

3301-
trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3302+
trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
33023303

33033304
// Check that the lower subtrie was created
33043305
let idx = path_subtrie_index_unchecked(&path);
@@ -3322,7 +3323,7 @@ mod tests {
33223323
let node = create_leaf_node([0x4, 0x5], 42);
33233324
let masks = TrieMasks::none();
33243325

3325-
trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3326+
trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
33263327

33273328
// Check that the lower subtrie's path hasn't changed
33283329
let idx = path_subtrie_index_unchecked(&path);
@@ -3383,7 +3384,7 @@ mod tests {
33833384
let node = create_extension_node([0x2], child_hash);
33843385
let masks = TrieMasks::none();
33853386

3386-
trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3387+
trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
33873388

33883389
// Extension node should be in upper trie
33893390
assert_matches!(
@@ -3445,7 +3446,7 @@ mod tests {
34453446
let node = create_branch_node_with_children(&[0x0, 0x7, 0xf], child_hashes.clone());
34463447
let masks = TrieMasks::none();
34473448

3448-
trie.reveal_nodes(vec![RevealedSparseNode { path, node, masks }]).unwrap();
3449+
trie.reveal_nodes(vec![ProofTrieNode { path, node, masks }]).unwrap();
34493450

34503451
// Branch node should be in upper trie
34513452
assert_matches!(
@@ -3502,10 +3503,10 @@ mod tests {
35023503

35033504
// Reveal nodes using reveal_nodes
35043505
trie.reveal_nodes(vec![
3505-
RevealedSparseNode { path: branch_path, node: branch_node, masks: TrieMasks::none() },
3506-
RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
3507-
RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
3508-
RevealedSparseNode { path: leaf_3_path, node: leaf_3, masks: TrieMasks::none() },
3506+
ProofTrieNode { path: branch_path, node: branch_node, masks: TrieMasks::none() },
3507+
ProofTrieNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
3508+
ProofTrieNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
3509+
ProofTrieNode { path: leaf_3_path, node: leaf_3, masks: TrieMasks::none() },
35093510
])
35103511
.unwrap();
35113512

@@ -4207,7 +4208,7 @@ mod tests {
42074208
// Convert the logs into reveal_nodes call on a fresh ParallelSparseTrie
42084209
let nodes = vec![
42094210
// Branch at 0x4f8807
4210-
RevealedSparseNode {
4211+
ProofTrieNode {
42114212
path: branch_path,
42124213
node: {
42134214
TrieNode::Branch(BranchNode::new(
@@ -4270,7 +4271,7 @@ mod tests {
42704271
},
42714272
},
42724273
// Branch at 0x4f88072
4273-
RevealedSparseNode {
4274+
ProofTrieNode {
42744275
path: removed_branch_path,
42754276
node: {
42764277
let stack = vec![
@@ -4290,7 +4291,7 @@ mod tests {
42904291
},
42914292
},
42924293
// Extension at 0x4f880722
4293-
RevealedSparseNode {
4294+
ProofTrieNode {
42944295
path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0x2]),
42954296
node: {
42964297
let extension_node = ExtensionNode::new(
@@ -4304,7 +4305,7 @@ mod tests {
43044305
masks: TrieMasks { hash_mask: None, tree_mask: None },
43054306
},
43064307
// Leaf at 0x4f88072c
4307-
RevealedSparseNode {
4308+
ProofTrieNode {
43084309
path: Nibbles::from_nibbles([0x4, 0xf, 0x8, 0x8, 0x0, 0x7, 0x2, 0xc]),
43094310
node: {
43104311
let leaf_node = LeafNode::new(
@@ -4423,9 +4424,9 @@ mod tests {
44234424
// Step 2: Reveal nodes in the trie
44244425
let mut trie = ParallelSparseTrie::from_root(extension, TrieMasks::none(), true).unwrap();
44254426
trie.reveal_nodes(vec![
4426-
RevealedSparseNode { path: branch_path, node: branch, masks: TrieMasks::none() },
4427-
RevealedSparseNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
4428-
RevealedSparseNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
4427+
ProofTrieNode { path: branch_path, node: branch, masks: TrieMasks::none() },
4428+
ProofTrieNode { path: leaf_1_path, node: leaf_1, masks: TrieMasks::none() },
4429+
ProofTrieNode { path: leaf_2_path, node: leaf_2, masks: TrieMasks::none() },
44294430
])
44304431
.unwrap();
44314432

@@ -4960,12 +4961,12 @@ mod tests {
49604961
// └── 1 -> Leaf (Path = 1)
49614962
sparse
49624963
.reveal_nodes(vec![
4963-
RevealedSparseNode {
4964+
ProofTrieNode {
49644965
path: Nibbles::default(),
49654966
node: branch,
49664967
masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
49674968
},
4968-
RevealedSparseNode {
4969+
ProofTrieNode {
49694970
path: Nibbles::from_nibbles([0x1]),
49704971
node: TrieNode::Leaf(leaf),
49714972
masks: TrieMasks::none(),
@@ -5009,12 +5010,12 @@ mod tests {
50095010
// └── 1 -> Leaf (Path = 1)
50105011
sparse
50115012
.reveal_nodes(vec![
5012-
RevealedSparseNode {
5013+
ProofTrieNode {
50135014
path: Nibbles::default(),
50145015
node: branch,
50155016
masks: TrieMasks { hash_mask: None, tree_mask: Some(TrieMask::new(0b01)) },
50165017
},
5017-
RevealedSparseNode {
5018+
ProofTrieNode {
50185019
path: Nibbles::from_nibbles([0x1]),
50195020
node: TrieNode::Leaf(leaf),
50205021
masks: TrieMasks::none(),
@@ -5361,13 +5362,13 @@ mod tests {
53615362
Default::default(),
53625363
[key1()],
53635364
);
5364-
let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5365+
let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
53655366
.nodes_sorted()
53665367
.into_iter()
53675368
.map(|(path, node)| {
53685369
let hash_mask = branch_node_hash_masks.get(&path).copied();
53695370
let tree_mask = branch_node_tree_masks.get(&path).copied();
5370-
RevealedSparseNode {
5371+
ProofTrieNode {
53715372
path,
53725373
node: TrieNode::decode(&mut &node[..]).unwrap(),
53735374
masks: TrieMasks { hash_mask, tree_mask },
@@ -5399,13 +5400,13 @@ mod tests {
53995400
Default::default(),
54005401
[key3()],
54015402
);
5402-
let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5403+
let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
54035404
.nodes_sorted()
54045405
.into_iter()
54055406
.map(|(path, node)| {
54065407
let hash_mask = branch_node_hash_masks.get(&path).copied();
54075408
let tree_mask = branch_node_tree_masks.get(&path).copied();
5408-
RevealedSparseNode {
5409+
ProofTrieNode {
54095410
path,
54105411
node: TrieNode::decode(&mut &node[..]).unwrap(),
54115412
masks: TrieMasks { hash_mask, tree_mask },
@@ -5478,13 +5479,13 @@ mod tests {
54785479
Default::default(),
54795480
[key1(), Nibbles::from_nibbles_unchecked([0x01])],
54805481
);
5481-
let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5482+
let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
54825483
.nodes_sorted()
54835484
.into_iter()
54845485
.map(|(path, node)| {
54855486
let hash_mask = branch_node_hash_masks.get(&path).copied();
54865487
let tree_mask = branch_node_tree_masks.get(&path).copied();
5487-
RevealedSparseNode {
5488+
ProofTrieNode {
54885489
path,
54895490
node: TrieNode::decode(&mut &node[..]).unwrap(),
54905491
masks: TrieMasks { hash_mask, tree_mask },
@@ -5516,13 +5517,13 @@ mod tests {
55165517
Default::default(),
55175518
[key2()],
55185519
);
5519-
let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5520+
let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
55205521
.nodes_sorted()
55215522
.into_iter()
55225523
.map(|(path, node)| {
55235524
let hash_mask = branch_node_hash_masks.get(&path).copied();
55245525
let tree_mask = branch_node_tree_masks.get(&path).copied();
5525-
RevealedSparseNode {
5526+
ProofTrieNode {
55265527
path,
55275528
node: TrieNode::decode(&mut &node[..]).unwrap(),
55285529
masks: TrieMasks { hash_mask, tree_mask },
@@ -5601,13 +5602,13 @@ mod tests {
56015602
Default::default(),
56025603
[key1()],
56035604
);
5604-
let revealed_nodes: Vec<RevealedSparseNode> = hash_builder_proof_nodes
5605+
let revealed_nodes: Vec<ProofTrieNode> = hash_builder_proof_nodes
56055606
.nodes_sorted()
56065607
.into_iter()
56075608
.map(|(path, node)| {
56085609
let hash_mask = branch_node_hash_masks.get(&path).copied();
56095610
let tree_mask = branch_node_tree_masks.get(&path).copied();
5610-
RevealedSparseNode {
5611+
ProofTrieNode {
56115612
path,
56125613
node: TrieNode::decode(&mut &node[..]).unwrap(),
56135614
masks: TrieMasks { hash_mask, tree_mask },
@@ -6595,16 +6596,12 @@ mod tests {
65956596
let leaf_masks = TrieMasks::none();
65966597

65976598
trie.reveal_nodes(vec![
6598-
RevealedSparseNode {
6599+
ProofTrieNode {
65996600
path: Nibbles::from_nibbles([0x3]),
66006601
node: TrieNode::Branch(branch_0x3_node),
66016602
masks: branch_0x3_masks,
66026603
},
6603-
RevealedSparseNode {
6604-
path: leaf_path,
6605-
node: TrieNode::Leaf(leaf_node),
6606-
masks: leaf_masks,
6607-
},
6604+
ProofTrieNode { path: leaf_path, node: TrieNode::Leaf(leaf_node), masks: leaf_masks },
66086605
])
66096606
.unwrap();
66106607

0 commit comments

Comments
 (0)