diff --git a/Cargo.lock b/Cargo.lock index 5d80e16bc9..5a1b1023f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13766,8 +13766,6 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-transaction-pool", - "reth-trie", - "reth-trie-common", "reth-trie-db", "revm", "revm-primitives", diff --git a/crates/reth/node/Cargo.toml b/crates/reth/node/Cargo.toml index 5e3628fdc6..84775c4701 100644 --- a/crates/reth/node/Cargo.toml +++ b/crates/reth/node/Cargo.toml @@ -29,8 +29,6 @@ reth-payload-validator.workspace = true reth-primitives.workspace = true reth-provider.workspace = true reth-transaction-pool.workspace = true -reth-trie.workspace = true -reth-trie-common.workspace = true reth-trie-db.workspace = true revm.workspace = true revm-primitives.workspace = true diff --git a/crates/reth/node/src/evm.rs b/crates/reth/node/src/evm.rs index e71c376fb0..aca7f72f1f 100644 --- a/crates/reth/node/src/evm.rs +++ b/crates/reth/node/src/evm.rs @@ -4,9 +4,11 @@ use reth_chainspec::ChainSpec; use reth_evm::{ConfigureEvm, ConfigureEvmEnv, NextBlockEnvAttributes}; use reth_node_ethereum::EthEvmConfig; use reth_primitives::{Header, TransactionSigned}; +use revm::{inspector_handle_register, Database, Evm, EvmBuilder, GetInspector}; use revm_primitives::{ Address, AnalysisKind, BlockEnv, Bytes, CfgEnvWithHandlerCfg, Env, TxEnv, U256, }; +use strata_reth_evm::set_evm_handles; /// Custom EVM configuration #[derive(Debug, Clone)] @@ -66,6 +68,28 @@ impl ConfigureEvmEnv for StrataEvmConfig { impl ConfigureEvm for StrataEvmConfig { type DefaultExternalContext<'a> = (); + fn evm(&self, db: DB) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> { + EvmBuilder::default() + .with_db(db) + // add additional precompiles + .append_handler_register(set_evm_handles) + .build() + } + + fn evm_with_inspector(&self, db: DB, inspector: I) -> Evm<'_, I, DB> + where + DB: Database, + I: GetInspector, + { + EvmBuilder::default() + .with_db(db) + .with_external_context(inspector) + // add additional precompiles + .append_handler_register(set_evm_handles) + .append_handler_register(inspector_handle_register) + .build() + } + #[doc = " Provides the default external context."] fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a> { self.inner.default_external_context() diff --git a/crates/reth/node/src/node.rs b/crates/reth/node/src/node.rs index 1c3a29bc50..7819494580 100644 --- a/crates/reth/node/src/node.rs +++ b/crates/reth/node/src/node.rs @@ -9,7 +9,7 @@ use reth_node_builder::{ }; use reth_node_ethereum::{ node::{EthereumConsensusBuilder, EthereumNetworkBuilder, EthereumPoolBuilder}, - BasicBlockExecutorProvider, EthExecutionStrategyFactory, EthExecutorProvider, + BasicBlockExecutorProvider, EthExecutionStrategyFactory, }; use reth_primitives::{BlockBody, PooledTransactionsElement}; use reth_provider::{ @@ -313,15 +313,20 @@ where Node: FullNodeTypes>, { type EVM = StrataEvmConfig; - type Executor = BasicBlockExecutorProvider; + type Executor = BasicBlockExecutorProvider>; async fn build_evm( self, ctx: &BuilderContext, ) -> eyre::Result<(Self::EVM, Self::Executor)> { + let evm_config = StrataEvmConfig::new(ctx.chain_spec()); + Ok(( - StrataEvmConfig::new(ctx.chain_spec()), - EthExecutorProvider::ethereum(ctx.chain_spec()), + evm_config.clone(), + BasicBlockExecutorProvider::new(EthExecutionStrategyFactory::new( + ctx.chain_spec(), + evm_config, + )), )) } } diff --git a/crates/reth/node/src/payload.rs b/crates/reth/node/src/payload.rs index e9592d084e..afe8b5556b 100644 --- a/crates/reth/node/src/payload.rs +++ b/crates/reth/node/src/payload.rs @@ -125,7 +125,7 @@ impl BuiltPayload for StrataBuiltPayload { } fn requests(&self) -> Option { - None + self.inner.requests() } } diff --git a/crates/reth/node/src/payload_builder.rs b/crates/reth/node/src/payload_builder.rs index e386d26324..7777e4076a 100644 --- a/crates/reth/node/src/payload_builder.rs +++ b/crates/reth/node/src/payload_builder.rs @@ -14,7 +14,7 @@ use reth_basic_payload_builder::*; use reth_chain_state::ExecutedBlock; use reth_chainspec::{ChainSpec, ChainSpecProvider, EthereumHardforks}; use reth_errors::RethError; -use reth_evm::system_calls::SystemCaller; +use reth_evm::{system_calls::SystemCaller, ConfigureEvmEnv, NextBlockEnvAttributes}; use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig}; use reth_node_api::{ ConfigureEvm, FullNodeTypes, NodeTypesWithEngine, PayloadBuilderAttributes, TxTy, @@ -30,14 +30,13 @@ use reth_transaction_pool::{ error::InvalidPoolTransactionError, BestTransactions, BestTransactionsAttributes, PoolTransaction, TransactionPool, }; -use reth_trie::HashedPostState; -use reth_trie_common::KeccakKeyHasher; use revm::{ db::{states::bundle_state::BundleRetention, State}, DatabaseCommit, }; use revm_primitives::{ - calc_excess_blob_gas, EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState, U256, + calc_excess_blob_gas, BlockEnv, CfgEnvWithHandlerCfg, EVMError, EnvWithHandlerCfg, + InvalidTransaction, ResultAndState, TxEnv, U256, }; use strata_reth_evm::collect_withdrawal_intents; use tracing::{debug, trace, warn}; @@ -56,6 +55,24 @@ pub struct StrataPayloadBuilder { evm_config: StrataEvmConfig, } +impl StrataPayloadBuilder { + /// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload + /// (that has the `parent` as its parent). + pub fn cfg_and_block_env( + &self, + attributes: &StrataPayloadBuilderAttributes, + parent: &Header, + ) -> Result<(CfgEnvWithHandlerCfg, BlockEnv), ::Error> { + let next_attributes = NextBlockEnvAttributes { + timestamp: attributes.timestamp(), + suggested_fee_recipient: attributes.suggested_fee_recipient(), + prev_randao: attributes.prev_randao(), + }; + self.evm_config + .next_cfg_and_block_env(parent, next_attributes) + } +} + impl PayloadBuilder for StrataPayloadBuilder where Client: StateProviderFactory + ChainSpecProvider, @@ -68,7 +85,11 @@ where &self, args: BuildArguments, ) -> Result, PayloadBuilderError> { - try_build_payload(self.evm_config.clone(), args) + let (cfg_env, block_env) = self + .cfg_and_block_env(&args.config.attributes, &args.config.parent_header) + .map_err(PayloadBuilderError::other)?; + + try_build_payload(self.evm_config.clone(), args, cfg_env, block_env) } fn build_empty_payload( @@ -189,6 +210,8 @@ where pub fn try_build_payload( evm_config: EvmConfig, args: BuildArguments, + initialized_cfg: CfgEnvWithHandlerCfg, + initialized_block_env: BlockEnv, ) -> Result, PayloadBuilderError> where EvmConfig: ConfigureEvm
, @@ -204,42 +227,28 @@ where best_payload, } = args; + let PayloadConfig { + parent_header, + attributes, + extra_data, + } = config; + // convert to eth payload let best_payload = best_payload.map(|p| p.inner); let chain_spec = client.chain_spec(); - let state_provider = client.state_by_block_hash(config.parent_header.hash())?; + let state_provider = client.state_by_block_hash(parent_header.hash())?; let state = StateProviderDatabase::new(state_provider); let mut db = State::builder() - .with_database_ref(cached_reads.as_db(state)) + .with_database(cached_reads.as_db_mut(state)) .with_bundle_update() .build(); - let PayloadConfig { - parent_header, - attributes, - extra_data, - } = config; - debug!(target: "payload_builder", id=%attributes.payload_id(), parent_hash = ?parent_header.hash(), parent_number = parent_header.number, "building new payload"); - let (initialized_cfg, initialized_block_env) = evm_config - .next_cfg_and_block_env( - &parent_header, - reth_evm::NextBlockEnvAttributes { - timestamp: attributes.timestamp(), - suggested_fee_recipient: attributes.suggested_fee_recipient(), - prev_randao: attributes.prev_randao(), - }, - ) - .map_err(PayloadBuilderError::other)?; - let mut cumulative_gas_used = 0; let mut sum_blob_gas_used = 0; - let block_gas_limit: u64 = initialized_block_env - .gas_limit - .try_into() - .unwrap_or(chain_spec.max_gas_limit); + let block_gas_limit: u64 = initialized_block_env.gas_limit.to::(); let base_fee = initialized_block_env.basefee.to::(); let mut executed_senders = Vec::new(); @@ -285,6 +294,13 @@ where ) .map_err(|err| PayloadBuilderError::Internal(err.into()))?; + let env = EnvWithHandlerCfg::new_with_cfg_env( + initialized_cfg.clone(), + initialized_block_env.clone(), + TxEnv::default(), + ); + let mut evm = evm_config.evm_with_env(&mut db, env); + let mut receipts = Vec::new(); // let mut withdrawal_intents = Vec::new(); while let Some(pool_tx) = best_txs.next() { @@ -329,14 +345,8 @@ where } } - let env = EnvWithHandlerCfg::new_with_cfg_env( - initialized_cfg.clone(), - initialized_block_env.clone(), - evm_config.tx_env(tx.as_signed(), tx.signer()), - ); - - // Configure the environment for the block. - let mut evm = evm_config.evm_with_env(&mut db, env); + // Configure the environment for the tx. + *evm.tx_mut() = evm_config.tx_env(tx.as_signed(), tx.signer()); let ResultAndState { result, state } = match evm.transact() { Ok(res) => res, @@ -368,10 +378,8 @@ where } }; debug!(?result, "EVM transaction executed"); - // drop evm so db is released. - drop(evm); // commit changes - db.commit(state); + evm.db_mut().commit(state); // add to the total blob gas used if the transaction successfully executed if let Some(blob_tx) = tx.transaction.as_eip4844() { @@ -410,6 +418,9 @@ where executed_txs.push(tx.into_signed()); } + // drop evm so db is released. + drop(evm); + // check if we have a better block if !is_better_payload(best_payload.as_ref(), total_fees) { // can skip building the block @@ -477,14 +488,14 @@ where // merge all transitions into bundle state, this would apply the withdrawal balance changes // and 4788 contract call - db.merge_transitions(BundleRetention::PlainState); + db.merge_transitions(BundleRetention::Reverts); let requests_hash = requests.as_ref().map(|requests| requests.requests_hash()); let execution_outcome = ExecutionOutcome::new( db.take_bundle(), vec![receipts].into(), block_number, - vec![Requests::default()], + vec![requests.clone().unwrap_or_default()], ); let receipts_root = execution_outcome .receipts_root_slow(block_number) @@ -494,12 +505,10 @@ where .expect("Number is in range"); // calculate the state root - let hashed_state = - HashedPostState::from_bundle_state::(&execution_outcome.state().state); + let hashed_state = db.database.db.hashed_post_state(execution_outcome.state()); let (state_root, trie_output) = { - let state_provider = db.database.0.inner.borrow_mut(); - state_provider - .db + db.database + .inner() .state_root_with_updates(hashed_state.clone()) .inspect_err(|err| { warn!(target: "payload_builder",