mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(rpc): impl parity trace_transaction (#1765)
This commit is contained in:
@ -10,6 +10,20 @@ use std::collections::BTreeMap;
|
||||
/// Result type for parity style transaction trace
|
||||
pub type TraceResult = crate::trace::common::TraceResult<TraceOutput, String>;
|
||||
|
||||
// === impl TraceResult ===
|
||||
|
||||
impl TraceResult {
|
||||
/// Wraps the result type in a [TraceResult::Success] variant
|
||||
pub fn parity_success(result: TraceOutput) -> Self {
|
||||
TraceResult::Success { result }
|
||||
}
|
||||
|
||||
/// Wraps the result type in a [TraceResult::Error] variant
|
||||
pub fn parity_error(error: String) -> Self {
|
||||
TraceResult::Error { error }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum TraceType {
|
||||
@ -190,10 +204,18 @@ pub struct TransactionTrace {
|
||||
pub struct LocalizedTransactionTrace {
|
||||
#[serde(flatten)]
|
||||
pub trace: TransactionTrace,
|
||||
/// Transaction index within the block, None if pending.
|
||||
pub transaction_position: Option<usize>,
|
||||
/// Hash of the transaction
|
||||
pub transaction_hash: Option<H256>,
|
||||
pub block_number: U64,
|
||||
pub block_hash: H256,
|
||||
/// Block number the transaction is included in, None if pending.
|
||||
///
|
||||
/// Note: this deviates from <https://openethereum.github.io/JSONRPC-trace-module#trace_transaction> which always returns a block number
|
||||
pub block_number: Option<u64>,
|
||||
/// Hash of the block, if not pending
|
||||
///
|
||||
/// Note: this deviates from <https://openethereum.github.io/JSONRPC-trace-module#trace_transaction> which always returns a block number
|
||||
pub block_hash: Option<H256>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
|
||||
17
crates/rpc/rpc-types/src/eth/transaction/common.rs
Normal file
17
crates/rpc/rpc-types/src/eth/transaction/common.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//! Commonly used additional types that are not part of the JSON RPC spec but are often required
|
||||
//! when working with RPC types, such as [Transaction](crate::Transaction)
|
||||
|
||||
use reth_primitives::{TxHash, H256};
|
||||
|
||||
/// Additional fields in the context of a block that contains this transaction.
|
||||
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
|
||||
pub struct TransactionInfo {
|
||||
/// Hash of the transaction.
|
||||
pub hash: Option<TxHash>,
|
||||
/// Index of the transaction in the block
|
||||
pub index: Option<usize>,
|
||||
/// Hash of the block.
|
||||
pub block_hash: Option<H256>,
|
||||
/// Number of the block.
|
||||
pub block_number: Option<u64>,
|
||||
}
|
||||
@ -1,8 +1,10 @@
|
||||
mod common;
|
||||
mod receipt;
|
||||
mod request;
|
||||
mod signature;
|
||||
mod typed;
|
||||
|
||||
pub use common::TransactionInfo;
|
||||
pub use receipt::TransactionReceipt;
|
||||
pub use request::TransactionRequest;
|
||||
pub use signature::Signature;
|
||||
|
||||
@ -10,7 +10,7 @@ use reth_primitives::{
|
||||
};
|
||||
use reth_provider::{providers::ChainState, BlockProvider, EvmEnvProvider, StateProviderFactory};
|
||||
use reth_rlp::Decodable;
|
||||
use reth_rpc_types::{Index, Transaction, TransactionRequest};
|
||||
use reth_rpc_types::{Index, Transaction, TransactionInfo, TransactionRequest};
|
||||
use reth_transaction_pool::{TransactionOrigin, TransactionPool};
|
||||
use revm::primitives::{BlockEnv, CfgEnv};
|
||||
|
||||
@ -216,6 +216,45 @@ pub enum TransactionSource {
|
||||
},
|
||||
}
|
||||
|
||||
// === impl TransactionSource ===
|
||||
|
||||
impl TransactionSource {
|
||||
/// Consumes the type and returns the wrapped transaction.
|
||||
pub fn into_recovered(self) -> TransactionSignedEcRecovered {
|
||||
self.into()
|
||||
}
|
||||
|
||||
/// Returns the transaction and block related info, if not pending
|
||||
pub fn split(self) -> (TransactionSignedEcRecovered, TransactionInfo) {
|
||||
match self {
|
||||
TransactionSource::Pool(tx) => {
|
||||
let hash = tx.hash();
|
||||
(
|
||||
tx,
|
||||
TransactionInfo {
|
||||
hash: Some(hash),
|
||||
index: None,
|
||||
block_hash: None,
|
||||
block_number: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
TransactionSource::Database { transaction, index, block_hash, block_number } => {
|
||||
let hash = transaction.hash();
|
||||
(
|
||||
transaction,
|
||||
TransactionInfo {
|
||||
hash: Some(hash),
|
||||
index: Some(index),
|
||||
block_hash: Some(block_hash),
|
||||
block_number: Some(block_number),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransactionSource> for TransactionSignedEcRecovered {
|
||||
fn from(value: TransactionSource) -> Self {
|
||||
match value {
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
use crate::{
|
||||
eth::{cache::EthStateCache, EthTransactions},
|
||||
eth::{cache::EthStateCache, revm_utils::inspect, EthTransactions},
|
||||
result::internal_rpc_err,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult as Result;
|
||||
use reth_primitives::{BlockId, Bytes, H256};
|
||||
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
|
||||
use reth_revm::{
|
||||
database::{State, SubState},
|
||||
env::tx_env_with_recovered,
|
||||
tracing::{TraceInspectorConfig, TracingInspector},
|
||||
};
|
||||
use reth_rpc_api::TraceApiServer;
|
||||
use reth_rpc_types::{
|
||||
trace::{filter::TraceFilter, parity::*},
|
||||
CallRequest, Index,
|
||||
};
|
||||
use revm::primitives::Env;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// `trace` API implementation.
|
||||
@ -115,14 +121,28 @@ where
|
||||
&self,
|
||||
hash: H256,
|
||||
) -> Result<Option<Vec<LocalizedTransactionTrace>>> {
|
||||
let (_transaction, at) = match self.eth_api.transaction_by_hash_at(hash).await? {
|
||||
let (transaction, at) = match self.eth_api.transaction_by_hash_at(hash).await? {
|
||||
None => return Ok(None),
|
||||
Some(res) => res,
|
||||
};
|
||||
|
||||
let (_cfg, _block_env, _at) = self.eth_api.evm_env_at(at).await?;
|
||||
let (cfg, block, at) = self.eth_api.evm_env_at(at).await?;
|
||||
|
||||
Err(internal_rpc_err("unimplemented"))
|
||||
let (tx, tx_info) = transaction.split();
|
||||
|
||||
let traces = self.eth_api.with_state_at(at, |state| {
|
||||
let tx = tx_env_with_recovered(&tx);
|
||||
let env = Env { cfg, block, tx };
|
||||
let db = SubState::new(State::new(state));
|
||||
let mut inspector = TracingInspector::new(TraceInspectorConfig::default_parity());
|
||||
|
||||
inspect(db, env, &mut inspector)?;
|
||||
|
||||
let traces = inspector.into_parity_builder().into_localized_transaction_traces(tx_info);
|
||||
|
||||
Ok(traces)
|
||||
})?;
|
||||
Ok(Some(traces))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user