reth_trie_common/
trie_node_v2.rs1use crate::BranchNodeMasks;
4use alloc::vec::Vec;
5use alloy_primitives::hex;
6use alloy_rlp::{bytes, Decodable, Encodable, EMPTY_STRING_CODE};
7use alloy_trie::{
8 nodes::{BranchNodeRef, ExtensionNode, ExtensionNodeRef, LeafNode, RlpNode, TrieNode},
9 Nibbles, TrieMask,
10};
11use core::fmt;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct ProofTrieNodeV2 {
16 pub path: Nibbles,
18 pub node: TrieNodeV2,
20 pub masks: Option<BranchNodeMasks>,
23}
24
25impl ProofTrieNodeV2 {
26 pub fn empty() -> Self {
29 Self { path: Nibbles::default(), node: TrieNodeV2::EmptyRoot, masks: None }
30 }
31
32 pub fn from_sorted_trie_nodes(
38 iter: impl IntoIterator<Item = (Nibbles, TrieNode, Option<BranchNodeMasks>)>,
39 ) -> Vec<Self> {
40 let iter = iter.into_iter();
41 let mut result = Vec::with_capacity(iter.size_hint().0);
42
43 for (path, node, masks) in iter {
44 match node {
45 TrieNode::EmptyRoot => {
46 result.push(Self { path, node: TrieNodeV2::EmptyRoot, masks });
47 }
48 TrieNode::Leaf(leaf) => {
49 result.push(Self { path, node: TrieNodeV2::Leaf(leaf), masks });
50 }
51 TrieNode::Branch(branch) => {
52 result.push(Self {
53 path,
54 node: TrieNodeV2::Branch(BranchNodeV2 {
55 key: Nibbles::new(),
56 branch_rlp_node: None,
57 stack: branch.stack,
58 state_mask: branch.state_mask,
59 }),
60 masks,
61 });
62 }
63 TrieNode::Extension(ext) => {
64 let expected_branch_path = path.join(&ext.key);
68
69 if let Some(last) = result.last_mut() &&
71 last.path == expected_branch_path &&
72 let TrieNodeV2::Branch(branch_v2) = &mut last.node
73 {
74 debug_assert!(
75 branch_v2.key.is_empty(),
76 "Branch at {:?} already has extension key {:?}",
77 last.path,
78 branch_v2.key
79 );
80 branch_v2.key = ext.key;
81 branch_v2.branch_rlp_node = Some(ext.child);
82 last.path = path;
83 }
84
85 }
91 }
92 }
93
94 result
95 }
96}
97
98#[derive(PartialEq, Eq, Clone, Debug)]
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104pub enum TrieNodeV2 {
105 EmptyRoot,
107 Branch(BranchNodeV2),
109 Leaf(LeafNode),
111 Extension(ExtensionNode),
117}
118
119impl Encodable for TrieNodeV2 {
120 fn encode(&self, out: &mut dyn bytes::BufMut) {
121 match self {
122 Self::EmptyRoot => {
123 out.put_u8(EMPTY_STRING_CODE);
124 }
125 Self::Leaf(leaf) => {
126 leaf.as_ref().encode(out);
127 }
128 Self::Branch(branch) => branch.encode(out),
129 Self::Extension(ext) => {
130 ext.encode(out);
131 }
132 }
133 }
134}
135
136impl Decodable for TrieNodeV2 {
137 fn decode(buf: &mut &[u8]) -> Result<Self, alloy_rlp::Error> {
138 match TrieNode::decode(buf)? {
139 TrieNode::EmptyRoot => Ok(Self::EmptyRoot),
140 TrieNode::Leaf(leaf) => Ok(Self::Leaf(leaf)),
141 TrieNode::Branch(branch) => Ok(Self::Branch(BranchNodeV2::new(
142 Default::default(),
143 branch.stack,
144 branch.state_mask,
145 None,
146 ))),
147 TrieNode::Extension(ext) => {
148 if ext.child.is_hash() {
149 Ok(Self::Extension(ext))
150 } else {
151 let Self::Branch(mut branch) = Self::decode(&mut ext.child.as_ref())? else {
152 return Err(alloy_rlp::Error::Custom(
153 "extension node child is not a branch",
154 ));
155 };
156
157 branch.key = ext.key;
158
159 Ok(Self::Branch(branch))
160 }
161 }
162 }
163 }
164}
165
166#[derive(PartialEq, Eq, Clone, Default)]
174#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175pub struct BranchNodeV2 {
176 pub key: Nibbles,
179 pub stack: Vec<RlpNode>,
181 pub state_mask: TrieMask,
183 pub branch_rlp_node: Option<RlpNode>,
186}
187
188impl fmt::Debug for BranchNodeV2 {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 f.debug_struct("BranchNode")
191 .field("key", &self.key)
192 .field("stack", &self.stack.iter().map(hex::encode).collect::<Vec<_>>())
193 .field("state_mask", &self.state_mask)
194 .field("branch_rlp_node", &self.branch_rlp_node)
195 .finish()
196 }
197}
198
199impl BranchNodeV2 {
200 pub const fn new(
202 key: Nibbles,
203 stack: Vec<RlpNode>,
204 state_mask: TrieMask,
205 branch_rlp_node: Option<RlpNode>,
206 ) -> Self {
207 Self { key, stack, state_mask, branch_rlp_node }
208 }
209}
210
211impl Encodable for BranchNodeV2 {
212 fn encode(&self, out: &mut dyn bytes::BufMut) {
213 if self.key.is_empty() {
214 BranchNodeRef::new(&self.stack, self.state_mask).encode(out);
215 return;
216 }
217
218 let branch_rlp_node = self
219 .branch_rlp_node
220 .as_ref()
221 .expect("branch_rlp_node must always be present for extension nodes");
222
223 ExtensionNodeRef::new(&self.key, branch_rlp_node.as_slice()).encode(out);
224 }
225
226 fn length(&self) -> usize {
227 if self.key.is_empty() {
228 return BranchNodeRef::new(&self.stack, self.state_mask).length()
229 }
230
231 let branch_rlp_node = self
232 .branch_rlp_node
233 .as_ref()
234 .expect("branch_rlp_node must always be present for extension nodes");
235
236 ExtensionNodeRef::new(&self.key, branch_rlp_node.as_slice()).length()
237 }
238}