From 18411ae181e9e47915febe80372fc1080895f1b0 Mon Sep 17 00:00:00 2001 From: c0np4nn4 Date: Mon, 14 Oct 2024 22:42:11 +0900 Subject: [PATCH] port: migrated functions for computing trie root from reth to alloy --- Cargo.toml | 1 + src/lib.rs | 2 ++ src/root.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/root.rs diff --git a/Cargo.toml b/Cargo.toml index cbe3e59..f221a13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ alloy-primitives = { version = "0.8.5", default-features = false, features = [ ] } alloy-rlp = { version = "0.3.8", default-features = false, features = [ "derive", + "arrayvec", ] } arrayvec = { version = "0.7", default-features = false } diff --git a/src/lib.rs b/src/lib.rs index 4bd8cd0..8b05c04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,8 @@ pub mod proof; mod mask; pub use mask::TrieMask; +pub mod root; + #[doc(hidden)] pub use alloy_primitives::map::HashMap; diff --git a/src/root.rs b/src/root.rs new file mode 100644 index 0000000..b6a2ba7 --- /dev/null +++ b/src/root.rs @@ -0,0 +1,49 @@ +use alloy_primitives::B256; +use alloy_rlp::Encodable; +use nybbles::Nibbles; +use alloc::vec::Vec; + +use crate::{HashBuilder, EMPTY_ROOT_HASH}; + +/// Adjust the index of an item for rlp encoding. +pub const fn adjust_index_for_rlp(i: usize, len: usize) -> usize { + if i > 0x7f { + i + } else if i == 0x7f || i + 1 == len { + 0 + } else { + i + 1 + } +} + +/// Compute a trie root of the collection of rlp encodable items. +pub fn ordered_trie_root(items: &[T]) -> B256 { + ordered_trie_root_with_encoder(items, |item, buf| item.encode(buf)) +} + +/// Compute a trie root of the collection of items with a custom encoder. +pub fn ordered_trie_root_with_encoder(items: &[T], mut encode: F) -> B256 +where + F: FnMut(&T, &mut Vec), +{ + if items.is_empty() { + return EMPTY_ROOT_HASH; + } + + let mut value_buffer = Vec::new(); + + let mut hb = HashBuilder::default(); + let items_len = items.len(); + for i in 0..items_len { + let index = adjust_index_for_rlp(i, items_len); + + let index_buffer = alloy_rlp::encode_fixed_size(&index); + + value_buffer.clear(); + encode(&items[index], &mut value_buffer); + + hb.add_leaf(Nibbles::unpack(&index_buffer), &value_buffer); + } + + hb.root() +}