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;
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, 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 state: ArenaSparseNodeState,
173 },
174 Branch(ArenaSparseNodeBranch),
176 Leaf {
178 state: ArenaSparseNodeState,
180 value: Vec<u8>,
182 key: Nibbles,
184 },
185 Subtrie(Box<ArenaSparseSubtrie>),
187 TakenSubtrie,
189}
190
191impl ArenaSparseNode {
192 pub(super) fn state_ref(&self) -> Option<&ArenaSparseNodeState> {
195 match self {
196 Self::EmptyRoot { state } | Self::Leaf { state, .. } => Some(state),
197 Self::Branch(b) => Some(&b.state),
198 Self::Subtrie(s) => s.arena[s.root].state_ref(),
199 _ => None,
200 }
201 }
202
203 pub(super) fn state_mut(&mut self) -> &mut ArenaSparseNodeState {
209 match self {
210 Self::EmptyRoot { state } | Self::Leaf { state, .. } => state,
211 Self::Branch(b) => &mut b.state,
212 _ => panic!("state_mut called on non-EmptyRoot/Branch/Leaf node"),
213 }
214 }
215
216 pub(super) fn is_cached(&self) -> bool {
218 self.state_ref().is_some_and(|s| matches!(s, ArenaSparseNodeState::Cached { .. }))
219 }
220
221 pub(super) const fn short_key(&self) -> Option<&Nibbles> {
223 match self {
224 Self::Branch(b) => Some(&b.short_key),
225 Self::Leaf { key, .. } => Some(key),
226 _ => None,
227 }
228 }
229
230 pub(super) fn branch_ref(&self) -> &ArenaSparseNodeBranch {
236 match self {
237 Self::Branch(b) => b,
238 _ => panic!("branch_ref called on non-Branch node {self:?}"),
239 }
240 }
241
242 pub(super) fn branch_mut(&mut self) -> &mut ArenaSparseNodeBranch {
248 match self {
249 Self::Branch(b) => b,
250 _ => panic!("branch_mut called on non-Branch node {self:?}"),
251 }
252 }
253
254 #[cfg(debug_assertions)]
256 pub(super) const fn as_subtrie(&self) -> Option<&ArenaSparseSubtrie> {
257 match self {
258 Self::Subtrie(s) => Some(s),
259 _ => None,
260 }
261 }
262
263 pub(super) fn as_branch(&self) -> Option<&ArenaSparseNodeBranch> {
265 match self {
266 Self::Branch(b) => Some(b),
267 Self::Subtrie(s) => s.arena[s.root].as_branch(),
268 _ => None,
269 }
270 }
271
272 pub(super) fn hash_mask_bit(&self) -> bool {
278 self.as_branch().is_some_and(|b| {
279 b.short_key.is_empty() &&
280 b.state.cached_rlp_node().expect("branch's RlpNode must be cached").is_hash()
281 })
282 }
283
284 pub(super) fn tree_mask_bit(&self) -> bool {
288 self.as_branch().is_some_and(|b| !b.branch_masks.is_empty())
289 }
290
291 pub(super) fn cached_hash(&self) -> B256 {
297 let rlp_node = match self {
298 Self::Branch(ArenaSparseNodeBranch { state, .. }) | Self::Leaf { state, .. } => state
299 .cached_rlp_node()
300 .expect("cached_hash called on non-Cached branch or leaf: {self:?}"),
301 Self::Subtrie(s) => return s.arena[s.root].cached_hash(),
302 _ => panic!("cached_hash called on {self:?}"),
303 };
304 rlp_node.as_hash().unwrap_or_else(|| keccak256(rlp_node.as_slice()))
305 }
306}
307
308impl ArenaSparseNode {
309 pub(super) fn from_proof_node(proof_node: ProofTrieNodeV2) -> Self {
316 let ProofTrieNodeV2 { node, masks, .. } = proof_node;
317 match node {
318 TrieNodeV2::EmptyRoot => Self::EmptyRoot { state: ArenaSparseNodeState::Revealed },
319 TrieNodeV2::Leaf(leaf) => Self::Leaf {
320 state: ArenaSparseNodeState::Revealed,
321 key: leaf.key,
322 value: leaf.value,
323 },
324 TrieNodeV2::Branch(branch) => {
325 let children = branch.stack[..branch.state_mask.count_bits() as usize]
326 .iter()
327 .map(|rlp| ArenaSparseNodeBranchChild::Blinded(rlp.clone()))
328 .collect();
329 Self::Branch(ArenaSparseNodeBranch {
330 state: ArenaSparseNodeState::Revealed,
331 children,
332 state_mask: branch.state_mask,
333 short_key: branch.key,
334 branch_masks: masks.unwrap_or_default(),
335 })
336 }
337 TrieNodeV2::Extension(_) => {
338 panic!("Extension nodes should be merged into branches by TrieNodeV2")
339 }
340 }
341 }
342}