1use super::{
2 branch_child_idx::{BranchChildIdx, BranchChildIter},
3 ArenaSparseSubtrie, Index, NodeArena,
4};
5use alloc::{boxed::Box, vec::Vec};
6use alloy_primitives::{keccak256, B256};
7use alloy_trie::{BranchNodeCompact, TrieMask};
8use reth_trie_common::{BranchNodeMasks, Nibbles, ProofTrieNodeV2, RlpNode, TrieNodeV2};
9use smallvec::SmallVec;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub(super) enum ArenaSparseNodeState {
14 Revealed,
16 Cached {
18 rlp_node: RlpNode,
20 },
21 Dirty,
23}
24
25impl ArenaSparseNodeState {
26 pub(super) const fn to_dirty(&self) -> Self {
28 Self::Dirty
29 }
30
31 pub(super) const fn cached_rlp_node(&self) -> Option<&RlpNode> {
33 match self {
34 Self::Cached { rlp_node, .. } => Some(rlp_node),
35 _ => None,
36 }
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
42pub(super) enum ArenaSparseNodeBranchChild {
43 Revealed(Index),
45 Blinded(RlpNode),
47}
48
49impl ArenaSparseNodeBranchChild {
50 pub(super) const fn is_blinded(&self) -> bool {
52 matches!(self, Self::Blinded(_))
53 }
54}
55
56#[derive(Debug, Clone)]
58pub(super) struct ArenaSparseNodeBranch {
59 pub(super) state: ArenaSparseNodeState,
61 pub(super) children: SmallVec<[ArenaSparseNodeBranchChild; 4]>,
64 pub(super) state_mask: TrieMask,
67 pub(super) short_key: Nibbles,
70 pub(super) branch_masks: BranchNodeMasks,
72}
73
74impl ArenaSparseNodeBranch {
75 pub(super) const fn unset_child_bit(&mut self, nibble: u8) {
77 self.state_mask.unset_bit(nibble);
78 }
79
80 pub(super) fn set_child(&mut self, nibble: u8, child: ArenaSparseNodeBranchChild) {
83 let insert_pos = BranchChildIdx::insertion_point(self.state_mask, nibble);
84 self.state_mask.set_bit(nibble);
85 self.children.insert(insert_pos.get(), child);
86 self.state = ArenaSparseNodeState::Dirty;
87 }
88
89 pub(super) fn remove_child(&mut self, nibble: u8) {
96 let child_idx =
97 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
98 self.children.remove(child_idx.get());
99 self.unset_child_bit(nibble);
100 self.state = ArenaSparseNodeState::Dirty;
101 }
102
103 pub(super) fn sibling_child(&self, nibble: u8) -> &ArenaSparseNodeBranchChild {
109 debug_assert_eq!(
110 self.state_mask.count_bits(),
111 2,
112 "sibling_child requires exactly 2 children"
113 );
114 let child_idx =
115 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
116 &self.children[1 - child_idx.get()]
118 }
119
120 pub(super) fn child_iter(
122 &self,
123 ) -> impl Iterator<Item = (u8, &ArenaSparseNodeBranchChild)> + '_ {
124 BranchChildIter::new(self.state_mask).map(|(idx, nibble)| (nibble, &self.children[idx]))
125 }
126
127 pub(super) fn branch_node_compact(&self, arena: &NodeArena) -> BranchNodeCompact {
129 let mut hashes = Vec::new();
130 for (nibble, child) in self.child_iter() {
131 if self.branch_masks.hash_mask.is_bit_set(nibble) {
132 let hash = match child {
133 ArenaSparseNodeBranchChild::Blinded(rlp_node) => {
134 rlp_node.as_hash().expect("blinded child must be a hash")
135 }
136 ArenaSparseNodeBranchChild::Revealed(child_idx) => {
137 arena[*child_idx].cached_hash()
138 }
139 };
140 hashes.push(hash);
141 }
142 }
143 BranchNodeCompact::new(
144 self.state_mask,
145 self.branch_masks.tree_mask,
146 self.branch_masks.hash_mask,
147 hashes,
148 None,
149 )
150 }
151}
152
153#[derive(Debug, Clone)]
155pub(super) enum ArenaSparseNode {
156 EmptyRoot,
158 Branch(ArenaSparseNodeBranch),
160 Leaf {
162 state: ArenaSparseNodeState,
164 value: Vec<u8>,
166 key: Nibbles,
168 },
169 Subtrie(Box<ArenaSparseSubtrie>),
171 TakenSubtrie,
173}
174
175impl ArenaSparseNode {
176 pub(super) fn state_ref(&self) -> Option<&ArenaSparseNodeState> {
178 match self {
179 Self::Branch(b) => Some(&b.state),
180 Self::Leaf { state, .. } => Some(state),
181 Self::Subtrie(s) => s.arena[s.root].state_ref(),
182 _ => None,
183 }
184 }
185
186 pub(super) fn state_mut(&mut self) -> &mut ArenaSparseNodeState {
192 match self {
193 Self::Branch(b) => &mut b.state,
194 Self::Leaf { state, .. } => state,
195 _ => panic!("state_mut called on non-Branch/Leaf node"),
196 }
197 }
198
199 pub(super) fn is_cached(&self) -> bool {
201 self.state_ref().is_some_and(|s| matches!(s, ArenaSparseNodeState::Cached { .. }))
202 }
203
204 pub(super) const fn short_key(&self) -> Option<&Nibbles> {
206 match self {
207 Self::Branch(b) => Some(&b.short_key),
208 Self::Leaf { key, .. } => Some(key),
209 _ => None,
210 }
211 }
212
213 pub(super) fn branch_ref(&self) -> &ArenaSparseNodeBranch {
219 match self {
220 Self::Branch(b) => b,
221 _ => panic!("branch_ref called on non-Branch node {self:?}"),
222 }
223 }
224
225 pub(super) fn branch_mut(&mut self) -> &mut ArenaSparseNodeBranch {
231 match self {
232 Self::Branch(b) => b,
233 _ => panic!("branch_mut called on non-Branch node {self:?}"),
234 }
235 }
236
237 #[cfg(debug_assertions)]
239 pub(super) const fn as_subtrie(&self) -> Option<&ArenaSparseSubtrie> {
240 match self {
241 Self::Subtrie(s) => Some(s),
242 _ => None,
243 }
244 }
245
246 pub(super) fn as_branch(&self) -> Option<&ArenaSparseNodeBranch> {
248 match self {
249 Self::Branch(b) => Some(b),
250 Self::Subtrie(s) => s.arena[s.root].as_branch(),
251 _ => None,
252 }
253 }
254
255 pub(super) fn hash_mask_bit(&self) -> bool {
261 self.as_branch().is_some_and(|b| {
262 b.short_key.is_empty() &&
263 b.state.cached_rlp_node().expect("branch's RlpNode must be cached").is_hash()
264 })
265 }
266
267 pub(super) fn tree_mask_bit(&self) -> bool {
271 self.as_branch().is_some_and(|b| !b.branch_masks.is_empty())
272 }
273
274 pub(super) fn cached_hash(&self) -> B256 {
280 let rlp_node = match self {
281 Self::Branch(ArenaSparseNodeBranch { state, .. }) | Self::Leaf { state, .. } => state
282 .cached_rlp_node()
283 .expect("cached_hash called on non-Cached branch or leaf: {self:?}"),
284 Self::Subtrie(s) => return s.arena[s.root].cached_hash(),
285 _ => panic!("cached_hash called on {self:?}"),
286 };
287 rlp_node.as_hash().unwrap_or_else(|| keccak256(rlp_node.as_slice()))
288 }
289}
290
291impl ArenaSparseNode {
292 pub(super) fn from_proof_node(proof_node: ProofTrieNodeV2) -> Self {
299 let ProofTrieNodeV2 { node, masks, .. } = proof_node;
300 match node {
301 TrieNodeV2::EmptyRoot => Self::EmptyRoot,
302 TrieNodeV2::Leaf(leaf) => Self::Leaf {
303 state: ArenaSparseNodeState::Revealed,
304 key: leaf.key,
305 value: leaf.value,
306 },
307 TrieNodeV2::Branch(branch) => {
308 let children = branch.stack[..branch.state_mask.count_bits() as usize]
309 .iter()
310 .map(|rlp| ArenaSparseNodeBranchChild::Blinded(rlp.clone()))
311 .collect();
312 Self::Branch(ArenaSparseNodeBranch {
313 state: ArenaSparseNodeState::Revealed,
314 children,
315 state_mask: branch.state_mask,
316 short_key: branch.key,
317 branch_masks: masks.unwrap_or_default(),
318 })
319 }
320 TrieNodeV2::Extension(_) => {
321 panic!("Extension nodes should be merged into branches by TrieNodeV2")
322 }
323 }
324 }
325
326 pub(super) fn extra_heap_bytes(&self) -> usize {
328 match self {
329 Self::Leaf { value, .. } => value.capacity(),
330 Self::Branch(b) if b.children.spilled() => {
331 b.children.capacity() * core::mem::size_of::<ArenaSparseNodeBranchChild>()
332 }
333 _ => 0,
334 }
335 }
336}