Skip to content

Commit

Permalink
trace_filter RPC (paritytech#288)
Browse files Browse the repository at this point in the history
Adds trace_filter RPC endpoint, with a background task to keep a cache of the traces to avoid redundant computations.
  • Loading branch information
nanocryk authored Apr 1, 2021
1 parent c07e756 commit 56fadee
Show file tree
Hide file tree
Showing 24 changed files with 1,843 additions and 250 deletions.
83 changes: 72 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 4 additions & 8 deletions client/rpc-core/debug/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,13 @@ use jsonrpc_core::Result;
use jsonrpc_derive::rpc;
use serde::Deserialize;

pub use crate::types::{StepLog, TraceExecutorResponse};

pub use rpc_impl_Debug::gen_server::Debug as DebugServer;

pub mod types {
pub use moonbeam_rpc_primitives_debug::{StepLog, TraceExecutorResponse};
pub use moonbeam_rpc_primitives_debug::single;
}

// TODO: Add support for additional params.
// - `disableStorage`, `disableMemory`, `disableStack`.
// - `timeout` should be ignored unless we find out a way for actually evaluating the tracer input.
use crate::types::single;

#[derive(Clone, Eq, PartialEq, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TraceParams {
Expand All @@ -48,5 +44,5 @@ pub trait Debug {
&self,
transaction_hash: H256,
params: Option<TraceParams>,
) -> Result<TraceExecutorResponse>;
) -> Result<single::TransactionTrace>;
}
18 changes: 18 additions & 0 deletions client/rpc-core/trace/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "moonbeam-rpc-core-trace"
version = '0.6.0'
authors = ['PureStake']
edition = '2018'
homepage = 'https://moonbeam.network'
license = 'GPL-3.0-only'
repository = 'https://github.com/PureStake/moonbeam/'

[dependencies]
ethereum-types = "0.11.0"
jsonrpc-core = "15.0.0"
jsonrpc-core-client = "14.0.3"
jsonrpc-derive = "14.0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
futures = { version = "0.3.1", features = ["compat"] }
moonbeam-rpc-primitives-debug = { path = "../../../primitives/rpc/debug" }
83 changes: 83 additions & 0 deletions client/rpc-core/trace/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2019-2020 PureStake Inc.
// This file is part of Moonbeam.

// Moonbeam is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Moonbeam is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.

use ethereum_types::H160;
use futures::{compat::Compat, future::BoxFuture};
use jsonrpc_derive::rpc;
pub use moonbeam_rpc_primitives_debug::block::TransactionTrace;
use serde::{de::Error, Deserialize, Deserializer};

pub use rpc_impl_Trace::gen_server::Trace as TraceServer;

#[rpc(server)]
pub trait Trace {
#[rpc(name = "trace_filter")]
fn filter(
&self,
filter: FilterRequest,
) -> Compat<BoxFuture<'static, jsonrpc_core::Result<Vec<TransactionTrace>>>>;
}

#[derive(Clone, Eq, PartialEq, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FilterRequest {
/// (optional?) From this block.
pub from_block: Option<RequestBlockId>,

/// (optional?) To this block.
pub to_block: Option<RequestBlockId>,

/// (optional) Sent from these addresses.
pub from_address: Option<Vec<H160>>,

/// (optional) Sent to these addresses.
pub to_address: Option<Vec<H160>>,

/// (optional) The offset trace number
pub after: Option<u32>,

/// (optional) Integer number of traces to display in a batch.
pub count: Option<u32>,
}

#[derive(Clone, Eq, PartialEq, Debug, Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub enum RequestBlockId {
Number(#[serde(deserialize_with = "deserialize_u32_0x")] u32),
Tag(RequestBlockTag),
}

#[derive(Clone, Eq, PartialEq, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum RequestBlockTag {
Earliest,
Latest,
Pending,
}

fn deserialize_u32_0x<'de, D>(deserializer: D) -> Result<u32, D::Error>
where
D: Deserializer<'de>,
{
let buf = String::deserialize(deserializer)?;

let parsed = match buf.strip_prefix("0x") {
Some(buf) => u32::from_str_radix(&buf, 16),
None => u32::from_str_radix(&buf, 10),
};

parsed.map_err(|e| Error::custom(format!("parsing error: {:?} from '{}'", e, buf)))
}
16 changes: 7 additions & 9 deletions client/rpc/debug/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,21 @@
// You should have received a copy of the GNU General Public License
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.

pub use moonbeam_rpc_core_debug::{
Debug as DebugT, DebugServer, StepLog, TraceExecutorResponse, TraceParams,
};
pub use moonbeam_rpc_core_debug::{Debug as DebugT, DebugServer, TraceParams};

use ethereum_types::{H128, H256};
use fp_rpc::EthereumRuntimeRPCApi;
use jsonrpc_core::Result as RpcResult;
use jsonrpc_core::{Error as RpcError, ErrorCode};
use moonbeam_rpc_primitives_debug::{DebugRuntimeApi, TraceType};
use moonbeam_rpc_primitives_debug::{single, DebugRuntimeApi};
use sc_client_api::backend::{AuxStore, Backend, StateBackend};
use sp_api::{BlockId, HeaderT, ProvideRuntimeApi};
use sp_block_builder::BlockBuilder;
use sp_blockchain::{
Backend as BlockchainBackend, Error as BlockChainError, HeaderBackend, HeaderMetadata,
};
use sp_runtime::traits::{BlakeTwo256, Block as BlockT};
use std::{str::FromStr, sync::Arc};
use std::{marker::PhantomData, str::FromStr, sync::Arc};

pub fn internal_err<T: ToString>(message: T) -> RpcError {
RpcError {
Expand Down Expand Up @@ -142,7 +140,7 @@ where
&self,
transaction_hash: H256,
params: Option<TraceParams>,
) -> RpcResult<TraceExecutorResponse> {
) -> RpcResult<single::TransactionTrace> {
let (hash, index) = match self
.load_transactions(transaction_hash)
.map_err(|err| internal_err(format!("{:?}", err)))?
Expand All @@ -159,7 +157,7 @@ where
_ => return Err(internal_err("Block hash not found".to_string())),
};

// Get ApiRef
// Get ApiRef. This handle allow to keep changes between txs in an internal buffer.
let api = self.client.runtime_api();
// Get Blockchain backend
let blockchain = self.backend.blockchain();
Expand All @@ -185,15 +183,15 @@ where
let hash: H128 = sp_io::hashing::twox_128(&tracer.as_bytes()).into();
let blockscout_hash = H128::from_str("0x94d9f08796f91eb13a2e82a6066882f7").unwrap();
if hash == blockscout_hash {
TraceType::Blockscout
single::TraceType::CallList
} else {
return Err(internal_err(format!(
"javascript based tracing is not available (hash :{:?})",
hash
)));
}
}
_ => TraceType::Raw,
_ => single::TraceType::Raw,
};

// Get the actual ethereum transaction.
Expand Down
Loading

0 comments on commit 56fadee

Please sign in to comment.