chore: move proof types and root functions from primitives/proofs into reth-trie-common (#8724)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
joshieDo
2024-06-13 18:36:18 +02:00
committed by GitHub
parent 763317d356
commit 76c8f4842c
47 changed files with 401 additions and 394 deletions

125
Cargo.lock generated
View File

@ -109,9 +109,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "alloy-chains"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03fd095a9d70f4b1c5c102c84a4c782867a5c6416dbf6dcd42a63e7c7a89d3c8"
checksum = "24ceb48af11349cd7fbd12aa739800be3c4b3965f640b7ae26666907f3bdf091"
dependencies = [
"alloy-rlp",
"arbitrary",
@ -140,7 +140,7 @@ dependencies = [
[[package]]
name = "alloy-consensus"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy#7578618d61213ea832c40c7e613f1d644ce08f27"
source = "git+https://github.com/alloy-rs/alloy#b000e16f06161c15b42a4c59f27cb3feb23b3c14"
dependencies = [
"alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)",
"alloy-primitives",
@ -189,7 +189,7 @@ dependencies = [
[[package]]
name = "alloy-eips"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy#7578618d61213ea832c40c7e613f1d644ce08f27"
source = "git+https://github.com/alloy-rs/alloy#b000e16f06161c15b42a4c59f27cb3feb23b3c14"
dependencies = [
"alloy-primitives",
"alloy-rlp",
@ -214,7 +214,7 @@ dependencies = [
[[package]]
name = "alloy-genesis"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy#7578618d61213ea832c40c7e613f1d644ce08f27"
source = "git+https://github.com/alloy-rs/alloy#b000e16f06161c15b42a4c59f27cb3feb23b3c14"
dependencies = [
"alloy-primitives",
"alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)",
@ -418,7 +418,7 @@ dependencies = [
[[package]]
name = "alloy-rpc-types"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy#7578618d61213ea832c40c7e613f1d644ce08f27"
source = "git+https://github.com/alloy-rs/alloy#b000e16f06161c15b42a4c59f27cb3feb23b3c14"
dependencies = [
"alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy)",
"alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)",
@ -490,7 +490,7 @@ dependencies = [
[[package]]
name = "alloy-rpc-types-eth"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy#7578618d61213ea832c40c7e613f1d644ce08f27"
source = "git+https://github.com/alloy-rs/alloy#b000e16f06161c15b42a4c59f27cb3feb23b3c14"
dependencies = [
"alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)",
"alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)",
@ -530,7 +530,7 @@ dependencies = [
[[package]]
name = "alloy-serde"
version = "0.1.0"
source = "git+https://github.com/alloy-rs/alloy#7578618d61213ea832c40c7e613f1d644ce08f27"
source = "git+https://github.com/alloy-rs/alloy#b000e16f06161c15b42a4c59f27cb3feb23b3c14"
dependencies = [
"alloy-primitives",
"serde",
@ -680,7 +680,7 @@ dependencies = [
"alloy-transport",
"bytes",
"futures",
"interprocess 2.1.1",
"interprocess 2.2.0",
"pin-project",
"serde_json",
"tokio",
@ -697,7 +697,7 @@ dependencies = [
"alloy-transport",
"futures",
"http 1.1.0",
"rustls 0.23.9",
"rustls 0.23.10",
"serde_json",
"tokio",
"tokio-tungstenite",
@ -1122,9 +1122,9 @@ dependencies = [
[[package]]
name = "backtrace"
version = "0.3.72"
version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11"
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
@ -3647,9 +3647,9 @@ dependencies = [
[[package]]
name = "httparse"
version = "1.9.2"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f3935c160d00ac752e09787e6e6bfc26494c2183cc922f1bc678a60d4733bc2"
checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545"
[[package]]
name = "httpdate"
@ -3728,7 +3728,7 @@ dependencies = [
"hyper",
"hyper-util",
"log",
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.0",
@ -4110,9 +4110,9 @@ dependencies = [
[[package]]
name = "interprocess"
version = "2.1.1"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13f2533e1f1a70bec71ea7a85d1c0a4dab141c314035ce76e51a19a2f48be708"
checksum = "67bafc2f5dbdad79a6d925649758d5472647b416028099f0b829d1b67fdd47d3"
dependencies = [
"doctest-file",
"futures-core",
@ -4285,7 +4285,7 @@ dependencies = [
"http 1.1.0",
"jsonrpsee-core",
"pin-project",
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-pki-types",
"rustls-platform-verifier",
"soketto",
@ -4340,7 +4340,7 @@ dependencies = [
"hyper-util",
"jsonrpsee-core",
"jsonrpsee-types",
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-platform-verifier",
"serde",
"serde_json",
@ -4605,9 +4605,9 @@ dependencies = [
[[package]]
name = "libp2p-identity"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "999ec70441b2fb35355076726a6bc466c932e9bdc66f6a11c6c0aa17c7ab9be0"
checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8"
dependencies = [
"asn1_der",
"bs58",
@ -4835,9 +4835,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.7.2"
version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768"
[[package]]
name = "memmap2"
@ -5333,9 +5333,9 @@ dependencies = [
[[package]]
name = "object"
version = "0.35.0"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
dependencies = [
"memchr",
]
@ -6656,7 +6656,7 @@ dependencies = [
"reth-stages-types",
"reth-storage-errors",
"reth-tracing",
"reth-trie-types",
"reth-trie-common",
"rustc-hash",
"serde",
"serde_json",
@ -6690,7 +6690,7 @@ dependencies = [
"reth-prune-types",
"reth-stages-types",
"reth-storage-errors",
"reth-trie-types",
"reth-trie-common",
"serde",
"serde_json",
"test-fuzz",
@ -7711,12 +7711,9 @@ dependencies = [
"c-kzg",
"criterion",
"derive_more",
"hash-db",
"itertools 0.12.1",
"modular-bitfield",
"nybbles",
"once_cell",
"plain_hasher",
"pprof",
"proptest",
"proptest-derive",
@ -7727,7 +7724,7 @@ dependencies = [
"reth-network-peers",
"reth-primitives-traits",
"reth-static-file-types",
"reth-trie-types",
"reth-trie-common",
"revm",
"revm-primitives",
"roaring",
@ -8077,6 +8074,7 @@ dependencies = [
"alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=00d81d7)",
"reth-primitives",
"reth-rpc-types",
"reth-trie-common",
"serde_json",
]
@ -8162,7 +8160,7 @@ dependencies = [
"proptest-derive",
"rand 0.8.5",
"reth-codecs",
"reth-trie-types",
"reth-trie-common",
"serde",
"test-fuzz",
]
@ -8329,7 +8327,7 @@ dependencies = [
"reth-provider",
"reth-stages-types",
"reth-storage-errors",
"reth-trie-types",
"reth-trie-common",
"revm",
"serde_json",
"similar-asserts",
@ -8339,6 +8337,34 @@ dependencies = [
"triehash",
]
[[package]]
name = "reth-trie-common"
version = "1.0.0-rc.1"
dependencies = [
"alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=00d81d7)",
"alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=00d81d7)",
"alloy-primitives",
"alloy-rlp",
"alloy-trie",
"arbitrary",
"assert_matches",
"bytes",
"derive_more",
"hash-db",
"itertools 0.12.1",
"nybbles",
"plain_hasher",
"proptest",
"proptest-derive",
"reth-codecs",
"reth-primitives-traits",
"revm-primitives",
"serde",
"serde_json",
"test-fuzz",
"toml",
]
[[package]]
name = "reth-trie-parallel"
version = "1.0.0-rc.1"
@ -8364,27 +8390,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "reth-trie-types"
version = "1.0.0-rc.1"
dependencies = [
"alloy-primitives",
"alloy-rlp",
"alloy-trie",
"arbitrary",
"assert_matches",
"bytes",
"derive_more",
"nybbles",
"proptest",
"proptest-derive",
"reth-codecs",
"serde",
"serde_json",
"test-fuzz",
"toml",
]
[[package]]
name = "revm"
version = "9.0.0"
@ -8695,9 +8700,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.9"
version = "0.23.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a218f0f6d05669de4eabfb24f31ce802035c952429d037507b4a4a39f0e60c5b"
checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402"
dependencies = [
"log",
"once_cell",
@ -8748,7 +8753,7 @@ dependencies = [
"jni",
"log",
"once_cell",
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
@ -9855,7 +9860,7 @@ version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
dependencies = [
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-pki-types",
"tokio",
]
@ -9880,7 +9885,7 @@ checksum = "becd34a233e7e31a3dbf7c7241b38320f57393dcae8e7324b0167d21b8e320b0"
dependencies = [
"futures-util",
"log",
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.0",
@ -10221,7 +10226,7 @@ dependencies = [
"httparse",
"log",
"rand 0.8.5",
"rustls 0.23.9",
"rustls 0.23.10",
"rustls-pki-types",
"sha1",
"thiserror",

View File

@ -99,9 +99,9 @@ members = [
"crates/tokio-util/",
"crates/tracing/",
"crates/transaction-pool/",
"crates/trie/common",
"crates/trie/parallel/",
"crates/trie/trie",
"crates/trie/types",
"examples/beacon-api-sidecar-fetcher/",
"examples/beacon-api-sse/",
"examples/bsc-p2p",
@ -332,8 +332,8 @@ reth-tokio-util = { path = "crates/tokio-util" }
reth-tracing = { path = "crates/tracing" }
reth-transaction-pool = { path = "crates/transaction-pool" }
reth-trie = { path = "crates/trie/trie" }
reth-trie-common = { path = "crates/trie/common" }
reth-trie-parallel = { path = "crates/trie/parallel" }
reth-trie-types = { path = "crates/trie/types" }
# revm
revm = { version = "9.0.0", features = [

View File

@ -1383,7 +1383,7 @@ mod tests {
use reth_primitives::{
constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_ROOT_HASH, ETHEREUM_BLOCK_GAS_LIMIT},
keccak256,
proofs::{calculate_transaction_root, state_root_unhashed},
proofs::calculate_transaction_root,
revm_primitives::AccountInfo,
Account, Address, ChainSpecBuilder, Genesis, GenesisAccount, Header, Signature,
Transaction, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, Withdrawals, B256,
@ -1394,7 +1394,7 @@ mod tests {
ProviderFactory,
};
use reth_stages_api::StageCheckpoint;
use reth_trie::StateRoot;
use reth_trie::{root::state_root_unhashed, StateRoot};
use std::collections::HashMap;
fn setup_externals(

View File

@ -18,7 +18,7 @@ reth-codecs.workspace = true
reth-ethereum-forks.workspace = true
reth-network-peers.workspace = true
reth-static-file-types.workspace = true
reth-trie-types.workspace = true
reth-trie-common.workspace = true
revm.workspace = true
revm-primitives = { workspace = true, features = ["serde"] }
@ -27,7 +27,6 @@ alloy-chains = { workspace = true, features = ["serde", "rlp"] }
alloy-consensus = { workspace = true, features = ["arbitrary", "serde"] }
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
alloy-rlp = { workspace = true, features = ["arrayvec"] }
alloy-trie = { workspace = true, features = ["serde"] }
alloy-rpc-types = { workspace = true, optional = true }
alloy-genesis.workspace = true
alloy-eips = { workspace = true, features = ["serde"] }
@ -45,7 +44,6 @@ c-kzg = { workspace = true, features = ["serde"], optional = true }
bytes.workspace = true
byteorder = "1"
derive_more.workspace = true
itertools.workspace = true
modular-bitfield.workspace = true
once_cell.workspace = true
rayon.workspace = true
@ -56,10 +54,6 @@ thiserror.workspace = true
zstd = { version = "0.13", features = ["experimental"], optional = true }
roaring = "0.10.2"
# `test-utils` feature
hash-db = { version = "~0.15", optional = true }
plain_hasher = { version = "0.2", optional = true }
# arbitrary utils
arbitrary = { workspace = true, features = ["derive"], optional = true }
proptest = { workspace = true, optional = true }
@ -82,9 +76,6 @@ test-fuzz.workspace = true
toml.workspace = true
triehash = "0.8"
hash-db = "~0.15"
plain_hasher = "0.2"
sucds = "0.8.1"
criterion.workspace = true
@ -126,7 +117,7 @@ optimism = [
"revm/optimism",
]
alloy-compat = ["alloy-rpc-types"]
test-utils = ["dep:plain_hasher", "dep:hash-db"]
test-utils = []
[[bench]]
name = "recover_ecdsa_crit"
@ -137,11 +128,6 @@ name = "validate_blob_tx"
required-features = ["arbitrary", "c-kzg"]
harness = false
[[bench]]
name = "trie_root"
required-features = ["arbitrary", "test-utils"]
harness = false
[[bench]]
name = "integer_list"
harness = false

View File

@ -5,13 +5,13 @@ use crate::{
},
holesky_nodes,
net::{goerli_nodes, mainnet_nodes, sepolia_nodes},
proofs::state_root_ref_unhashed,
revm_primitives::{address, b256},
Address, BlockNumber, Chain, ChainKind, ForkFilter, ForkFilterKey, ForkHash, ForkId, Genesis,
Hardfork, Head, Header, NamedChain, NodeRecord, SealedHeader, B256, EMPTY_OMMER_ROOT_HASH,
MAINNET_DEPOSIT_CONTRACT, U256,
};
use once_cell::sync::Lazy;
use reth_trie_common::root::state_root_ref_unhashed;
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
@ -1726,8 +1726,10 @@ impl OptimismGenesisInfo {
#[cfg(test)]
mod tests {
use reth_trie_common::TrieAccount;
use super::*;
use crate::{b256, hex, proofs::IntoTrieAccount, ChainConfig, GenesisAccount};
use crate::{b256, hex, ChainConfig, GenesisAccount};
use std::{collections::HashMap, str::FromStr};
fn test_fork_ids(spec: &ChainSpec, cases: &[(Head, ForkId)]) {
for (block, expected_id) in cases {
@ -2829,10 +2831,7 @@ Post-merge hard forks (timestamp based):
for (key, expected_rlp) in key_rlp {
let account = chainspec.genesis.alloc.get(&key).expect("account should exist");
assert_eq!(
&alloy_rlp::encode(IntoTrieAccount::to_trie_account(account.clone())),
expected_rlp
);
assert_eq!(&alloy_rlp::encode(TrieAccount::from(account.clone())), expected_rlp);
}
assert_eq!(chainspec.genesis_hash, None);

View File

@ -1,58 +1,12 @@
//! Helper function for calculating Merkle proofs and hashes.
use crate::{
constants::EMPTY_OMMER_ROOT_HASH, keccak256, Address, Header, Receipt, ReceiptWithBloom,
ReceiptWithBloomRef, Request, TransactionSigned, Withdrawal, B256, U256,
constants::EMPTY_OMMER_ROOT_HASH, keccak256, Header, Receipt, ReceiptWithBloom,
ReceiptWithBloomRef, Request, TransactionSigned, Withdrawal, B256,
};
use reth_trie_types::{hash_builder::HashBuilder, Nibbles};
mod types;
pub use types::{AccountProof, StorageProof};
mod traits;
pub use traits::IntoTrieAccount;
use reth_trie_common::root::{ordered_trie_root, ordered_trie_root_with_encoder};
use alloy_eips::eip7685::Encodable7685;
use alloy_rlp::Encodable;
use itertools::Itertools;
/// 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<T: Encodable>(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<T, F>(items: &[T], mut encode: F) -> B256
where
F: FnMut(&T, &mut Vec<u8>),
{
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()
}
/// Calculate a transaction root.
///
@ -175,109 +129,16 @@ pub fn calculate_ommers_root(ommers: &[Header]) -> B256 {
keccak256(ommers_rlp)
}
/// Hashes and sorts account keys, then proceeds to calculating the root hash of the state
/// represented as MPT.
/// See [`state_root_unsorted`] for more info.
pub fn state_root_ref_unhashed<'a, A: IntoTrieAccount + Clone + 'a>(
state: impl IntoIterator<Item = (&'a Address, &'a A)>,
) -> B256 {
state_root_unsorted(
state.into_iter().map(|(address, account)| (keccak256(address), account.clone())),
)
}
/// Hashes and sorts account keys, then proceeds to calculating the root hash of the state
/// represented as MPT.
/// See [`state_root_unsorted`] for more info.
pub fn state_root_unhashed<A: IntoTrieAccount>(
state: impl IntoIterator<Item = (Address, A)>,
) -> B256 {
state_root_unsorted(state.into_iter().map(|(address, account)| (keccak256(address), account)))
}
/// Sorts the hashed account keys and calculates the root hash of the state represented as MPT.
/// See [`state_root`] for more info.
pub fn state_root_unsorted<A: IntoTrieAccount>(state: impl IntoIterator<Item = (B256, A)>) -> B256 {
state_root(state.into_iter().sorted_by_key(|(key, _)| *key))
}
/// Calculates the root hash of the state represented as MPT.
/// Corresponds to [geth's `deriveHash`](https://github.com/ethereum/go-ethereum/blob/6c149fd4ad063f7c24d726a73bc0546badd1bc73/core/genesis.go#L119).
///
/// # Panics
///
/// If the items are not in sorted order.
pub fn state_root<A: IntoTrieAccount>(state: impl IntoIterator<Item = (B256, A)>) -> B256 {
let mut hb = HashBuilder::default();
let mut account_rlp_buf = Vec::new();
for (hashed_key, account) in state {
account_rlp_buf.clear();
account.to_trie_account().encode(&mut account_rlp_buf);
hb.add_leaf(Nibbles::unpack(hashed_key), &account_rlp_buf);
}
hb.root()
}
/// Hashes storage keys, sorts them and them calculates the root hash of the storage trie.
/// See [`storage_root_unsorted`] for more info.
pub fn storage_root_unhashed(storage: impl IntoIterator<Item = (B256, U256)>) -> B256 {
storage_root_unsorted(storage.into_iter().map(|(slot, value)| (keccak256(slot), value)))
}
/// Sorts and calculates the root hash of account storage trie.
/// See [`storage_root`] for more info.
pub fn storage_root_unsorted(storage: impl IntoIterator<Item = (B256, U256)>) -> B256 {
storage_root(storage.into_iter().sorted_by_key(|(key, _)| *key))
}
/// Calculates the root hash of account storage trie.
///
/// # Panics
///
/// If the items are not in sorted order.
pub fn storage_root(storage: impl IntoIterator<Item = (B256, U256)>) -> B256 {
let mut hb = HashBuilder::default();
for (hashed_slot, value) in storage {
hb.add_leaf(Nibbles::unpack(hashed_slot), alloy_rlp::encode_fixed_size(&value).as_ref());
}
hb.root()
}
/// Implementation of hasher using our keccak256 hashing function
/// for compatibility with `triehash` crate.
#[cfg(any(test, feature = "test-utils"))]
pub mod triehash {
use super::{keccak256, B256};
use hash_db::Hasher;
use plain_hasher::PlainHasher;
/// A [Hasher] that calculates a keccak256 hash of the given data.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct KeccakHasher;
#[cfg(any(test, feature = "test-utils"))]
impl Hasher for KeccakHasher {
type Out = B256;
type StdHasher = PlainHasher;
const LENGTH: usize = 32;
fn hash(x: &[u8]) -> Self::Out {
keccak256(x)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
bloom, constants::EMPTY_ROOT_HASH, hex_literal::hex, Block, GenesisAccount, Log, TxType,
GOERLI, HOLESKY, MAINNET, SEPOLIA,
GOERLI, HOLESKY, MAINNET, SEPOLIA, U256,
};
use alloy_primitives::{b256, LogData};
use alloy_primitives::{b256, Address, LogData};
use alloy_rlp::Decodable;
use reth_trie_common::root::{state_root_ref_unhashed, state_root_unhashed};
use std::collections::HashMap;
#[test]

View File

@ -1,59 +0,0 @@
use crate::Account;
use alloy_consensus::constants::{EMPTY_ROOT_HASH, KECCAK_EMPTY};
use alloy_genesis::GenesisAccount;
use alloy_primitives::{keccak256, B256, U256};
use reth_trie_types::TrieAccount;
use revm_primitives::AccountInfo;
/// Converts a type into a [`TrieAccount`].
pub trait IntoTrieAccount {
/// Converts to this type into a [`TrieAccount`].
fn to_trie_account(self) -> TrieAccount;
}
impl IntoTrieAccount for GenesisAccount {
fn to_trie_account(self) -> TrieAccount {
let storage_root = self
.storage
.map(|storage| {
super::storage_root_unhashed(
storage
.into_iter()
.filter(|(_, value)| *value != B256::ZERO)
.map(|(slot, value)| (slot, U256::from_be_bytes(*value))),
)
})
.unwrap_or(EMPTY_ROOT_HASH);
TrieAccount {
nonce: self.nonce.unwrap_or_default(),
balance: self.balance,
storage_root,
code_hash: self.code.map_or(KECCAK_EMPTY, keccak256),
}
}
}
impl IntoTrieAccount for (Account, B256) {
fn to_trie_account(self) -> TrieAccount {
let (account, storage_root) = self;
TrieAccount {
nonce: account.nonce,
balance: account.balance,
storage_root,
code_hash: account.bytecode_hash.unwrap_or(KECCAK_EMPTY),
}
}
}
impl IntoTrieAccount for (AccountInfo, B256) {
fn to_trie_account(self) -> TrieAccount {
let (account, storage_root) = self;
TrieAccount {
nonce: account.nonce,
balance: account.balance,
storage_root,
code_hash: account.code_hash,
}
}
}

View File

@ -1,10 +1,9 @@
use reth_primitives::{
keccak256, proofs::AccountProof, Account, Address, BlockNumber, Bytecode, Bytes, StorageKey,
B256, U256,
keccak256, Account, Address, BlockNumber, Bytecode, Bytes, StorageKey, B256, U256,
};
use reth_storage_api::{AccountReader, BlockHashReader, StateProvider, StateRootProvider};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::updates::TrieUpdates;
use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::db::BundleState;
use std::collections::HashMap;

View File

@ -14,6 +14,7 @@ workspace = true
[dependencies]
reth-primitives.workspace = true
reth-rpc-types.workspace = true
reth-trie-common.workspace = true
alloy-rlp.workspace = true
alloy-rpc-types.workspace = true

View File

@ -1,12 +1,10 @@
//! Compatibility functions for rpc proof related types.
use reth_primitives::{
proofs::{AccountProof, StorageProof},
U64,
};
use reth_primitives::U64;
use reth_rpc_types::{
serde_helpers::JsonStorageKey, EIP1186AccountProofResponse, EIP1186StorageProof,
};
use reth_trie_common::{AccountProof, StorageProof};
/// Creates a new rpc storage proof from a primitive storage proof type.
pub fn from_primitive_storage_proof(proof: StorageProof) -> EIP1186StorageProof {

View File

@ -13,7 +13,7 @@ workspace = true
[dependencies]
reth-codecs.workspace = true
reth-trie-types.workspace = true
reth-trie-common.workspace = true
alloy-primitives.workspace = true
modular-bitfield.workspace = true

View File

@ -1,7 +1,7 @@
use alloy_primitives::{Address, BlockNumber, B256};
use bytes::Buf;
use reth_codecs::{main_codec, Compact};
use reth_trie_types::{hash_builder::HashBuilderState, StoredSubNode};
use reth_trie_common::{hash_builder::HashBuilderState, StoredSubNode};
use std::ops::RangeInclusive;
use super::StageId;

View File

@ -18,7 +18,7 @@ reth-primitives.workspace = true
reth-prune-types.workspace = true
reth-storage-errors.workspace = true
reth-stages-types.workspace = true
reth-trie-types.workspace = true
reth-trie-common.workspace = true
# codecs
modular-bitfield.workspace = true

View File

@ -8,7 +8,7 @@ use reth_codecs::{main_codec, Compact};
use reth_primitives::{Address, B256, *};
use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::StageCheckpoint;
use reth_trie_types::{StoredNibbles, StoredNibblesSubKey, *};
use reth_trie_common::{StoredNibbles, StoredNibblesSubKey, *};
pub mod accounts;
pub mod blocks;

View File

@ -25,7 +25,7 @@ reth-nippy-jar.workspace = true
reth-prune-types.workspace = true
reth-stages-types.workspace = true
reth-tracing.workspace = true
reth-trie-types.workspace = true
reth-trie-common.workspace = true
# codecs
serde = { workspace = true, default-features = false }

View File

@ -37,7 +37,7 @@ use reth_primitives::{
};
use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::StageCheckpoint;
use reth_trie_types::{StorageTrieEntry, StoredBranchNode, StoredNibbles, StoredNibblesSubKey};
use reth_trie_common::{StorageTrieEntry, StoredBranchNode, StoredNibbles, StoredNibblesSubKey};
use serde::{Deserialize, Serialize};
use std::fmt;

View File

@ -1,9 +1,9 @@
use crate::{
AccountReader, BlockHashReader, ExecutionDataProvider, StateProvider, StateRootProvider,
};
use reth_primitives::{proofs::AccountProof, Account, Address, BlockNumber, Bytecode, B256};
use reth_primitives::{Account, Address, BlockNumber, Bytecode, B256};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::updates::TrieUpdates;
use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::db::BundleState;
/// A state provider that resolves to data from either a wrapped [`crate::ExecutionOutcome`]

View File

@ -10,11 +10,11 @@ use reth_db_api::{
transaction::DbTx,
};
use reth_primitives::{
constants::EPOCH_SLOTS, proofs::AccountProof, Account, Address, BlockNumber, Bytecode,
StaticFileSegment, StorageKey, StorageValue, B256,
constants::EPOCH_SLOTS, Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey,
StorageValue, B256,
};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, HashedPostState};
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState};
use revm::db::BundleState;
use std::fmt::Debug;

View File

@ -8,11 +8,10 @@ use reth_db_api::{
transaction::DbTx,
};
use reth_primitives::{
proofs::AccountProof, Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey,
StorageValue, B256,
Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey, StorageValue, B256,
};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::{proof::Proof, updates::TrieUpdates, HashedPostState};
use reth_trie::{proof::Proof, updates::TrieUpdates, AccountProof, HashedPostState};
use revm::db::BundleState;
/// State provider over latest state that takes tx reference.

View File

@ -43,7 +43,7 @@ macro_rules! delegate_provider_impls {
}
StateProvider $(where [$($generics)*])?{
fn storage(&self, account: reth_primitives::Address, storage_key: reth_primitives::StorageKey) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::StorageValue>>;
fn proof(&self, address: reth_primitives::Address, keys: &[reth_primitives::B256]) -> reth_storage_errors::provider::ProviderResult<reth_primitives::proofs::AccountProof>;
fn proof(&self, address: reth_primitives::Address, keys: &[reth_primitives::B256]) -> reth_storage_errors::provider::ProviderResult<reth_trie::AccountProof>;
fn bytecode_by_hash(&self, code_hash: reth_primitives::B256) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Bytecode>>;
}
);

View File

@ -5,13 +5,11 @@ use alloy_rlp::Decodable;
use reth_db::tables;
use reth_db_api::{database::Database, models::StoredBlockBodyIndices};
use reth_primitives::{
alloy_primitives, b256,
hex_literal::hex,
proofs::{state_root_unhashed, storage_root_unhashed},
revm::compat::into_reth_acc,
Address, BlockNumber, Bytes, Header, Receipt, Requests, SealedBlock, SealedBlockWithSenders,
TxType, Withdrawal, Withdrawals, B256, U256,
alloy_primitives, b256, hex_literal::hex, revm::compat::into_reth_acc, Address, BlockNumber,
Bytes, Header, Receipt, Requests, SealedBlock, SealedBlockWithSenders, TxType, Withdrawal,
Withdrawals, B256, U256,
};
use reth_trie::root::{state_root_unhashed, storage_root_unhashed};
use revm::{
db::BundleState,
primitives::{AccountInfo, HashMap},

View File

@ -9,14 +9,14 @@ use parking_lot::Mutex;
use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
use reth_evm::ConfigureEvmEnv;
use reth_primitives::{
keccak256, proofs::AccountProof, Account, Address, Block, BlockHash, BlockHashOrNumber,
BlockId, BlockNumber, BlockWithSenders, Bytecode, Bytes, ChainInfo, ChainSpec, Header, Receipt,
SealedBlock, SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta,
keccak256, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber,
BlockWithSenders, Bytecode, Bytes, ChainInfo, ChainSpec, Header, Receipt, SealedBlock,
SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta,
TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256,
U256,
};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::updates::TrieUpdates;
use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::{
db::BundleState,
primitives::{BlockEnv, CfgEnvWithHandlerCfg},

View File

@ -9,16 +9,15 @@ use crate::{
use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
use reth_evm::ConfigureEvmEnv;
use reth_primitives::{
proofs::AccountProof, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId,
BlockNumber, BlockWithSenders, Bytecode, ChainInfo, ChainSpec, Header, Receipt, SealedBlock,
SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta,
TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256,
MAINNET, U256,
Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, BlockWithSenders,
Bytecode, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, SealedBlockWithSenders,
SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned,
TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, MAINNET, U256,
};
use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::updates::TrieUpdates;
use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::{
db::BundleState,
primitives::{BlockEnv, CfgEnvWithHandlerCfg},

View File

@ -2,10 +2,11 @@ use super::{AccountReader, BlockHashReader, BlockIdReader, StateRootProvider};
use auto_impl::auto_impl;
use reth_execution_types::ExecutionOutcome;
use reth_primitives::{
proofs::AccountProof, Address, BlockHash, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag,
Bytecode, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256,
Address, BlockHash, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag, Bytecode, StorageKey,
StorageValue, B256, KECCAK_EMPTY, U256,
};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::AccountProof;
/// Type alias of boxed [`StateProvider`].
pub type StateProviderBox = Box<dyn StateProvider>;

View File

@ -1,5 +1,5 @@
[package]
name = "reth-trie-types"
name = "reth-trie-common"
version.workspace = true
edition.workspace = true
homepage.workspace = true
@ -12,17 +12,29 @@ description = "Commonly used types for trie usage in reth."
workspace = true
[dependencies]
reth-primitives-traits.workspace = true
reth-codecs.workspace = true
alloy-primitives.workspace = true
alloy-rlp = { workspace = true, features = ["arrayvec"] }
alloy-trie = { workspace = true, features = ["serde"] }
alloy-consensus.workspace = true
alloy-genesis.workspace = true
revm-primitives.workspace = true
bytes.workspace = true
derive_more.workspace = true
serde.workspace = true
itertools.workspace = true
nybbles = { workspace = true, features = ["serde", "rlp"] }
# `test-utils` feature
hash-db = { version = "~0.15", optional = true }
plain_hasher = { version = "0.2", optional = true }
arbitrary = { workspace = true, features = ["derive"], optional = true }
proptest = { workspace = true, optional = true }
proptest-derive = { workspace = true, optional = true }
[dev-dependencies]
arbitrary = { workspace = true, features = ["derive"] }
assert_matches.workspace = true
@ -31,3 +43,14 @@ proptest-derive.workspace = true
serde_json.workspace = true
test-fuzz.workspace = true
toml.workspace = true
hash-db = "~0.15"
plain_hasher = "0.2"
[features]
test-utils = ["dep:plain_hasher", "dep:hash-db", "arbitrary"]
arbitrary = [
"alloy-trie/arbitrary",
"dep:arbitrary",
"dep:proptest",
"dep:proptest-derive",
]

View File

@ -0,0 +1,73 @@
use crate::root::storage_root_unhashed;
use alloy_consensus::constants::KECCAK_EMPTY;
use alloy_genesis::GenesisAccount;
use alloy_primitives::{keccak256, B256, U256};
use alloy_rlp::{RlpDecodable, RlpEncodable};
use alloy_trie::EMPTY_ROOT_HASH;
use reth_primitives_traits::Account;
use revm_primitives::AccountInfo;
/// An Ethereum account as represented in the trie.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)]
pub struct TrieAccount {
/// Account nonce.
pub nonce: u64,
/// Account balance.
pub balance: U256,
/// Account's storage root.
pub storage_root: B256,
/// Hash of the account's bytecode.
pub code_hash: B256,
}
impl TrieAccount {
/// Get account's storage root.
pub const fn storage_root(&self) -> B256 {
self.storage_root
}
}
impl From<GenesisAccount> for TrieAccount {
fn from(account: GenesisAccount) -> Self {
let storage_root = account
.storage
.map(|storage| {
storage_root_unhashed(
storage
.into_iter()
.filter(|(_, value)| *value != B256::ZERO)
.map(|(slot, value)| (slot, U256::from_be_bytes(*value))),
)
})
.unwrap_or(EMPTY_ROOT_HASH);
Self {
nonce: account.nonce.unwrap_or_default(),
balance: account.balance,
storage_root,
code_hash: account.code.map_or(KECCAK_EMPTY, keccak256),
}
}
}
impl From<(Account, B256)> for TrieAccount {
fn from((account, storage_root): (Account, B256)) -> Self {
Self {
nonce: account.nonce,
balance: account.balance,
storage_root,
code_hash: account.bytecode_hash.unwrap_or(KECCAK_EMPTY),
}
}
}
impl From<(AccountInfo, B256)> for TrieAccount {
fn from((account, storage_root): (AccountInfo, B256)) -> Self {
Self {
nonce: account.nonce,
balance: account.balance,
storage_root,
code_hash: account.code_hash,
}
}
}

View File

@ -31,4 +31,11 @@ pub use storage::StorageTrieEntry;
mod subnode;
pub use subnode::StoredSubNode;
mod proofs;
#[cfg(any(test, feature = "test-utils"))]
pub use proofs::triehash;
pub use proofs::{AccountProof, StorageProof};
pub mod root;
pub use alloy_trie::{proof, BranchNodeCompact, HashBuilder, TrieMask, EMPTY_ROOT_HASH};

View File

@ -1,12 +1,13 @@
//! Merkle trie proofs.
use super::{traits::IntoTrieAccount, Nibbles};
use crate::{keccak256, Account, Address, Bytes, B256, U256};
use crate::{Nibbles, TrieAccount};
use alloy_primitives::{keccak256, Address, Bytes, B256, U256};
use alloy_rlp::encode_fixed_size;
use alloy_trie::{
proof::{verify_proof, ProofVerificationError},
EMPTY_ROOT_HASH,
};
use reth_primitives_traits::Account;
/// The merkle proof with the relevant account info.
#[derive(PartialEq, Eq, Debug)]
@ -64,7 +65,7 @@ impl AccountProof {
let expected = if self.info.is_none() && self.storage_root == EMPTY_ROOT_HASH {
None
} else {
Some(alloy_rlp::encode(IntoTrieAccount::to_trie_account((
Some(alloy_rlp::encode(TrieAccount::from((
self.info.unwrap_or_default(),
self.storage_root,
))))
@ -122,3 +123,29 @@ impl StorageProof {
verify_proof(root, self.nibbles.clone(), expected, &self.proof)
}
}
/// Implementation of hasher using our keccak256 hashing function
/// for compatibility with `triehash` crate.
#[cfg(any(test, feature = "test-utils"))]
pub mod triehash {
use alloy_primitives::{keccak256, B256};
use hash_db::Hasher;
use plain_hasher::PlainHasher;
/// A [Hasher] that calculates a keccak256 hash of the given data.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct KeccakHasher;
#[cfg(any(test, feature = "test-utils"))]
impl Hasher for KeccakHasher {
type Out = B256;
type StdHasher = PlainHasher;
const LENGTH: usize = 32;
fn hash(x: &[u8]) -> Self::Out {
keccak256(x)
}
}
}

View File

@ -0,0 +1,117 @@
//! Common root computation functions.
use crate::TrieAccount;
use alloy_primitives::{keccak256, Address, B256, U256};
use alloy_rlp::Encodable;
use alloy_trie::HashBuilder;
use itertools::Itertools;
use nybbles::Nibbles;
/// 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<T: Encodable>(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<T, F>(items: &[T], mut encode: F) -> B256
where
F: FnMut(&T, &mut Vec<u8>),
{
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()
}
/// Hashes and sorts account keys, then proceeds to calculating the root hash of the state
/// represented as MPT.
/// See [`state_root_unsorted`] for more info.
pub fn state_root_ref_unhashed<'a, A: Into<TrieAccount> + Clone + 'a>(
state: impl IntoIterator<Item = (&'a Address, &'a A)>,
) -> B256 {
state_root_unsorted(
state.into_iter().map(|(address, account)| (keccak256(address), account.clone())),
)
}
/// Hashes and sorts account keys, then proceeds to calculating the root hash of the state
/// represented as MPT.
/// See [`state_root_unsorted`] for more info.
pub fn state_root_unhashed<A: Into<TrieAccount>>(
state: impl IntoIterator<Item = (Address, A)>,
) -> B256 {
state_root_unsorted(state.into_iter().map(|(address, account)| (keccak256(address), account)))
}
/// Sorts the hashed account keys and calculates the root hash of the state represented as MPT.
/// See [`state_root`] for more info.
pub fn state_root_unsorted<A: Into<TrieAccount>>(
state: impl IntoIterator<Item = (B256, A)>,
) -> B256 {
state_root(state.into_iter().sorted_by_key(|(key, _)| *key))
}
/// Calculates the root hash of the state represented as MPT.
/// Corresponds to [geth's `deriveHash`](https://github.com/ethereum/go-ethereum/blob/6c149fd4ad063f7c24d726a73bc0546badd1bc73/core/genesis.go#L119).
///
/// # Panics
///
/// If the items are not in sorted order.
pub fn state_root<A: Into<TrieAccount>>(state: impl IntoIterator<Item = (B256, A)>) -> B256 {
let mut hb = HashBuilder::default();
let mut account_rlp_buf = Vec::new();
for (hashed_key, account) in state {
account_rlp_buf.clear();
account.into().encode(&mut account_rlp_buf);
hb.add_leaf(Nibbles::unpack(hashed_key), &account_rlp_buf);
}
hb.root()
}
/// Hashes storage keys, sorts them and them calculates the root hash of the storage trie.
/// See [`storage_root_unsorted`] for more info.
pub fn storage_root_unhashed(storage: impl IntoIterator<Item = (B256, U256)>) -> B256 {
storage_root_unsorted(storage.into_iter().map(|(slot, value)| (keccak256(slot), value)))
}
/// Sorts and calculates the root hash of account storage trie.
/// See [`storage_root`] for more info.
pub fn storage_root_unsorted(storage: impl IntoIterator<Item = (B256, U256)>) -> B256 {
storage_root(storage.into_iter().sorted_by_key(|(key, _)| *key))
}
/// Calculates the root hash of account storage trie.
///
/// # Panics
///
/// If the items are not in sorted order.
pub fn storage_root(storage: impl IntoIterator<Item = (B256, U256)>) -> B256 {
let mut hb = HashBuilder::default();
for (hashed_slot, value) in storage {
hb.add_leaf(Nibbles::unpack(hashed_slot), alloy_rlp::encode_fixed_size(&value).as_ref());
}
hb.root()
}

View File

@ -3,7 +3,7 @@ use alloy_rlp::{BufMut, Encodable};
use itertools::Itertools;
use reth_db_api::database::Database;
use reth_execution_errors::StorageRootError;
use reth_primitives::{proofs::IntoTrieAccount, B256};
use reth_primitives::B256;
use reth_provider::{providers::ConsistentDbView, DatabaseProviderFactory, ProviderError};
use reth_tasks::pool::BlockingTaskPool;
use reth_trie::{
@ -12,7 +12,7 @@ use reth_trie::{
trie_cursor::TrieCursorFactory,
updates::TrieUpdates,
walker::TrieWalker,
HashBuilder, HashedPostState, Nibbles, StorageRoot,
HashBuilder, HashedPostState, Nibbles, StorageRoot, TrieAccount,
};
use std::{collections::HashMap, sync::Arc};
use thiserror::Error;
@ -170,7 +170,7 @@ where
}
account_rlp.clear();
let account = IntoTrieAccount::to_trie_account((account, storage_root));
let account = TrieAccount::from((account, storage_root));
account.encode(&mut account_rlp as &mut dyn BufMut);
hash_builder.add_leaf(Nibbles::unpack(hashed_address), &account_rlp);
}

View File

@ -3,7 +3,7 @@ use alloy_rlp::{BufMut, Encodable};
use rayon::prelude::*;
use reth_db_api::database::Database;
use reth_execution_errors::StorageRootError;
use reth_primitives::{proofs::IntoTrieAccount, B256};
use reth_primitives::B256;
use reth_provider::{providers::ConsistentDbView, DatabaseProviderFactory, ProviderError};
use reth_trie::{
hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory},
@ -11,7 +11,7 @@ use reth_trie::{
trie_cursor::TrieCursorFactory,
updates::TrieUpdates,
walker::TrieWalker,
HashBuilder, HashedPostState, Nibbles, StorageRoot,
HashBuilder, HashedPostState, Nibbles, StorageRoot, TrieAccount,
};
use std::collections::HashMap;
use thiserror::Error;
@ -152,7 +152,7 @@ where
}
account_rlp.clear();
let account = IntoTrieAccount::to_trie_account((account, storage_root));
let account = TrieAccount::from((account, storage_root));
account.encode(&mut account_rlp as &mut dyn BufMut);
hash_builder.add_leaf(Nibbles::unpack(hashed_address), &account_rlp);
}

View File

@ -18,7 +18,7 @@ reth-execution-errors.workspace = true
reth-db.workspace = true
reth-db-api.workspace = true
reth-stages-types.workspace = true
reth-trie-types.workspace = true
reth-trie-common.workspace = true
revm.workspace = true
@ -46,6 +46,7 @@ reth-primitives = { workspace = true, features = ["test-utils", "arbitrary"] }
reth-db = { workspace = true, features = ["test-utils"] }
reth-provider = { workspace = true, features = ["test-utils"] }
reth-storage-errors.workspace = true
reth-trie-common = { workspace = true, features = ["test-utils", "arbitrary"] }
# trie
triehash = "0.8"
@ -65,7 +66,7 @@ criterion.workspace = true
[features]
metrics = ["reth-metrics", "dep:metrics"]
test-utils = ["triehash"]
test-utils = ["triehash", "reth-trie-common/test-utils"]
[[bench]]
name = "prefix_set"
@ -74,3 +75,8 @@ harness = false
[[bench]]
name = "hash_post_state"
harness = false
[[bench]]
name = "trie_root"
required-features = ["test-utils"]
harness = false

View File

@ -1,7 +1,8 @@
#![allow(missing_docs, unreachable_pub)]
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner};
use reth_primitives::{proofs::triehash::KeccakHasher, ReceiptWithBloom, B256};
use reth_primitives::{ReceiptWithBloom, B256};
use reth_trie::triehash::KeccakHasher;
/// Benchmarks different implementations of the root calculation.
pub fn trie_root_benchmark(c: &mut Criterion) {
@ -41,8 +42,7 @@ criterion_main!(benches);
mod implementations {
use super::*;
use alloy_rlp::Encodable;
use reth_primitives::proofs::adjust_index_for_rlp;
use reth_trie_types::{HashBuilder, Nibbles};
use reth_trie_common::{root::adjust_index_for_rlp, HashBuilder, Nibbles};
pub fn trie_hash_ordered_trie_root(receipts: &[ReceiptWithBloom]) -> B256 {
triehash::ordered_trie_root::<KeccakHasher, _>(receipts.iter().map(|receipt| {

View File

@ -51,7 +51,7 @@ pub use progress::{IntermediateStateRootState, StateRootProgress};
pub mod stats;
// re-export for convenience
pub use reth_trie_types::*;
pub use reth_trie_common::*;
/// Trie calculation metrics.
#[cfg(feature = "metrics")]

View File

@ -10,13 +10,8 @@ use alloy_rlp::{BufMut, Encodable};
use reth_db::tables;
use reth_db_api::transaction::DbTx;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives::{
constants::EMPTY_ROOT_HASH,
keccak256,
proofs::{AccountProof, IntoTrieAccount, StorageProof},
Address, B256,
};
use reth_trie_types::proof::ProofRetainer;
use reth_primitives::{constants::EMPTY_ROOT_HASH, keccak256, Address, B256};
use reth_trie_common::{proof::ProofRetainer, AccountProof, StorageProof, TrieAccount};
/// A struct for generating merkle proofs.
///
/// Proof generator adds the target address and slots to the prefix set, enables the proof retainer
@ -83,7 +78,7 @@ where
};
account_rlp.clear();
let account = IntoTrieAccount::to_trie_account((account, storage_root));
let account = TrieAccount::from((account, storage_root));
account.encode(&mut account_rlp as &mut dyn BufMut);
hash_builder.add_leaf(Nibbles::unpack(hashed_address), &account_rlp);

View File

@ -1,8 +1,6 @@
use alloy_rlp::encode_fixed_size;
use reth_primitives::{
proofs::{triehash::KeccakHasher, IntoTrieAccount},
Account, Address, B256, U256,
};
use reth_primitives::{Account, Address, B256, U256};
use reth_trie_common::{triehash::KeccakHasher, TrieAccount};
/// Re-export of [triehash].
pub use triehash;
@ -15,7 +13,7 @@ where
{
let encoded_accounts = accounts.into_iter().map(|(address, (account, storage))| {
let storage_root = storage_root(storage);
let account = IntoTrieAccount::to_trie_account((account, storage_root));
let account = TrieAccount::from((account, storage_root));
(address, alloy_rlp::encode(account))
});
triehash::sec_trie_root::<KeccakHasher, _, _, _>(encoded_accounts)
@ -36,7 +34,7 @@ where
{
let encoded_accounts = accounts.into_iter().map(|(address, (account, storage))| {
let storage_root = storage_root_prehashed(storage);
let account = IntoTrieAccount::to_trie_account((account, storage_root));
let account = TrieAccount::from((account, storage_root));
(address, alloy_rlp::encode(account))
});

View File

@ -7,14 +7,12 @@ use crate::{
trie_cursor::TrieCursorFactory,
updates::{TrieKey, TrieOp, TrieUpdates},
walker::TrieWalker,
HashBuilder, Nibbles,
HashBuilder, Nibbles, TrieAccount,
};
use alloy_rlp::{BufMut, Encodable};
use reth_db_api::transaction::DbTx;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives::{
constants::EMPTY_ROOT_HASH, keccak256, proofs::IntoTrieAccount, Address, BlockNumber, B256,
};
use reth_primitives::{constants::EMPTY_ROOT_HASH, keccak256, Address, BlockNumber, B256};
use std::ops::RangeInclusive;
use tracing::{debug, trace};
@ -282,7 +280,7 @@ where
};
account_rlp.clear();
let account = IntoTrieAccount::to_trie_account((account, storage_root));
let account = TrieAccount::from((account, storage_root));
account.encode(&mut account_rlp as &mut dyn BufMut);
hash_builder.add_leaf(Nibbles::unpack(hashed_address), &account_rlp);
@ -558,10 +556,9 @@ mod tests {
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
transaction::DbTxMut,
};
use reth_primitives::{
hex_literal::hex, proofs::triehash::KeccakHasher, Account, StorageEntry, U256,
};
use reth_primitives::{hex_literal::hex, Account, StorageEntry, U256};
use reth_provider::{test_utils::create_test_provider_factory, DatabaseProviderRW};
use reth_trie_common::triehash::KeccakHasher;
use std::{
collections::{BTreeMap, HashMap},
ops::Mul,
@ -828,8 +825,7 @@ mod tests {
}
fn encode_account(account: Account, storage_root: Option<B256>) -> Vec<u8> {
let account =
IntoTrieAccount::to_trie_account((account, storage_root.unwrap_or(EMPTY_ROOT_HASH)));
let account = TrieAccount::from((account, storage_root.unwrap_or(EMPTY_ROOT_HASH)));
let mut account_rlp = Vec::with_capacity(account.length());
account.encode(&mut account_rlp);
account_rlp

View File

@ -1,22 +0,0 @@
use alloy_primitives::{B256, U256};
use alloy_rlp::{RlpDecodable, RlpEncodable};
/// An Ethereum account as represented in the trie.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)]
pub struct TrieAccount {
/// Account nonce.
pub nonce: u64,
/// Account balance.
pub balance: U256,
/// Account's storage root.
pub storage_root: B256,
/// Hash of the account's bytecode.
pub code_hash: B256,
}
impl TrieAccount {
/// Get account's storage root.
pub const fn storage_root(&self) -> B256 {
self.storage_root
}
}