mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: add Consensus to ExecutionStage (#14447)
This commit is contained in:
@ -21,7 +21,7 @@ use reth_consensus_common::validation::{
|
||||
validate_against_parent_timestamp, validate_block_pre_execution, validate_body_against_header,
|
||||
validate_header_base_fee, validate_header_extra_data, validate_header_gas,
|
||||
};
|
||||
use reth_primitives::{NodePrimitives, Receipt, RecoveredBlock, SealedBlock, SealedHeader};
|
||||
use reth_primitives::{NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
|
||||
use reth_primitives_traits::{
|
||||
constants::{GAS_LIMIT_BOUND_DIVISOR, MINIMUM_GAS_LIMIT},
|
||||
Block, BlockHeader,
|
||||
@ -99,7 +99,7 @@ impl<ChainSpec: EthChainSpec + EthereumHardforks> EthBeaconConsensus<ChainSpec>
|
||||
impl<ChainSpec, N> FullConsensus<N> for EthBeaconConsensus<ChainSpec>
|
||||
where
|
||||
ChainSpec: Send + Sync + EthChainSpec + EthereumHardforks + Debug,
|
||||
N: NodePrimitives<Receipt = Receipt>,
|
||||
N: NodePrimitives,
|
||||
{
|
||||
fn validate_block_post_execution(
|
||||
&self,
|
||||
|
||||
@ -3,26 +3,27 @@ use alloy_eips::eip7685::Requests;
|
||||
use alloy_primitives::{Bloom, B256};
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_primitives::{gas_spent_by_transactions, GotExpected, Receipt, RecoveredBlock};
|
||||
use reth_primitives_traits::Block;
|
||||
use reth_primitives::{gas_spent_by_transactions, GotExpected, RecoveredBlock};
|
||||
use reth_primitives_traits::{Block, Receipt};
|
||||
|
||||
/// 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<B, ChainSpec>(
|
||||
pub fn validate_block_post_execution<B, R, ChainSpec>(
|
||||
block: &RecoveredBlock<B>,
|
||||
chain_spec: &ChainSpec,
|
||||
receipts: &[Receipt],
|
||||
receipts: &[R],
|
||||
requests: &Requests,
|
||||
) -> Result<(), ConsensusError>
|
||||
where
|
||||
B: Block,
|
||||
R: Receipt,
|
||||
ChainSpec: EthereumHardforks,
|
||||
{
|
||||
// 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);
|
||||
receipts.last().map(|receipt| receipt.cumulative_gas_used()).unwrap_or(0);
|
||||
if block.header().gas_used() != cumulative_gas_used {
|
||||
return Err(ConsensusError::BlockGasUsed {
|
||||
gas: GotExpected { got: cumulative_gas_used, expected: block.header().gas_used() },
|
||||
@ -61,13 +62,13 @@ where
|
||||
|
||||
/// Calculate the receipts root, and compare it against against the expected receipts root and logs
|
||||
/// bloom.
|
||||
fn verify_receipts(
|
||||
fn verify_receipts<R: Receipt>(
|
||||
expected_receipts_root: B256,
|
||||
expected_logs_bloom: Bloom,
|
||||
receipts: &[Receipt],
|
||||
receipts: &[R],
|
||||
) -> Result<(), ConsensusError> {
|
||||
// Calculate receipts root.
|
||||
let receipts_with_bloom = receipts.iter().map(Receipt::with_bloom_ref).collect::<Vec<_>>();
|
||||
let receipts_with_bloom = receipts.iter().map(TxReceipt::with_bloom_ref).collect::<Vec<_>>();
|
||||
let receipts_root = calculate_receipt_root(&receipts_with_bloom);
|
||||
|
||||
// Calculate header logs bloom.
|
||||
@ -109,6 +110,7 @@ fn compare_receipts_root_and_logs_bloom(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloy_primitives::hex;
|
||||
use reth_primitives::Receipt;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -291,10 +291,8 @@ mod tests {
|
||||
};
|
||||
use alloy_primitives::{b256, fixed_bytes, keccak256, Bytes, TxKind, B256, U256};
|
||||
use reth_chainspec::{ChainSpecBuilder, ForkCondition};
|
||||
use reth_evm::execute::{
|
||||
BasicBlockExecutorProvider, BatchExecutor, BlockExecutorProvider, Executor,
|
||||
};
|
||||
use reth_execution_types::BlockExecutionOutput;
|
||||
use reth_evm::execute::{BasicBlockExecutorProvider, BlockExecutorProvider, Executor};
|
||||
use reth_execution_types::BlockExecutionResult;
|
||||
use reth_primitives::{Account, Block, BlockBody, Transaction};
|
||||
use reth_primitives_traits::{crypto::secp256k1::public_key_to_address, Block as _};
|
||||
use reth_revm::{
|
||||
@ -368,11 +366,11 @@ mod tests {
|
||||
|
||||
let provider = executor_provider(chain_spec);
|
||||
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// attempt to execute a block without parent beacon block root, expect err
|
||||
let err = executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header: header.clone(),
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
@ -393,7 +391,7 @@ mod tests {
|
||||
|
||||
// Now execute a block with the fixed header, ensure that it does not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header: header.clone(),
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
@ -452,8 +450,8 @@ mod tests {
|
||||
|
||||
// attempt to execute an empty block with parent beacon block root, this should not fail
|
||||
provider
|
||||
.batch_executor(StateProviderDatabase::new(&db))
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.executor(StateProviderDatabase::new(&db))
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header,
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
@ -493,11 +491,11 @@ mod tests {
|
||||
..Header::default()
|
||||
};
|
||||
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// attempt to execute an empty block with parent beacon block root, this should not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block {
|
||||
header,
|
||||
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
|
||||
@ -528,12 +526,12 @@ mod tests {
|
||||
|
||||
let mut header = chain_spec.genesis_header().clone();
|
||||
let provider = executor_provider(chain_spec);
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// attempt to execute the genesis block with non-zero parent beacon block root, expect err
|
||||
header.parent_beacon_block_root = Some(B256::with_last_byte(0x69));
|
||||
let _err = executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header: header.clone(), body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -548,7 +546,7 @@ mod tests {
|
||||
// now try to process the genesis block again, this time ensuring that a system contract
|
||||
// call does not occur
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -592,11 +590,11 @@ mod tests {
|
||||
let provider = executor_provider(chain_spec);
|
||||
|
||||
// execute header
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// Now execute a block with the fixed header, ensure that it does not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header: header.clone(), body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -659,14 +657,14 @@ mod tests {
|
||||
);
|
||||
|
||||
let provider = executor_provider(chain_spec);
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// construct the header for block one
|
||||
let header = Header { timestamp: 1, number: 1, ..Header::default() };
|
||||
|
||||
// attempt to execute an empty block, this should not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -700,11 +698,11 @@ mod tests {
|
||||
|
||||
let header = chain_spec.genesis_header().clone();
|
||||
let provider = executor_provider(chain_spec);
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// attempt to execute genesis block, this should not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -747,11 +745,11 @@ mod tests {
|
||||
..Header::default()
|
||||
};
|
||||
let provider = executor_provider(chain_spec);
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// attempt to execute the fork activation block, this should not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -791,7 +789,7 @@ mod tests {
|
||||
);
|
||||
|
||||
let provider = executor_provider(chain_spec);
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
let header = Header {
|
||||
parent_hash: B256::random(),
|
||||
@ -805,7 +803,7 @@ mod tests {
|
||||
|
||||
// attempt to execute the fork activation block, this should not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -834,11 +832,11 @@ mod tests {
|
||||
let header_hash = header.hash_slow();
|
||||
|
||||
let provider = executor_provider(chain_spec);
|
||||
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// attempt to execute the genesis block, this should not fail
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -869,7 +867,7 @@ mod tests {
|
||||
let header_hash = header.hash_slow();
|
||||
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -903,7 +901,7 @@ mod tests {
|
||||
};
|
||||
|
||||
executor
|
||||
.execute_and_verify_one(&RecoveredBlock::new_unhashed(
|
||||
.execute_one(&RecoveredBlock::new_unhashed(
|
||||
Block { header, body: Default::default() },
|
||||
vec![],
|
||||
))
|
||||
@ -984,10 +982,10 @@ mod tests {
|
||||
|
||||
let provider = executor_provider(chain_spec);
|
||||
|
||||
let executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = provider.executor(StateProviderDatabase::new(&db));
|
||||
|
||||
let BlockExecutionOutput { receipts, requests, .. } = executor
|
||||
.execute(
|
||||
let BlockExecutionResult { receipts, requests, .. } = executor
|
||||
.execute_one(
|
||||
&Block { header, body: BlockBody { transactions: vec![tx], ..Default::default() } }
|
||||
.try_into_recovered()
|
||||
.unwrap(),
|
||||
@ -1060,10 +1058,10 @@ mod tests {
|
||||
);
|
||||
|
||||
// Create an executor from the state provider
|
||||
let executor = executor_provider(chain_spec).executor(StateProviderDatabase::new(&db));
|
||||
let mut executor = executor_provider(chain_spec).executor(StateProviderDatabase::new(&db));
|
||||
|
||||
// Execute the block and capture the result
|
||||
let exec_result = executor.execute(
|
||||
let exec_result = executor.execute_one(
|
||||
&Block { header, body: BlockBody { transactions: vec![tx], ..Default::default() } }
|
||||
.try_into_recovered()
|
||||
.unwrap(),
|
||||
|
||||
Reference in New Issue
Block a user