test(trie): more complex trie node iter test (#15244)

This commit is contained in:
Alexey Shekhirin
2025-03-24 21:32:11 +00:00
committed by GitHub
parent d456af044e
commit c0c29862bc

View File

@@ -229,21 +229,31 @@ mod tests {
#[test]
fn test_trie_node_iter() {
fn empty_leaf_rlp_for_key(key: Nibbles) -> RlpNode {
RlpNode::from_rlp(&alloy_rlp::encode(LeafNode::new(
key,
alloy_rlp::encode(TrieAccount::default()),
)))
}
reth_tracing::init_test_tracing();
// Extension (Key = 0000000000000000000000000000000000000000000000000000000000000)
// └── Branch (`branch_node`)
// ├── 0 -> Branch (`child_branch_node`)
// │ ├── 0 -> Leaf (account_1, marked as changed)
// │ └── 1 -> Leaf (account_2)
// ├── 1 -> Branch (`child_branch_node`)
// │ ├── 0 -> Leaf (account_5)
// │ ── 1 -> Leaf (account_6)
// Extension (Key = 0x0000000000000000000000000000000000000000000000000000000000000)
// └── Branch (`branch_node_0`)
// ├── 0 -> Branch (`branch_node_1`)
// │ ├── 0 -> Leaf (`account_1`, Key = 0x0)
// │ └── 1 -> Leaf (`account_2`, Key = 0x0)
// ├── 1 -> Branch (`branch_node_2`)
// │ ├── 0 -> Branch (`branch_node_3`)
// │ │ ├── 0 -> Leaf (`account_3`, marked as changed)
// │ │ └── 1 -> Leaf (`account_4`)
// │ └── 1 -> Leaf (`account_5`, Key = 0x0)
let account_1 = b256!("0x0000000000000000000000000000000000000000000000000000000000000000");
let account_2 = b256!("0x0000000000000000000000000000000000000000000000000000000000000001");
let account_3 = b256!("0x0000000000000000000000000000000000000000000000000000000000000010");
let account_4 = b256!("0x0000000000000000000000000000000000000000000000000000000000000011");
let account_2 = b256!("0x0000000000000000000000000000000000000000000000000000000000000010");
let account_3 = b256!("0x0000000000000000000000000000000000000000000000000000000000000100");
let account_4 = b256!("0x0000000000000000000000000000000000000000000000000000000000000101");
let account_5 = b256!("0x0000000000000000000000000000000000000000000000000000000000000110");
let empty_account = Account::default();
let hash_builder_branch_nodes = get_hash_builder_branch_nodes(vec![
@@ -251,36 +261,51 @@ mod tests {
(Nibbles::unpack(account_2), empty_account),
(Nibbles::unpack(account_3), empty_account),
(Nibbles::unpack(account_4), empty_account),
(Nibbles::unpack(account_5), empty_account),
]);
let empty_leaf_rlp = RlpNode::from_rlp(&alloy_rlp::encode(LeafNode::new(
Nibbles::default(),
alloy_rlp::encode(TrieAccount::default()),
)));
let child_branch_node_rlp = RlpNode::from_rlp(&alloy_rlp::encode(BranchNode::new(
vec![empty_leaf_rlp.clone(), empty_leaf_rlp],
let branch_node_1_rlp = RlpNode::from_rlp(&alloy_rlp::encode(BranchNode::new(
vec![
empty_leaf_rlp_for_key(Nibbles::from_nibbles([0])),
empty_leaf_rlp_for_key(Nibbles::from_nibbles([0])),
],
TrieMask::new(0b11),
)));
let branch_node = (
Nibbles::from_nibbles([0; 62]),
let branch_node_3_rlp = RlpNode::from_rlp(&alloy_rlp::encode(BranchNode::new(
vec![
empty_leaf_rlp_for_key(Nibbles::default()),
empty_leaf_rlp_for_key(Nibbles::default()),
],
TrieMask::new(0b11),
)));
let branch_node_2 = (
Nibbles::from_nibbles([vec![0; 61], vec![1]].concat()),
BranchNodeCompact::new(
TrieMask::new(0b11),
// Tree mask has no bits set, because both child branch nodes have empty tree and
// hash masks.
TrieMask::new(0b00),
// Hash mask bits are set, because both child nodes are branches.
TrieMask::new(0b01),
vec![branch_node_3_rlp.as_hash().unwrap()],
None,
),
);
let branch_node_2_rlp = RlpNode::from_rlp(&alloy_rlp::encode(BranchNode::new(
vec![branch_node_3_rlp, empty_leaf_rlp_for_key(Nibbles::from_nibbles([0]))],
TrieMask::new(0b11),
)));
let branch_node_0 = (
Nibbles::from_nibbles([0; 61]),
BranchNodeCompact::new(
TrieMask::new(0b11),
vec![
child_branch_node_rlp.as_hash().unwrap(),
child_branch_node_rlp.as_hash().unwrap(),
],
TrieMask::new(0b10),
TrieMask::new(0b11),
vec![branch_node_1_rlp.as_hash().unwrap(), branch_node_2_rlp.as_hash().unwrap()],
None,
),
);
let mock_trie_nodes = vec![branch_node.clone()];
let mock_trie_nodes = vec![branch_node_0.clone(), branch_node_2.clone()];
pretty_assertions::assert_eq!(
hash_builder_branch_nodes.into_iter().sorted().collect::<Vec<_>>(),
mock_trie_nodes,
@@ -289,9 +314,9 @@ mod tests {
let trie_cursor_factory =
MockTrieCursorFactory::new(mock_trie_nodes.into_iter().collect(), B256Map::default());
// Mark the account 1 as changed.
// Mark the account 3 as changed.
let mut prefix_set = PrefixSetMut::default();
prefix_set.insert(Nibbles::unpack(account_1));
prefix_set.insert(Nibbles::unpack(account_3));
let prefix_set = prefix_set.freeze();
let walker =
@@ -303,6 +328,7 @@ mod tests {
(account_2, empty_account),
(account_3, empty_account),
(account_4, empty_account),
(account_5, empty_account),
]),
B256Map::default(),
);
@@ -322,7 +348,11 @@ mod tests {
},
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(Nibbles::from_nibbles([0x0])),
visited_key: Some(branch_node.0)
visited_key: Some(branch_node_0.0)
},
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(branch_node_2.0.clone()),
visited_key: Some(branch_node_2.0)
},
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(Nibbles::from_nibbles([0x1])),
@@ -333,23 +363,35 @@ mod tests {
pretty_assertions::assert_eq!(
*hashed_cursor_factory.visited_account_keys(),
vec![
// Why do we seek account 1 one additional times?
// Why do we always seek this key first?
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(account_1),
visited_key: Some(account_1)
},
// Seek to the modified account.
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(account_1),
visited_key: Some(account_1)
visit_type: KeyVisitType::SeekNonExact(account_3),
visited_key: Some(account_3)
},
KeyVisit { visit_type: KeyVisitType::Next, visited_key: Some(account_2) },
KeyVisit { visit_type: KeyVisitType::Next, visited_key: Some(account_3) },
// Why do we seek the modified account two more times?
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(b256!(
"0x0000000000000000000000000000000000000000000000000000000000000020"
)),
visited_key: None
visit_type: KeyVisitType::SeekNonExact(account_3),
visited_key: Some(account_3)
},
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(account_3),
visited_key: Some(account_3)
},
// Collect the siblings of the modified account
KeyVisit { visit_type: KeyVisitType::Next, visited_key: Some(account_4) },
KeyVisit { visit_type: KeyVisitType::Next, visited_key: Some(account_5) },
// We seek the account 5 because its hash is not in the branch node, but we already
// walked it before, so there should be no need for it.
KeyVisit {
visit_type: KeyVisitType::SeekNonExact(account_5),
visited_key: Some(account_5)
},
KeyVisit { visit_type: KeyVisitType::Next, visited_key: None },
],
);
}