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 core::mem;
9use reth_trie_common::{BranchNodeMasks, Nibbles, ProofTrieNodeV2, RlpNode, TrieNodeV2};
10use smallvec::SmallVec;
11use strum::AsRefStr;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
15pub(super) enum ArenaSparseNodeState {
16 Revealed,
18 Cached {
20 rlp_node: RlpNode,
22 was_dirty: bool,
25 },
26 Dirty,
28}
29
30impl ArenaSparseNodeState {
31 pub(super) const fn to_dirty(&self) -> Self {
33 Self::Dirty
34 }
35
36 pub(super) const fn cached_rlp_node(&self) -> Option<&RlpNode> {
38 match self {
39 Self::Cached { rlp_node, .. } => Some(rlp_node),
40 _ => None,
41 }
42 }
43
44 pub(super) fn take_cached_was_dirty(&mut self) -> bool {
46 match self {
47 Self::Cached { was_dirty, .. } => mem::take(was_dirty),
48 _ => false,
49 }
50 }
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
55pub(super) enum ArenaSparseNodeBranchChild {
56 Revealed(Index),
58 Blinded(RlpNode),
60}
61
62impl ArenaSparseNodeBranchChild {
63 pub(super) const fn is_blinded(&self) -> bool {
65 matches!(self, Self::Blinded(_))
66 }
67}
68
69#[derive(Debug, Clone)]
71pub(super) struct ArenaSparseNodeBranch {
72 pub(super) state: ArenaSparseNodeState,
74 pub(super) children: SmallVec<[ArenaSparseNodeBranchChild; 4]>,
77 pub(super) state_mask: TrieMask,
80 pub(super) short_key: Nibbles,
83 pub(super) branch_masks: BranchNodeMasks,
85}
86
87impl ArenaSparseNodeBranch {
88 pub(super) const fn unset_child_bit(&mut self, nibble: u8) {
90 self.state_mask.unset_bit(nibble);
91 }
92
93 pub(super) fn set_child(&mut self, nibble: u8, child: ArenaSparseNodeBranchChild) {
96 let insert_pos = BranchChildIdx::insertion_point(self.state_mask, nibble);
97 self.state_mask.set_bit(nibble);
98 self.children.insert(insert_pos.get(), child);
99 self.state = ArenaSparseNodeState::Dirty;
100 }
101
102 pub(super) fn remove_child(&mut self, nibble: u8) {
109 let child_idx =
110 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
111 self.children.remove(child_idx.get());
112 self.unset_child_bit(nibble);
113 self.state = ArenaSparseNodeState::Dirty;
114 }
115
116 pub(super) fn sibling_child(&self, nibble: u8) -> &ArenaSparseNodeBranchChild {
122 debug_assert_eq!(
123 self.state_mask.count_bits(),
124 2,
125 "sibling_child requires exactly 2 children"
126 );
127 let child_idx =
128 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
129 &self.children[1 - child_idx.get()]
131 }
132
133 pub(super) fn child_iter(
135 &self,
136 ) -> impl Iterator<Item = (u8, &ArenaSparseNodeBranchChild)> + '_ {
137 BranchChildIter::new(self.state_mask).map(|(idx, nibble)| (nibble, &self.children[idx]))
138 }
139
140 pub(super) fn branch_node_compact(&self, arena: &NodeArena) -> BranchNodeCompact {
142 let mut hashes = Vec::new();
143 for (nibble, child) in self.child_iter() {
144 if self.branch_masks.hash_mask.is_bit_set(nibble) {
145 let hash = match child {
146 ArenaSparseNodeBranchChild::Blinded(rlp_node) => {
147 rlp_node.as_hash().expect("blinded child must be a hash")
148 }
149 ArenaSparseNodeBranchChild::Revealed(child_idx) => {
150 arena[*child_idx].cached_hash()
151 }
152 };
153 hashes.push(hash);
154 }
155 }
156 BranchNodeCompact::new(
157 self.state_mask,
158 self.branch_masks.tree_mask,
159 self.branch_masks.hash_mask,
160 hashes,
161 None,
162 )
163 }
164}
165
166#[derive(Debug, Clone, AsRefStr)]
168pub(super) enum ArenaSparseNode {
169 EmptyRoot,
171 Branch(ArenaSparseNodeBranch),
173 Leaf {
175 state: ArenaSparseNodeState,
177 value: Vec<u8>,
179 key: Nibbles,
181 },
182 Subtrie(Box<ArenaSparseSubtrie>),
184 TakenSubtrie,
186}
187
188impl ArenaSparseNode {
189 pub(super) fn state_ref(&self) -> Option<&ArenaSparseNodeState> {
191 match self {
192 Self::Branch(b) => Some(&b.state),
193 Self::Leaf { state, .. } => Some(state),
194 Self::Subtrie(s) => s.arena[s.root].state_ref(),
195 _ => None,
196 }
197 }
198
199 pub(super) fn state_mut(&mut self) -> &mut ArenaSparseNodeState {
205 match self {
206 Self::Branch(b) => &mut b.state,
207 Self::Leaf { state, .. } => state,
208 _ => panic!("state_mut called on non-Branch/Leaf node"),
209 }
210 }
211
212 pub(super) fn is_cached(&self) -> bool {
214 self.state_ref().is_some_and(|s| matches!(s, ArenaSparseNodeState::Cached { .. }))
215 }
216
217 pub(super) const fn short_key(&self) -> Option<&Nibbles> {
219 match self {
220 Self::Branch(b) => Some(&b.short_key),
221 Self::Leaf { key, .. } => Some(key),
222 _ => None,
223 }
224 }
225
226 pub(super) fn branch_ref(&self) -> &ArenaSparseNodeBranch {
232 match self {
233 Self::Branch(b) => b,
234 _ => panic!("branch_ref called on non-Branch node {self:?}"),
235 }
236 }
237
238 pub(super) fn branch_mut(&mut self) -> &mut ArenaSparseNodeBranch {
244 match self {
245 Self::Branch(b) => b,
246 _ => panic!("branch_mut called on non-Branch node {self:?}"),
247 }
248 }
249
250 #[cfg(debug_assertions)]
252 pub(super) const fn as_subtrie(&self) -> Option<&ArenaSparseSubtrie> {
253 match self {
254 Self::Subtrie(s) => Some(s),
255 _ => None,
256 }
257 }
258
259 pub(super) fn as_branch(&self) -> Option<&ArenaSparseNodeBranch> {
261 match self {
262 Self::Branch(b) => Some(b),
263 Self::Subtrie(s) => s.arena[s.root].as_branch(),
264 _ => None,
265 }
266 }
267
268 pub(super) fn hash_mask_bit(&self) -> bool {
274 self.as_branch().is_some_and(|b| {
275 b.short_key.is_empty() &&
276 b.state.cached_rlp_node().expect("branch's RlpNode must be cached").is_hash()
277 })
278 }
279
280 pub(super) fn tree_mask_bit(&self) -> bool {
284 self.as_branch().is_some_and(|b| !b.branch_masks.is_empty())
285 }
286
287 pub(super) fn cached_hash(&self) -> B256 {
293 let rlp_node = match self {
294 Self::Branch(ArenaSparseNodeBranch { state, .. }) | Self::Leaf { state, .. } => state
295 .cached_rlp_node()
296 .expect("cached_hash called on non-Cached branch or leaf: {self:?}"),
297 Self::Subtrie(s) => return s.arena[s.root].cached_hash(),
298 _ => panic!("cached_hash called on {self:?}"),
299 };
300 rlp_node.as_hash().unwrap_or_else(|| keccak256(rlp_node.as_slice()))
301 }
302}
303
304impl ArenaSparseNode {
305 pub(super) fn from_proof_node(proof_node: ProofTrieNodeV2) -> Self {
312 let ProofTrieNodeV2 { node, masks, .. } = proof_node;
313 match node {
314 TrieNodeV2::EmptyRoot => Self::EmptyRoot,
315 TrieNodeV2::Leaf(leaf) => Self::Leaf {
316 state: ArenaSparseNodeState::Revealed,
317 key: leaf.key,
318 value: leaf.value,
319 },
320 TrieNodeV2::Branch(branch) => {
321 let children = branch.stack[..branch.state_mask.count_bits() as usize]
322 .iter()
323 .map(|rlp| ArenaSparseNodeBranchChild::Blinded(rlp.clone()))
324 .collect();
325 Self::Branch(ArenaSparseNodeBranch {
326 state: ArenaSparseNodeState::Revealed,
327 children,
328 state_mask: branch.state_mask,
329 short_key: branch.key,
330 branch_masks: masks.unwrap_or_default(),
331 })
332 }
333 TrieNodeV2::Extension(_) => {
334 panic!("Extension nodes should be merged into branches by TrieNodeV2")
335 }
336 }
337 }
338
339 pub(super) fn extra_heap_bytes(&self) -> usize {
341 match self {
342 Self::Leaf { value, .. } => value.capacity(),
343 Self::Branch(b) if b.children.spilled() => {
344 b.children.capacity() * core::mem::size_of::<ArenaSparseNodeBranchChild>()
345 }
346 _ => 0,
347 }
348 }
349}