chore: remove op-flagged arguments from receipt root calc (#6517)

This commit is contained in:
Dan Cline
2024-02-09 12:55:08 -05:00
committed by GitHub
parent cede8b7dd6
commit cd0a2f34bc
6 changed files with 141 additions and 49 deletions

View File

@ -1243,10 +1243,14 @@ mod tests {
use reth_db::{tables, test_utils::TempDatabase, transaction::DbTxMut, DatabaseEnv};
use reth_interfaces::test_utils::TestConsensus;
use reth_node_ethereum::EthEvmConfig;
#[cfg(not(feature = "optimism"))]
use reth_primitives::proofs::calculate_receipt_root;
#[cfg(feature = "optimism")]
use reth_primitives::proofs::calculate_receipt_root_optimism;
use reth_primitives::{
constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_ROOT_HASH, ETHEREUM_BLOCK_GAS_LIMIT},
keccak256,
proofs::{calculate_receipt_root, calculate_transaction_root, state_root_unhashed},
proofs::{calculate_transaction_root, state_root_unhashed},
revm_primitives::AccountInfo,
stage::StageCheckpoint,
Account, Address, ChainSpecBuilder, Genesis, GenesisAccount, Header, Signature,
@ -1466,7 +1470,7 @@ mod tests {
let receipts_root = calculate_receipt_root(&receipts);
#[cfg(feature = "optimism")]
let receipts_root = calculate_receipt_root(&receipts, &chain_spec, 0);
let receipts_root = calculate_receipt_root_optimism(&receipts, &chain_spec, 0);
SealedBlockWithSenders::new(
SealedBlock {

View File

@ -345,13 +345,17 @@ impl StorageInner {
/// Fills in the post-execution header fields based on the given BundleState and gas used.
/// In doing this, the state root is calculated and the final header is returned.
///
/// This is optimism-specific and contains the `ChainSpec` so the proper state root can be
/// calculated.
#[cfg(feature = "optimism")]
pub(crate) fn complete_header<S: StateProviderFactory>(
&self,
mut header: Header,
bundle_state: &BundleStateWithReceipts,
client: &S,
gas_used: u64,
#[cfg(feature = "optimism")] chain_spec: &ChainSpec,
chain_spec: &ChainSpec,
) -> Result<Header, BlockExecutionError> {
let receipts = bundle_state.receipts_by_block(header.number);
header.receipts_root = if receipts.is_empty() {
@ -363,11 +367,9 @@ impl StorageInner {
.collect::<Vec<ReceiptWithBloom>>();
header.logs_bloom =
receipts_with_bloom.iter().fold(Bloom::ZERO, |bloom, r| bloom | r.bloom);
proofs::calculate_receipt_root(
proofs::calculate_receipt_root_optimism(
&receipts_with_bloom,
#[cfg(feature = "optimism")]
chain_spec,
#[cfg(feature = "optimism")]
header.timestamp,
)
};
@ -384,6 +386,41 @@ impl StorageInner {
Ok(header)
}
/// Fills in the post-execution header fields based on the given BundleState and gas used.
/// In doing this, the state root is calculated and the final header is returned.
#[cfg(not(feature = "optimism"))]
pub(crate) fn complete_header<S: StateProviderFactory>(
&self,
mut header: Header,
bundle_state: &BundleStateWithReceipts,
client: &S,
gas_used: u64,
) -> Result<Header, BlockExecutionError> {
let receipts = bundle_state.receipts_by_block(header.number);
header.receipts_root = if receipts.is_empty() {
EMPTY_RECEIPTS
} else {
let receipts_with_bloom = receipts
.iter()
.map(|r| (*r).clone().expect("receipts have not been pruned").into())
.collect::<Vec<ReceiptWithBloom>>();
header.logs_bloom =
receipts_with_bloom.iter().fold(Bloom::ZERO, |bloom, r| bloom | r.bloom);
proofs::calculate_receipt_root(&receipts_with_bloom)
};
header.gas_used = gas_used;
// calculate the state root
let state_root = client
.latest()
.map_err(|_| BlockExecutionError::ProviderError)?
.state_root(bundle_state)
.unwrap();
header.state_root = state_root;
Ok(header)
}
/// Builds and executes a new block with the given transactions, on the provided [EVMProcessor].
///
/// This returns the header of the executed block, as well as the poststate from execution.

View File

@ -69,14 +69,13 @@ pub fn calculate_withdrawals_root(withdrawals: &[Withdrawal]) -> B256 {
}
/// Calculates the receipt root for a header.
#[cfg(not(feature = "optimism"))]
pub fn calculate_receipt_root(receipts: &[ReceiptWithBloom]) -> B256 {
ordered_trie_root_with_encoder(receipts, |r, buf| r.encode_inner(buf, false))
}
/// Calculates the receipt root for a header.
#[cfg(feature = "optimism")]
pub fn calculate_receipt_root(
pub fn calculate_receipt_root_optimism(
receipts: &[ReceiptWithBloom],
chain_spec: &crate::ChainSpec,
timestamp: u64,
@ -109,7 +108,6 @@ pub fn calculate_receipt_root(
/// Calculates the receipt root for a header for the reference type of [Receipt].
///
/// NOTE: Prefer [calculate_receipt_root] if you have log blooms memoized.
#[cfg(not(feature = "optimism"))]
pub fn calculate_receipt_root_ref(receipts: &[&Receipt]) -> B256 {
ordered_trie_root_with_encoder(receipts, |r, buf| {
ReceiptWithBloomRef::from(*r).encode_inner(buf, false)
@ -120,7 +118,7 @@ pub fn calculate_receipt_root_ref(receipts: &[&Receipt]) -> B256 {
///
/// NOTE: Prefer [calculate_receipt_root] if you have log blooms memoized.
#[cfg(feature = "optimism")]
pub fn calculate_receipt_root_ref(
pub fn calculate_receipt_root_ref_optimism(
receipts: &[&Receipt],
chain_spec: &crate::ChainSpec,
timestamp: u64,
@ -263,11 +261,10 @@ pub mod triehash {
#[cfg(test)]
mod tests {
use super::*;
#[cfg(not(feature = "optimism"))]
use crate::proofs::calculate_receipt_root;
use crate::{
bloom,
constants::EMPTY_ROOT_HASH,
hex_literal::hex,
proofs::{calculate_receipt_root, calculate_transaction_root},
bloom, constants::EMPTY_ROOT_HASH, hex_literal::hex, proofs::calculate_transaction_root,
Address, Block, GenesisAccount, Log, Receipt, ReceiptWithBloom, TxType, B256, GOERLI,
HOLESKY, MAINNET, SEPOLIA, U256,
};
@ -543,13 +540,14 @@ mod tests {
bloom: Bloom(hex!("00000000000000000000000000000000400000000000000000000000000000000000004000000000000001000000000000000002000000000100000000000000000000000000000000000008000000000000000000000000000000000000000004000000020000000000000000000800000000000000000000000010200100200008000002000000000000000000800000000000000000000002000000000000000000000000000000080000000000000000000000004000000000000000000000000002000000000000000000000000000000000000200000000000000020002000000000000000002000000000000000000000000000000000000000000000").into()),
},
];
let root = calculate_receipt_root(&receipts, OP_GOERLI.as_ref(), case.1);
let root = calculate_receipt_root_optimism(&receipts, OP_GOERLI.as_ref(), case.1);
assert_eq!(root, case.2);
}
}
#[cfg(feature = "optimism")]
#[test]
fn check_receipt_root() {
fn check_receipt_root_optimism() {
let logs = vec![Log { address: Address::ZERO, topics: vec![], data: Default::default() }];
let bloom = bloom!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
let receipt = ReceiptWithBloom {
@ -558,21 +556,32 @@ mod tests {
success: true,
cumulative_gas_used: 102068,
logs,
#[cfg(feature = "optimism")]
deposit_nonce: None,
#[cfg(feature = "optimism")]
deposit_receipt_version: None,
},
bloom,
};
let receipt = vec![receipt];
let root = calculate_receipt_root(
&receipt,
#[cfg(feature = "optimism")]
crate::OP_GOERLI.as_ref(),
#[cfg(feature = "optimism")]
0,
);
let root = calculate_receipt_root_optimism(&receipt, crate::OP_GOERLI.as_ref(), 0);
assert_eq!(root, b256!("fe70ae4a136d98944951b2123859698d59ad251a381abc9960fa81cae3d0d4a0"));
}
#[cfg(not(feature = "optimism"))]
#[test]
fn check_receipt_root_optimism() {
let logs = vec![Log { address: Address::ZERO, topics: vec![], data: Default::default() }];
let bloom = bloom!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
let receipt = ReceiptWithBloom {
receipt: Receipt {
tx_type: TxType::EIP2930,
success: true,
cumulative_gas_used: 102068,
logs,
},
bloom,
};
let receipt = vec![receipt];
let root = calculate_receipt_root(&receipt);
assert_eq!(root, b256!("fe70ae4a136d98944951b2123859698d59ad251a381abc9960fa81cae3d0d4a0"));
}

View File

@ -1,8 +1,10 @@
#[cfg(not(feature = "optimism"))]
use crate::proofs::calculate_receipt_root_ref;
#[cfg(feature = "optimism")]
use crate::proofs::calculate_receipt_root_ref_optimism;
use crate::{
compression::{RECEIPT_COMPRESSOR, RECEIPT_DECOMPRESSOR},
logs_bloom,
proofs::calculate_receipt_root_ref,
Bloom, Log, PruneSegmentError, TxType, B256,
logs_bloom, Bloom, Log, PruneSegmentError, TxType, B256,
};
use alloy_rlp::{length_of_length, Decodable, Encodable};
use bytes::{Buf, BufMut, BytesMut};
@ -110,7 +112,7 @@ impl Receipts {
chain_spec: &crate::ChainSpec,
timestamp: u64,
) -> Option<B256> {
Some(calculate_receipt_root_ref(
Some(calculate_receipt_root_ref_optimism(
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
chain_spec,
timestamp,

View File

@ -1,16 +1,43 @@
use crate::processor::{verify_receipt, EVMProcessor};
use crate::processor::{compare_receipts_root_and_logs_bloom, EVMProcessor};
use reth_interfaces::executor::{
BlockExecutionError, BlockValidationError, OptimismBlockExecutionError,
};
use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{
revm_primitives::ResultAndState, BlockWithSenders, Hardfork, Receipt, TxType, U256,
proofs::calculate_receipt_root_optimism, revm_primitives::ResultAndState, BlockWithSenders,
Bloom, ChainSpec, Hardfork, Receipt, ReceiptWithBloom, TxType, B256, U256,
};
use reth_provider::{BlockExecutor, BlockExecutorStats, BundleStateWithReceipts};
use revm::DatabaseCommit;
use std::time::Instant;
use tracing::{debug, trace};
/// Verify the calculated receipts root against the expected receipts root.
pub fn verify_receipt_optimism<'a>(
expected_receipts_root: B256,
expected_logs_bloom: Bloom,
receipts: impl Iterator<Item = &'a Receipt> + Clone,
chain_spec: &ChainSpec,
timestamp: u64,
) -> Result<(), BlockExecutionError> {
// Calculate receipts root.
let receipts_with_bloom = receipts.map(|r| r.clone().into()).collect::<Vec<ReceiptWithBloom>>();
let receipts_root =
calculate_receipt_root_optimism(&receipts_with_bloom, chain_spec, timestamp);
// 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(())
}
impl<'a, EvmConfig> BlockExecutor for EVMProcessor<'a, EvmConfig>
where
EvmConfig: ConfigureEvmEnv,
@ -38,7 +65,7 @@ where
// See more about EIP here: https://eips.ethereum.org/EIPS/eip-658
if self.chain_spec.fork(Hardfork::Byzantium).active_at_block(block.header.number) {
let time = Instant::now();
if let Err(error) = verify_receipt(
if let Err(error) = verify_receipt_optimism(
block.header.receipts_root,
block.header.logs_bloom,
receipts.iter(),

View File

@ -530,35 +530,48 @@ where
}
}
/// Verify receipts
/// Calculate the receipts root, and copmare it against against the expected receipts root and logs
/// bloom.
pub fn verify_receipt<'a>(
expected_receipts_root: B256,
expected_logs_bloom: Bloom,
receipts: impl Iterator<Item = &'a Receipt> + Clone,
#[cfg(feature = "optimism")] chain_spec: &ChainSpec,
#[cfg(feature = "optimism")] timestamp: u64,
) -> Result<(), BlockExecutionError> {
// Check receipts root.
// 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,
#[cfg(feature = "optimism")]
chain_spec,
#[cfg(feature = "optimism")]
timestamp,
);
if receipts_root != expected_receipts_root {
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 copmare
/// the calculated logs bloom with the expected logs bloom.
pub fn compare_receipts_root_and_logs_bloom(
calculated_receipts_root: B256,
calculated_logs_bloom: Bloom,
expected_receipts_root: B256,
expected_logs_bloom: Bloom,
) -> Result<(), BlockExecutionError> {
if calculated_receipts_root != expected_receipts_root {
return Err(BlockValidationError::ReceiptRootDiff(
GotExpected { got: receipts_root, expected: expected_receipts_root }.into(),
GotExpected { got: calculated_receipts_root, expected: expected_receipts_root }.into(),
)
.into())
}
// Create header log bloom.
let logs_bloom = receipts_with_bloom.iter().fold(Bloom::ZERO, |bloom, r| bloom | r.bloom);
if logs_bloom != expected_logs_bloom {
if calculated_logs_bloom != expected_logs_bloom {
return Err(BlockValidationError::BloomLogDiff(
GotExpected { got: logs_bloom, expected: expected_logs_bloom }.into(),
GotExpected { got: calculated_logs_bloom, expected: expected_logs_bloom }.into(),
)
.into())
}