mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
feat: relax bounds for eth_simulateV1 (#13232)
This commit is contained in:
@ -26,7 +26,6 @@ reth-rpc-types-compat.workspace = true
|
||||
reth-tasks = { workspace = true, features = ["rayon"] }
|
||||
reth-transaction-pool.workspace = true
|
||||
reth-chainspec.workspace = true
|
||||
reth-execution-types.workspace = true
|
||||
reth-rpc-eth-types.workspace = true
|
||||
reth-rpc-server-types.workspace = true
|
||||
reth-network-api.workspace = true
|
||||
|
||||
@ -13,7 +13,6 @@ use alloy_rpc_types_eth::{
|
||||
};
|
||||
use alloy_serde::JsonStorageKey;
|
||||
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
|
||||
use reth_provider::BlockReader;
|
||||
use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult};
|
||||
use tracing::trace;
|
||||
|
||||
@ -372,12 +371,7 @@ impl<T>
|
||||
RpcHeader<T::NetworkTypes>,
|
||||
> for T
|
||||
where
|
||||
T: FullEthApi<
|
||||
Provider: BlockReader<
|
||||
Header = alloy_consensus::Header,
|
||||
Transaction = reth_primitives::TransactionSigned,
|
||||
>,
|
||||
>,
|
||||
T: FullEthApi,
|
||||
jsonrpsee_types::error::ErrorObject<'static>: From<T::Error>,
|
||||
{
|
||||
/// Handler for: `eth_protocolVersion`
|
||||
|
||||
@ -20,9 +20,7 @@ use reth_chainspec::EthChainSpec;
|
||||
use reth_evm::{ConfigureEvm, ConfigureEvmEnv};
|
||||
use reth_node_api::BlockBody;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::{
|
||||
BlockIdReader, BlockReader, ChainSpecProvider, HeaderProvider, ProviderHeader,
|
||||
};
|
||||
use reth_provider::{BlockIdReader, ChainSpecProvider, HeaderProvider, ProviderHeader};
|
||||
use reth_revm::{
|
||||
database::StateProviderDatabase,
|
||||
db::CacheDB,
|
||||
@ -50,7 +48,7 @@ pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>,
|
||||
|
||||
/// Execution related functions for the [`EthApiServer`](crate::EthApiServer) trait in
|
||||
/// the `eth_` namespace.
|
||||
pub trait EthCall: EstimateCall + Call + LoadPendingBlock {
|
||||
pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthApiTypes {
|
||||
/// Estimate gas needed for execution of the `request` at the [`BlockId`].
|
||||
fn estimate_gas_at(
|
||||
&self,
|
||||
@ -70,15 +68,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock {
|
||||
&self,
|
||||
payload: SimulatePayload,
|
||||
block: Option<BlockId>,
|
||||
) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadBlock<
|
||||
Provider: BlockReader<
|
||||
Header = alloy_consensus::Header,
|
||||
Transaction = reth_primitives::TransactionSigned,
|
||||
>,
|
||||
> + FullEthApiTypes,
|
||||
{
|
||||
) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
|
||||
async move {
|
||||
if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
|
||||
return Err(EthApiError::InvalidParams("too many blocks.".to_string()).into())
|
||||
@ -171,9 +161,11 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock {
|
||||
block_env.gas_limit.to(),
|
||||
cfg.chain_id,
|
||||
&mut db,
|
||||
this.tx_resp_builder(),
|
||||
)?;
|
||||
|
||||
let mut calls = calls.into_iter().peekable();
|
||||
let mut senders = Vec::with_capacity(transactions.len());
|
||||
let mut results = Vec::with_capacity(calls.len());
|
||||
|
||||
while let Some(tx) = calls.next() {
|
||||
@ -197,18 +189,27 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock {
|
||||
db.commit(res.state);
|
||||
}
|
||||
|
||||
results.push((env.tx.caller, res.result));
|
||||
senders.push(env.tx.caller);
|
||||
results.push(res.result);
|
||||
}
|
||||
|
||||
let (block, _) = this.assemble_block_and_receipts(
|
||||
&block_env,
|
||||
parent_hash,
|
||||
// state root calculation is skipped for performance reasons
|
||||
B256::ZERO,
|
||||
transactions,
|
||||
results.clone(),
|
||||
);
|
||||
|
||||
let block: SimulatedBlock<RpcBlock<Self::NetworkTypes>> =
|
||||
simulate::build_block(
|
||||
simulate::build_simulated_block(
|
||||
senders,
|
||||
results,
|
||||
transactions,
|
||||
&block_env,
|
||||
parent_hash,
|
||||
total_difficulty,
|
||||
return_full_transactions,
|
||||
this.tx_resp_builder(),
|
||||
block,
|
||||
)?;
|
||||
|
||||
parent_hash = block.inner.header.hash;
|
||||
@ -245,10 +246,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock {
|
||||
bundle: Bundle,
|
||||
state_context: Option<StateContext>,
|
||||
mut state_override: Option<StateOverride>,
|
||||
) -> impl Future<Output = Result<Vec<EthCallResponse>, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadBlock,
|
||||
{
|
||||
) -> impl Future<Output = Result<Vec<EthCallResponse>, Self::Error>> + Send {
|
||||
async move {
|
||||
let Bundle { transactions, block_override } = bundle;
|
||||
if transactions.is_empty() {
|
||||
@ -608,7 +606,7 @@ pub trait Call:
|
||||
f: F,
|
||||
) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadBlock + LoadPendingBlock + LoadTransaction,
|
||||
Self: LoadBlock + LoadTransaction,
|
||||
F: FnOnce(TransactionInfo, ResultAndState, StateCacheDb<'_>) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
|
||||
@ -42,12 +42,9 @@ pub use transaction::{EthTransactions, LoadTransaction};
|
||||
use crate::FullEthApiTypes;
|
||||
|
||||
/// Extension trait that bundles traits needed for tracing transactions.
|
||||
pub trait TraceExt:
|
||||
LoadTransaction + LoadBlock + LoadPendingBlock + SpawnBlocking + Trace + Call
|
||||
{
|
||||
}
|
||||
pub trait TraceExt: LoadTransaction + LoadBlock + SpawnBlocking + Trace + Call {}
|
||||
|
||||
impl<T> TraceExt for T where T: LoadTransaction + LoadBlock + LoadPendingBlock + Trace + Call {}
|
||||
impl<T> TraceExt for T where T: LoadTransaction + LoadBlock + Trace + Call {}
|
||||
|
||||
/// Helper trait to unify all `eth` rpc server building block traits, for simplicity.
|
||||
///
|
||||
|
||||
@ -15,8 +15,7 @@ use reth_evm::{
|
||||
state_change::post_block_withdrawals_balance_increments, system_calls::SystemCaller,
|
||||
ConfigureEvm, ConfigureEvmEnv, NextBlockEnvAttributes,
|
||||
};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_primitives::{BlockExt, InvalidTransactionError, RecoveredTx, SealedBlockWithSenders};
|
||||
use reth_primitives::{BlockExt, InvalidTransactionError, SealedBlockWithSenders};
|
||||
use reth_primitives_traits::receipt::ReceiptExt;
|
||||
use reth_provider::{
|
||||
BlockReader, BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, ProviderBlock, ProviderError,
|
||||
@ -199,7 +198,7 @@ pub trait LoadPendingBlock:
|
||||
/// Assembles a receipt for a transaction, based on its [`ExecutionResult`].
|
||||
fn assemble_receipt(
|
||||
&self,
|
||||
tx: &RecoveredTx<ProviderTx<Self::Provider>>,
|
||||
tx: &ProviderTx<Self::Provider>,
|
||||
result: ExecutionResult,
|
||||
cumulative_gas_used: u64,
|
||||
) -> ProviderReceipt<Self::Provider>;
|
||||
@ -207,14 +206,36 @@ pub trait LoadPendingBlock:
|
||||
/// Assembles a pending block.
|
||||
fn assemble_block(
|
||||
&self,
|
||||
cfg: CfgEnvWithHandlerCfg,
|
||||
block_env: BlockEnv,
|
||||
block_env: &BlockEnv,
|
||||
parent_hash: revm_primitives::B256,
|
||||
state_root: revm_primitives::B256,
|
||||
transactions: Vec<ProviderTx<Self::Provider>>,
|
||||
receipts: &[ProviderReceipt<Self::Provider>],
|
||||
) -> ProviderBlock<Self::Provider>;
|
||||
|
||||
/// Helper to invoke both [`Self::assemble_block`] and [`Self::assemble_receipt`].
|
||||
fn assemble_block_and_receipts(
|
||||
&self,
|
||||
block_env: &BlockEnv,
|
||||
parent_hash: revm_primitives::B256,
|
||||
state_root: revm_primitives::B256,
|
||||
transactions: Vec<ProviderTx<Self::Provider>>,
|
||||
results: Vec<ExecutionResult>,
|
||||
) -> (ProviderBlock<Self::Provider>, Vec<ProviderReceipt<Self::Provider>>) {
|
||||
let mut cumulative_gas_used = 0;
|
||||
let mut receipts = Vec::with_capacity(results.len());
|
||||
|
||||
for (tx, outcome) in transactions.iter().zip(results) {
|
||||
cumulative_gas_used += outcome.gas_used();
|
||||
receipts.push(self.assemble_receipt(tx, outcome, cumulative_gas_used));
|
||||
}
|
||||
|
||||
let block =
|
||||
self.assemble_block(block_env, parent_hash, state_root, transactions, &receipts);
|
||||
|
||||
(block, receipts)
|
||||
}
|
||||
|
||||
/// Builds a pending block using the configured provider and pool.
|
||||
///
|
||||
/// If the origin is the actual pending block, the block is built with withdrawals.
|
||||
@ -248,7 +269,6 @@ pub trait LoadPendingBlock:
|
||||
let mut sum_blob_gas_used = 0;
|
||||
let block_gas_limit: u64 = block_env.gas_limit.to::<u64>();
|
||||
let base_fee = block_env.basefee.to::<u64>();
|
||||
let block_number = block_env.number.to::<u64>();
|
||||
|
||||
let mut executed_txs = Vec::new();
|
||||
let mut senders = Vec::new();
|
||||
@ -266,7 +286,7 @@ pub trait LoadPendingBlock:
|
||||
.pre_block_blockhashes_contract_call(&mut db, &cfg, &block_env, parent_hash)
|
||||
.map_err(|err| EthApiError::Internal(err.into()))?;
|
||||
|
||||
let mut receipts = Vec::new();
|
||||
let mut results = Vec::new();
|
||||
|
||||
while let Some(pool_tx) = best_txs.next() {
|
||||
// ensure we still have capacity for this transaction
|
||||
@ -374,13 +394,11 @@ pub trait LoadPendingBlock:
|
||||
// add gas used by the transaction to cumulative gas used, before creating the receipt
|
||||
cumulative_gas_used += gas_used;
|
||||
|
||||
// Push transaction changeset and calculate header bloom filter for receipt.
|
||||
receipts.push(Some(self.assemble_receipt(&tx, result, cumulative_gas_used)));
|
||||
|
||||
// append transaction to the list of executed transactions
|
||||
let (tx, sender) = tx.to_components();
|
||||
executed_txs.push(tx);
|
||||
senders.push(sender);
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
// executes the withdrawals and commits them to the Database and BundleState.
|
||||
@ -396,22 +414,19 @@ pub trait LoadPendingBlock:
|
||||
// merge all transitions into bundle state.
|
||||
db.merge_transitions(BundleRetention::PlainState);
|
||||
|
||||
let execution_outcome: ExecutionOutcome<ProviderReceipt<Self::Provider>> =
|
||||
ExecutionOutcome::new(
|
||||
db.take_bundle(),
|
||||
vec![receipts.clone()].into(),
|
||||
block_number,
|
||||
Vec::new(),
|
||||
);
|
||||
let hashed_state = db.database.hashed_post_state(execution_outcome.state());
|
||||
let bundle_state = db.take_bundle();
|
||||
let hashed_state = db.database.hashed_post_state(&bundle_state);
|
||||
|
||||
// calculate the state root
|
||||
let state_root = db.database.state_root(hashed_state).map_err(Self::Error::from_eth_err)?;
|
||||
|
||||
// Convert Vec<Option<Receipt>> to Vec<Receipt>
|
||||
let receipts: Vec<_> = receipts.into_iter().flatten().collect();
|
||||
let block =
|
||||
self.assemble_block(cfg, block_env, parent_hash, state_root, executed_txs, &receipts);
|
||||
let (block, receipts) = self.assemble_block_and_receipts(
|
||||
&block_env,
|
||||
parent_hash,
|
||||
state_root,
|
||||
executed_txs,
|
||||
results,
|
||||
);
|
||||
|
||||
Ok((SealedBlockWithSenders { block: block.seal_slow(), senders }, receipts))
|
||||
}
|
||||
|
||||
@ -25,9 +25,7 @@ use reth_rpc_types_compat::transaction::{from_recovered, from_recovered_with_blo
|
||||
use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{
|
||||
EthApiSpec, EthSigner, LoadBlock, LoadPendingBlock, LoadReceipt, LoadState, SpawnBlocking,
|
||||
};
|
||||
use super::{EthApiSpec, EthSigner, LoadBlock, LoadReceipt, LoadState, SpawnBlocking};
|
||||
use crate::{
|
||||
helpers::estimate::EstimateCall, FromEthApiError, FullEthApiTypes, IntoEthApiError,
|
||||
RpcNodeCore, RpcNodeCoreExt, RpcReceipt, RpcTransaction,
|
||||
@ -365,7 +363,7 @@ pub trait EthTransactions: LoadTransaction<Provider: BlockReaderIdExt> {
|
||||
mut request: TransactionRequest,
|
||||
) -> impl Future<Output = Result<B256, Self::Error>> + Send
|
||||
where
|
||||
Self: EthApiSpec + LoadBlock + LoadPendingBlock + EstimateCall,
|
||||
Self: EthApiSpec + LoadBlock + EstimateCall,
|
||||
{
|
||||
async move {
|
||||
let from = match request.from {
|
||||
|
||||
Reference in New Issue
Block a user