1use super::{
2 branch_child_idx::{BranchChildIdx, BranchChildIter},
3 ArenaSparseSubtrie, BranchChild, 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;
10use strum::AsRefStr;
11
12use crate::TrieNodeEpoch;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub(super) enum ArenaSparseNodeState {
17 Revealed,
19 Cached {
21 rlp_node: RlpNode,
23 epoch: TrieNodeEpoch,
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) const fn cached_epoch(&self) -> Option<TrieNodeEpoch> {
46 match self {
47 Self::Cached { epoch, .. } => Some(*epoch),
48 _ => None,
49 }
50 }
51}
52
53#[derive(Debug, Clone)]
55pub(super) struct ArenaSparseNodeBranch {
56 pub(super) state: ArenaSparseNodeState,
58 pub(super) children: SmallVec<[BranchChild; 16]>,
62 pub(super) state_mask: TrieMask,
65 pub(super) short_key: Nibbles,
68 pub(super) branch_masks: BranchNodeMasks,
70}
71
72impl ArenaSparseNodeBranch {
73 pub(super) const fn unset_child_bit(&mut self, nibble: u8) {
75 self.state_mask.unset_bit(nibble);
76 }
77
78 pub(super) fn set_child(&mut self, nibble: u8, child: BranchChild) {
81 let insert_pos = BranchChildIdx::insertion_point(self.state_mask, nibble);
82 self.state_mask.set_bit(nibble);
83 self.children.insert(insert_pos.get(), child);
84 self.state = ArenaSparseNodeState::Dirty;
85 }
86
87 pub(super) fn remove_child(&mut self, nibble: u8) {
94 let child_idx =
95 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
96 self.children.remove(child_idx.get());
97 self.unset_child_bit(nibble);
98 self.state = ArenaSparseNodeState::Dirty;
99 }
100
101 pub(super) fn sibling_child(&self, nibble: u8) -> BranchChild {
107 debug_assert_eq!(
108 self.state_mask.count_bits(),
109 2,
110 "sibling_child requires exactly 2 children"
111 );
112 let child_idx =
113 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
114 self.children[1 - child_idx.get()]
116 }
117
118 pub(super) fn child_iter(&self) -> impl Iterator<Item = (u8, BranchChild)> + '_ {
120 BranchChildIter::new(self.state_mask).map(|(idx, nibble)| (nibble, self.children[idx]))
121 }
122
123 pub(super) fn branch_node_compact(&self, arena: &NodeArena) -> BranchNodeCompact {
125 let mut hashes = Vec::with_capacity(self.branch_masks.hash_mask.count_bits() as usize);
126 for (nibble, child) in self.child_iter() {
127 if self.branch_masks.hash_mask.is_bit_set(nibble) {
128 let hash = match child.revealed_index() {
129 Some(child_idx) => arena[child_idx].cached_hash(),
130 None => arena.blinded(child).as_hash().expect("blinded child must be a hash"),
131 };
132 hashes.push(hash);
133 }
134 }
135 BranchNodeCompact::new(
136 self.state_mask,
137 self.branch_masks.tree_mask,
138 self.branch_masks.hash_mask,
139 hashes,
140 None,
141 )
142 }
143}
144
145#[derive(Debug, Clone, AsRefStr)]
147pub(super) enum ArenaSparseNode {
148 EmptyRoot {
150 state: ArenaSparseNodeState,
152 },
153 Branch(ArenaSparseNodeBranch),
155 Leaf {
157 state: ArenaSparseNodeState,
159 value: Vec<u8>,
161 key: Nibbles,
163 },
164 Subtrie(Box<ArenaSparseSubtrie>),
166 TakenSubtrie,
168 Free,
172}
173
174impl ArenaSparseNode {
175 pub(super) fn state_ref(&self) -> Option<&ArenaSparseNodeState> {
178 match self {
179 Self::EmptyRoot { state } | Self::Leaf { state, .. } => Some(state),
180 Self::Branch(b) => Some(&b.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::EmptyRoot { state } | Self::Leaf { state, .. } => state,
194 Self::Branch(b) => &mut b.state,
195 _ => panic!("state_mut called on non-EmptyRoot/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(all(debug_assertions, not(feature = "dst")))]
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(arena: &mut NodeArena, proof_node: ProofTrieNodeV2) -> Self {
300 let ProofTrieNodeV2 { node, masks, .. } = proof_node;
301 match node {
302 TrieNodeV2::EmptyRoot => Self::EmptyRoot { state: ArenaSparseNodeState::Revealed },
303 TrieNodeV2::Leaf(leaf) => Self::Leaf {
304 state: ArenaSparseNodeState::Revealed,
305 key: leaf.key,
306 value: leaf.value,
307 },
308 TrieNodeV2::Branch(branch) => {
309 let children = branch.stack[..branch.state_mask.count_bits() as usize]
310 .iter()
311 .map(|rlp| arena.insert_blinded(rlp.clone()))
312 .collect();
313 Self::Branch(ArenaSparseNodeBranch {
314 state: ArenaSparseNodeState::Revealed,
315 children,
316 state_mask: branch.state_mask,
317 short_key: branch.key,
318 branch_masks: masks.unwrap_or_default(),
319 })
320 }
321 TrieNodeV2::Extension(_) => {
322 panic!("Extension nodes should be merged into branches by TrieNodeV2")
323 }
324 }
325 }
326}