Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: extract optimism receipts hashing logic to reth-optimism-consensus #11230

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion crates/consensus/auto-seal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ 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"] }
tokio-stream.workspace = true
tracing.workspace = true

[features]
optimism = ["reth-provider/optimism"]
optimism = ["reth-provider/optimism", "reth-optimism-consensus"]
8 changes: 7 additions & 1 deletion crates/consensus/auto-seal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down
3 changes: 1 addition & 2 deletions crates/evm/execution-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -27,6 +26,6 @@ alloy-eips.workspace = true

[features]
default = ["std"]
optimism = ["dep:reth-chainspec"]
optimism = []
serde = ["dep:serde", "reth-trie/serde", "revm/serde"]
std = []
17 changes: 7 additions & 10 deletions crates/evm/execution-types/src/execution_outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,24 +198,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.
Expand Down
2 changes: 2 additions & 0 deletions crates/optimism/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
37 changes: 36 additions & 1 deletion crates/optimism/consensus/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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::*;
Expand Down
1 change: 1 addition & 0 deletions crates/optimism/payload/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 4 additions & 5 deletions crates/optimism/payload/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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");

Expand Down
1 change: 1 addition & 0 deletions crates/optimism/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 9 additions & 6 deletions crates/optimism/rpc/src/eth/pending_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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")
}
}
5 changes: 0 additions & 5 deletions crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand Down
41 changes: 0 additions & 41 deletions crates/primitives/src/proofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 5 additions & 20 deletions crates/primitives/src/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
}
}

Expand Down
Loading