feat: port over tracing from rust-web3 (#93)

This commit is contained in:
Georgios Konstantopoulos 2020-10-31 12:44:08 +02:00 committed by GitHub
parent 98c63f9a3d
commit c30f45fc72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1916 additions and 3 deletions

View File

@ -30,3 +30,6 @@ pub use signature::*;
mod txpool; mod txpool;
pub use txpool::*; pub use txpool::*;
mod trace;
pub use trace::*;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
r#"[{
"output": "0x",
"stateDiff": {
"0x5df9b87991262f6ba471f09758cde1c0fc1de734": {
"balance": {
"+": "0x7a69"
},
"code": {
"+": "0x"
},
"nonce": {
"+": "0x0"
},
"storage": {}
},
"0xa1e4380a3b1f749673e270229993ee55f35663b4": {
"balance": {
"*": {
"from": "0x6c6b935b8bbd400000",
"to": "0x6c5d01021be7168597"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x0",
"to": "0x1"
}
},
"storage": {}
},
"0xe6a7a1d47ff21b6321162aea7c6cb457d5476bca": {
"balance": {
"*": {
"from": "0xf3426785a8ab466000",
"to": "0xf350f9df18816f6000"
}
},
"code": "=",
"nonce": "=",
"storage": {}
}
},
"trace": [
{
"action": {
"callType": "call",
"from": "0xa1e4380a3b1f749673e270229993ee55f35663b4",
"gas": "0x0",
"input": "0x",
"to": "0x5df9b87991262f6ba471f09758cde1c0fc1de734",
"value": "0x7a69"
},
"result": {
"gasUsed": "0x0",
"output": "0x"
},
"subtraces": 0,
"traceAddress": [],
"type": "call"
}
],
"transactionHash": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060",
"vmTrace": {
"code": "0x",
"ops": []
}
}]"#

View File

@ -0,0 +1,360 @@
//! Types for the Parity Transaction-Trace Filtering API
use crate::types::{Address, BlockNumber, Bytes, H160, H256, U256};
use serde::{Deserialize, Serialize};
/// Trace filter
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct TraceFilter {
/// From block
#[serde(rename = "fromBlock", skip_serializing_if = "Option::is_none")]
from_block: Option<BlockNumber>,
/// To block
#[serde(rename = "toBlock", skip_serializing_if = "Option::is_none")]
to_block: Option<BlockNumber>,
/// From address
#[serde(rename = "fromAddress", skip_serializing_if = "Option::is_none")]
from_address: Option<Vec<Address>>,
/// To address
#[serde(rename = "toAddress", skip_serializing_if = "Option::is_none")]
to_address: Option<Vec<Address>>,
/// Output offset
#[serde(skip_serializing_if = "Option::is_none")]
after: Option<usize>,
/// Output amount
#[serde(skip_serializing_if = "Option::is_none")]
count: Option<usize>,
}
impl TraceFilter {
/// Sets From block
#[allow(clippy::wrong_self_convention)]
pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
self.from_block = Some(block.into());
self
}
/// Sets to block
#[allow(clippy::wrong_self_convention)]
pub fn to_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
self.to_block = Some(block.into());
self
}
/// Sets to address
#[allow(clippy::wrong_self_convention)]
pub fn to_address(mut self, address: Vec<H160>) -> Self {
self.to_address = Some(address);
self
}
/// Sets from address
#[allow(clippy::wrong_self_convention)]
pub fn from_address(mut self, address: Vec<H160>) -> Self {
self.from_address = Some(address);
self
}
/// Sets after offset
pub fn after(mut self, after: usize) -> Self {
self.after = Some(after);
self
}
/// Sets amount of traces to display
pub fn count(mut self, count: usize) -> Self {
self.count = Some(count);
self
}
}
// `LocalizedTrace` in Parity
/// Trace-Filtering API trace type
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct Trace {
/// Action
pub action: Action,
/// Result
pub result: Option<Res>,
/// Trace address
#[serde(rename = "traceAddress")]
pub trace_address: Vec<usize>,
/// Subtraces
pub subtraces: usize,
/// Transaction position
#[serde(rename = "transactionPosition")]
pub transaction_position: Option<usize>,
/// Transaction hash
#[serde(rename = "transactionHash")]
pub transaction_hash: Option<H256>,
/// Block Number
#[serde(rename = "blockNumber")]
pub block_number: u64,
/// Block Hash
#[serde(rename = "blockHash")]
pub block_hash: H256,
/// Action Type
#[serde(rename = "type")]
pub action_type: ActionType,
/// Error
pub error: Option<String>,
}
/// Response
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Res {
/// Call
Call(CallResult),
/// Create
Create(CreateResult),
/// None
None,
}
impl Default for Res {
fn default() -> Res {
Res::None
}
}
/// Action
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "lowercase")]
pub enum Action {
/// Call
Call(Call),
/// Create
Create(Create),
/// Suicide
Suicide(Suicide),
/// Reward
Reward(Reward),
}
/// An external action type.
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ActionType {
/// Contract call.
Call,
/// Contract creation.
Create,
/// Contract suicide.
Suicide,
/// A block reward.
Reward,
}
/// Call Result
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
pub struct CallResult {
/// Gas used
#[serde(rename = "gasUsed")]
pub gas_used: U256,
/// Output bytes
pub output: Bytes,
}
/// Craete Result
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
pub struct CreateResult {
/// Gas used
#[serde(rename = "gasUsed")]
pub gas_used: U256,
/// Code
pub code: Bytes,
/// Assigned address
pub address: Address,
}
/// Call response
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
pub struct Call {
/// Sender
pub from: Address,
/// Recipient
pub to: Address,
/// Transfered Value
pub value: U256,
/// Gas
pub gas: U256,
/// Input data
pub input: Bytes,
/// The type of the call.
#[serde(rename = "callType")]
pub call_type: CallType,
}
/// Call type.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub enum CallType {
/// None
#[serde(rename = "none")]
None,
/// Call
#[serde(rename = "call")]
Call,
/// Call code
#[serde(rename = "callcode")]
CallCode,
/// Delegate call
#[serde(rename = "delegatecall")]
DelegateCall,
/// Static call
#[serde(rename = "staticcall")]
StaticCall,
}
impl Default for CallType {
fn default() -> CallType {
CallType::None
}
}
/// Create response
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
pub struct Create {
/// Sender
pub from: Address,
/// Value
pub value: U256,
/// Gas
pub gas: U256,
/// Initialization code
pub init: Bytes,
}
/// Suicide
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
pub struct Suicide {
/// Address.
pub address: Address,
/// Refund address.
#[serde(rename = "refundAddress")]
pub refund_address: Address,
/// Balance.
pub balance: U256,
}
/// Reward action
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct Reward {
/// Author's address.
pub author: Address,
/// Reward amount.
pub value: U256,
/// Reward type.
#[serde(rename = "rewardType")]
pub reward_type: RewardType,
}
/// Reward type.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub enum RewardType {
/// Block
#[serde(rename = "block")]
Block,
/// Uncle
#[serde(rename = "uncle")]
Uncle,
/// EmptyStep (AuthorityRound)
#[serde(rename = "emptyStep")]
EmptyStep,
/// External (attributed as part of an external protocol)
#[serde(rename = "external")]
External,
}
#[cfg(test)]
mod tests {
use super::*;
const EXAMPLE_TRACE_CALL: &str = r#"{
"action": {
"callType": "call",
"from": "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"gas": "0x63ab9",
"input": "0xb9f256cd000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d3590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000e85468697320697320746865206f6666696369616c20457468657265756d20466f756e646174696f6e20546970204a61722e20466f722065766572792061626f76652061206365727461696e2076616c756520646f6e6174696f6e207765276c6c2063726561746520616e642073656e6420746f20796f752061206272616e64206e657720556e69636f726e20546f6b656e2028f09fa684292e20436865636b2074686520756e69636f726e2070726963652062656c6f77202831206574686572203d20313030302066696e6e6579292e205468616e6b7320666f722074686520737570706f72742100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"to": "0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359",
"value": "0x0"
},
"blockHash": "0x6474a53a9ebf72d306a1406ec12ded12e210b6c3141b4373bfb3a3cea987dfb8",
"blockNumber": 988775,
"result": {
"gasUsed": "0x4b419",
"output": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"subtraces": 1,
"traceAddress": [],
"transactionHash": "0x342c284238149db221f9d87db87f90ffad7ac0aac57c0c480142f4c21b63f652",
"transactionPosition": 1,
"type": "call"
}"#;
const EXAMPLE_TRACE_CREATE: &str = r#"{
"action": {
"from": "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"gas": "0x63ab9",
"init": "0xb9f256cd000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d3590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000e85468697320697320746865206f6666696369616c20457468657265756d20466f756e646174696f6e20546970204a61722e20466f722065766572792061626f76652061206365727461696e2076616c756520646f6e6174696f6e207765276c6c2063726561746520616e642073656e6420746f20796f752061206272616e64206e657720556e69636f726e20546f6b656e2028f09fa684292e20436865636b2074686520756e69636f726e2070726963652062656c6f77202831206574686572203d20313030302066696e6e6579292e205468616e6b7320666f722074686520737570706f72742100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"value": "0x0"
},
"blockHash": "0x6474a53a9ebf72d306a1406ec12ded12e210b6c3141b4373bfb3a3cea987dfb8",
"blockNumber": 988775,
"result": {
"gasUsed": "0x4b419",
"output": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"subtraces": 1,
"traceAddress": [],
"transactionHash": "0x342c284238149db221f9d87db87f90ffad7ac0aac57c0c480142f4c21b63f652",
"transactionPosition": 1,
"type": "create"
}"#;
const EXAMPLE_TRACE_SUICIDE: &str = r#"{
"action": {
"address": "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"refundAddress": "0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359",
"balance": "0x0"
},
"blockHash": "0x6474a53a9ebf72d306a1406ec12ded12e210b6c3141b4373bfb3a3cea987dfb8",
"blockNumber": 988775,
"result": {
"gasUsed": "0x4b419",
"output": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"subtraces": 1,
"traceAddress": [],
"transactionHash": "0x342c284238149db221f9d87db87f90ffad7ac0aac57c0c480142f4c21b63f652",
"transactionPosition": 1,
"type": "suicide"
}"#;
const EXAMPLE_TRACE_REWARD: &str = r#"{
"action": {
"author": "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"value": "0x0",
"rewardType": "block"
},
"blockHash": "0x6474a53a9ebf72d306a1406ec12ded12e210b6c3141b4373bfb3a3cea987dfb8",
"blockNumber": 988775,
"result": {
"gasUsed": "0x4b419",
"output": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"subtraces": 1,
"traceAddress": [],
"transactionHash": "0x342c284238149db221f9d87db87f90ffad7ac0aac57c0c480142f4c21b63f652",
"transactionPosition": 1,
"type": "reward"
}"#;
#[test]
fn test_deserialize_trace() {
let _trace: Trace = serde_json::from_str(EXAMPLE_TRACE_CALL).unwrap();
let _trace: Trace = serde_json::from_str(EXAMPLE_TRACE_CREATE).unwrap();
let _trace: Trace = serde_json::from_str(EXAMPLE_TRACE_SUICIDE).unwrap();
let _trace: Trace = serde_json::from_str(EXAMPLE_TRACE_REWARD).unwrap();
}
}

View File

@ -0,0 +1,197 @@
//! Types for the Parity Ad-Hoc Trace API
//!
//! https://openethereum.github.io/wiki/JSONRPC-trace-module
use crate::types::{Bytes, H160, H256, U256};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
mod filter;
pub use filter::*;
#[derive(Debug, Clone, Serialize)]
/// Description of the type of trace to make
pub enum TraceType {
/// Transaction Trace
#[serde(rename = "trace")]
Trace,
/// Virtual Machine Execution Trace
#[serde(rename = "vmTrace")]
VmTrace,
/// State Difference
#[serde(rename = "stateDiff")]
StateDiff,
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
/// Ad-Hoc trace API type
pub struct BlockTrace {
/// Output Bytes
pub output: Bytes,
/// Transaction Trace
pub trace: Option<Vec<TransactionTrace>>,
/// Virtual Machine Execution Trace
#[serde(rename = "vmTrace")]
pub vm_trace: Option<VMTrace>,
/// State Difference
#[serde(rename = "stateDiff")]
pub state_diff: Option<StateDiff>,
/// Transaction Hash
#[serde(rename = "transactionHash")]
pub transaction_hash: Option<H256>,
}
//---------------- State Diff ----------------
/// Aux type for Diff::Changed.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct ChangedType<T> {
/// Previous value.
pub from: T,
/// Current value.
pub to: T,
}
/// Serde-friendly `Diff` shadow.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub enum Diff<T> {
/// No change.
#[serde(rename = "=")]
Same,
/// A new value has been set.
#[serde(rename = "+")]
Born(T),
/// A value has been removed.
#[serde(rename = "-")]
Died(T),
/// Value changed.
#[serde(rename = "*")]
Changed(ChangedType<T>),
}
/// Serde-friendly `AccountDiff` shadow.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct AccountDiff {
/// Account balance.
pub balance: Diff<U256>,
/// Account nonce.
pub nonce: Diff<U256>,
/// Account code.
pub code: Diff<Bytes>,
/// Account storage.
pub storage: BTreeMap<H256, Diff<H256>>,
}
/// Serde-friendly `StateDiff` shadow.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct StateDiff(pub BTreeMap<H160, AccountDiff>);
// ------------------ Trace -------------
/// Trace
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct TransactionTrace {
/// Trace address
#[serde(rename = "traceAddress")]
pub trace_address: Vec<usize>,
/// Subtraces
pub subtraces: usize,
/// Action
pub action: Action,
/// Action Type
#[serde(rename = "type")]
pub action_type: ActionType,
/// Result
pub result: Option<Res>,
/// Error
pub error: Option<String>,
}
// ---------------- VmTrace ------------------------------
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
/// A record of a full VM trace for a CALL/CREATE.
pub struct VMTrace {
/// The code to be executed.
pub code: Bytes,
/// The operations executed.
pub ops: Vec<VMOperation>,
}
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
/// A record of the execution of a single VM operation.
pub struct VMOperation {
/// The program counter.
pub pc: usize,
/// The gas cost for this instruction.
pub cost: u64,
/// Information concerning the execution of the operation.
pub ex: Option<VMExecutedOperation>,
/// Subordinate trace of the CALL/CREATE if applicable.
// #[serde(bound="VMTrace: Deserialize")]
pub sub: Option<VMTrace>,
}
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
/// A record of an executed VM operation.
pub struct VMExecutedOperation {
/// The total gas used.
#[serde(rename = "used")]
pub used: u64,
/// The stack item placed, if any.
pub push: Vec<U256>,
/// If altered, the memory delta.
#[serde(rename = "mem")]
pub mem: Option<MemoryDiff>,
/// The altered storage value, if any.
#[serde(rename = "store")]
pub store: Option<StorageDiff>,
}
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
/// A diff of some chunk of memory.
pub struct MemoryDiff {
/// Offset into memory the change begins.
pub off: usize,
/// The changed data.
pub data: Bytes,
}
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
/// A diff of some storage value.
pub struct StorageDiff {
/// Which key in storage is changed.
pub key: U256,
/// What the value has been changed to.
pub val: U256,
}
#[cfg(test)]
mod tests {
use super::*;
// tx: https://etherscan.io/tx/0x4a91b11dbd2b11c308cfe7775eac2036f20c501691e3f8005d83b2dcce62d6b5
// using the 'trace_replayTransaction' API function
// with 'trace', 'vmTrace', 'stateDiff'
const EXAMPLE_TRACE: &str = include!("./example-trace-str.rs");
// block: https://etherscan.io/block/46147
// using the 'trace_replayBlockTransactions' API function
// with 'trace', 'vmTrace', 'stateDiff'
const EXAMPLE_TRACES: &str = include!("./example-traces-str.rs");
#[test]
fn test_serialize_trace_type() {
let trace_type_str = r#"["trace","vmTrace","stateDiff"]"#;
let trace_type = vec![TraceType::Trace, TraceType::VmTrace, TraceType::StateDiff];
let se_trace_str: String = serde_json::to_string(&trace_type).unwrap();
assert_eq!(trace_type_str, se_trace_str);
}
#[test]
fn test_deserialize_blocktrace() {
let _trace: BlockTrace = serde_json::from_str(EXAMPLE_TRACE).unwrap();
}
#[test]
fn test_deserialize_blocktraces() {
let _traces: Vec<BlockTrace> = serde_json::from_str(EXAMPLE_TRACES).unwrap();
}
}

View File

@ -0,0 +1 @@

View File

@ -358,6 +358,8 @@ pub trait Middleware: Sync + Send + Debug {
self.inner().pending_transaction(tx_hash) self.inner().pending_transaction(tx_hash)
} }
// Mempool inspection for Geth's API
async fn txpool_content(&self) -> Result<TxpoolContent, Self::Error> { async fn txpool_content(&self) -> Result<TxpoolContent, Self::Error> {
self.inner().txpool_content().await.map_err(FromErr::from) self.inner().txpool_content().await.map_err(FromErr::from)
} }
@ -369,4 +371,88 @@ pub trait Middleware: Sync + Send + Debug {
async fn txpool_status(&self) -> Result<TxpoolStatus, Self::Error> { async fn txpool_status(&self) -> Result<TxpoolStatus, Self::Error> {
self.inner().txpool_status().await.map_err(FromErr::from) self.inner().txpool_status().await.map_err(FromErr::from)
} }
// Parity `trace` support
/// Executes the given call and returns a number of possible traces for it
async fn trace_call(
&self,
req: TransactionRequest,
trace_type: Vec<TraceType>,
block: Option<BlockNumber>,
) -> Result<BlockTrace, ProviderError> {
self.inner()
.trace_call(req, trace_type, block)
.await
.map_err(FromErr::from)
}
/// Traces a call to `eth_sendRawTransaction` without making the call, returning the traces
async fn trace_raw_transaction(
&self,
data: Bytes,
trace_type: Vec<TraceType>,
) -> Result<BlockTrace, ProviderError> {
self.inner()
.trace_raw_transaction(data, trace_type)
.await
.map_err(FromErr::from)
}
/// Replays a transaction, returning the traces
async fn trace_replay_transaction(
&self,
hash: H256,
trace_type: Vec<TraceType>,
) -> Result<BlockTrace, ProviderError> {
self.inner()
.trace_replay_transaction(hash, trace_type)
.await
.map_err(FromErr::from)
}
/// Replays all transactions in a block returning the requested traces for each transaction
async fn trace_replay_block_transactions(
&self,
block: BlockNumber,
trace_type: Vec<TraceType>,
) -> Result<Vec<BlockTrace>, ProviderError> {
self.inner()
.trace_replay_block_transactions(block, trace_type)
.await
.map_err(FromErr::from)
}
/// Returns traces created at given block
async fn trace_block(&self, block: BlockNumber) -> Result<Vec<Trace>, ProviderError> {
self.inner().trace_block(block).await.map_err(FromErr::from)
}
/// Return traces matching the given filter
async fn trace_filter(&self, filter: TraceFilter) -> Result<Vec<Trace>, ProviderError> {
self.inner()
.trace_filter(filter)
.await
.map_err(FromErr::from)
}
/// Returns trace at the given position
async fn trace_get<T: Into<U64> + Send + Sync>(
&self,
hash: H256,
index: Vec<T>,
) -> Result<Trace, ProviderError> {
self.inner()
.trace_get(hash, index)
.await
.map_err(FromErr::from)
}
/// Returns all traces of a given transaction
async fn trace_transaction(&self, hash: H256) -> Result<Vec<Trace>, ProviderError> {
self.inner()
.trace_transaction(hash)
.await
.map_err(FromErr::from)
}
} }

View File

@ -7,9 +7,9 @@ use crate::{
use ethers_core::{ use ethers_core::{
abi::{self, Detokenize, ParamType}, abi::{self, Detokenize, ParamType},
types::{ types::{
Address, Block, BlockId, BlockNumber, Bytes, Filter, Log, NameOrAddress, Selector, Address, Block, BlockId, BlockNumber, BlockTrace, Bytes, Filter, Log, NameOrAddress,
Signature, Transaction, TransactionReceipt, TransactionRequest, TxHash, TxpoolContent, Selector, Signature, Trace, TraceFilter, TraceType, Transaction, TransactionReceipt,
TxpoolInspect, TxpoolStatus, H256, U256, U64, TransactionRequest, TxHash, TxpoolContent, TxpoolInspect, TxpoolStatus, H256, U256, U64,
}, },
utils, utils,
}; };
@ -541,6 +541,107 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
.await .await
.map_err(Into::into)?) .map_err(Into::into)?)
} }
/// Executes the given call and returns a number of possible traces for it
async fn trace_call(
&self,
req: TransactionRequest,
trace_type: Vec<TraceType>,
block: Option<BlockNumber>,
) -> Result<BlockTrace, ProviderError> {
let req = utils::serialize(&req);
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
let trace_type = utils::serialize(&trace_type);
self.0
.request("trace_call", [req, trace_type, block])
.await
.map_err(Into::into)
}
/// Traces a call to `eth_sendRawTransaction` without making the call, returning the traces
async fn trace_raw_transaction(
&self,
data: Bytes,
trace_type: Vec<TraceType>,
) -> Result<BlockTrace, ProviderError> {
let data = utils::serialize(&data);
let trace_type = utils::serialize(&trace_type);
self.0
.request("trace_rawTransaction", [data, trace_type])
.await
.map_err(Into::into)
}
/// Replays a transaction, returning the traces
async fn trace_replay_transaction(
&self,
hash: H256,
trace_type: Vec<TraceType>,
) -> Result<BlockTrace, ProviderError> {
let hash = utils::serialize(&hash);
let trace_type = utils::serialize(&trace_type);
Ok(self
.0
.request("trace_replayTransaction", [hash, trace_type])
.await
.map_err(Into::into)?)
}
/// Replays all transactions in a block returning the requested traces for each transaction
async fn trace_replay_block_transactions(
&self,
block: BlockNumber,
trace_type: Vec<TraceType>,
) -> Result<Vec<BlockTrace>, ProviderError> {
let block = utils::serialize(&block);
let trace_type = utils::serialize(&trace_type);
self.0
.request("trace_replayBlockTransactions", [block, trace_type])
.await
.map_err(Into::into)
}
/// Returns traces created at given block
async fn trace_block(&self, block: BlockNumber) -> Result<Vec<Trace>, ProviderError> {
let block = utils::serialize(&block);
self.0
.request("trace_block", [block])
.await
.map_err(Into::into)
}
/// Return traces matching the given filter
async fn trace_filter(&self, filter: TraceFilter) -> Result<Vec<Trace>, ProviderError> {
let filter = utils::serialize(&filter);
self.0
.request("trace_filter", vec![filter])
.await
.map_err(Into::into)
}
/// Returns trace at the given position
async fn trace_get<T: Into<U64> + Send + Sync>(
&self,
hash: H256,
index: Vec<T>,
) -> Result<Trace, ProviderError> {
let hash = utils::serialize(&hash);
let index: Vec<U64> = index.into_iter().map(|i| i.into()).collect();
let index = utils::serialize(&index);
self.0
.request("trace_get", vec![hash, index])
.await
.map_err(Into::into)
}
/// Returns all traces of a given transaction
async fn trace_transaction(&self, hash: H256) -> Result<Vec<Trace>, ProviderError> {
let hash = utils::serialize(&hash);
self.0
.request("trace_transaction", vec![hash])
.await
.map_err(Into::into)
}
} }
impl<P: JsonRpcClient> Provider<P> { impl<P: JsonRpcClient> Provider<P> {