diff --git a/src/node/evm/executor.rs b/src/node/evm/executor.rs index 88e03010a..358ceb453 100644 --- a/src/node/evm/executor.rs +++ b/src/node/evm/executor.rs @@ -4,7 +4,7 @@ use crate::{ hardforks::HlHardforks, node::{ primitives::TransactionSigned, - types::{ReadPrecompileInput, ReadPrecompileResult}, + types::{HlExtras, ReadPrecompileInput, ReadPrecompileResult}, }, }; use alloy_consensus::{Transaction, TxReceipt}; @@ -102,7 +102,7 @@ where { /// Creates a new HlBlockExecutor. pub fn new(mut evm: EVM, ctx: HlBlockExecutionCtx<'a>, spec: Spec, receipt_builder: R) -> Self { - apply_precompiles(&mut evm, &ctx); + apply_precompiles(&mut evm, &ctx.extras); Self { spec, evm, gas_used: 0, receipts: vec![], receipt_builder, ctx } } @@ -155,7 +155,7 @@ where type Evm = E; fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError> { - apply_precompiles(&mut self.evm, &self.ctx); + apply_precompiles(&mut self.evm, &self.ctx.extras); self.deploy_corewriter_contract()?; Ok(()) @@ -240,10 +240,9 @@ where } } -fn apply_precompiles<'a, DB, EVM>(evm: &mut EVM, ctx: &HlBlockExecutionCtx<'a>) +pub fn apply_precompiles(evm: &mut EVM, extras: &HlExtras) where - EVM: Evm, Precompiles = PrecompilesMap>, - DB: Database + 'a, + EVM: Evm, { let block_number = evm.block().number; let precompiles_mut = evm.precompiles_mut(); @@ -255,9 +254,7 @@ where precompiles_mut.apply_precompile(&address, |_| None); } } - for (address, precompile) in - ctx.extras.read_precompile_calls.clone().unwrap_or_default().0.iter() - { + for (address, precompile) in extras.read_precompile_calls.clone().unwrap_or_default().0.iter() { let precompile = precompile.clone(); precompiles_mut.apply_precompile(address, |_| { let precompiles_map: HashMap = @@ -271,7 +268,7 @@ where // NOTE: This is adapted from hyperliquid-dex/hyper-evm-sync#5 const WARM_PRECOMPILES_BLOCK_NUMBER: u64 = 8_197_684; if block_number >= U256::from(WARM_PRECOMPILES_BLOCK_NUMBER) { - fill_all_precompiles(ctx, precompiles_mut); + fill_all_precompiles(extras, precompiles_mut); } } @@ -279,9 +276,9 @@ fn address_to_u64(address: Address) -> u64 { address.into_u256().try_into().unwrap() } -fn fill_all_precompiles<'a>(ctx: &HlBlockExecutionCtx<'a>, precompiles_mut: &mut PrecompilesMap) { +fn fill_all_precompiles(extras: &HlExtras, precompiles_mut: &mut PrecompilesMap) { let lowest_address = 0x800; - let highest_address = ctx.extras.highest_precompile_address.map_or(0x80D, address_to_u64); + let highest_address = extras.highest_precompile_address.map_or(0x80D, address_to_u64); for address in lowest_address..=highest_address { let address = Address::from(U160::from(address)); precompiles_mut.apply_precompile(&address, |f| { diff --git a/src/node/evm/mod.rs b/src/node/evm/mod.rs index f489fbf5e..da5098708 100644 --- a/src/node/evm/mod.rs +++ b/src/node/evm/mod.rs @@ -32,6 +32,8 @@ mod factory; mod patch; pub mod receipt_builder; +pub use executor::apply_precompiles; + /// HL EVM implementation. /// /// This is a wrapper type around the `revm` evm with optional [`Inspector`] (tracing) diff --git a/src/node/primitives/tx_wrapper.rs b/src/node/primitives/tx_wrapper.rs index 8f4c77333..1ef366153 100644 --- a/src/node/primitives/tx_wrapper.rs +++ b/src/node/primitives/tx_wrapper.rs @@ -212,10 +212,6 @@ impl From impl Compress for TransactionSigned { type Compressed = Vec; - fn compress(self) -> Self::Compressed { - self.into_inner().compress() - } - fn compress_to_buf>(&self, buf: &mut B) { self.inner().compress_to_buf(buf); } diff --git a/src/node/rpc/block.rs b/src/node/rpc/block.rs index c9a70c83c..ea4867fbb 100644 --- a/src/node/rpc/block.rs +++ b/src/node/rpc/block.rs @@ -1,4 +1,4 @@ -use crate::node::rpc::HlEthApi; +use crate::node::rpc::{HlEthApi, HlRpcNodeCore}; use reth::rpc::server_types::eth::{ builder::config::PendingBlockKind, error::FromEvmError, EthApiError, PendingBlock, }; @@ -6,12 +6,12 @@ use reth_rpc_eth_api::{ helpers::{ pending_block::PendingEnvBuilder, EthBlocks, LoadBlock, LoadPendingBlock, LoadReceipt, }, - RpcConvert, RpcNodeCore, + RpcConvert, }; impl EthBlocks for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { @@ -19,7 +19,7 @@ where impl LoadBlock for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { @@ -27,7 +27,7 @@ where impl LoadPendingBlock for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { @@ -49,7 +49,7 @@ where impl LoadReceipt for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { diff --git a/src/node/rpc/call.rs b/src/node/rpc/call.rs index 943f6825d..3519fb2fd 100644 --- a/src/node/rpc/call.rs +++ b/src/node/rpc/call.rs @@ -1,14 +1,23 @@ -use super::HlEthApi; +use super::{HlEthApi, HlRpcNodeCore}; +use crate::{node::evm::apply_precompiles, HlBlock}; +use alloy_evm::Evm; +use alloy_primitives::B256; use reth::rpc::server_types::eth::EthApiError; -use reth_evm::TxEnvFor; +use reth_evm::{ConfigureEvm, Database, EvmEnvFor, TxEnvFor}; +use reth_primitives::{NodePrimitives, Recovered}; +use reth_primitives_traits::SignedTransaction; +use reth_provider::{ProviderError, ProviderTx}; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall}, FromEvmError, RpcConvert, RpcNodeCore, }; +use revm::DatabaseCommit; + +impl HlRpcNodeCore for N where N: RpcNodeCore> {} impl EthCall for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert>, { @@ -16,7 +25,7 @@ where impl EstimateCall for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert>, { @@ -24,7 +33,7 @@ where impl Call for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert>, { @@ -37,4 +46,35 @@ where fn max_simulate_blocks(&self) -> u64 { self.inner.eth_api.max_simulate_blocks() } + + fn replay_transactions_until<'a, DB, I>( + &self, + db: &mut DB, + evm_env: EvmEnvFor, + transactions: I, + target_tx_hash: B256, + ) -> Result + where + DB: Database + DatabaseCommit + core::fmt::Debug, + I: IntoIterator>>, + { + let block_number = evm_env.block_env().number; + let hl_extras = self.get_hl_extras(block_number.try_into().unwrap())?; + + let mut evm = self.evm_config().evm_with_env(db, evm_env); + apply_precompiles(&mut evm, &hl_extras); + + let mut index = 0; + for tx in transactions { + if *tx.tx_hash() == target_tx_hash { + // reached the target transaction + break; + } + + let tx_env = self.evm_config().tx_env(tx); + evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?; + index += 1; + } + Ok(index) + } } diff --git a/src/node/rpc/mod.rs b/src/node/rpc/mod.rs index ce55a65c7..b647e9352 100644 --- a/src/node/rpc/mod.rs +++ b/src/node/rpc/mod.rs @@ -1,3 +1,9 @@ +use crate::{ + chainspec::HlChainSpec, + node::{evm::apply_precompiles, types::HlExtras}, + HlBlock, HlPrimitives, +}; +use alloy_evm::Evm; use alloy_network::Ethereum; use alloy_primitives::U256; use reth::{ @@ -18,8 +24,9 @@ use reth::{ TaskSpawner, }, }; -use reth_evm::ConfigureEvm; -use reth_provider::{ChainSpecProvider, ProviderHeader, ProviderTx}; +use reth_evm::{ConfigureEvm, Database, EvmEnvFor, HaltReasonFor, InspectorFor, TxEnvFor}; +use reth_primitives::NodePrimitives; +use reth_provider::{BlockReader, ChainSpecProvider, ProviderError, ProviderHeader, ProviderTx}; use reth_rpc::RpcTypes; use reth_rpc_eth_api::{ helpers::{ @@ -29,17 +36,18 @@ use reth_rpc_eth_api::{ EthApiTypes, FromEvmError, RpcConvert, RpcConverter, RpcNodeCore, RpcNodeCoreExt, SignableTxRequest, }; +use revm::context::result::ResultAndState; use std::{fmt, marker::PhantomData, sync::Arc}; -use crate::chainspec::HlChainSpec; - mod block; mod call; pub mod engine_api; mod transaction; +pub trait HlRpcNodeCore: RpcNodeCore> {} + /// Container type `HlEthApi` -pub(crate) struct HlEthApiInner { +pub(crate) struct HlEthApiInner { /// Gateway to node's core components. pub(crate) eth_api: EthApiInner, } @@ -48,14 +56,14 @@ type HlRpcConvert = RpcConverter::Evm, EthReceiptConverter>; #[derive(Clone)] -pub struct HlEthApi { +pub struct HlEthApi { /// Gateway to node's core components. pub(crate) inner: Arc>, } impl fmt::Debug for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -65,7 +73,7 @@ where impl EthApiTypes for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { type Error = EthApiError; @@ -79,7 +87,7 @@ where impl RpcNodeCore for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { type Primitives = N::Primitives; @@ -111,7 +119,7 @@ where impl RpcNodeCoreExt for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { #[inline] @@ -122,7 +130,7 @@ where impl EthApiSpec for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { type Transaction = ProviderTx; @@ -141,7 +149,7 @@ where impl SpawnBlocking for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { #[inline] @@ -162,7 +170,7 @@ where impl LoadFee for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { @@ -179,14 +187,14 @@ where impl LoadState for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { } impl EthState for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { #[inline] @@ -197,7 +205,7 @@ where impl EthFees for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { @@ -205,15 +213,50 @@ where impl Trace for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { + fn inspect( + &self, + db: DB, + evm_env: EvmEnvFor, + tx_env: TxEnvFor, + inspector: I, + ) -> Result>, Self::Error> + where + DB: Database, + I: InspectorFor, + { + let block_number = evm_env.block_env().number; + let hl_extras = self.get_hl_extras(block_number.try_into().unwrap())?; + + let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector); + apply_precompiles(&mut evm, &hl_extras); + evm.transact(tx_env).map_err(Self::Error::from_evm_err) + } +} + +impl HlEthApi +where + N: HlRpcNodeCore, + Rpc: RpcConvert, +{ + fn get_hl_extras(&self, block_number: u64) -> Result { + Ok(self + .provider() + .block_by_number(block_number)? + .map(|block| HlExtras { + read_precompile_calls: block.body.read_precompile_calls.clone(), + highest_precompile_address: block.body.highest_precompile_address, + }) + .unwrap_or_default()) + } } impl AddDevSigners for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert< Network: RpcTypes>>, >, @@ -239,7 +282,7 @@ impl Default for HlEthApiBuilder { impl EthApiBuilder for HlEthApiBuilder where - N: FullNodeComponents> + N: FullNodeComponents> + RpcNodeCore< Primitives = PrimitivesTy, Evm: ConfigureEvm>>, diff --git a/src/node/rpc/transaction.rs b/src/node/rpc/transaction.rs index 160f8bbdd..d24bea2ba 100644 --- a/src/node/rpc/transaction.rs +++ b/src/node/rpc/transaction.rs @@ -1,21 +1,21 @@ -use crate::node::rpc::HlEthApi; +use crate::node::rpc::{HlEthApi, HlRpcNodeCore}; use alloy_primitives::{Bytes, B256}; use reth::rpc::server_types::eth::EthApiError; use reth_rpc_eth_api::{ helpers::{spec::SignersForRpc, EthTransactions, LoadTransaction}, - RpcConvert, RpcNodeCore, + RpcConvert, }; impl LoadTransaction for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { } impl EthTransactions for HlEthApi where - N: RpcNodeCore, + N: HlRpcNodeCore, Rpc: RpcConvert, { fn signers(&self) -> &SignersForRpc {