1use super::{
4 BranchNodeCompact, EMPTY_ROOT_HASH, Nibbles, TrieMask,
5 nodes::{BranchNodeRef, ExtensionNodeRef, LeafNodeRef},
6 proof::{ProofNodes, ProofRetainer},
7};
8use crate::{HashMap, nodes::RlpNode, proof::AddedRemovedKeys};
9use alloc::vec::Vec;
10use alloy_primitives::{B256, keccak256};
11use core::cmp;
12use tracing::trace;
13
14mod value;
15pub use value::{HashBuilderValue, HashBuilderValueRef};
16
17#[derive(Debug, Clone)]
42#[allow(missing_docs)]
43pub struct HashBuilder<K = AddedRemovedKeys> {
44 pub key: Nibbles,
45 pub value: HashBuilderValue,
46 pub stack: Vec<RlpNode>,
47
48 pub state_masks: Vec<TrieMask>,
49 pub tree_masks: Vec<TrieMask>,
50 pub hash_masks: Vec<TrieMask>,
51
52 pub stored_in_database: bool,
53
54 pub updated_branch_nodes: Option<HashMap<Nibbles, BranchNodeCompact>>,
55 pub proof_retainer: Option<ProofRetainer<K>>,
56
57 pub rlp_buf: Vec<u8>,
58}
59
60impl Default for HashBuilder {
61 fn default() -> Self {
62 Self {
63 key: Default::default(),
64 value: Default::default(),
65 stack: Default::default(),
66 state_masks: Default::default(),
67 tree_masks: Default::default(),
68 hash_masks: Default::default(),
69 stored_in_database: Default::default(),
70 updated_branch_nodes: None,
71 proof_retainer: None,
72 rlp_buf: Default::default(),
73 }
74 }
75}
76
77impl<K> HashBuilder<K> {
78 pub fn with_updates(mut self, retain_updates: bool) -> Self {
82 self.set_updates(retain_updates);
83 self
84 }
85
86 pub fn with_proof_retainer<K2>(self, retainer: ProofRetainer<K2>) -> HashBuilder<K2> {
88 HashBuilder {
89 key: self.key,
90 value: self.value,
91 stack: self.stack,
92 state_masks: self.state_masks,
93 tree_masks: self.tree_masks,
94 hash_masks: self.hash_masks,
95 stored_in_database: self.stored_in_database,
96 updated_branch_nodes: self.updated_branch_nodes,
97 proof_retainer: Some(retainer),
98 rlp_buf: self.rlp_buf,
99 }
100 }
101
102 pub fn set_updates(&mut self, retain_updates: bool) {
106 if retain_updates {
107 self.updated_branch_nodes = Some(HashMap::default());
108 }
109 }
110}
111
112impl<K: AsRef<AddedRemovedKeys>> HashBuilder<K> {
113 pub fn split(mut self) -> (Self, HashMap<Nibbles, BranchNodeCompact>) {
115 let updates = self.updated_branch_nodes.take();
116 (self, updates.unwrap_or_default())
117 }
118
119 pub fn take_proof_nodes(&mut self) -> ProofNodes {
121 self.proof_retainer.take().map(ProofRetainer::into_proof_nodes).unwrap_or_default()
122 }
123
124 pub fn updates_len(&self) -> usize {
127 self.updated_branch_nodes.as_ref().map(|u| u.len()).unwrap_or(0)
128 }
129
130 #[cfg(feature = "std")]
132 pub fn print_stack(&self) {
133 println!("============ STACK ===============");
134 for item in &self.stack {
135 println!("{}", alloy_primitives::hex::encode(item));
136 }
137 println!("============ END STACK ===============");
138 }
139
140 pub fn add_leaf(&mut self, key: Nibbles, value: &[u8]) {
146 assert!(key > self.key, "add_leaf key {:?} self.key {:?}", key, self.key);
147 self.add_leaf_unchecked(key, value);
148 }
149
150 pub fn add_leaf_unchecked(&mut self, key: Nibbles, value: &[u8]) {
155 debug_assert!(key > self.key, "add_leaf_unchecked key {:?} self.key {:?}", key, self.key);
156 if !self.key.is_empty() {
157 self.update(&key);
158 }
159 self.set_key_value(key, HashBuilderValueRef::Bytes(value));
160 }
161
162 pub fn add_branch(&mut self, key: Nibbles, value: B256, stored_in_database: bool) {
164 assert!(
165 key > self.key || (self.key.is_empty() && key.is_empty()),
166 "add_branch key {:?} self.key {:?}",
167 key,
168 self.key
169 );
170 if !self.key.is_empty() {
171 self.update(&key);
172 } else if key.is_empty() {
173 self.stack.push(RlpNode::word_rlp(&value));
174 }
175 self.set_key_value(key, HashBuilderValueRef::Hash(&value));
176 self.stored_in_database = stored_in_database;
177 }
178
179 pub fn root(&mut self) -> B256 {
181 if !self.key.is_empty() {
183 self.update(&Nibbles::default());
184 self.key.clear();
185 self.value.clear();
186 }
187 let root = self.current_root();
188 if root == EMPTY_ROOT_HASH {
189 if let Some(proof_retainer) = self.proof_retainer.as_mut() {
190 proof_retainer.retain_empty_root_proof();
191 }
192 }
193 root
194 }
195
196 #[inline]
197 fn set_key_value(&mut self, key: Nibbles, value: HashBuilderValueRef<'_>) {
198 self.log_key_value("old value");
199 self.key = key;
200 self.value.set_from_ref(value);
201 self.log_key_value("new value");
202 }
203
204 fn log_key_value(&self, msg: &str) {
205 trace!(target: "trie::hash_builder",
206 key = ?self.key,
207 value = ?self.value,
208 "{msg}",
209 );
210 }
211
212 fn current_root(&self) -> B256 {
213 if let Some(node_ref) = self.stack.last() {
214 if let Some(hash) = node_ref.as_hash() { hash } else { keccak256(node_ref) }
215 } else {
216 EMPTY_ROOT_HASH
217 }
218 }
219
220 fn update(&mut self, succeeding: &Nibbles) {
225 let mut build_extensions = false;
226 let mut current = self.key;
228 debug_assert!(!current.is_empty());
229
230 trace!(target: "trie::hash_builder", ?current, ?succeeding, "updating merkle tree");
231
232 let mut i = 0usize;
233 loop {
234 let _span = tracing::trace_span!(target: "trie::hash_builder", "loop", i, ?current, build_extensions).entered();
235
236 let preceding_exists = !self.state_masks.is_empty();
237 let preceding_len = self.state_masks.len().saturating_sub(1);
238
239 let common_prefix_len = succeeding.common_prefix_length(¤t);
240 let len = cmp::max(preceding_len, common_prefix_len);
241 assert!(len < current.len(), "len {} current.len {}", len, current.len());
242
243 trace!(
244 target: "trie::hash_builder",
245 ?len,
246 ?common_prefix_len,
247 ?preceding_len,
248 preceding_exists,
249 "prefix lengths after comparing keys"
250 );
251
252 let extra_digit = current.get_unchecked(len);
254 if self.state_masks.len() <= len {
255 let new_len = len + 1;
256 trace!(target: "trie::hash_builder", new_len, old_len = self.state_masks.len(), "scaling state masks to fit");
257 self.state_masks.resize(new_len, TrieMask::default());
258 }
259 self.state_masks[len] |= TrieMask::from_nibble(extra_digit);
260 trace!(
261 target: "trie::hash_builder",
262 ?extra_digit,
263 state_masks = ?self.state_masks,
264 );
265
266 if self.tree_masks.len() < current.len() {
268 self.resize_masks(current.len());
269 }
270
271 let mut len_from = len;
272 if !succeeding.is_empty() || preceding_exists {
273 len_from += 1;
274 }
275 trace!(target: "trie::hash_builder", "skipping {len_from} nibbles");
276
277 let short_node_key = current.slice(len_from..);
279 trace!(target: "trie::hash_builder", ?short_node_key);
280
281 if !build_extensions {
283 match self.value.as_ref() {
284 HashBuilderValueRef::Bytes(leaf_value) => {
285 let leaf_node = LeafNodeRef::new(&short_node_key, leaf_value);
286 self.rlp_buf.clear();
287 let rlp = leaf_node.rlp(&mut self.rlp_buf);
288
289 let path = current.slice(..len_from);
290 trace!(
291 target: "trie::hash_builder",
292 ?path,
293 ?leaf_node,
294 ?rlp,
295 "pushing leaf node",
296 );
297 self.stack.push(rlp);
298
299 if let Some(proof_retainer) = self.proof_retainer.as_mut() {
300 proof_retainer.retain_leaf_proof(&path, &self.rlp_buf)
301 }
302 }
303 HashBuilderValueRef::Hash(hash) => {
304 trace!(target: "trie::hash_builder", ?hash, "pushing branch node hash");
305 self.stack.push(RlpNode::word_rlp(hash));
306
307 if self.stored_in_database {
308 self.tree_masks[current.len() - 1] |=
309 TrieMask::from_nibble(current.last().unwrap());
310 }
311 self.hash_masks[current.len() - 1] |=
312 TrieMask::from_nibble(current.last().unwrap());
313
314 build_extensions = true;
315 }
316 }
317 }
318
319 if build_extensions && !short_node_key.is_empty() {
320 self.update_masks(¤t, len_from);
321 let stack_last = self.stack.pop().expect("there should be at least one stack item");
322 let extension_node = ExtensionNodeRef::new(&short_node_key, &stack_last);
323
324 self.rlp_buf.clear();
325 let rlp = extension_node.rlp(&mut self.rlp_buf);
326
327 let path = current.slice(..len_from);
328 trace!(
329 target: "trie::hash_builder",
330 ?path,
331 ?extension_node,
332 ?rlp,
333 "pushing extension node",
334 );
335 self.stack.push(rlp);
336
337 if let Some(proof_retainer) = self.proof_retainer.as_mut() {
338 proof_retainer.retain_extension_proof(&path, &short_node_key, &self.rlp_buf)
339 }
340
341 self.resize_masks(len_from);
342 }
343
344 if preceding_len <= common_prefix_len && !succeeding.is_empty() {
345 trace!(target: "trie::hash_builder", "no common prefix to create branch nodes from, returning");
346 return;
347 }
348
349 if !succeeding.is_empty() || preceding_exists {
351 let children = self.push_branch_node(¤t, len);
353 self.store_branch_node(¤t, len, children);
355 }
356
357 self.state_masks.resize(len, TrieMask::default());
358 self.resize_masks(len);
359
360 if preceding_len == 0 {
361 trace!(target: "trie::hash_builder", "0 or 1 state masks means we have no more elements to process");
362 return;
363 }
364
365 current.truncate(preceding_len);
366 trace!(target: "trie::hash_builder", ?current, "truncated nibbles to {} bytes", preceding_len);
367
368 trace!(target: "trie::hash_builder", state_masks = ?self.state_masks, "popping empty state masks");
369 while self.state_masks.last() == Some(&TrieMask::default()) {
370 self.state_masks.pop();
371 }
372
373 build_extensions = true;
374
375 i += 1;
376 }
377 }
378
379 fn push_branch_node(&mut self, current: &Nibbles, len: usize) -> Vec<B256> {
386 let state_mask = self.state_masks[len];
387 let hash_mask = self.hash_masks[len];
388 let branch_node = BranchNodeRef::new(&self.stack, state_mask);
389 let children = if self.updated_branch_nodes.is_some() {
391 branch_node.child_hashes(hash_mask).collect()
392 } else {
393 vec![]
394 };
395
396 self.rlp_buf.clear();
397 let rlp = branch_node.rlp(&mut self.rlp_buf);
398 let path = current.slice(..len);
399 trace!(
400 target: "trie::hash_builder",
401 ?path,
402 ?branch_node,
403 ?rlp,
404 "pushing branch node",
405 );
406
407 if let Some(proof_retainer) = self.proof_retainer.as_mut() {
408 proof_retainer.retain_branch_proof(&path, state_mask, &self.rlp_buf);
409 }
410
411 let first_child_idx = self.stack.len() - state_mask.count_ones() as usize;
413 trace!(
414 target: "trie::hash_builder",
415 new_len = first_child_idx,
416 old_len = self.stack.len(),
417 "resizing stack to prepare branch node"
418 );
419 self.stack.resize_with(first_child_idx, Default::default);
420
421 self.stack.push(rlp);
422 children
423 }
424
425 fn store_branch_node(&mut self, current: &Nibbles, len: usize, children: Vec<B256>) {
430 if len > 0 {
431 let parent_index = len - 1;
432 self.hash_masks[parent_index] |=
433 TrieMask::from_nibble(current.get_unchecked(parent_index));
434 }
435
436 let store_in_db_trie = !self.tree_masks[len].is_empty() || !self.hash_masks[len].is_empty();
437 if store_in_db_trie {
438 if len > 0 {
439 let parent_index = len - 1;
440 self.tree_masks[parent_index] |=
441 TrieMask::from_nibble(current.get_unchecked(parent_index));
442 }
443
444 if self.updated_branch_nodes.is_some() {
445 let common_prefix = current.slice(..len);
446 let node = BranchNodeCompact::new(
447 self.state_masks[len],
448 self.tree_masks[len],
449 self.hash_masks[len],
450 children,
451 (len == 0).then(|| self.current_root()),
452 );
453 self.updated_branch_nodes.as_mut().unwrap().insert(common_prefix, node);
454 }
455 }
456 }
457
458 fn update_masks(&mut self, current: &Nibbles, len_from: usize) {
459 if len_from > 0 {
460 let flag = TrieMask::from_nibble(current.get_unchecked(len_from - 1));
461
462 self.hash_masks[len_from - 1] &= !flag;
463
464 if !self.tree_masks[current.len() - 1].is_empty() {
465 self.tree_masks[len_from - 1] |= flag;
466 }
467 }
468 }
469
470 fn resize_masks(&mut self, new_len: usize) {
471 trace!(
472 target: "trie::hash_builder",
473 new_len,
474 old_tree_mask_len = self.tree_masks.len(),
475 old_hash_mask_len = self.hash_masks.len(),
476 "resizing tree/hash masks"
477 );
478 self.tree_masks.resize(new_len, TrieMask::default());
479 self.hash_masks.resize(new_len, TrieMask::default());
480 }
481}
482
483#[cfg(test)]
484mod tests {
485 use super::*;
486 use crate::{nodes::LeafNode, triehash_trie_root};
487 use alloc::collections::BTreeMap;
488 use alloy_primitives::{U256, b256, hex};
489 use alloy_rlp::Encodable;
490
491 fn assert_hashed_trie_root<'a, I, K>(iter: I)
493 where
494 I: Iterator<Item = (K, &'a U256)>,
495 K: AsRef<[u8]> + Ord,
496 {
497 let hashed = iter
498 .map(|(k, v)| (keccak256(k.as_ref()), alloy_rlp::encode(v).to_vec()))
499 .collect::<BTreeMap<_, _>>();
501
502 let mut hb = HashBuilder::default();
503
504 hashed.iter().for_each(|(key, val)| {
505 let nibbles = Nibbles::unpack(key);
506 hb.add_leaf(nibbles, val);
507 });
508
509 assert_eq!(hb.root(), triehash_trie_root(&hashed));
510 }
511
512 fn assert_trie_root<I, K, V>(iter: I)
514 where
515 I: IntoIterator<Item = (K, V)>,
516 K: AsRef<[u8]> + Ord,
517 V: AsRef<[u8]>,
518 {
519 let mut hb = HashBuilder::default();
520
521 let data = iter.into_iter().collect::<BTreeMap<_, _>>();
522 data.iter().for_each(|(key, val)| {
523 let nibbles = Nibbles::unpack(key.as_ref());
524 hb.add_leaf(nibbles, val.as_ref());
525 });
526
527 assert_eq!(hb.root(), triehash_trie_root(data));
528 }
529
530 #[test]
531 fn empty() {
532 assert_eq!(HashBuilder::default().root(), EMPTY_ROOT_HASH);
533 }
534
535 #[test]
536 #[cfg(feature = "arbitrary")]
537 #[cfg_attr(miri, ignore = "no proptest")]
538 fn arbitrary_hashed_root() {
539 use proptest::prelude::*;
540 proptest!(|(state: BTreeMap<B256, U256>)| {
541 assert_hashed_trie_root(state.iter());
542 });
543 }
544
545 #[test]
546 fn test_generates_branch_node() {
547 let mut hb = HashBuilder::default().with_updates(true);
548
549 let data = BTreeMap::from([
567 (
568 hex!("1000000000000000000000000000000000000000000000000000000000000000").to_vec(),
571 Vec::new(),
572 ),
573 (
574 hex!("1100000000000000000000000000000000000000000000000000000000000000").to_vec(),
575 Vec::new(),
576 ),
577 (
578 hex!("1110000000000000000000000000000000000000000000000000000000000000").to_vec(),
579 Vec::new(),
580 ),
581 (
582 hex!("1200000000000000000000000000000000000000000000000000000000000000").to_vec(),
583 Vec::new(),
584 ),
585 (
586 hex!("1220000000000000000000000000000000000000000000000000000000000000").to_vec(),
587 Vec::new(),
588 ),
589 (
590 hex!("1320000000000000000000000000000000000000000000000000000000000000").to_vec(),
593 Vec::new(),
594 ),
595 ]);
596 data.iter().for_each(|(key, val)| {
597 let nibbles = Nibbles::unpack(key);
598 hb.add_leaf(nibbles, val.as_ref());
599 });
600 let _root = hb.root();
601
602 let (_, updates) = hb.split();
603
604 let update = updates.get(&Nibbles::from_nibbles_unchecked(hex!("01"))).unwrap();
605 assert_eq!(update.state_mask, TrieMask::new(0b1111));
607 assert_eq!(update.tree_mask, TrieMask::new(0b0000));
609 assert_eq!(update.hash_mask, TrieMask::new(0b0110));
611 assert_eq!(update.hashes.len(), 2);
613
614 assert_eq!(_root, triehash_trie_root(data));
615 }
616
617 #[test]
618 fn test_root_raw_data() {
619 let data = [
620 (hex!("646f").to_vec(), hex!("76657262").to_vec()),
621 (hex!("676f6f64").to_vec(), hex!("7075707079").to_vec()),
622 (hex!("676f6b32").to_vec(), hex!("7075707079").to_vec()),
623 (hex!("676f6b34").to_vec(), hex!("7075707079").to_vec()),
624 ];
625 assert_trie_root(data);
626 }
627
628 #[test]
629 fn test_root_rlp_hashed_data() {
630 let data: HashMap<_, _, _> = HashMap::from([
631 (B256::with_last_byte(1), U256::from(2)),
632 (B256::with_last_byte(3), U256::from(4)),
633 ]);
634 assert_hashed_trie_root(data.iter());
635 }
636
637 #[test]
638 fn test_root_known_hash() {
639 let root_hash = b256!("45596e474b536a6b4d64764e4f75514d544577646c414e684271706871446456");
640 let mut hb = HashBuilder::default();
641 hb.add_branch(Nibbles::default(), root_hash, false);
642 assert_eq!(hb.root(), root_hash);
643 }
644
645 #[test]
646 fn manual_branch_node_ok() {
647 let raw_input = vec![
648 (hex!("646f").to_vec(), hex!("76657262").to_vec()),
649 (hex!("676f6f64").to_vec(), hex!("7075707079").to_vec()),
650 ];
651 let expected = triehash_trie_root(raw_input.clone());
652
653 let mut hb = HashBuilder::default();
655 for (key, val) in &raw_input {
656 hb.add_leaf(Nibbles::unpack(key), val);
657 }
658
659 let leaf1 = LeafNode::new(Nibbles::unpack(&raw_input[0].0[1..]), raw_input[0].1.clone());
663 let leaf2 = LeafNode::new(Nibbles::unpack(&raw_input[1].0[1..]), raw_input[1].1.clone());
664 let mut branch: [&dyn Encodable; 17] = [b""; 17];
665 branch[4] = &leaf1;
668 branch[7] = &leaf2;
669 let mut branch_node_rlp = Vec::new();
670 alloy_rlp::encode_list::<_, dyn Encodable>(&branch, &mut branch_node_rlp);
671 let branch_node_hash = keccak256(branch_node_rlp);
672
673 let mut hb2 = HashBuilder::default();
674 hb2.add_branch(Nibbles::from_nibbles_unchecked([0x6]), branch_node_hash, false);
676
677 assert_eq!(hb.root(), expected);
678 assert_eq!(hb2.root(), expected);
679 }
680}