mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: alloy-evm and new revm integration (#14021)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> Co-authored-by: rakita <rakita@users.noreply.github.com>
This commit is contained in:
@ -13,9 +13,9 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
# reth
|
||||
revm.workspace = true
|
||||
revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee"] }
|
||||
revm-inspectors.workspace = true
|
||||
revm-primitives = { workspace = true, features = ["dev"] }
|
||||
revm-primitives = { workspace = true }
|
||||
reth-primitives-traits.workspace = true
|
||||
reth-errors.workspace = true
|
||||
reth-evm.workspace = true
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
|
||||
use super::{LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace};
|
||||
use crate::{
|
||||
helpers::estimate::EstimateCall, FromEthApiError, FromEvmError, FullEthApiTypes, RpcBlock,
|
||||
RpcNodeCore,
|
||||
helpers::estimate::EstimateCall, FromEvmError, FullEthApiTypes, RpcBlock, RpcNodeCore,
|
||||
};
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::{eip1559::calc_next_block_base_fee, eip2930::AccessListResult};
|
||||
@ -18,16 +17,14 @@ use alloy_rpc_types_eth::{
|
||||
use futures::Future;
|
||||
use reth_chainspec::EthChainSpec;
|
||||
use reth_errors::ProviderError;
|
||||
use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, TransactionEnv};
|
||||
use reth_evm::{
|
||||
ConfigureEvm, ConfigureEvmEnv, Evm, EvmEnv, HaltReasonFor, InspectorFor, SpecFor,
|
||||
TransactionEnv,
|
||||
};
|
||||
use reth_node_api::BlockBody;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::{BlockIdReader, ChainSpecProvider, ProviderHeader};
|
||||
use reth_revm::{
|
||||
database::StateProviderDatabase,
|
||||
db::CacheDB,
|
||||
primitives::{BlockEnv, ExecutionResult, ResultAndState},
|
||||
DatabaseRef,
|
||||
};
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef};
|
||||
use reth_rpc_eth_types::{
|
||||
cache::db::{StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper},
|
||||
error::{api::FromEvmHalt, ensure_success},
|
||||
@ -35,7 +32,13 @@ use reth_rpc_eth_types::{
|
||||
simulate::{self, EthSimulateError},
|
||||
EthApiError, RevertError, RpcInvalidTransactionError, StateCacheDb,
|
||||
};
|
||||
use revm::{DatabaseCommit, GetInspector};
|
||||
use revm::{
|
||||
context_interface::{
|
||||
result::{ExecutionResult, ResultAndState},
|
||||
Transaction,
|
||||
},
|
||||
Database, DatabaseCommit,
|
||||
};
|
||||
use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector};
|
||||
use tracing::trace;
|
||||
|
||||
@ -106,12 +109,12 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
let chain_spec = RpcNodeCore::provider(&this).chain_spec();
|
||||
while let Some(block) = block_state_calls.next() {
|
||||
// Increase number and timestamp for every new block
|
||||
evm_env.block_env.number += U256::from(1);
|
||||
evm_env.block_env.timestamp += U256::from(1);
|
||||
evm_env.block_env.number += 1;
|
||||
evm_env.block_env.timestamp += 1;
|
||||
|
||||
if validation {
|
||||
let base_fee_params = chain_spec
|
||||
.base_fee_params_at_timestamp(evm_env.block_env.timestamp.to());
|
||||
let base_fee_params =
|
||||
chain_spec.base_fee_params_at_timestamp(evm_env.block_env.timestamp);
|
||||
let base_fee = if let Some(latest) = blocks.last() {
|
||||
let header = &latest.inner.header;
|
||||
calc_next_block_base_fee(
|
||||
@ -123,9 +126,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
} else {
|
||||
base_block.next_block_base_fee(base_fee_params).unwrap_or_default()
|
||||
};
|
||||
evm_env.block_env.basefee = U256::from(base_fee);
|
||||
evm_env.block_env.basefee = base_fee;
|
||||
} else {
|
||||
evm_env.block_env.basefee = U256::ZERO;
|
||||
evm_env.block_env.basefee = 0;
|
||||
}
|
||||
|
||||
let SimBlock { block_overrides, state_overrides, calls } = block;
|
||||
@ -137,7 +140,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
apply_state_overrides(state_overrides, &mut db)?;
|
||||
}
|
||||
|
||||
if (total_gas_limit - gas_used) < evm_env.block_env.gas_limit.to() {
|
||||
if (total_gas_limit - gas_used) < evm_env.block_env.gas_limit {
|
||||
return Err(
|
||||
EthApiError::Other(Box::new(EthSimulateError::GasLimitReached)).into()
|
||||
)
|
||||
@ -148,7 +151,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
let txs_without_gas_limit =
|
||||
calls.iter().filter(|tx| tx.gas.is_none()).count();
|
||||
|
||||
if total_specified_gas > evm_env.block_env.gas_limit.to() {
|
||||
if total_specified_gas > evm_env.block_env.gas_limit {
|
||||
return Err(EthApiError::Other(Box::new(
|
||||
EthSimulateError::BlockGasLimitExceeded,
|
||||
))
|
||||
@ -156,7 +159,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
}
|
||||
|
||||
if txs_without_gas_limit > 0 {
|
||||
(evm_env.block_env.gas_limit.to::<u64>() - total_specified_gas) /
|
||||
(evm_env.block_env.gas_limit - total_specified_gas) /
|
||||
txs_without_gas_limit as u64
|
||||
} else {
|
||||
0
|
||||
@ -252,7 +255,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
let (res, _env) =
|
||||
self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
|
||||
|
||||
ensure_success(res.result).map_err(Self::Error::from_eth_err)
|
||||
ensure_success(res.result)
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +344,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
this.prepare_call_env(evm_env.clone(), tx, &mut db, overrides)?;
|
||||
let (res, _) = this.transact(&mut db, evm_env, tx)?;
|
||||
|
||||
match ensure_success(res.result) {
|
||||
match ensure_success::<_, Self::Error>(res.result) {
|
||||
Ok(output) => {
|
||||
results.push(EthCallResponse { value: Some(output), error: None });
|
||||
}
|
||||
@ -397,8 +400,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
Self: Trace,
|
||||
{
|
||||
let state = self.state_at_block_id(at)?;
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
|
||||
let mut tx_env = self.create_txn_env(&evm_env.block_env, request.clone())?;
|
||||
let mut tx_env = self.create_txn_env(&evm_env, request.clone(), &mut db)?;
|
||||
|
||||
// we want to disable this in eth_createAccessList, since this is common practice used by
|
||||
// other node impls and providers <https://github.com/foundry-rs/foundry/issues/4388>
|
||||
@ -409,12 +413,10 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
// <https://github.com/ethereum/go-ethereum/blob/8990c92aea01ca07801597b00c0d83d4e2d9b811/internal/ethapi/api.go#L1476-L1476>
|
||||
evm_env.cfg_env.disable_base_fee = true;
|
||||
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
|
||||
if request.gas.is_none() && tx_env.gas_price() > U256::ZERO {
|
||||
if request.gas.is_none() && tx_env.gas_price() > 0 {
|
||||
let cap = caller_gas_allowance(&mut db, &tx_env)?;
|
||||
// no gas limit was provided in the request, so we need to cap the request's gas limit
|
||||
tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit).saturating_to());
|
||||
tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit));
|
||||
}
|
||||
|
||||
// can consume the list since we're not using the request anymore
|
||||
@ -494,7 +496,7 @@ pub trait Call:
|
||||
tx_env: <Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
) -> Result<
|
||||
(
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
(EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>, <Self::Evm as ConfigureEvmEnv>::TxEnv),
|
||||
),
|
||||
Self::Error,
|
||||
@ -511,21 +513,22 @@ pub trait Call:
|
||||
/// Executes the [`EvmEnv`] against the given [Database] without committing state
|
||||
/// changes.
|
||||
#[expect(clippy::type_complexity)]
|
||||
fn transact_with_inspector<DB>(
|
||||
fn transact_with_inspector<DB, I>(
|
||||
&self,
|
||||
db: DB,
|
||||
evm_env: EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>,
|
||||
tx_env: <Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
inspector: impl GetInspector<DB>,
|
||||
inspector: I,
|
||||
) -> Result<
|
||||
(
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
(EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>, <Self::Evm as ConfigureEvmEnv>::TxEnv),
|
||||
),
|
||||
Self::Error,
|
||||
>
|
||||
where
|
||||
DB: Database<Error = ProviderError>,
|
||||
I: InspectorFor<DB, Self::Evm>,
|
||||
{
|
||||
let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env.clone(), inspector);
|
||||
let res = evm.transact(tx_env.clone()).map_err(Self::Error::from_evm_err)?;
|
||||
@ -543,7 +546,7 @@ pub trait Call:
|
||||
) -> impl Future<
|
||||
Output = Result<
|
||||
(
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
(
|
||||
EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>,
|
||||
<Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
@ -643,7 +646,11 @@ pub trait Call:
|
||||
) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadBlock + LoadTransaction,
|
||||
F: FnOnce(TransactionInfo, ResultAndState, StateCacheDb<'_>) -> Result<R, Self::Error>
|
||||
F: FnOnce(
|
||||
TransactionInfo,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
R: Send + 'static,
|
||||
@ -716,11 +723,12 @@ pub trait Call:
|
||||
/// Configures a new `TxEnv` for the [`TransactionRequest`]
|
||||
///
|
||||
/// All `TxEnv` fields are derived from the given [`TransactionRequest`], if fields are
|
||||
/// `None`, they fall back to the [`BlockEnv`]'s settings.
|
||||
/// `None`, they fall back to the [`EvmEnv`]'s settings.
|
||||
fn create_txn_env(
|
||||
&self,
|
||||
block_env: &BlockEnv,
|
||||
evm_env: &EvmEnv<SpecFor<Self::Evm>>,
|
||||
request: TransactionRequest,
|
||||
db: impl Database<Error: Into<EthApiError>>,
|
||||
) -> Result<<Self::Evm as ConfigureEvmEnv>::TxEnv, Self::Error>;
|
||||
|
||||
/// Prepares the [`EvmEnv`] for execution of calls.
|
||||
@ -759,7 +767,7 @@ pub trait Call:
|
||||
}
|
||||
|
||||
// apply configured gas cap
|
||||
evm_env.block_env.gas_limit = U256::from(self.call_gas_limit());
|
||||
evm_env.block_env.gas_limit = self.call_gas_limit();
|
||||
|
||||
// Disabled because eth_call is sometimes used with eoa senders
|
||||
// See <https://github.com/paradigmxyz/reth/issues/1959>
|
||||
@ -781,16 +789,16 @@ pub trait Call:
|
||||
}
|
||||
|
||||
let request_gas = request.gas;
|
||||
let mut tx_env = self.create_txn_env(&evm_env.block_env, request)?;
|
||||
let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
|
||||
|
||||
if request_gas.is_none() {
|
||||
// No gas limit was provided in the request, so we need to cap the transaction gas limit
|
||||
if tx_env.gas_price() > U256::ZERO {
|
||||
if tx_env.gas_price() > 0 {
|
||||
// If gas price is specified, cap transaction gas limit with caller allowance
|
||||
trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
|
||||
let cap = caller_gas_allowance(db, &tx_env)?;
|
||||
// ensure we cap gas_limit to the block's
|
||||
tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit).saturating_to());
|
||||
tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,15 +7,16 @@ use alloy_rpc_types_eth::{state::StateOverride, transaction::TransactionRequest,
|
||||
use futures::Future;
|
||||
use reth_chainspec::MIN_TRANSACTION_GAS;
|
||||
use reth_errors::ProviderError;
|
||||
use reth_evm::{env::EvmEnv, ConfigureEvmEnv, Database, TransactionEnv};
|
||||
use reth_evm::{ConfigureEvmEnv, Database, EvmEnv, TransactionEnv};
|
||||
use reth_provider::StateProvider;
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB, primitives::ExecutionResult};
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB};
|
||||
use reth_rpc_eth_types::{
|
||||
error::api::FromEvmHalt,
|
||||
revm_utils::{apply_state_overrides, caller_gas_allowance},
|
||||
EthApiError, RevertError, RpcInvalidTransactionError,
|
||||
};
|
||||
use reth_rpc_server_types::constants::gas_oracle::{CALL_STIPEND_GAS, ESTIMATE_GAS_ERROR_RATIO};
|
||||
use revm::context_interface::{result::ExecutionResult, Transaction};
|
||||
use revm_primitives::TxKind;
|
||||
use tracing::trace;
|
||||
|
||||
@ -55,7 +56,7 @@ pub trait EstimateCall: Call {
|
||||
request.nonce = None;
|
||||
|
||||
// Keep a copy of gas related request values
|
||||
let tx_request_gas_limit = request.gas.map(U256::from);
|
||||
let tx_request_gas_limit = request.gas;
|
||||
let tx_request_gas_price = request.gas_price;
|
||||
// the gas limit of the corresponding block
|
||||
let block_env_gas_limit = evm_env.block_env.gas_limit;
|
||||
@ -73,8 +74,8 @@ pub trait EstimateCall: Call {
|
||||
.unwrap_or(block_env_gas_limit);
|
||||
|
||||
// Configure the evm env
|
||||
let mut tx_env = self.create_txn_env(&evm_env.block_env, request)?;
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
let mut tx_env = self.create_txn_env(&evm_env, request, &mut db)?;
|
||||
|
||||
// Apply any state overrides if specified.
|
||||
if let Some(state_override) = state_override {
|
||||
@ -107,15 +108,12 @@ pub trait EstimateCall: Call {
|
||||
// Check funds of the sender (only useful to check if transaction gas price is more than 0).
|
||||
//
|
||||
// The caller allowance is check by doing `(account.balance - tx.value) / tx.gas_price`
|
||||
if tx_env.gas_price() > U256::ZERO {
|
||||
if tx_env.gas_price() > 0 {
|
||||
// cap the highest gas limit by max gas caller can afford with given gas price
|
||||
highest_gas_limit = highest_gas_limit
|
||||
.min(caller_gas_allowance(&mut db, &tx_env).map_err(Self::Error::from_eth_err)?);
|
||||
}
|
||||
|
||||
// We can now normalize the highest gas limit to a u64
|
||||
let mut highest_gas_limit = highest_gas_limit.saturating_to::<u64>();
|
||||
|
||||
// If the provided gas limit is less than computed cap, use that
|
||||
tx_env.set_gas_limit(tx_env.gas_limit().min(highest_gas_limit));
|
||||
|
||||
@ -288,7 +286,7 @@ pub trait EstimateCall: Call {
|
||||
#[inline]
|
||||
fn map_out_of_gas_err<DB>(
|
||||
&self,
|
||||
env_gas_limit: U256,
|
||||
env_gas_limit: u64,
|
||||
evm_env: EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>,
|
||||
mut tx_env: <Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
db: &mut DB,
|
||||
@ -298,7 +296,7 @@ pub trait EstimateCall: Call {
|
||||
EthApiError: From<DB::Error>,
|
||||
{
|
||||
let req_gas_limit = tx_env.gas_limit();
|
||||
tx_env.set_gas_limit(env_gas_limit.try_into().unwrap_or(u64::MAX));
|
||||
tx_env.set_gas_limit(env_gas_limit);
|
||||
let (res, _) = match self.transact(db, evm_env, tx_env) {
|
||||
Ok(res) => res,
|
||||
Err(err) => return err,
|
||||
@ -314,7 +312,7 @@ pub trait EstimateCall: Call {
|
||||
RpcInvalidTransactionError::Revert(RevertError::new(output)).into_eth_err()
|
||||
}
|
||||
ExecutionResult::Halt { reason, .. } => {
|
||||
RpcInvalidTransactionError::EvmHalt(reason).into_eth_err()
|
||||
Self::Error::from_evm_halt(reason, req_gas_limit)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -326,8 +324,8 @@ pub trait EstimateCall: Call {
|
||||
/// gas limit for a transaction. It adjusts the highest or lowest gas limits depending on
|
||||
/// whether the execution succeeded, reverted, or halted due to specific reasons.
|
||||
#[inline]
|
||||
pub fn update_estimated_gas_range(
|
||||
result: ExecutionResult,
|
||||
pub fn update_estimated_gas_range<Halt>(
|
||||
result: ExecutionResult<Halt>,
|
||||
tx_gas_limit: u64,
|
||||
highest_gas_limit: &mut u64,
|
||||
lowest_gas_limit: &mut u64,
|
||||
|
||||
@ -11,8 +11,8 @@ use futures::Future;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
||||
use reth_errors::RethError;
|
||||
use reth_evm::{
|
||||
env::EvmEnv, state_change::post_block_withdrawals_balance_increments,
|
||||
system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Evm, EvmError, InvalidTxError,
|
||||
state_change::post_block_withdrawals_balance_increments, system_calls::SystemCaller,
|
||||
ConfigureEvm, ConfigureEvmEnv, Evm, EvmEnv, EvmError, HaltReasonFor, InvalidTxError,
|
||||
NextBlockEnvAttributes,
|
||||
};
|
||||
use reth_primitives::{InvalidTransactionError, RecoveredBlock};
|
||||
@ -23,14 +23,21 @@ use reth_provider::{
|
||||
};
|
||||
use reth_revm::{
|
||||
database::StateProviderDatabase,
|
||||
primitives::{BlockEnv, ExecutionResult, ResultAndState},
|
||||
db::{states::bundle_state::BundleRetention, State},
|
||||
};
|
||||
use reth_rpc_eth_types::{EthApiError, PendingBlock, PendingBlockEnv, PendingBlockEnvOrigin};
|
||||
use reth_transaction_pool::{
|
||||
error::InvalidPoolTransactionError, BestTransactionsAttributes, PoolTransaction,
|
||||
TransactionPool,
|
||||
};
|
||||
use revm::{db::states::bundle_state::BundleRetention, DatabaseCommit, State};
|
||||
use revm::{
|
||||
context::BlockEnv,
|
||||
context_interface::{
|
||||
result::{ExecutionResult, ResultAndState},
|
||||
Block,
|
||||
},
|
||||
DatabaseCommit,
|
||||
};
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::debug;
|
||||
@ -155,7 +162,7 @@ pub trait LoadPendingBlock:
|
||||
// check if the block is still good
|
||||
if let Some(pending_block) = lock.as_ref() {
|
||||
// this is guaranteed to be the `latest` header
|
||||
if pending.evm_env.block_env.number.to::<u64>() == pending_block.block.number() &&
|
||||
if pending.evm_env.block_env.number == pending_block.block.number() &&
|
||||
parent_hash == pending_block.block.parent_hash() &&
|
||||
now <= pending_block.expires_at
|
||||
{
|
||||
@ -193,7 +200,7 @@ pub trait LoadPendingBlock:
|
||||
fn assemble_receipt(
|
||||
&self,
|
||||
tx: &ProviderTx<Self::Provider>,
|
||||
result: ExecutionResult,
|
||||
result: ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
cumulative_gas_used: u64,
|
||||
) -> ProviderReceipt<Self::Provider>;
|
||||
|
||||
@ -214,7 +221,7 @@ pub trait LoadPendingBlock:
|
||||
parent_hash: B256,
|
||||
state_root: B256,
|
||||
transactions: Vec<ProviderTx<Self::Provider>>,
|
||||
results: Vec<ExecutionResult>,
|
||||
results: Vec<ExecutionResult<HaltReasonFor<Self::Evm>>>,
|
||||
) -> (ProviderBlock<Self::Provider>, Vec<ProviderReceipt<Self::Provider>>) {
|
||||
let mut cumulative_gas_used = 0;
|
||||
let mut receipts = Vec::with_capacity(results.len());
|
||||
@ -257,15 +264,15 @@ pub trait LoadPendingBlock:
|
||||
|
||||
let mut cumulative_gas_used = 0;
|
||||
let mut sum_blob_gas_used = 0;
|
||||
let block_gas_limit: u64 = evm_env.block_env.gas_limit.to::<u64>();
|
||||
let base_fee = evm_env.block_env.basefee.to::<u64>();
|
||||
let block_gas_limit: u64 = evm_env.block_env.gas_limit;
|
||||
let base_fee = evm_env.block_env.basefee;
|
||||
|
||||
let mut executed_txs = Vec::new();
|
||||
let mut senders = Vec::new();
|
||||
let mut best_txs =
|
||||
self.pool().best_transactions_with_attributes(BestTransactionsAttributes::new(
|
||||
base_fee,
|
||||
evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64),
|
||||
evm_env.block_env.blob_gasprice().map(|gasprice| gasprice as u64),
|
||||
));
|
||||
|
||||
let chain_spec = self.provider().chain_spec();
|
||||
@ -384,7 +391,7 @@ pub trait LoadPendingBlock:
|
||||
// executes the withdrawals and commits them to the Database and BundleState.
|
||||
let balance_increments = post_block_withdrawals_balance_increments(
|
||||
chain_spec.as_ref(),
|
||||
evm_env.block_env.timestamp.try_into().unwrap_or(u64::MAX),
|
||||
evm_env.block_env.timestamp,
|
||||
&[],
|
||||
);
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ use alloy_serde::JsonStorageKey;
|
||||
use futures::Future;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
||||
use reth_errors::RethError;
|
||||
use reth_evm::{env::EvmEnv, ConfigureEvmEnv};
|
||||
use reth_evm::{ConfigureEvmEnv, EvmEnv};
|
||||
use reth_provider::{
|
||||
BlockIdReader, BlockNumReader, ChainSpecProvider, StateProvider, StateProviderBox,
|
||||
StateProviderFactory,
|
||||
|
||||
@ -9,20 +9,24 @@ use futures::Future;
|
||||
use reth_chainspec::ChainSpecProvider;
|
||||
use reth_errors::ProviderError;
|
||||
use reth_evm::{
|
||||
env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Database, Evm,
|
||||
system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Database, Evm, EvmEnv,
|
||||
HaltReasonFor, InspectorFor,
|
||||
};
|
||||
use reth_primitives::RecoveredBlock;
|
||||
use reth_primitives_traits::{BlockBody, SignedTransaction};
|
||||
use reth_provider::{BlockReader, ProviderBlock, ProviderHeader, ProviderTx};
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB};
|
||||
use reth_rpc_eth_types::{
|
||||
cache::db::{StateCacheDb, StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper},
|
||||
EthApiError,
|
||||
};
|
||||
use revm::{db::CacheDB, DatabaseCommit, GetInspector, Inspector};
|
||||
use revm::{
|
||||
context_interface::result::{ExecutionResult, ResultAndState},
|
||||
state::EvmState,
|
||||
DatabaseCommit,
|
||||
};
|
||||
use revm_inspectors::tracing::{TracingInspector, TracingInspectorConfig};
|
||||
use revm_primitives::{EvmState, ExecutionResult, ResultAndState};
|
||||
use std::{fmt::Display, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Executes CPU heavy tasks.
|
||||
pub trait Trace:
|
||||
@ -46,14 +50,14 @@ pub trait Trace:
|
||||
inspector: I,
|
||||
) -> Result<
|
||||
(
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
(EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>, <Self::Evm as ConfigureEvmEnv>::TxEnv),
|
||||
),
|
||||
Self::Error,
|
||||
>
|
||||
where
|
||||
DB: Database<Error = ProviderError>,
|
||||
I: GetInspector<DB>,
|
||||
I: InspectorFor<DB, Self::Evm>,
|
||||
{
|
||||
let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env.clone(), inspector);
|
||||
let res = evm.transact(tx_env.clone()).map_err(Self::Error::from_evm_err)?;
|
||||
@ -77,7 +81,10 @@ pub trait Trace:
|
||||
) -> Result<R, Self::Error>
|
||||
where
|
||||
Self: Call,
|
||||
F: FnOnce(TracingInspector, ResultAndState) -> Result<R, Self::Error>,
|
||||
F: FnOnce(
|
||||
TracingInspector,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
) -> Result<R, Self::Error>,
|
||||
{
|
||||
self.with_state_at_block(at, |state| {
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
@ -104,7 +111,11 @@ pub trait Trace:
|
||||
) -> impl Future<Output = Result<R, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadPendingBlock + Call,
|
||||
F: FnOnce(TracingInspector, ResultAndState, StateCacheDb<'_>) -> Result<R, Self::Error>
|
||||
F: FnOnce(
|
||||
TracingInspector,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
R: Send + 'static,
|
||||
@ -138,7 +149,7 @@ pub trait Trace:
|
||||
F: FnOnce(
|
||||
TransactionInfo,
|
||||
TracingInspector,
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
@ -168,12 +179,13 @@ pub trait Trace:
|
||||
F: FnOnce(
|
||||
TransactionInfo,
|
||||
Insp,
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
Insp: for<'a, 'b> Inspector<StateCacheDbRefMutWrapper<'a, 'b>> + Send + 'static,
|
||||
Insp:
|
||||
for<'a, 'b> InspectorFor<StateCacheDbRefMutWrapper<'a, 'b>, Self::Evm> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
async move {
|
||||
@ -232,7 +244,7 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
TracingInspector,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
@ -272,14 +284,15 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
Insp,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
Setup: FnMut() -> Insp + Send + 'static,
|
||||
Insp: for<'a, 'b> Inspector<StateCacheDbRefMutWrapper<'a, 'b>> + Send + 'static,
|
||||
Insp:
|
||||
for<'a, 'b> InspectorFor<StateCacheDbRefMutWrapper<'a, 'b>, Self::Evm> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
async move {
|
||||
@ -306,8 +319,8 @@ pub trait Trace:
|
||||
let state_at = block.parent_hash();
|
||||
let block_hash = block.hash();
|
||||
|
||||
let block_number = evm_env.block_env.number.saturating_to::<u64>();
|
||||
let base_fee = evm_env.block_env.basefee.saturating_to::<u64>();
|
||||
let block_number = evm_env.block_env.number;
|
||||
let base_fee = evm_env.block_env.basefee;
|
||||
|
||||
// now get the state
|
||||
let state = this.state_at_block_id(state_at.into())?;
|
||||
@ -391,7 +404,7 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
TracingInspector,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
@ -430,14 +443,15 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
Insp,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
Setup: FnMut() -> Insp + Send + 'static,
|
||||
Insp: for<'a, 'b> Inspector<StateCacheDbRefMutWrapper<'a, 'b>> + Send + 'static,
|
||||
Insp:
|
||||
for<'a, 'b> InspectorFor<StateCacheDbRefMutWrapper<'a, 'b>, Self::Evm> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.trace_block_until_with_inspector(block_id, block, None, insp_setup, f)
|
||||
@ -448,7 +462,7 @@ pub trait Trace:
|
||||
/// Note: This should only be called when tracing an entire block vs individual transactions.
|
||||
/// When tracing transaction on top of an already committed block state, those transitions are
|
||||
/// already applied.
|
||||
fn apply_pre_execution_changes<DB: Send + Database<Error: Display> + DatabaseCommit>(
|
||||
fn apply_pre_execution_changes<DB: Send + Database + DatabaseCommit>(
|
||||
&self,
|
||||
block: &RecoveredBlock<ProviderBlock<Self::Provider>>,
|
||||
db: &mut DB,
|
||||
|
||||
@ -38,8 +38,7 @@ use std::sync::Arc;
|
||||
/// There are subtle differences between when transacting [`TransactionRequest`]:
|
||||
///
|
||||
/// The endpoints `eth_call` and `eth_estimateGas` and `eth_createAccessList` should always
|
||||
/// __disable__ the base fee check in the
|
||||
/// [`EnvWithHandlerCfg`](revm_primitives::CfgEnvWithHandlerCfg).
|
||||
/// __disable__ the base fee check in the [`CfgEnv`](revm::context::CfgEnv).
|
||||
///
|
||||
/// The behaviour for tracing endpoints is not consistent across clients.
|
||||
/// Geth also disables the basefee check for tracing: <https://github.com/ethereum/go-ethereum/blob/bc0b87ca196f92e5af49bd33cc190ef0ec32b197/eth/tracers/api.go#L955-L955>
|
||||
|
||||
@ -35,8 +35,9 @@ alloy-consensus.workspace = true
|
||||
alloy-sol-types.workspace = true
|
||||
alloy-rpc-types-eth.workspace = true
|
||||
revm.workspace = true
|
||||
revm-database.workspace = true
|
||||
revm-inspectors.workspace = true
|
||||
revm-primitives = { workspace = true, features = ["dev"] }
|
||||
revm-primitives.workspace = true
|
||||
|
||||
# rpc
|
||||
jsonrpsee-core.workspace = true
|
||||
|
||||
18
crates/rpc/rpc-eth-types/src/cache/db.rs
vendored
18
crates/rpc/rpc-eth-types/src/cache/db.rs
vendored
@ -4,10 +4,14 @@
|
||||
|
||||
use alloy_primitives::{Address, B256, U256};
|
||||
use reth_errors::ProviderResult;
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef};
|
||||
use reth_revm::{database::StateProviderDatabase, DatabaseRef};
|
||||
use reth_storage_api::{HashedPostStateProvider, StateProvider};
|
||||
use reth_trie::{HashedStorage, MultiProofTargets};
|
||||
use revm::Database;
|
||||
use revm::{
|
||||
state::{AccountInfo, Bytecode},
|
||||
Database,
|
||||
};
|
||||
use revm_database::CacheDB;
|
||||
|
||||
/// Helper alias type for the state's [`CacheDB`]
|
||||
pub type StateCacheDb<'a> = CacheDB<StateProviderDatabase<StateProviderTraitObjWrapper<'a>>>;
|
||||
@ -138,7 +142,7 @@ impl reth_storage_api::BlockHashReader for StateProviderTraitObjWrapper<'_> {
|
||||
impl HashedPostStateProvider for StateProviderTraitObjWrapper<'_> {
|
||||
fn hashed_post_state(
|
||||
&self,
|
||||
bundle_state: &revm::db::BundleState,
|
||||
bundle_state: &revm_database::BundleState,
|
||||
) -> reth_trie::HashedPostState {
|
||||
self.0.hashed_post_state(bundle_state)
|
||||
}
|
||||
@ -192,11 +196,11 @@ impl<'a> Database for StateCacheDbRefMutWrapper<'a, '_> {
|
||||
fn basic(
|
||||
&mut self,
|
||||
address: revm_primitives::Address,
|
||||
) -> Result<Option<revm_primitives::AccountInfo>, Self::Error> {
|
||||
) -> Result<Option<AccountInfo>, Self::Error> {
|
||||
self.0.basic(address)
|
||||
}
|
||||
|
||||
fn code_by_hash(&mut self, code_hash: B256) -> Result<revm_primitives::Bytecode, Self::Error> {
|
||||
fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
|
||||
self.0.code_by_hash(code_hash)
|
||||
}
|
||||
|
||||
@ -219,11 +223,11 @@ impl<'a> DatabaseRef for StateCacheDbRefMutWrapper<'a, '_> {
|
||||
fn basic_ref(
|
||||
&self,
|
||||
address: revm_primitives::Address,
|
||||
) -> Result<Option<revm_primitives::AccountInfo>, Self::Error> {
|
||||
) -> Result<Option<AccountInfo>, Self::Error> {
|
||||
self.0.basic_ref(address)
|
||||
}
|
||||
|
||||
fn code_by_hash_ref(&self, code_hash: B256) -> Result<revm_primitives::Bytecode, Self::Error> {
|
||||
fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
|
||||
self.0.code_by_hash_ref(code_hash)
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
//! Helper traits to wrap generic l1 errors, in network specific error type configured in
|
||||
//! `reth_rpc_eth_api::EthApiTypes`.
|
||||
|
||||
use crate::{EthApiError, RpcInvalidTransactionError};
|
||||
use crate::EthApiError;
|
||||
use reth_errors::ProviderError;
|
||||
use reth_evm::ConfigureEvm;
|
||||
use revm_primitives::HaltReason;
|
||||
use reth_evm::{ConfigureEvm, EvmErrorFor, HaltReasonFor};
|
||||
use revm::context_interface::result::HaltReason;
|
||||
|
||||
use super::RpcInvalidTransactionError;
|
||||
|
||||
/// Helper trait to wrap core [`EthApiError`].
|
||||
pub trait FromEthApiError: From<EthApiError> {
|
||||
@ -81,28 +83,28 @@ impl AsEthApiError for EthApiError {
|
||||
|
||||
/// Helper trait to convert from revm errors.
|
||||
pub trait FromEvmError<Evm: ConfigureEvm>:
|
||||
From<Evm::EvmError<ProviderError>> + FromEvmHalt
|
||||
From<EvmErrorFor<Evm, ProviderError>> + FromEvmHalt<HaltReasonFor<Evm>>
|
||||
{
|
||||
/// Converts from EVM error to this type.
|
||||
fn from_evm_err(err: Evm::EvmError<ProviderError>) -> Self {
|
||||
fn from_evm_err(err: EvmErrorFor<Evm, ProviderError>) -> Self {
|
||||
err.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Evm> FromEvmError<Evm> for T
|
||||
where
|
||||
T: From<Evm::EvmError<ProviderError>> + FromEvmHalt,
|
||||
T: From<EvmErrorFor<Evm, ProviderError>> + FromEvmHalt<HaltReasonFor<Evm>>,
|
||||
Evm: ConfigureEvm,
|
||||
{
|
||||
}
|
||||
|
||||
/// Helper trait to convert from revm errors.
|
||||
pub trait FromEvmHalt<Halt = HaltReason> {
|
||||
pub trait FromEvmHalt<Halt> {
|
||||
/// Converts from EVM halt to this type.
|
||||
fn from_evm_halt(halt: Halt, gas_limit: u64) -> Self;
|
||||
}
|
||||
|
||||
impl FromEvmHalt for EthApiError {
|
||||
impl FromEvmHalt<HaltReason> for EthApiError {
|
||||
fn from_evm_halt(halt: HaltReason, gas_limit: u64) -> Self {
|
||||
RpcInvalidTransactionError::halt(halt, gas_limit).into()
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
//! Implementation specific Errors for the `eth_` namespace.
|
||||
|
||||
pub mod api;
|
||||
pub use api::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError};
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use crate::error::api::FromEvmHalt;
|
||||
use alloy_eips::BlockId;
|
||||
use alloy_primitives::{Address, Bytes, U256};
|
||||
use alloy_rpc_types_eth::{error::EthRpcErrorCode, request::TransactionInputError, BlockError};
|
||||
use alloy_sol_types::{ContractError, RevertReason};
|
||||
pub use api::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError};
|
||||
use core::time::Duration;
|
||||
use reth_errors::RethError;
|
||||
use reth_primitives_traits::transaction::signed::RecoveryError;
|
||||
use reth_rpc_server_types::result::{
|
||||
@ -18,9 +17,10 @@ use reth_transaction_pool::error::{
|
||||
Eip4844PoolTransactionError, Eip7702PoolTransactionError, InvalidPoolTransactionError,
|
||||
PoolError, PoolErrorKind, PoolTransactionError,
|
||||
};
|
||||
use revm::primitives::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, OutOfGasError};
|
||||
use revm::context_interface::result::{
|
||||
EVMError, ExecutionResult, HaltReason, InvalidHeader, InvalidTransaction, OutOfGasError,
|
||||
};
|
||||
use revm_inspectors::tracing::MuxError;
|
||||
use revm_primitives::InvalidHeader;
|
||||
use tracing::error;
|
||||
|
||||
/// A trait to convert an error to an RPC error.
|
||||
@ -273,11 +273,20 @@ impl From<reth_errors::ProviderError> for EthApiError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<EVMError<T>> for EthApiError
|
||||
impl From<InvalidHeader> for EthApiError {
|
||||
fn from(value: InvalidHeader) -> Self {
|
||||
match value {
|
||||
InvalidHeader::ExcessBlobGasNotSet => Self::ExcessBlobGasNotSet,
|
||||
InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<EVMError<T, InvalidTransaction>> for EthApiError
|
||||
where
|
||||
T: Into<Self>,
|
||||
{
|
||||
fn from(err: EVMError<T>) -> Self {
|
||||
fn from(err: EVMError<T, InvalidTransaction>) -> Self {
|
||||
match err {
|
||||
EVMError::Transaction(invalid_tx) => match invalid_tx {
|
||||
InvalidTransaction::NonceTooLow { tx, state } => {
|
||||
@ -285,8 +294,7 @@ where
|
||||
}
|
||||
_ => RpcInvalidTransactionError::from(invalid_tx).into(),
|
||||
},
|
||||
EVMError::Header(InvalidHeader::PrevrandaoNotSet) => Self::PrevrandaoNotSet,
|
||||
EVMError::Header(InvalidHeader::ExcessBlobGasNotSet) => Self::ExcessBlobGasNotSet,
|
||||
EVMError::Header(err) => err.into(),
|
||||
EVMError::Database(err) => err.into(),
|
||||
EVMError::Custom(err) => Self::EvmCustom(err),
|
||||
EVMError::Precompile(err) => Self::EvmPrecompile(err),
|
||||
@ -489,7 +497,9 @@ impl RpcInvalidTransactionError {
|
||||
/// Converts the out of gas error
|
||||
pub const fn out_of_gas(reason: OutOfGasError, gas_limit: u64) -> Self {
|
||||
match reason {
|
||||
OutOfGasError::Basic => Self::BasicOutOfGas(gas_limit),
|
||||
OutOfGasError::Basic | OutOfGasError::ReentrancySentry => {
|
||||
Self::BasicOutOfGas(gas_limit)
|
||||
}
|
||||
OutOfGasError::Memory | OutOfGasError::MemoryLimit => Self::MemoryOutOfGas(gas_limit),
|
||||
OutOfGasError::Precompile => Self::PrecompileOutOfGas(gas_limit),
|
||||
OutOfGasError::InvalidOperand => Self::InvalidOperandOutOfGas(gas_limit),
|
||||
@ -514,9 +524,8 @@ impl From<RpcInvalidTransactionError> for jsonrpsee_types::error::ErrorObject<'s
|
||||
}
|
||||
}
|
||||
|
||||
impl From<revm::primitives::InvalidTransaction> for RpcInvalidTransactionError {
|
||||
fn from(err: revm::primitives::InvalidTransaction) -> Self {
|
||||
use revm::primitives::InvalidTransaction;
|
||||
impl From<InvalidTransaction> for RpcInvalidTransactionError {
|
||||
fn from(err: InvalidTransaction) -> Self {
|
||||
match err {
|
||||
InvalidTransaction::InvalidChainId => Self::InvalidChainId,
|
||||
InvalidTransaction::PriorityFeeGreaterThanMaxFee => Self::TipAboveFeeCap,
|
||||
@ -546,7 +555,7 @@ impl From<revm::primitives::InvalidTransaction> for RpcInvalidTransactionError {
|
||||
InvalidTransaction::BlobGasPriceGreaterThanMax => Self::BlobFeeCapTooLow,
|
||||
InvalidTransaction::EmptyBlobs => Self::BlobTransactionMissingBlobHashes,
|
||||
InvalidTransaction::BlobVersionNotSupported => Self::BlobHashVersionMismatch,
|
||||
InvalidTransaction::TooManyBlobs { have } => Self::TooManyBlobs { have },
|
||||
InvalidTransaction::TooManyBlobs { have, .. } => Self::TooManyBlobs { have },
|
||||
InvalidTransaction::BlobCreateTransaction => Self::BlobTransactionIsCreate,
|
||||
InvalidTransaction::EofCrateShouldHaveToAddress => Self::EofCrateShouldHaveToAddress,
|
||||
InvalidTransaction::AuthorizationListNotSupported => {
|
||||
@ -779,15 +788,15 @@ pub enum SignError {
|
||||
|
||||
/// Converts the evm [`ExecutionResult`] into a result where `Ok` variant is the output bytes if it
|
||||
/// is [`ExecutionResult::Success`].
|
||||
pub fn ensure_success(result: ExecutionResult) -> EthResult<Bytes> {
|
||||
pub fn ensure_success<Halt, Error: FromEvmHalt<Halt> + FromEthApiError>(
|
||||
result: ExecutionResult<Halt>,
|
||||
) -> Result<Bytes, Error> {
|
||||
match result {
|
||||
ExecutionResult::Success { output, .. } => Ok(output.into_data()),
|
||||
ExecutionResult::Revert { output, .. } => {
|
||||
Err(RpcInvalidTransactionError::Revert(RevertError::new(output)).into())
|
||||
}
|
||||
ExecutionResult::Halt { reason, gas_used } => {
|
||||
Err(RpcInvalidTransactionError::halt(reason, gas_used).into())
|
||||
Err(Error::from_eth_err(RpcInvalidTransactionError::Revert(RevertError::new(output))))
|
||||
}
|
||||
ExecutionResult::Halt { reason, gas_used } => Err(Error::from_evm_halt(reason, gas_used)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,24 +6,12 @@ use alloy_rpc_types_eth::{
|
||||
BlockOverrides,
|
||||
};
|
||||
use reth_evm::TransactionEnv;
|
||||
use revm::{
|
||||
db::CacheDB,
|
||||
precompile::{PrecompileSpecId, Precompiles},
|
||||
primitives::{db::DatabaseRef, Bytecode, SpecId},
|
||||
Database,
|
||||
};
|
||||
use revm_primitives::BlockEnv;
|
||||
use revm::{context::BlockEnv, state::Bytecode, Database, DatabaseRef};
|
||||
use revm_database::CacheDB;
|
||||
use std::cmp::min;
|
||||
|
||||
use super::{EthApiError, EthResult, RpcInvalidTransactionError};
|
||||
|
||||
/// Returns the addresses of the precompiles corresponding to the `SpecId`.
|
||||
#[inline]
|
||||
pub fn get_precompiles(spec_id: SpecId) -> impl IntoIterator<Item = Address> {
|
||||
let spec = PrecompileSpecId::from_spec_id(spec_id);
|
||||
Precompiles::new(spec).addresses().copied()
|
||||
}
|
||||
|
||||
/// Calculates the caller gas allowance.
|
||||
///
|
||||
/// `allowance = (account.balance - tx.value) / tx.gas_price`
|
||||
@ -33,7 +21,7 @@ pub fn get_precompiles(spec_id: SpecId) -> impl IntoIterator<Item = Address> {
|
||||
///
|
||||
/// Note: this takes the mut [Database] trait because the loaded sender can be reused for the
|
||||
/// following operation like `eth_call`.
|
||||
pub fn caller_gas_allowance<DB>(db: &mut DB, env: &impl TransactionEnv) -> EthResult<U256>
|
||||
pub fn caller_gas_allowance<DB>(db: &mut DB, env: &impl TransactionEnv) -> EthResult<u64>
|
||||
where
|
||||
DB: Database,
|
||||
EthApiError: From<<DB as Database>::Error>,
|
||||
@ -52,9 +40,10 @@ where
|
||||
|
||||
Ok(balance
|
||||
// Calculate the amount of gas the caller can afford with the specified gas price.
|
||||
.checked_div(env.gas_price())
|
||||
.checked_div(U256::from(env.gas_price()))
|
||||
// This will be 0 if gas price is 0. It is fine, because we check it before.
|
||||
.unwrap_or_default())
|
||||
.unwrap_or_default()
|
||||
.saturating_to())
|
||||
}
|
||||
|
||||
/// Helper type for representing the fees of a `TransactionRequest`
|
||||
@ -220,25 +209,25 @@ pub fn apply_block_overrides<DB>(
|
||||
}
|
||||
|
||||
if let Some(number) = number {
|
||||
env.number = number;
|
||||
env.number = number.saturating_to();
|
||||
}
|
||||
if let Some(difficulty) = difficulty {
|
||||
env.difficulty = difficulty;
|
||||
}
|
||||
if let Some(time) = time {
|
||||
env.timestamp = U256::from(time);
|
||||
env.timestamp = time;
|
||||
}
|
||||
if let Some(gas_limit) = gas_limit {
|
||||
env.gas_limit = U256::from(gas_limit);
|
||||
env.gas_limit = gas_limit;
|
||||
}
|
||||
if let Some(coinbase) = coinbase {
|
||||
env.coinbase = coinbase;
|
||||
env.beneficiary = coinbase;
|
||||
}
|
||||
if let Some(random) = random {
|
||||
env.prevrandao = Some(random);
|
||||
}
|
||||
if let Some(base_fee) = base_fee {
|
||||
env.basefee = base_fee;
|
||||
env.basefee = base_fee.saturating_to();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,8 @@ use reth_primitives::RecoveredBlock;
|
||||
use reth_primitives_traits::{block::BlockTx, BlockBody as _, SignedTransaction};
|
||||
use reth_rpc_server_types::result::rpc_err;
|
||||
use reth_rpc_types_compat::{block::from_block, TransactionCompat};
|
||||
use revm::Database;
|
||||
use revm_primitives::{Address, Bytes, ExecutionResult, TxKind};
|
||||
use revm::{context_interface::result::ExecutionResult, Database};
|
||||
use revm_primitives::{Address, Bytes, TxKind};
|
||||
|
||||
use crate::{
|
||||
error::{
|
||||
@ -113,15 +113,15 @@ where
|
||||
|
||||
/// Handles outputs of the calls execution and builds a [`SimulatedBlock`].
|
||||
#[expect(clippy::type_complexity)]
|
||||
pub fn build_simulated_block<T, B>(
|
||||
pub fn build_simulated_block<T, B, Halt: Clone>(
|
||||
senders: Vec<Address>,
|
||||
results: Vec<ExecutionResult>,
|
||||
results: Vec<ExecutionResult<Halt>>,
|
||||
full_transactions: bool,
|
||||
tx_resp_builder: &T,
|
||||
block: B,
|
||||
) -> Result<SimulatedBlock<Block<T::Transaction, Header<B::Header>>>, T::Error>
|
||||
where
|
||||
T: TransactionCompat<BlockTx<B>, Error: FromEthApiError + FromEvmHalt>,
|
||||
T: TransactionCompat<BlockTx<B>, Error: FromEthApiError + FromEvmHalt<Halt>>,
|
||||
B: reth_primitives_traits::Block,
|
||||
{
|
||||
let mut calls: Vec<SimCallResult> = Vec::with_capacity(results.len());
|
||||
@ -130,7 +130,7 @@ where
|
||||
for (index, (result, tx)) in results.iter().zip(block.body().transactions()).enumerate() {
|
||||
let call = match result {
|
||||
ExecutionResult::Halt { reason, gas_used } => {
|
||||
let error = T::Error::from_evm_halt(*reason, tx.gas_limit());
|
||||
let error = T::Error::from_evm_halt(reason.clone(), tx.gas_limit());
|
||||
SimCallResult {
|
||||
return_data: Bytes::new(),
|
||||
error: Some(SimulateError {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::{eip2718::Encodable2718, BlockId, BlockNumberOrTag};
|
||||
use alloy_genesis::ChainConfig;
|
||||
use alloy_primitives::{Address, Bytes, B256, U256};
|
||||
use alloy_primitives::{Address, Bytes, B256};
|
||||
use alloy_rlp::{Decodable, Encodable};
|
||||
use alloy_rpc_types_debug::ExecutionWitness;
|
||||
use alloy_rpc_types_eth::{
|
||||
@ -17,9 +17,8 @@ use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
||||
use reth_evm::{
|
||||
env::EvmEnv,
|
||||
execute::{BlockExecutorProvider, Executor},
|
||||
ConfigureEvmEnv, TransactionEnv,
|
||||
ConfigureEvmEnv, EvmEnv,
|
||||
};
|
||||
use reth_primitives::{NodePrimitives, ReceiptWithBloom, RecoveredBlock};
|
||||
use reth_primitives_traits::{Block as _, BlockBody, SignedTransaction};
|
||||
@ -28,7 +27,11 @@ use reth_provider::{
|
||||
ReceiptProviderIdExt, StateProofProvider, StateProvider, StateProviderFactory,
|
||||
TransactionVariant,
|
||||
};
|
||||
use reth_revm::{database::StateProviderDatabase, witness::ExecutionWitnessRecord};
|
||||
use reth_revm::{
|
||||
database::StateProviderDatabase,
|
||||
db::{CacheDB, State},
|
||||
witness::ExecutionWitnessRecord,
|
||||
};
|
||||
use reth_rpc_api::DebugApiServer;
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{EthTransactions, TraceExt},
|
||||
@ -37,10 +40,7 @@ use reth_rpc_eth_api::{
|
||||
use reth_rpc_eth_types::{EthApiError, StateCacheDb};
|
||||
use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult};
|
||||
use reth_tasks::pool::BlockingTaskGuard;
|
||||
use revm::{
|
||||
db::{CacheDB, State},
|
||||
primitives::db::DatabaseCommit,
|
||||
};
|
||||
use revm::{context_interface::Transaction, state::EvmState, DatabaseCommit};
|
||||
use revm_inspectors::tracing::{
|
||||
FourByteInspector, MuxInspector, TracingInspector, TracingInspectorConfig, TransactionContext,
|
||||
};
|
||||
@ -369,12 +369,8 @@ where
|
||||
let db = db.0;
|
||||
|
||||
let tx_info = TransactionInfo {
|
||||
block_number: Some(
|
||||
evm_env.block_env.number.try_into().unwrap_or_default(),
|
||||
),
|
||||
base_fee: Some(
|
||||
evm_env.block_env.basefee.try_into().unwrap_or_default(),
|
||||
),
|
||||
block_number: Some(evm_env.block_env.number),
|
||||
base_fee: Some(evm_env.block_env.basefee),
|
||||
hash: None,
|
||||
block_hash: None,
|
||||
index: None,
|
||||
@ -447,12 +443,9 @@ where
|
||||
tx_env.clone(),
|
||||
&mut inspector,
|
||||
)?;
|
||||
let env = revm_primitives::Env::boxed(
|
||||
evm_env.cfg_env,
|
||||
evm_env.block_env,
|
||||
tx_env.into(),
|
||||
);
|
||||
inspector.json_result(res, &env, db).map_err(Eth::Error::from_eth_err)
|
||||
inspector
|
||||
.json_result(res, &tx_env, &evm_env.block_env, db)
|
||||
.map_err(Eth::Error::from_eth_err)
|
||||
})
|
||||
.await?;
|
||||
|
||||
@ -588,8 +581,8 @@ where
|
||||
results.push(trace);
|
||||
}
|
||||
// Increment block_env number and timestamp for the next bundle
|
||||
evm_env.block_env.number += U256::from(1);
|
||||
evm_env.block_env.timestamp += U256::from(12);
|
||||
evm_env.block_env.number += 1;
|
||||
evm_env.block_env.timestamp += 12;
|
||||
|
||||
all_bundles.push(results);
|
||||
}
|
||||
@ -700,7 +693,7 @@ where
|
||||
db: &mut StateCacheDb<'_>,
|
||||
transaction_context: Option<TransactionContext>,
|
||||
fused_inspector: &mut Option<TracingInspector>,
|
||||
) -> Result<(GethTrace, revm_primitives::EvmState), Eth::Error> {
|
||||
) -> Result<(GethTrace, EvmState), Eth::Error> {
|
||||
let GethDebugTracingOptions { config, tracer, tracer_config, .. } = opts;
|
||||
|
||||
let tx_info = TransactionInfo {
|
||||
@ -710,8 +703,8 @@ where
|
||||
.map(|c| c.tx_index.map(|i| i as u64))
|
||||
.unwrap_or_default(),
|
||||
block_hash: transaction_context.as_ref().map(|c| c.block_hash).unwrap_or_default(),
|
||||
block_number: Some(evm_env.block_env.number.try_into().unwrap_or_default()),
|
||||
base_fee: Some(evm_env.block_env.basefee.try_into().unwrap_or_default()),
|
||||
block_number: Some(evm_env.block_env.number),
|
||||
base_fee: Some(evm_env.block_env.basefee),
|
||||
};
|
||||
|
||||
if let Some(tracer) = tracer {
|
||||
@ -825,13 +818,9 @@ where
|
||||
self.eth_api().inspect(&mut *db, evm_env, tx_env, &mut inspector)?;
|
||||
|
||||
let state = res.state.clone();
|
||||
let env = revm_primitives::Env::boxed(
|
||||
evm_env.cfg_env,
|
||||
evm_env.block_env,
|
||||
tx_env.into(),
|
||||
);
|
||||
let result =
|
||||
inspector.json_result(res, &env, db).map_err(Eth::Error::from_eth_err)?;
|
||||
let result = inspector
|
||||
.json_result(res, &tx_env, &evm_env.block_env, db)
|
||||
.map_err(Eth::Error::from_eth_err)?;
|
||||
Ok((GethTrace::JS(result), state))
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ use alloy_rpc_types_mev::{EthCallBundle, EthCallBundleResponse, EthCallBundleTra
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use reth_evm::{ConfigureEvm, ConfigureEvmEnv, Evm};
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB};
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{Call, EthTransactions, LoadPendingBlock},
|
||||
EthCallBundleApiServer, FromEthApiError, FromEvmError,
|
||||
@ -17,10 +17,7 @@ use reth_tasks::pool::BlockingTaskGuard;
|
||||
use reth_transaction_pool::{
|
||||
EthBlobTransactionSidecar, EthPoolTransaction, PoolPooledTx, PoolTransaction, TransactionPool,
|
||||
};
|
||||
use revm::{
|
||||
db::{CacheDB, DatabaseCommit, DatabaseRef},
|
||||
primitives::ResultAndState,
|
||||
};
|
||||
use revm::{context_interface::result::ResultAndState, DatabaseCommit, DatabaseRef};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// `Eth` bundle implementation.
|
||||
@ -101,14 +98,14 @@ where
|
||||
let (mut evm_env, at) = self.eth_api().evm_env_at(block_id).await?;
|
||||
|
||||
if let Some(coinbase) = coinbase {
|
||||
evm_env.block_env.coinbase = coinbase;
|
||||
evm_env.block_env.beneficiary = coinbase;
|
||||
}
|
||||
|
||||
// need to adjust the timestamp for the next block
|
||||
if let Some(timestamp) = timestamp {
|
||||
evm_env.block_env.timestamp = U256::from(timestamp);
|
||||
evm_env.block_env.timestamp = timestamp;
|
||||
} else {
|
||||
evm_env.block_env.timestamp += U256::from(12);
|
||||
evm_env.block_env.timestamp += 12;
|
||||
}
|
||||
|
||||
if let Some(difficulty) = difficulty {
|
||||
@ -116,9 +113,8 @@ where
|
||||
}
|
||||
|
||||
// default to call gas limit unless user requests a smaller limit
|
||||
evm_env.block_env.gas_limit = U256::from(self.inner.eth_api.call_gas_limit());
|
||||
evm_env.block_env.gas_limit = self.inner.eth_api.call_gas_limit();
|
||||
if let Some(gas_limit) = gas_limit {
|
||||
let gas_limit = U256::from(gas_limit);
|
||||
if gas_limit > evm_env.block_env.gas_limit {
|
||||
return Err(
|
||||
EthApiError::InvalidTransaction(RpcInvalidTransactionError::GasTooHigh).into()
|
||||
@ -128,19 +124,19 @@ where
|
||||
}
|
||||
|
||||
if let Some(base_fee) = base_fee {
|
||||
evm_env.block_env.basefee = U256::from(base_fee);
|
||||
evm_env.block_env.basefee = base_fee.try_into().unwrap_or(u64::MAX);
|
||||
}
|
||||
|
||||
let state_block_number = evm_env.block_env.number;
|
||||
// use the block number of the request
|
||||
evm_env.block_env.number = U256::from(block_number);
|
||||
evm_env.block_env.number = block_number;
|
||||
|
||||
let eth_api = self.eth_api().clone();
|
||||
|
||||
self.eth_api()
|
||||
.spawn_with_state_at_block(at, move |state| {
|
||||
let coinbase = evm_env.block_env.coinbase;
|
||||
let basefee = Some(evm_env.block_env.basefee.to::<u64>());
|
||||
let coinbase = evm_env.block_env.beneficiary;
|
||||
let basefee = Some(evm_env.block_env.basefee);
|
||||
let db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
|
||||
let initial_coinbase = db
|
||||
@ -244,7 +240,7 @@ where
|
||||
eth_sent_to_coinbase,
|
||||
gas_fees: total_gas_fess,
|
||||
results,
|
||||
state_block_number: state_block_number.to(),
|
||||
state_block_number,
|
||||
total_gas_used,
|
||||
};
|
||||
|
||||
|
||||
@ -2,15 +2,16 @@
|
||||
|
||||
use crate::EthApi;
|
||||
use alloy_consensus::Header;
|
||||
use alloy_primitives::{TxKind, U256};
|
||||
use alloy_rpc_types::TransactionRequest;
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_evm::{ConfigureEvm, EvmEnv, SpecFor};
|
||||
use reth_provider::{BlockReader, ProviderHeader};
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{estimate::EstimateCall, Call, EthCall, LoadPendingBlock, LoadState, SpawnBlocking},
|
||||
FromEthApiError, FromEvmError, FullEthApiTypes, IntoEthApiError,
|
||||
};
|
||||
use reth_rpc_eth_types::{revm_utils::CallFees, RpcInvalidTransactionError};
|
||||
use revm_primitives::{BlockEnv, TxEnv, TxKind, U256};
|
||||
use reth_rpc_eth_types::{revm_utils::CallFees, EthApiError, RpcInvalidTransactionError};
|
||||
use revm::{context::TxEnv, context_interface::Block, Database};
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig> EthCall for EthApi<Provider, Pool, Network, EvmConfig>
|
||||
where
|
||||
@ -40,14 +41,17 @@ where
|
||||
|
||||
fn create_txn_env(
|
||||
&self,
|
||||
block_env: &BlockEnv,
|
||||
evm_env: &EvmEnv<SpecFor<Self::Evm>>,
|
||||
request: TransactionRequest,
|
||||
mut db: impl Database<Error: Into<EthApiError>>,
|
||||
) -> Result<TxEnv, Self::Error> {
|
||||
// Ensure that if versioned hashes are set, they're not empty
|
||||
if request.blob_versioned_hashes.as_ref().is_some_and(|hashes| hashes.is_empty()) {
|
||||
return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into_eth_err())
|
||||
}
|
||||
|
||||
let tx_type = request.preferred_type() as u8;
|
||||
|
||||
let TransactionRequest {
|
||||
from,
|
||||
to,
|
||||
@ -72,42 +76,54 @@ where
|
||||
gas_price.map(U256::from),
|
||||
max_fee_per_gas.map(U256::from),
|
||||
max_priority_fee_per_gas.map(U256::from),
|
||||
block_env.basefee,
|
||||
U256::from(evm_env.block_env.basefee),
|
||||
blob_versioned_hashes.as_deref(),
|
||||
max_fee_per_blob_gas.map(U256::from),
|
||||
block_env.get_blob_gasprice().map(U256::from),
|
||||
evm_env.block_env.blob_gasprice().map(U256::from),
|
||||
)?;
|
||||
|
||||
let gas_limit = gas.unwrap_or_else(|| {
|
||||
let gas_limit = gas.unwrap_or(
|
||||
// Use maximum allowed gas limit. The reason for this
|
||||
// is that both Erigon and Geth use pre-configured gas cap even if
|
||||
// it's possible to derive the gas limit from the block:
|
||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
||||
block_env.gas_limit.saturating_to()
|
||||
});
|
||||
evm_env.block_env.gas_limit,
|
||||
);
|
||||
|
||||
let chain_id = chain_id.unwrap_or(evm_env.cfg_env.chain_id);
|
||||
|
||||
let caller = from.unwrap_or_default();
|
||||
|
||||
let nonce = if let Some(nonce) = nonce {
|
||||
nonce
|
||||
} else {
|
||||
db.basic(caller).map_err(Into::into)?.map(|acc| acc.nonce).unwrap_or_default()
|
||||
};
|
||||
|
||||
#[allow(clippy::needless_update)]
|
||||
let env = TxEnv {
|
||||
tx_type,
|
||||
gas_limit,
|
||||
nonce,
|
||||
caller: from.unwrap_or_default(),
|
||||
gas_price,
|
||||
gas_priority_fee: max_priority_fee_per_gas,
|
||||
transact_to: to.unwrap_or(TxKind::Create),
|
||||
caller,
|
||||
gas_price: gas_price.saturating_to(),
|
||||
gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()),
|
||||
kind: to.unwrap_or(TxKind::Create),
|
||||
value: value.unwrap_or_default(),
|
||||
data: input
|
||||
.try_into_unique_input()
|
||||
.map_err(Self::Error::from_eth_err)?
|
||||
.unwrap_or_default(),
|
||||
chain_id,
|
||||
access_list: access_list.unwrap_or_default().into(),
|
||||
chain_id: Some(chain_id),
|
||||
access_list: access_list.unwrap_or_default(),
|
||||
// EIP-4844 fields
|
||||
blob_hashes: blob_versioned_hashes.unwrap_or_default(),
|
||||
max_fee_per_blob_gas,
|
||||
max_fee_per_blob_gas: max_fee_per_blob_gas
|
||||
.map(|v| v.saturating_to())
|
||||
.unwrap_or_default(),
|
||||
// EIP-7702 fields
|
||||
authorization_list: authorization_list.map(Into::into),
|
||||
..Default::default()
|
||||
authorization_list: authorization_list.unwrap_or_default(),
|
||||
};
|
||||
|
||||
Ok(env)
|
||||
|
||||
@ -4,7 +4,7 @@ use alloy_consensus::{constants::EMPTY_WITHDRAWALS, Header, Transaction, EMPTY_O
|
||||
use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE};
|
||||
use alloy_primitives::U256;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_evm::{ConfigureEvm, HaltReasonFor};
|
||||
use reth_primitives::{logs_bloom, BlockBody, Receipt};
|
||||
use reth_primitives_traits::proofs::calculate_transaction_root;
|
||||
use reth_provider::{
|
||||
@ -18,7 +18,11 @@ use reth_rpc_eth_api::{
|
||||
};
|
||||
use reth_rpc_eth_types::PendingBlock;
|
||||
use reth_transaction_pool::{PoolTransaction, TransactionPool};
|
||||
use revm_primitives::{BlockEnv, B256};
|
||||
use revm::{
|
||||
context::BlockEnv,
|
||||
context_interface::{result::ExecutionResult, Block},
|
||||
};
|
||||
use revm_primitives::B256;
|
||||
|
||||
use crate::EthApi;
|
||||
|
||||
@ -67,7 +71,7 @@ where
|
||||
|
||||
let logs_bloom = logs_bloom(receipts.iter().flat_map(|r| &r.logs));
|
||||
|
||||
let timestamp = block_env.timestamp.to::<u64>();
|
||||
let timestamp = block_env.timestamp;
|
||||
let is_shanghai = chain_spec.is_shanghai_active_at_timestamp(timestamp);
|
||||
let is_cancun = chain_spec.is_cancun_active_at_timestamp(timestamp);
|
||||
let is_prague = chain_spec.is_prague_active_at_timestamp(timestamp);
|
||||
@ -75,24 +79,24 @@ where
|
||||
let header = Header {
|
||||
parent_hash,
|
||||
ommers_hash: EMPTY_OMMER_ROOT_HASH,
|
||||
beneficiary: block_env.coinbase,
|
||||
beneficiary: block_env.beneficiary,
|
||||
state_root,
|
||||
transactions_root,
|
||||
receipts_root,
|
||||
withdrawals_root: is_shanghai.then_some(EMPTY_WITHDRAWALS),
|
||||
logs_bloom,
|
||||
timestamp: block_env.timestamp.to::<u64>(),
|
||||
timestamp: block_env.timestamp,
|
||||
mix_hash: block_env.prevrandao.unwrap_or_default(),
|
||||
nonce: BEACON_NONCE.into(),
|
||||
base_fee_per_gas: Some(block_env.basefee.to::<u64>()),
|
||||
number: block_env.number.to::<u64>(),
|
||||
gas_limit: block_env.gas_limit.to::<u64>(),
|
||||
base_fee_per_gas: Some(block_env.basefee),
|
||||
number: block_env.number,
|
||||
gas_limit: block_env.gas_limit,
|
||||
difficulty: U256::ZERO,
|
||||
gas_used: receipts.last().map(|r| r.cumulative_gas_used).unwrap_or_default(),
|
||||
blob_gas_used: is_cancun.then(|| {
|
||||
transactions.iter().map(|tx| tx.blob_gas_used().unwrap_or_default()).sum::<u64>()
|
||||
}),
|
||||
excess_blob_gas: block_env.get_blob_excess_gas(),
|
||||
excess_blob_gas: block_env.blob_excess_gas(),
|
||||
extra_data: Default::default(),
|
||||
parent_beacon_block_root: is_cancun.then_some(B256::ZERO),
|
||||
requests_hash: is_prague.then_some(EMPTY_REQUESTS_HASH),
|
||||
@ -108,7 +112,7 @@ where
|
||||
fn assemble_receipt(
|
||||
&self,
|
||||
tx: &ProviderTx<Self::Provider>,
|
||||
result: revm_primitives::ExecutionResult,
|
||||
result: ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
cumulative_gas_used: u64,
|
||||
) -> reth_provider::ProviderReceipt<Self::Provider> {
|
||||
#[allow(clippy::needless_update)]
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::BlockNumberOrTag;
|
||||
use alloy_primitives::U256;
|
||||
use alloy_rpc_types_eth::{BlockId, BlockOverrides};
|
||||
use alloy_rpc_types_eth::BlockId;
|
||||
use alloy_rpc_types_mev::{
|
||||
BundleItem, Inclusion, Privacy, RefundConfig, SendBundleRequest, SimBundleLogs,
|
||||
SimBundleOverrides, SimBundleResponse, Validity,
|
||||
@ -11,20 +11,19 @@ use alloy_rpc_types_mev::{
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use reth_evm::{ConfigureEvm, ConfigureEvmEnv, Evm};
|
||||
use reth_provider::ProviderTx;
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB};
|
||||
use reth_rpc_api::MevSimApiServer;
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{block::LoadBlock, Call, EthTransactions},
|
||||
FromEthApiError, FromEvmError,
|
||||
};
|
||||
use reth_rpc_eth_types::{utils::recover_raw_transaction, EthApiError};
|
||||
use reth_rpc_eth_types::{
|
||||
revm_utils::apply_block_overrides, utils::recover_raw_transaction, EthApiError,
|
||||
};
|
||||
use reth_tasks::pool::BlockingTaskGuard;
|
||||
use reth_transaction_pool::{PoolConsensusTx, PoolPooledTx, PoolTransaction, TransactionPool};
|
||||
use revm::{
|
||||
db::CacheDB,
|
||||
primitives::{Address, ResultAndState},
|
||||
DatabaseCommit, DatabaseRef,
|
||||
};
|
||||
use revm::{context_interface::result::ResultAndState, DatabaseCommit, DatabaseRef};
|
||||
use revm_primitives::Address;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tracing::info;
|
||||
|
||||
@ -229,7 +228,6 @@ where
|
||||
logs: bool,
|
||||
) -> Result<SimBundleResponse, Eth::Error> {
|
||||
let SimBundleOverrides { parent_block, block_overrides, .. } = overrides;
|
||||
let BlockOverrides { number, coinbase, time, gas_limit, base_fee, .. } = block_overrides;
|
||||
|
||||
// Parse and validate bundle
|
||||
// Also, flatten the bundle here so that its easier to process
|
||||
@ -240,27 +238,6 @@ where
|
||||
let current_block = self.eth_api().block_with_senders(current_block_id).await?;
|
||||
let current_block = current_block.ok_or(EthApiError::HeaderNotFound(block_id))?;
|
||||
|
||||
// apply overrides
|
||||
if let Some(block_number) = number {
|
||||
evm_env.block_env.number = U256::from(block_number);
|
||||
}
|
||||
|
||||
if let Some(coinbase) = coinbase {
|
||||
evm_env.block_env.coinbase = coinbase;
|
||||
}
|
||||
|
||||
if let Some(timestamp) = time {
|
||||
evm_env.block_env.timestamp = U256::from(timestamp);
|
||||
}
|
||||
|
||||
if let Some(gas_limit) = gas_limit {
|
||||
evm_env.block_env.gas_limit = U256::from(gas_limit);
|
||||
}
|
||||
|
||||
if let Some(base_fee) = base_fee {
|
||||
evm_env.block_env.basefee = U256::from(base_fee);
|
||||
}
|
||||
|
||||
let eth_api = self.inner.eth_api.clone();
|
||||
|
||||
let sim_response = self
|
||||
@ -269,9 +246,12 @@ where
|
||||
.spawn_with_state_at_block(current_block_id, move |state| {
|
||||
// Setup environment
|
||||
let current_block_number = current_block.number();
|
||||
let coinbase = evm_env.block_env.coinbase;
|
||||
let coinbase = evm_env.block_env.beneficiary;
|
||||
let basefee = evm_env.block_env.basefee;
|
||||
let db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
|
||||
// apply overrides
|
||||
apply_block_overrides(block_overrides, &mut db, &mut evm_env.block_env);
|
||||
|
||||
let initial_coinbase_balance = DatabaseRef::basic_ref(&db, coinbase)
|
||||
.map_err(EthApiError::from_eth_err)?
|
||||
@ -354,7 +334,7 @@ where
|
||||
});
|
||||
|
||||
// Calculate payout transaction fee
|
||||
let payout_tx_fee = basefee *
|
||||
let payout_tx_fee = U256::from(basefee) *
|
||||
U256::from(SBUNDLE_PAYOUT_MAX_COST) *
|
||||
U256::from(refund_configs.len() as u64);
|
||||
|
||||
|
||||
@ -19,11 +19,11 @@ use reth_rpc_eth_api::{
|
||||
};
|
||||
use reth_rpc_eth_types::{utils::binary_search, EthApiError};
|
||||
use reth_rpc_server_types::result::internal_rpc_err;
|
||||
use revm::context_interface::result::ExecutionResult;
|
||||
use revm_inspectors::{
|
||||
tracing::{types::CallTraceNode, TracingInspectorConfig},
|
||||
transfer::{TransferInspector, TransferKind},
|
||||
};
|
||||
use revm_primitives::ExecutionResult;
|
||||
|
||||
const API_LEVEL: u64 = 8;
|
||||
|
||||
|
||||
@ -19,13 +19,13 @@ use reth_consensus_common::calc::{base_block_reward_pre_merge, block_reward, omm
|
||||
use reth_evm::ConfigureEvmEnv;
|
||||
use reth_primitives_traits::{BlockBody, BlockHeader};
|
||||
use reth_provider::{BlockNumReader, BlockReader, ChainSpecProvider};
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_revm::{database::StateProviderDatabase, db::CacheDB};
|
||||
use reth_rpc_api::TraceApiServer;
|
||||
use reth_rpc_eth_api::{helpers::TraceExt, FromEthApiError, RpcNodeCore};
|
||||
use reth_rpc_eth_types::{error::EthApiError, utils::recover_raw_transaction};
|
||||
use reth_tasks::pool::BlockingTaskGuard;
|
||||
use reth_transaction_pool::{PoolPooledTx, PoolTransaction, TransactionPool};
|
||||
use revm::db::{CacheDB, DatabaseCommit};
|
||||
use revm::DatabaseCommit;
|
||||
use revm_inspectors::{
|
||||
opcode::OpcodeGasInspector,
|
||||
tracing::{parity::populate_state_diff, TracingInspector, TracingInspectorConfig},
|
||||
|
||||
Reference in New Issue
Block a user