mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
feat: add spawn_replay_transaction to EthTransactions (#8036)
Co-authored-by: Oliver Nordbjerg <onbjerg@users.noreply.github.com>
This commit is contained in:
@ -376,6 +376,20 @@ pub trait EthTransactions: Send + Sync {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Retrieves the transaction if it exists and returns its trace.
|
||||
///
|
||||
/// Before the transaction is traced, all previous transaction in the block are applied to the
|
||||
/// state by executing them first.
|
||||
/// The callback `f` is invoked with the [ResultAndState] after the transaction was executed and
|
||||
/// the database that points to the beginning of the transaction.
|
||||
///
|
||||
/// Note: Implementers should use a threadpool where blocking is allowed, such as
|
||||
/// [BlockingTaskPool](reth_tasks::pool::BlockingTaskPool).
|
||||
async fn spawn_replay_transaction<F, R>(&self, hash: B256, f: F) -> EthResult<Option<R>>
|
||||
where
|
||||
F: FnOnce(TransactionInfo, ResultAndState, StateCacheDB) -> EthResult<R> + Send + 'static,
|
||||
R: Send + 'static;
|
||||
|
||||
/// Retrieves the transaction if it exists and returns its trace.
|
||||
///
|
||||
/// Before the transaction is traced, all previous transaction in the block are applied to the
|
||||
@ -1173,6 +1187,47 @@ where
|
||||
Ok(block.map(|block| (transaction, block.seal(block_hash))))
|
||||
}
|
||||
|
||||
async fn spawn_replay_transaction<F, R>(&self, hash: B256, f: F) -> EthResult<Option<R>>
|
||||
where
|
||||
F: FnOnce(TransactionInfo, ResultAndState, StateCacheDB) -> EthResult<R> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let (transaction, block) = match self.transaction_and_block(hash).await? {
|
||||
None => return Ok(None),
|
||||
Some(res) => res,
|
||||
};
|
||||
let (tx, tx_info) = transaction.split();
|
||||
|
||||
let (cfg, block_env, _) = self.evm_env_at(block.hash().into()).await?;
|
||||
|
||||
// we need to get the state of the parent block because we're essentially replaying the
|
||||
// block the transaction is included in
|
||||
let parent_block = block.parent_hash;
|
||||
let block_txs = block.into_transactions_ecrecovered();
|
||||
|
||||
let this = self.clone();
|
||||
self.spawn_with_state_at_block(parent_block.into(), move |state| {
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
|
||||
// replay all transactions prior to the targeted transaction
|
||||
this.replay_transactions_until(
|
||||
&mut db,
|
||||
cfg.clone(),
|
||||
block_env.clone(),
|
||||
block_txs,
|
||||
tx.hash,
|
||||
)?;
|
||||
|
||||
let env =
|
||||
EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, tx_env_with_recovered(&tx));
|
||||
|
||||
let (res, _) = this.transact(&mut db, env)?;
|
||||
f(tx_info, res, db)
|
||||
})
|
||||
.await
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
async fn spawn_trace_transaction_in_block_with_inspector<Insp, F, R>(
|
||||
&self,
|
||||
hash: B256,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use alloy_primitives::Bytes;
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use revm::inspectors::NoOpInspector;
|
||||
use revm_inspectors::transfer::{TransferInspector, TransferKind};
|
||||
use revm_primitives::ExecutionResult;
|
||||
|
||||
@ -81,14 +80,10 @@ where
|
||||
async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult<Option<Bytes>> {
|
||||
let maybe_revert = self
|
||||
.eth
|
||||
.spawn_trace_transaction_in_block_with_inspector(
|
||||
tx_hash,
|
||||
NoOpInspector,
|
||||
|_tx_info, _inspector, res, _| match res.result {
|
||||
ExecutionResult::Revert { output, .. } => Ok(Some(output)),
|
||||
_ => Ok(None),
|
||||
},
|
||||
)
|
||||
.spawn_replay_transaction(tx_hash, |_tx_info, res, _| match res.result {
|
||||
ExecutionResult::Revert { output, .. } => Ok(Some(output)),
|
||||
_ => Ok(None),
|
||||
})
|
||||
.await
|
||||
.map(Option::flatten)?;
|
||||
Ok(maybe_revert)
|
||||
|
||||
Reference in New Issue
Block a user