1use super::{
2 branch_child_idx::{BranchChildIdx, BranchChildIter},
3 ArenaSparseSubtrie, BranchChild, 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;
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) branch_masks: BranchNodeMasks,
67}
68
69impl ArenaSparseNodeBranch {
70 pub(super) const fn unset_child_bit(&mut self, nibble: u8) {
72 self.state_mask.unset_bit(nibble);
73 }
74
75 pub(super) fn set_child(&mut self, nibble: u8, child: BranchChild) {
78 let insert_pos = BranchChildIdx::insertion_point(self.state_mask, nibble);
79 self.state_mask.set_bit(nibble);
80 self.children.insert(insert_pos.get(), child);
81 self.state = ArenaSparseNodeState::Dirty;
82 }
83
84 pub(super) fn remove_child(&mut self, nibble: u8) {
91 let child_idx =
92 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
93 self.children.remove(child_idx.get());
94 self.unset_child_bit(nibble);
95 self.state = ArenaSparseNodeState::Dirty;
96 }
97
98 pub(super) fn sibling_child(&self, nibble: u8) -> BranchChild {
104 debug_assert_eq!(
105 self.state_mask.count_bits(),
106 2,
107 "sibling_child requires exactly 2 children"
108 );
109 let child_idx =
110 BranchChildIdx::new(self.state_mask, nibble).expect("nibble not found in state_mask");
111 self.children[1 - child_idx.get()]
113 }
114
115 pub(super) fn child_iter(&self) -> impl Iterator<Item = (u8, BranchChild)> + '_ {
117 BranchChildIter::new(self.state_mask).map(|(idx, nibble)| (nibble, self.children[idx]))
118 }
119
120 pub(super) fn branch_node_compact(&self, arena: &NodeArena) -> BranchNodeCompact {
122 let mut hashes = Vec::with_capacity(self.branch_masks.hash_mask.count_bits() as usize);
123 for (nibble, child) in self.child_iter() {
124 if self.branch_masks.hash_mask.is_bit_set(nibble) {
125 let hash = match child.revealed_index() {
126 Some(child_idx) => arena[child_idx].cached_hash(),
127 None => arena.blinded(child).as_hash().expect("blinded child must be a hash"),
128 };
129 hashes.push(hash);
130 }
131 }
132 BranchNodeCompact::new(
133 self.state_mask,
134 self.branch_masks.tree_mask,
135 self.branch_masks.hash_mask,
136 hashes,
137 None,
138 )
139 }
140}
141
142#[derive(Debug, Clone, AsRefStr)]
144pub(super) enum ArenaSparseNode {
145 EmptyRoot {
147 state: ArenaSparseNodeState,
149 },
150 Branch(ArenaSparseNodeBranch),
152 Extension {
154 key: Nibbles,
156 child: Index,
158 },
159 Leaf {
161 state: ArenaSparseNodeState,
163 value: Vec<u8>,
165 key: Nibbles,
167 },
168 Subtrie(Box<ArenaSparseSubtrie>),
170 TakenSubtrie,
172 Free,
176}
177
178impl ArenaSparseNode {
179 pub(super) fn state_ref(&self) -> Option<&ArenaSparseNodeState> {
182 match self {
183 Self::EmptyRoot { state } | Self::Leaf { state, .. } => Some(state),
184 Self::Branch(b) => Some(&b.state),
185 Self::Subtrie(s) => {
186 let root = &s.arena[s.root];
187 root.extension_child()
188 .and_then(|child| s.arena[child].state_ref())
189 .or_else(|| root.state_ref())
190 }
191 _ => None,
192 }
193 }
194
195 pub(super) fn state_mut(&mut self) -> &mut ArenaSparseNodeState {
201 match self {
202 Self::EmptyRoot { state } | Self::Leaf { state, .. } => state,
203 Self::Branch(b) => &mut b.state,
204 _ => panic!("state_mut called on non-EmptyRoot/Branch/Leaf node"),
205 }
206 }
207
208 pub(super) fn is_cached(&self) -> bool {
210 self.state_ref().is_some_and(|s| matches!(s, ArenaSparseNodeState::Cached { .. }))
211 }
212
213 pub(super) const fn short_key(&self) -> Option<&Nibbles> {
215 match self {
216 Self::Extension { key, .. } | Self::Leaf { key, .. } => Some(key),
217 _ => None,
218 }
219 }
220
221 pub(super) const fn extension_key(&self) -> Option<&Nibbles> {
223 match self {
224 Self::Extension { key, .. } => Some(key),
225 _ => None,
226 }
227 }
228
229 pub(super) const fn extension_child(&self) -> Option<Index> {
231 match self {
232 Self::Extension { child, .. } => Some(*child),
233 _ => None,
234 }
235 }
236
237 pub(super) fn branch_ref(&self) -> &ArenaSparseNodeBranch {
243 match self {
244 Self::Branch(b) => b,
245 _ => panic!("branch_ref called on non-Branch node {self:?}"),
246 }
247 }
248
249 pub(super) fn branch_mut(&mut self) -> &mut ArenaSparseNodeBranch {
255 match self {
256 Self::Branch(b) => b,
257 _ => panic!("branch_mut called on non-Branch node {self:?}"),
258 }
259 }
260
261 #[cfg(all(debug_assertions, not(feature = "fuzz")))]
263 pub(super) const fn as_subtrie(&self) -> Option<&ArenaSparseSubtrie> {
264 match self {
265 Self::Subtrie(s) => Some(s),
266 _ => None,
267 }
268 }
269
270 pub(super) fn hash_mask_bit(&self) -> bool {
275 match self {
276 Self::Branch(b) => {
277 b.state.cached_rlp_node().expect("branch's RlpNode must be cached").is_hash()
278 }
279 Self::Subtrie(s) => s.arena[s.root].hash_mask_bit(),
280 _ => false,
281 }
282 }
283
284 pub(super) fn cached_hash(&self) -> B256 {
290 let rlp_node = match self {
291 Self::Branch(ArenaSparseNodeBranch { state, .. }) | Self::Leaf { state, .. } => state
292 .cached_rlp_node()
293 .expect("cached_hash called on non-Cached branch or leaf: {self:?}"),
294 Self::Subtrie(s) => return s.arena[s.root].cached_hash(),
295 _ => panic!("cached_hash called on {self:?}"),
296 };
297 rlp_node.as_hash().unwrap_or_else(|| keccak256(rlp_node.as_slice()))
298 }
299}
300
301impl ArenaSparseNode {
302 pub(super) fn from_proof_node(arena: &mut NodeArena, proof_node: ProofTrieNodeV2) -> Self {
310 let ProofTrieNodeV2 { node, masks, .. } = proof_node;
311 match node {
312 TrieNodeV2::EmptyRoot => Self::EmptyRoot { state: ArenaSparseNodeState::Revealed },
313 TrieNodeV2::Leaf(leaf) => Self::Leaf {
314 state: ArenaSparseNodeState::Revealed,
315 key: leaf.key,
316 value: leaf.value,
317 },
318 TrieNodeV2::Branch(branch) => {
319 assert!(branch.key.is_empty(), "branches with a short key must be split first");
320 let children = branch.stack[..branch.state_mask.count_bits() as usize]
321 .iter()
322 .map(|rlp| arena.insert_blinded(rlp.clone()))
323 .collect();
324 Self::Branch(ArenaSparseNodeBranch {
325 state: ArenaSparseNodeState::Revealed,
326 children,
327 state_mask: branch.state_mask,
328 branch_masks: masks.unwrap_or_default(),
329 })
330 }
331 TrieNodeV2::Extension(_) => {
332 panic!("Extension nodes should be merged into branches by TrieNodeV2")
333 }
334 }
335 }
336}