Skip to content

Commit

Permalink
split eth/op validations
Browse files Browse the repository at this point in the history
  • Loading branch information
shekhirin committed May 22, 2024
1 parent 9bfde10 commit a0d47a6
Show file tree
Hide file tree
Showing 10 changed files with 31 additions and 97 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

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

82 changes: 1 addition & 81 deletions crates/consensus/common/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ use reth_primitives::{
eip4844::{DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK},
MAXIMUM_EXTRA_DATA_SIZE,
},
gas_spent_by_transactions,
op_mainnet::is_dup_tx,
BlockWithSenders, Bloom, ChainSpec, GotExpected, Hardfork, Header, Receipt, ReceiptWithBloom,
SealedBlock, SealedHeader, B256,
ChainSpec, GotExpected, Hardfork, Header, SealedBlock, SealedHeader,
};

/// Validate header standalone
Expand Down Expand Up @@ -113,84 +111,6 @@ pub fn validate_block_pre_execution(
Ok(())
}

/// Validate a block with regard to execution results:
///
///
/// - Compares the receipts root in the block header to the block body
/// - Compares the gas used in the block header to the actual gas usage after execution
pub fn validate_block_post_execution(
block: &BlockWithSenders,
chain_spec: &ChainSpec,
receipts: &[Receipt],
) -> Result<(), ConsensusError> {
// Before Byzantium, receipts contained state root that would mean that expensive
// operation as hashing that is required for state root got calculated in every
// transaction This was replaced with is_success flag.
// See more about EIP here: https://eips.ethereum.org/EIPS/eip-658
if chain_spec.is_byzantium_active_at_block(block.header.number) {
verify_receipts(block.header.receipts_root, block.header.logs_bloom, receipts.iter())?;
}

// Check if gas used matches the value set in header.
let cumulative_gas_used =
receipts.last().map(|receipt| receipt.cumulative_gas_used).unwrap_or(0);
if block.gas_used != cumulative_gas_used {
return Err(ConsensusError::BlockGasUsed {
gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used },
gas_spent_by_tx: gas_spent_by_transactions(receipts),
})
}

Ok(())
}

/// Calculate the receipts root, and compare it against against the expected receipts root and logs
/// bloom.
fn verify_receipts<'a>(
expected_receipts_root: B256,
expected_logs_bloom: Bloom,
receipts: impl Iterator<Item = &'a Receipt> + Clone,
) -> Result<(), ConsensusError> {
// Calculate receipts root.
let receipts_with_bloom = receipts.map(|r| r.clone().into()).collect::<Vec<ReceiptWithBloom>>();
let receipts_root = reth_primitives::proofs::calculate_receipt_root(&receipts_with_bloom);

// Create header log bloom.
let logs_bloom = receipts_with_bloom.iter().fold(Bloom::ZERO, |bloom, r| bloom | r.bloom);

compare_receipts_root_and_logs_bloom(
receipts_root,
logs_bloom,
expected_receipts_root,
expected_logs_bloom,
)?;

Ok(())
}

/// Compare the calculated receipts root with the expected receipts root, also compare
/// the calculated logs bloom with the expected logs bloom.
fn compare_receipts_root_and_logs_bloom(
calculated_receipts_root: B256,
calculated_logs_bloom: Bloom,
expected_receipts_root: B256,
expected_logs_bloom: Bloom,
) -> Result<(), ConsensusError> {
if calculated_receipts_root != expected_receipts_root {
return Err(ConsensusError::BodyReceiptRootDiff(
GotExpected { got: calculated_receipts_root, expected: expected_receipts_root }.into(),
))
}

if calculated_logs_bloom != expected_logs_bloom {
return Err(ConsensusError::BodyBloomLogDiff(
GotExpected { got: calculated_logs_bloom, expected: expected_logs_bloom }.into(),
))
}

Ok(())
}

/// Validates that the EIP-4844 header fields exist and conform to the spec. This ensures that:
///
/// * `blob_gas_used` exists as a header field
Expand Down
2 changes: 1 addition & 1 deletion crates/ethereum/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ reth-primitives.workspace = true
reth-consensus.workspace = true

[features]
optimism = ["reth-primitives/optimism"]
optimism = ["reth-primitives/optimism"]
17 changes: 11 additions & 6 deletions crates/ethereum/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

use reth_consensus::{Consensus, ConsensusError};
use reth_consensus_common::validation;
use reth_consensus_common::validation::{
validate_block_pre_execution, validate_header_extradata, validate_header_standalone,
};
use reth_primitives::{
BlockWithSenders, Chain, ChainSpec, Hardfork, Header, Receipt, SealedBlock, SealedHeader,
EMPTY_OMMER_ROOT_HASH, U256,
};
use std::{sync::Arc, time::SystemTime};

mod validation;
pub use validation::validate_block_post_execution;

/// Ethereum beacon consensus
///
/// This consensus engine does basic checks as outlined in the execution specs.
Expand All @@ -34,7 +39,7 @@ impl EthBeaconConsensus {

impl Consensus for EthBeaconConsensus {
fn validate_header(&self, header: &SealedHeader) -> Result<(), ConsensusError> {
validation::validate_header_standalone(header, &self.chain_spec)?;
validate_header_standalone(header, &self.chain_spec)?;
Ok(())
}

Expand Down Expand Up @@ -88,7 +93,7 @@ impl Consensus for EthBeaconConsensus {
// is greater than its parent timestamp.

// validate header extradata for all networks post merge
validation::validate_header_extradata(header)?;
validate_header_extradata(header)?;

// mixHash is used instead of difficulty inside EVM
// https://eips.ethereum.org/EIPS/eip-4399#using-mixhash-field-instead-of-difficulty
Expand All @@ -112,22 +117,22 @@ impl Consensus for EthBeaconConsensus {
// * If the network is goerli pre-merge, ignore the extradata check, since we do not
// support clique. Same goes for OP blocks below Bedrock.
if self.chain_spec.chain != Chain::goerli() && !self.chain_spec.is_optimism() {
validation::validate_header_extradata(header)?;
validate_header_extradata(header)?;
}
}

Ok(())
}

fn validate_block_pre_execution(&self, block: &SealedBlock) -> Result<(), ConsensusError> {
validation::validate_block_pre_execution(block, &self.chain_spec)
validate_block_pre_execution(block, &self.chain_spec)
}

fn validate_block_post_execution(
&self,
block: &BlockWithSenders,
receipts: &[Receipt],
) -> Result<(), ConsensusError> {
validation::validate_block_post_execution(block, &self.chain_spec, receipts)
validate_block_post_execution(block, &self.chain_spec, receipts)
}
}
2 changes: 1 addition & 1 deletion crates/ethereum/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ reth-evm.workspace = true
reth-primitives.workspace = true
reth-revm.workspace = true
reth-interfaces.workspace = true
reth-consensus-common.workspace = true
reth-ethereum-consensus.workspace = true

# Ethereum
revm-primitives.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
dao_fork::{DAO_HARDFORK_BENEFICIARY, DAO_HARDKFORK_ACCOUNTS},
EthEvmConfig,
};
use reth_consensus_common::validation::validate_block_post_execution;
use reth_ethereum_consensus::validate_block_post_execution;
use reth_evm::{
execute::{
BatchBlockExecutionOutput, BatchExecutor, BlockExecutionInput, BlockExecutionOutput,
Expand Down
2 changes: 1 addition & 1 deletion crates/optimism/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ reth-consensus.workspace = true
[features]
optimism = [
"reth-primitives/optimism",
]
]
13 changes: 9 additions & 4 deletions crates/optimism/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@
#![cfg(feature = "optimism")]

use reth_consensus::{Consensus, ConsensusError};
use reth_consensus_common::validation::{self, validate_header_extradata};
use reth_consensus_common::validation::{
validate_block_pre_execution, validate_header_extradata, validate_header_standalone,
};
use reth_primitives::{
BlockWithSenders, ChainSpec, Header, Receipt, SealedBlock, SealedHeader, EMPTY_OMMER_ROOT_HASH,
U256,
};
use std::{sync::Arc, time::SystemTime};

mod validation;
pub use validation::validate_block_post_execution;

/// Optimism consensus implementation.
///
/// Provides basic checks as outlined in the execution specs.
Expand All @@ -40,7 +45,7 @@ impl OptimismBeaconConsensus {

impl Consensus for OptimismBeaconConsensus {
fn validate_header(&self, header: &SealedHeader) -> Result<(), ConsensusError> {
validation::validate_header_standalone(header, &self.chain_spec)?;
validate_header_standalone(header, &self.chain_spec)?;
Ok(())
}

Expand Down Expand Up @@ -100,14 +105,14 @@ impl Consensus for OptimismBeaconConsensus {
}

fn validate_block_pre_execution(&self, block: &SealedBlock) -> Result<(), ConsensusError> {
validation::validate_block_pre_execution(block, &self.chain_spec)
validate_block_pre_execution(block, &self.chain_spec)
}

fn validate_block_post_execution(
&self,
block: &BlockWithSenders,
receipts: &[Receipt],
) -> Result<(), ConsensusError> {
validation::validate_block_post_execution(block, &self.chain_spec, receipts)
validate_block_post_execution(block, &self.chain_spec, receipts)
}
}
3 changes: 3 additions & 0 deletions crates/optimism/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ reth-provider.workspace = true
reth-consensus-common.workspace = true

# Optimism
reth-optimism-consensus.workspace = true

# revm
revm.workspace = true
revm-primitives.workspace = true

Expand Down
2 changes: 1 addition & 1 deletion crates/optimism/evm/src/execute.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Optimism block executor.
use crate::{l1::ensure_create2_deployer, OptimismBlockExecutionError, OptimismEvmConfig};
use reth_consensus_common::validation::validate_block_post_execution;
use reth_evm::{
execute::{
BatchBlockExecutionOutput, BatchExecutor, BlockExecutionInput, BlockExecutionOutput,
Expand All @@ -13,6 +12,7 @@ use reth_interfaces::{
executor::{BlockExecutionError, BlockValidationError},
provider::ProviderError,
};
use reth_optimism_consensus::validate_block_post_execution;
use reth_primitives::{
BlockNumber, BlockWithSenders, ChainSpec, Hardfork, Header, PruneModes, Receipt, Receipts,
TxType, Withdrawals, U256,
Expand Down

0 comments on commit a0d47a6

Please sign in to comment.