mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
refactor: extract optimism receipts hashing logic to reth-optimism-consensus (#11230)
This commit is contained in:
@ -35,6 +35,9 @@ alloy-primitives.workspace = true
|
||||
revm-primitives.workspace = true
|
||||
alloy-rpc-types-engine.workspace = true
|
||||
|
||||
# optimism
|
||||
reth-optimism-consensus = { workspace = true, optional = true }
|
||||
|
||||
# async
|
||||
futures-util.workspace = true
|
||||
tokio = { workspace = true, features = ["sync", "time"] }
|
||||
@ -42,4 +45,4 @@ tokio-stream.workspace = true
|
||||
tracing.workspace = true
|
||||
|
||||
[features]
|
||||
optimism = ["reth-provider/optimism"]
|
||||
optimism = ["reth-provider/optimism", "reth-optimism-consensus"]
|
||||
|
||||
@ -419,7 +419,13 @@ impl StorageInner {
|
||||
header.receipts_root = {
|
||||
#[cfg(feature = "optimism")]
|
||||
let receipts_root = execution_outcome
|
||||
.optimism_receipts_root_slow(header.number, &chain_spec, header.timestamp)
|
||||
.generic_receipts_root_slow(header.number, |receipts| {
|
||||
reth_optimism_consensus::calculate_receipt_root_no_memo_optimism(
|
||||
receipts,
|
||||
&chain_spec,
|
||||
header.timestamp,
|
||||
)
|
||||
})
|
||||
.expect("Receipts is present");
|
||||
|
||||
#[cfg(not(feature = "optimism"))]
|
||||
|
||||
@ -12,7 +12,6 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
reth-primitives.workspace = true
|
||||
reth-chainspec = { workspace = true, optional = true }
|
||||
reth-execution-errors.workspace = true
|
||||
reth-trie.workspace = true
|
||||
|
||||
@ -31,6 +30,6 @@ alloy-eips.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
optimism = ["dep:reth-chainspec"]
|
||||
optimism = []
|
||||
serde = ["dep:serde", "reth-trie/serde", "revm/serde"]
|
||||
std = []
|
||||
|
||||
@ -196,24 +196,21 @@ impl ExecutionOutcome {
|
||||
#[cfg(feature = "optimism")]
|
||||
panic!("This should not be called in optimism mode. Use `optimism_receipts_root_slow` instead.");
|
||||
#[cfg(not(feature = "optimism"))]
|
||||
self.receipts.root_slow(self.block_number_to_index(_block_number)?)
|
||||
self.receipts.root_slow(
|
||||
self.block_number_to_index(_block_number)?,
|
||||
reth_primitives::proofs::calculate_receipt_root_no_memo,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the receipt root for all recorded receipts.
|
||||
/// Note: this function calculated Bloom filters for every receipt and created merkle trees
|
||||
/// of receipt. This is a expensive operation.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub fn optimism_receipts_root_slow(
|
||||
pub fn generic_receipts_root_slow(
|
||||
&self,
|
||||
block_number: BlockNumber,
|
||||
chain_spec: impl reth_chainspec::Hardforks,
|
||||
timestamp: u64,
|
||||
f: impl FnOnce(&[&Receipt]) -> B256,
|
||||
) -> Option<B256> {
|
||||
self.receipts.optimism_root_slow(
|
||||
self.block_number_to_index(block_number)?,
|
||||
chain_spec,
|
||||
timestamp,
|
||||
)
|
||||
self.receipts.root_slow(self.block_number_to_index(block_number)?, f)
|
||||
}
|
||||
|
||||
/// Returns reference to receipts.
|
||||
|
||||
@ -25,6 +25,8 @@ use reth_primitives::{
|
||||
use std::{sync::Arc, time::SystemTime};
|
||||
|
||||
mod proof;
|
||||
pub use proof::calculate_receipt_root_no_memo_optimism;
|
||||
|
||||
mod validation;
|
||||
pub use validation::validate_block_post_execution;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use alloy_primitives::B256;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_optimism_forks::OptimismHardfork;
|
||||
use reth_primitives::ReceiptWithBloom;
|
||||
use reth_primitives::{Receipt, ReceiptWithBloom, ReceiptWithBloomRef};
|
||||
use reth_trie_common::root::ordered_trie_root_with_encoder;
|
||||
|
||||
/// Calculates the receipt root for a header.
|
||||
@ -37,6 +37,41 @@ pub(crate) fn calculate_receipt_root_optimism(
|
||||
ordered_trie_root_with_encoder(receipts, |r, buf| r.encode_inner(buf, false))
|
||||
}
|
||||
|
||||
/// Calculates the receipt root for a header for the reference type of [Receipt].
|
||||
///
|
||||
/// NOTE: Prefer calculate receipt root optimism if you have log blooms memoized.
|
||||
pub fn calculate_receipt_root_no_memo_optimism(
|
||||
receipts: &[&Receipt],
|
||||
chain_spec: impl reth_chainspec::Hardforks,
|
||||
timestamp: u64,
|
||||
) -> B256 {
|
||||
// There is a minor bug in op-geth and op-erigon where in the Regolith hardfork,
|
||||
// the receipt root calculation does not include the deposit nonce in the receipt
|
||||
// encoding. In the Regolith Hardfork, we must strip the deposit nonce from the
|
||||
// receipts before calculating the receipt root. This was corrected in the Canyon
|
||||
// hardfork.
|
||||
if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Regolith, timestamp) &&
|
||||
!chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Canyon, timestamp)
|
||||
{
|
||||
let receipts = receipts
|
||||
.iter()
|
||||
.map(|r| {
|
||||
let mut r = (*r).clone();
|
||||
r.deposit_nonce = None;
|
||||
r
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
return ordered_trie_root_with_encoder(&receipts, |r, buf| {
|
||||
ReceiptWithBloomRef::from(r).encode_inner(buf, false)
|
||||
})
|
||||
}
|
||||
|
||||
ordered_trie_root_with_encoder(receipts, |r, buf| {
|
||||
ReceiptWithBloomRef::from(*r).encode_inner(buf, false)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@ -29,6 +29,7 @@ reth-chain-state.workspace = true
|
||||
|
||||
# op-reth
|
||||
reth-evm-optimism.workspace = true
|
||||
reth-optimism-consensus.workspace = true
|
||||
reth-optimism-forks.workspace = true
|
||||
|
||||
# ethereum
|
||||
|
||||
@ -11,6 +11,7 @@ use reth_evm::{
|
||||
NextBlockEnvAttributes,
|
||||
};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism;
|
||||
use reth_optimism_forks::OptimismHardfork;
|
||||
use reth_payload_primitives::{PayloadBuilderAttributes, PayloadBuilderError};
|
||||
use reth_primitives::{
|
||||
@ -443,11 +444,9 @@ where
|
||||
Vec::new(),
|
||||
);
|
||||
let receipts_root = execution_outcome
|
||||
.optimism_receipts_root_slow(
|
||||
block_number,
|
||||
&chain_spec,
|
||||
attributes.payload_attributes.timestamp,
|
||||
)
|
||||
.generic_receipts_root_slow(block_number, |receipts| {
|
||||
calculate_receipt_root_no_memo_optimism(receipts, &chain_spec, attributes.timestamp())
|
||||
})
|
||||
.expect("Number is in range");
|
||||
let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range");
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ reth-chainspec.workspace = true
|
||||
|
||||
# op-reth
|
||||
reth-evm-optimism.workspace = true
|
||||
reth-optimism-consensus.workspace = true
|
||||
reth-optimism-forks.workspace = true
|
||||
|
||||
# ethereum
|
||||
|
||||
@ -4,6 +4,7 @@ use alloy_primitives::{BlockNumber, B256};
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_node_api::{FullNodeComponents, NodeTypes};
|
||||
use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism;
|
||||
use reth_primitives::{
|
||||
revm_primitives::BlockEnv, BlockNumberOrTag, Header, Receipt, SealedBlockWithSenders,
|
||||
};
|
||||
@ -79,16 +80,18 @@ where
|
||||
|
||||
fn receipts_root(
|
||||
&self,
|
||||
_block_env: &BlockEnv,
|
||||
block_env: &BlockEnv,
|
||||
execution_outcome: &ExecutionOutcome,
|
||||
block_number: BlockNumber,
|
||||
) -> B256 {
|
||||
execution_outcome
|
||||
.optimism_receipts_root_slow(
|
||||
block_number,
|
||||
self.provider().chain_spec().as_ref(),
|
||||
_block_env.timestamp.to::<u64>(),
|
||||
)
|
||||
.generic_receipts_root_slow(block_number, |receipts| {
|
||||
calculate_receipt_root_no_memo_optimism(
|
||||
receipts,
|
||||
self.provider().chain_spec().as_ref(),
|
||||
block_env.timestamp.to::<u64>(),
|
||||
)
|
||||
})
|
||||
.expect("Block is present")
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,12 +18,10 @@ reth-ethereum-forks.workspace = true
|
||||
reth-static-file-types.workspace = true
|
||||
reth-trie-common.workspace = true
|
||||
revm-primitives = { workspace = true, features = ["serde"] }
|
||||
reth-chainspec = { workspace = true, optional = true }
|
||||
reth-codecs = { workspace = true, optional = true }
|
||||
|
||||
# op-reth
|
||||
reth-optimism-chainspec = { workspace = true, optional = true }
|
||||
reth-optimism-forks = { workspace = true, optional = true }
|
||||
|
||||
# ethereum
|
||||
alloy-consensus.workspace = true
|
||||
@ -96,7 +94,6 @@ asm-keccak = ["alloy-primitives/asm-keccak"]
|
||||
arbitrary = [
|
||||
"reth-primitives-traits/arbitrary",
|
||||
"revm-primitives/arbitrary",
|
||||
"reth-chainspec?/arbitrary",
|
||||
"reth-ethereum-forks/arbitrary",
|
||||
"alloy-eips/arbitrary",
|
||||
"dep:arbitrary",
|
||||
@ -111,12 +108,10 @@ c-kzg = [
|
||||
"alloy-consensus/kzg",
|
||||
]
|
||||
optimism = [
|
||||
"reth-chainspec/optimism",
|
||||
"revm-primitives/optimism",
|
||||
"reth-codecs?/optimism",
|
||||
"dep:reth-optimism-chainspec",
|
||||
"dep:op-alloy-consensus",
|
||||
"reth-optimism-forks",
|
||||
]
|
||||
alloy-compat = [
|
||||
"dep:alloy-rpc-types",
|
||||
|
||||
@ -49,47 +49,6 @@ pub fn calculate_receipt_root_no_memo(receipts: &[&Receipt]) -> B256 {
|
||||
})
|
||||
}
|
||||
|
||||
/// Calculates the receipt root for a header for the reference type of [Receipt].
|
||||
///
|
||||
/// NOTE: Prefer calculate receipt root optimism if you have log blooms memoized.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub fn calculate_receipt_root_no_memo_optimism(
|
||||
receipts: &[&Receipt],
|
||||
chain_spec: impl reth_chainspec::Hardforks,
|
||||
timestamp: u64,
|
||||
) -> B256 {
|
||||
// There is a minor bug in op-geth and op-erigon where in the Regolith hardfork,
|
||||
// the receipt root calculation does not include the deposit nonce in the receipt
|
||||
// encoding. In the Regolith Hardfork, we must strip the deposit nonce from the
|
||||
// receipts before calculating the receipt root. This was corrected in the Canyon
|
||||
// hardfork.
|
||||
|
||||
if chain_spec
|
||||
.is_fork_active_at_timestamp(reth_optimism_forks::OptimismHardfork::Regolith, timestamp) &&
|
||||
!chain_spec.is_fork_active_at_timestamp(
|
||||
reth_optimism_forks::OptimismHardfork::Canyon,
|
||||
timestamp,
|
||||
)
|
||||
{
|
||||
let receipts = receipts
|
||||
.iter()
|
||||
.map(|r| {
|
||||
let mut r = (*r).clone();
|
||||
r.deposit_nonce = None;
|
||||
r
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
return ordered_trie_root_with_encoder(&receipts, |r, buf| {
|
||||
ReceiptWithBloomRef::from(r).encode_inner(buf, false)
|
||||
})
|
||||
}
|
||||
|
||||
ordered_trie_root_with_encoder(receipts, |r, buf| {
|
||||
ReceiptWithBloomRef::from(*r).encode_inner(buf, false)
|
||||
})
|
||||
}
|
||||
|
||||
/// Calculates the root hash for ommer/uncle headers.
|
||||
pub fn calculate_ommers_root(ommers: &[Header]) -> B256 {
|
||||
// Check if `ommers` list is empty
|
||||
|
||||
@ -100,26 +100,11 @@ impl Receipts {
|
||||
self.receipt_vec.push(receipts);
|
||||
}
|
||||
|
||||
/// Retrieves the receipt root for all recorded receipts from index.
|
||||
pub fn root_slow(&self, index: usize) -> Option<B256> {
|
||||
Some(crate::proofs::calculate_receipt_root_no_memo(
|
||||
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Retrieves the receipt root for all recorded receipts from index.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub fn optimism_root_slow(
|
||||
&self,
|
||||
index: usize,
|
||||
chain_spec: impl reth_chainspec::Hardforks,
|
||||
timestamp: u64,
|
||||
) -> Option<B256> {
|
||||
Some(crate::proofs::calculate_receipt_root_no_memo_optimism(
|
||||
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
|
||||
chain_spec,
|
||||
timestamp,
|
||||
))
|
||||
/// Retrieves all recorded receipts from index and calculates the root using the given closure.
|
||||
pub fn root_slow(&self, index: usize, f: impl FnOnce(&[&Receipt]) -> B256) -> Option<B256> {
|
||||
let receipts =
|
||||
self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?;
|
||||
Some(f(receipts.as_slice()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user