Skip to content

Commit 83e8636

Browse files
committed
refactor(evm): generalize ethereum block executor types
1 parent 47eb661 commit 83e8636

7 files changed

Lines changed: 156 additions & 108 deletions

File tree

crates/ethereum/evm/src/execution.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ use alloc::{
1313
vec::Vec,
1414
};
1515
#[cfg(test)]
16+
use alloy_consensus::Transaction;
17+
#[cfg(test)]
1618
use alloy_consensus::TxType;
1719
use alloy_consensus::{
18-
constants::ETH_TO_WEI,
19-
transaction::{Recovered, Transaction},
20-
BlockHeader, Header,
20+
constants::ETH_TO_WEI, transaction::Recovered, BlockHeader, Header, TxReceipt,
2121
};
2222
use alloy_eips::{
2323
eip2718::Typed2718,
@@ -27,7 +27,7 @@ use alloy_eips::{
2727
eip7251::CONSOLIDATION_REQUEST_TYPE,
2828
eip7685::Requests,
2929
};
30-
use alloy_primitives::{map::AddressMap, Address, Bytes, B256, KECCAK256_EMPTY, U256};
30+
use alloy_primitives::{map::AddressMap, Address, Bytes, Log, B256, KECCAK256_EMPTY, U256};
3131
use alloy_sol_types::{sol, SolEvent};
3232
use core::{any::Any, convert::Infallible};
3333
#[cfg(test)]
@@ -36,7 +36,6 @@ use evm2::evm::Db;
3636
use evm2::Precompiles;
3737
use evm2::{
3838
bytecode::Bytecode as ExecutableBytecode,
39-
ethereum::RecoveredTxEnvelope,
4039
evm::{
4140
AccountChange, AccountChangeRef, AccountInfo, BlockStateAccumulator, StateChangeSink,
4241
StateChangeSource, StateChanges, StorageChange, SystemTx, BEACON_ROOTS_ADDRESS,
@@ -49,20 +48,21 @@ use evm2::{
4948
#[cfg(test)]
5049
use evm2::{
5150
env::BlockEnv,
52-
ethereum::ethereum_tx_registry,
51+
ethereum::{ethereum_tx_registry, RecoveredTxEnvelope},
5352
evm::{precompile::PrecompileProvider, Database, DynDatabase},
5453
BaseEvmTypes, ExecutionConfig, Version,
5554
};
5655
use reth_ethereum_forks::EthereumHardforks;
56+
#[cfg(test)]
5757
use reth_ethereum_primitives::Receipt;
5858
#[cfg(test)]
5959
use reth_ethereum_primitives::TransactionSigned;
6060
use reth_evm::{BlockExecutionError, BlockValidationError, EvmError, InvalidTxError};
6161
#[cfg(test)]
6262
use reth_evm::{ReceiptBuilder, ReceiptBuilderCtx};
63-
#[cfg(test)]
64-
use reth_execution_types::BlockExecutionOutput;
6563
use reth_execution_types::HashedPostStateSink;
64+
#[cfg(test)]
65+
use reth_execution_types::{BlockExecutionOutput, BlockExecutionResult};
6666
use reth_trie_common::{HashedPostState, KeccakKeyHasher};
6767

6868
const DEPOSIT_BYTES_SIZE: usize = 48 + 32 + 8 + 96 + 8;
@@ -459,16 +459,17 @@ where
459459
context.withdrawals,
460460
)?;
461461

462-
let mut output = <RethReceiptBuilder as ReceiptBuilder<
463-
TxType,
464-
TxResult<BaseEvmTypes>,
465-
>>::build_block_output(&RethReceiptBuilder, receipts, block_state, blob_gas_used);
466-
output.result.requests = requests;
462+
let gas_used = receipts.last().map_or(0, TxReceipt::cumulative_gas_used);
463+
let output = BlockExecutionOutput::new(
464+
BlockExecutionResult { receipts, requests, gas_used, blob_gas_used },
465+
block_state,
466+
);
467467

468468
Ok(output)
469469
}
470470
}
471471

472+
#[cfg(test)]
472473
pub(crate) fn transaction_blob_gas_used(transaction: &RecoveredTxEnvelope) -> u64 {
473474
transaction.as_eip4844().map(|tx| tx.blob_gas_used().unwrap_or_default()).unwrap_or_default()
474475
}
@@ -828,11 +829,14 @@ pub(crate) fn pre_execution_system_call_state_changes<T: EvmTypes>(
828829
Ok(())
829830
}
830831

831-
pub(crate) fn block_requests_from_receipts(
832+
pub(crate) fn block_requests_from_receipts<R>(
832833
spec_id: SpecId,
833834
context: BlockExecutionContext<'_>,
834-
receipts: &[Receipt],
835-
) -> Result<Requests, EthExecutionError> {
835+
receipts: &[R],
836+
) -> Result<Requests, EthExecutionError>
837+
where
838+
R: TxReceipt<Log = Log>,
839+
{
836840
let mut requests = Requests::default();
837841
if context.system_calls.is_none() || !spec_id.enables(SpecId::PRAGUE) {
838842
return Ok(requests)
@@ -847,13 +851,16 @@ pub(crate) fn block_requests_from_receipts(
847851
Ok(requests)
848852
}
849853

850-
fn parse_deposit_requests_from_receipts(
854+
fn parse_deposit_requests_from_receipts<R>(
851855
deposit_contract_address: Address,
852-
receipts: &[Receipt],
853-
) -> Result<Vec<u8>, EthExecutionError> {
856+
receipts: &[R],
857+
) -> Result<Vec<u8>, EthExecutionError>
858+
where
859+
R: TxReceipt<Log = Log>,
860+
{
854861
let mut out = Vec::new();
855862
for receipt in receipts {
856-
for log in &receipt.logs {
863+
for log in receipt.logs() {
857864
if log.address != deposit_contract_address ||
858865
log.topics().first() != Some(&DepositEvent::SIGNATURE_HASH)
859866
{

crates/ethereum/evm/src/executor.rs

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,53 @@ use crate::{
55
base_block_reward, block_requests_from_receipts, commit_detached_transaction,
66
execute_transaction_without_commit, post_block_balance_state_changes,
77
post_execution_system_call_state_changes, pre_execution_system_call_state_changes,
8-
transaction_blob_gas_used, BlockExecutionContext, BlockSystemCalls, EthExecutionError,
8+
BlockExecutionContext, BlockSystemCalls, EthExecutionError,
99
},
1010
factory::{EthBlockExecutorFactory, EvmFactory},
1111
EthBlockExecutionCtx, EthEvmEnv, RethReceiptBuilder,
1212
};
1313
use alloc::{boxed::Box, sync::Arc, vec::Vec};
14-
use alloy_consensus::{Header, Transaction, TxType};
14+
use alloy_consensus::{
15+
transaction::{TransactionEnvelope, TxHashRef},
16+
Header, Transaction, TxType as EthTxType,
17+
};
1518
use alloy_eip7928::{BlockAccessIndex, BlockAccessList};
1619
use alloy_eips::{eip2718::Typed2718, eip4895::Withdrawal, eip7685::Requests};
1720
use alloy_primitives::{Address, B256};
1821
use evm2::{
1922
ethereum::TxEnvelope,
2023
evm::{Bal, BlockStateAccumulator, StateChangeSource},
2124
interpreter::Host,
22-
BaseEvmTypes, Evm, EvmTypes, TxResult, TxResultWithState,
25+
BaseEvmTypes, Evm, EvmTypes, TxResultWithState,
2326
};
2427
use reth_ethereum_forks::EthereumHardforks;
2528
use reth_ethereum_primitives::{Receipt, TransactionSigned};
2629
use reth_evm::{
2730
BlockExecutionError, BlockExecutionOutput, BlockExecutor, BlockTransactionResult,
2831
BlockValidationError, ExecutorTx, GasOutput, ReceiptBuilder, ReceiptBuilderCtx, RecoveredTx,
2932
};
33+
use reth_execution_types::BlockExecutionResult;
3034
use reth_trie_common::HashedPostState;
3135

3236
/// Configured Ethereum block executor backed by evm2.
3337
#[expect(missing_debug_implementations)]
34-
pub struct EthBlockExecutor<'a, T = BaseEvmTypes>
38+
pub struct EthBlockExecutor<'a, T = BaseEvmTypes, R = RethReceiptBuilder>
3539
where
36-
T: EvmTypes<Tx = TxEnvelope>,
40+
T: EvmTypes,
3741
T::Tx: Typed2718,
3842
T::TxResultExt: Send,
43+
R: ReceiptBuilder,
3944
{
4045
evm: Evm<'a, T>,
4146
ctx: EthBlockExecutionCtx<'a>,
47+
receipt_builder: R,
4248
spec_id: evm2::SpecId,
4349
base_block_reward: Option<u128>,
4450
deposit_contract_address: Option<Address>,
4551
block_state: BlockStateAccumulator,
4652
hashed_state_mode: HashedStateMode,
4753
hashed_state_update_hook: HashedStateUpdateHook,
48-
receipts: Vec<Receipt>,
54+
receipts: Vec<R::Receipt>,
4955
cumulative_gas_used: u64,
5056
block_regular_gas_used: u64,
5157
block_state_gas_used: u64,
@@ -56,7 +62,7 @@ where
5662

5763
/// Detached Ethereum transaction result with the metadata needed for canonical receipt commit.
5864
#[derive(Debug)]
59-
pub struct EthTransactionResultWithState<T = BaseEvmTypes>
65+
pub struct EthTransactionResultWithState<T = BaseEvmTypes, TxType = EthTxType>
6066
where
6167
T: EvmTypes,
6268
{
@@ -65,7 +71,7 @@ where
6571
blob_gas_used: u64,
6672
}
6773

68-
impl<T: EvmTypes> BlockTransactionResult<T> for EthTransactionResultWithState<T> {
74+
impl<T: EvmTypes, TxType> BlockTransactionResult<T> for EthTransactionResultWithState<T, TxType> {
6975
fn result(&self) -> &TxResultWithState<T> {
7076
&self.result
7177
}
@@ -89,11 +95,12 @@ impl HashedStateMode {
8995
}
9096
}
9197

92-
impl<'a, T> EthBlockExecutor<'a, T>
98+
impl<'a, T, R> EthBlockExecutor<'a, T, R>
9399
where
94-
T: EvmTypes<Tx = TxEnvelope>,
100+
T: EvmTypes,
95101
T::Tx: Typed2718,
96102
T::TxResultExt: Send,
103+
R: ReceiptBuilder,
97104
{
98105
/// Creates a configured Ethereum block executor.
99106
pub(crate) fn new<C>(
@@ -102,6 +109,7 @@ where
102109
chain_spec: &C,
103110
deposit_contract_address: Option<alloy_primitives::Address>,
104111
hashed_state_mode: HashedStateMode,
112+
receipt_builder: R,
105113
) -> Self
106114
where
107115
C: EthereumHardforks + ?Sized,
@@ -116,6 +124,7 @@ where
116124
Self {
117125
evm,
118126
ctx,
127+
receipt_builder,
119128
spec_id,
120129
base_block_reward: base_block_reward(chain_spec, block_number),
121130
deposit_contract_address,
@@ -152,24 +161,29 @@ where
152161
}
153162

154163
#[inline]
155-
fn set_transaction_block_access_index(&mut self) {
164+
const fn set_transaction_block_access_index(&mut self) {
156165
if self.block_access_list_builder_enabled() {
157166
let index = self.receipts.len() as u64 + 1 + self.bal_index_offset;
158-
self.set_block_access_index(BlockAccessIndex::new(index));
167+
self.evm.state_mut().set_bal_index(BlockAccessIndex::new(index));
159168
}
160169
}
161170
}
162171

163-
impl<'a, T> BlockExecutor for EthBlockExecutor<'a, T>
172+
impl<'a, T, R> BlockExecutor for EthBlockExecutor<'a, T, R>
164173
where
165-
T: EvmTypes<Tx = TxEnvelope>,
166-
T::Tx: Typed2718,
174+
T: EvmTypes,
175+
T::Tx: Transaction + Typed2718,
167176
T::TxResultExt: Send,
177+
R: ReceiptBuilder,
178+
R::Transaction: TxHashRef,
179+
R::Receipt: alloy_consensus::TxReceipt<Log = alloy_primitives::Log>,
180+
<R::Transaction as TransactionEnvelope>::TxType: Send + 'static,
168181
{
169-
type Transaction = TransactionSigned;
170-
type Receipt = Receipt;
182+
type Transaction = R::Transaction;
183+
type Receipt = R::Receipt;
171184
type Evm = Evm<'a, T>;
172-
type TransactionResultWithState = EthTransactionResultWithState<T>;
185+
type TransactionResultWithState =
186+
EthTransactionResultWithState<T, <R::Transaction as TransactionEnvelope>::TxType>;
173187
type BlockAccessList = Bal;
174188

175189
fn evm(&self) -> &Self::Evm {
@@ -267,9 +281,8 @@ where
267281
}
268282
.into())
269283
}
270-
let blob_gas_used = transaction_blob_gas_used(&transaction);
271-
let tx_type =
272-
TxType::try_from(transaction.ty()).expect("transaction envelope has valid type");
284+
let blob_gas_used = tx.tx().blob_gas_used().unwrap_or_default();
285+
let tx_type = tx.tx().tx_type();
273286
let result = execute_transaction_without_commit(&mut self.evm, &transaction)
274287
.map_err(|err| map_transaction_execution_error(err, tx_hash))?;
275288
Ok(EthTransactionResultWithState { result, tx_type, blob_gas_used })
@@ -294,21 +307,22 @@ where
294307
self.block_state_gas_used = self.block_state_gas_used.saturating_add(state_gas_used);
295308
self.cumulative_gas_used += tx_gas_used;
296309
self.blob_gas_used += blob_gas_used;
297-
self.receipts.push(RethReceiptBuilder.build_receipt(ReceiptBuilderCtx {
310+
self.receipts.push(self.receipt_builder.build_receipt(ReceiptBuilderCtx {
298311
tx_type,
299312
result: outcome,
300313
cumulative_gas_used: self.cumulative_gas_used,
301314
}));
302315
Ok(GasOutput::new_with_regular(tx_gas_used, regular_gas_used, state_gas_used))
303316
}
304317

305-
fn receipts(&self) -> &[Receipt] {
318+
fn receipts(&self) -> &[Self::Receipt] {
306319
&self.receipts
307320
}
308321

309322
fn finish_with_block_access_list(
310323
mut self,
311-
) -> Result<(BlockExecutionOutput<Receipt>, Option<BlockAccessList>), BlockExecutionError> {
324+
) -> Result<(BlockExecutionOutput<Self::Receipt>, Option<BlockAccessList>), BlockExecutionError>
325+
{
312326
self.set_transaction_block_access_index();
313327
let context = Self::block_context(
314328
self.deposit_contract_address,
@@ -359,15 +373,15 @@ where
359373
self.block_regular_gas_used,
360374
self.block_state_gas_used,
361375
);
362-
let mut output =
363-
<RethReceiptBuilder as ReceiptBuilder<TxType, TxResult<T>>>::build_block_output(
364-
&RethReceiptBuilder,
365-
self.receipts,
366-
self.block_state,
367-
self.blob_gas_used,
368-
);
369-
output.result.gas_used = block_gas_used;
370-
output.result.requests = requests;
376+
let output = BlockExecutionOutput::new(
377+
BlockExecutionResult {
378+
receipts: self.receipts,
379+
requests,
380+
gas_used: block_gas_used,
381+
blob_gas_used: self.blob_gas_used,
382+
},
383+
self.block_state,
384+
);
371385

372386
Ok((output, block_access_list))
373387
}
@@ -503,8 +517,8 @@ where
503517
<F::Types as evm2::EvmTypesHost>::Tx: Typed2718,
504518
<F::Types as evm2::EvmTypesHost>::TxResultExt: Send,
505519
{
506-
inner: EthBlockExecutor<'a, F::Types>,
507-
factory: &'a EthBlockExecutorFactory<C, F>,
520+
inner: EthBlockExecutor<'a, F::Types, &'a RethReceiptBuilder>,
521+
factory: &'a EthBlockExecutorFactory<RethReceiptBuilder, C, F>,
508522
chain_spec: Arc<C>,
509523
plan: EthBigBlockPlan<'a, F::Types>,
510524
next_segment: usize,
@@ -527,8 +541,8 @@ where
527541
<F::Types as evm2::EvmTypesHost>::TxResultExt: Send,
528542
{
529543
pub(crate) fn new(
530-
inner: EthBlockExecutor<'a, F::Types>,
531-
factory: &'a EthBlockExecutorFactory<C, F>,
544+
inner: EthBlockExecutor<'a, F::Types, &'a RethReceiptBuilder>,
545+
factory: &'a EthBlockExecutorFactory<RethReceiptBuilder, C, F>,
532546
chain_spec: Arc<C>,
533547
plan: EthBigBlockPlan<'a, F::Types>,
534548
) -> Self {

0 commit comments

Comments
 (0)