Multi-call RPC (#6195)
* Removing duplicated pending state accessors in miner. * Merge miner+client call. * Multicall & multicall RPC. * Sensible defaults. * Fix tests.
This commit is contained in:
committed by
Marek Kotewicz
parent
62153b1ff0
commit
f157461ee1
@@ -264,6 +264,7 @@ fn check_known<C>(client: &C, number: BlockNumber) -> Result<(), Error> where C:
|
||||
|
||||
match client.block_status(number.into()) {
|
||||
BlockStatus::InChain => Ok(()),
|
||||
BlockStatus::Pending => Ok(()),
|
||||
_ => Err(errors::unknown_block()),
|
||||
}
|
||||
}
|
||||
@@ -361,20 +362,12 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
fn balance(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
|
||||
let address = address.into();
|
||||
|
||||
let res = match num.unwrap_or_default() {
|
||||
BlockNumber::Pending => {
|
||||
match self.miner.balance(&*self.client, &address) {
|
||||
Some(balance) => Ok(balance.into()),
|
||||
None => Err(errors::database("latest balance missing"))
|
||||
}
|
||||
}
|
||||
id => {
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
match self.client.balance(&address, id.into()) {
|
||||
Some(balance) => Ok(balance.into()),
|
||||
None => Err(errors::state_pruned()),
|
||||
}
|
||||
}
|
||||
let id = num.unwrap_or_default();
|
||||
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
let res = match self.client.balance(&address, id.into()) {
|
||||
Some(balance) => Ok(balance.into()),
|
||||
None => Err(errors::state_pruned()),
|
||||
};
|
||||
|
||||
future::done(res).boxed()
|
||||
@@ -384,20 +377,12 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
let address: Address = RpcH160::into(address);
|
||||
let position: U256 = RpcU256::into(pos);
|
||||
|
||||
let res = match num.unwrap_or_default() {
|
||||
BlockNumber::Pending => {
|
||||
match self.miner.storage_at(&*self.client, &address, &H256::from(position)) {
|
||||
Some(s) => Ok(s.into()),
|
||||
None => Err(errors::database("latest storage missing"))
|
||||
}
|
||||
}
|
||||
id => {
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
match self.client.storage_at(&address, &H256::from(position), id.into()) {
|
||||
Some(s) => Ok(s.into()),
|
||||
None => Err(errors::state_pruned()),
|
||||
}
|
||||
}
|
||||
let id = num.unwrap_or_default();
|
||||
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
let res = match self.client.storage_at(&address, &H256::from(position), id.into()) {
|
||||
Some(s) => Ok(s.into()),
|
||||
None => Err(errors::state_pruned()),
|
||||
};
|
||||
|
||||
future::done(res).boxed()
|
||||
@@ -410,18 +395,12 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
BlockNumber::Pending if self.options.pending_nonce_from_queue => {
|
||||
let nonce = self.miner.last_nonce(&address)
|
||||
.map(|n| n + 1.into())
|
||||
.or_else(|| self.miner.nonce(&*self.client, &address));
|
||||
.or_else(|| self.client.nonce(&address, BlockNumber::Pending.into()));
|
||||
match nonce {
|
||||
Some(nonce) => Ok(nonce.into()),
|
||||
None => Err(errors::database("latest nonce missing"))
|
||||
}
|
||||
}
|
||||
BlockNumber::Pending => {
|
||||
match self.miner.nonce(&*self.client, &address) {
|
||||
Some(nonce) => Ok(nonce.into()),
|
||||
None => Err(errors::database("latest nonce missing"))
|
||||
}
|
||||
}
|
||||
id => {
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
match self.client.nonce(&address, id.into()) {
|
||||
@@ -468,20 +447,12 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
fn code_at(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<Bytes, Error> {
|
||||
let address: Address = RpcH160::into(address);
|
||||
|
||||
let res = match num.unwrap_or_default() {
|
||||
BlockNumber::Pending => {
|
||||
match self.miner.code(&*self.client, &address) {
|
||||
Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
|
||||
None => Err(errors::database("latest code missing"))
|
||||
}
|
||||
}
|
||||
id => {
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
match self.client.code(&address, id.into()) {
|
||||
Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
|
||||
None => Err(errors::state_pruned()),
|
||||
}
|
||||
}
|
||||
let id = num.unwrap_or_default();
|
||||
try_bf!(check_known(&*self.client, id.clone()));
|
||||
|
||||
let res = match self.client.code(&address, id.into()) {
|
||||
Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
|
||||
None => Err(errors::state_pruned()),
|
||||
};
|
||||
|
||||
future::done(res).boxed()
|
||||
@@ -648,10 +619,8 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
Err(e) => return future::err(e).boxed(),
|
||||
};
|
||||
|
||||
let result = match num.unwrap_or_default() {
|
||||
BlockNumber::Pending => self.miner.call(&*self.client, &signed, Default::default()),
|
||||
num => self.client.call(&signed, num.into(), Default::default()),
|
||||
};
|
||||
let num = num.unwrap_or_default();
|
||||
let result = self.client.call(&signed, Default::default(), num.into());
|
||||
|
||||
future::done(result
|
||||
.map(|b| b.output.into())
|
||||
|
||||
@@ -39,7 +39,7 @@ use v1::helpers::light_fetch::LightFetch;
|
||||
use v1::metadata::Metadata;
|
||||
use v1::traits::Parity;
|
||||
use v1::types::{
|
||||
Bytes, U256, H160, H256, H512,
|
||||
Bytes, U256, H160, H256, H512, CallRequest,
|
||||
Peers, Transaction, RpcSettings, Histogram,
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
@@ -389,4 +389,8 @@ impl Parity for ParityClient {
|
||||
fn ipfs_cid(&self, content: Bytes) -> Result<String, Error> {
|
||||
ipfs::cid(content)
|
||||
}
|
||||
|
||||
fn call(&self, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error> {
|
||||
future::err(errors::light_unimplemented(None)).boxed()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Trailing;
|
||||
use v1::traits::Traces;
|
||||
use v1::helpers::errors;
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, TraceOptions, H256};
|
||||
|
||||
/// Traces api implementation.
|
||||
// TODO: all calling APIs should be possible w. proved remote TX execution.
|
||||
@@ -43,15 +43,19 @@ impl Traces for TracesClient {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn call(&self, _request: CallRequest, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
fn call(&self, _request: CallRequest, _flags: TraceOptions, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
fn call_many(&self, _request: Vec<(CallRequest, TraceOptions)>, _block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<TraceResults, Error> {
|
||||
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: TraceOptions, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn replay_transaction(&self, _transaction_hash: H256, _flags: TraceOptions) -> Result<TraceResults, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,22 +28,23 @@ use crypto::ecies;
|
||||
use ethkey::{Brain, Generator};
|
||||
use ethstore::random_phrase;
|
||||
use ethsync::{SyncProvider, ManageNetwork};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::{MiningBlockChainClient};
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::{MiningBlockChainClient};
|
||||
use ethcore::mode::Mode;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::transaction::SignedTransaction;
|
||||
use updater::{Service as UpdateService};
|
||||
use crypto::DEFAULT_MAC;
|
||||
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Trailing;
|
||||
use v1::helpers::{self, errors, ipfs, SigningQueue, SignerService, NetworkSettings};
|
||||
use v1::helpers::{self, errors, fake_sign, ipfs, SigningQueue, SignerService, NetworkSettings};
|
||||
use v1::helpers::accounts::unwrap_provider;
|
||||
use v1::metadata::Metadata;
|
||||
use v1::traits::Parity;
|
||||
use v1::types::{
|
||||
Bytes, U256, H160, H256, H512,
|
||||
Bytes, U256, H160, H256, H512, CallRequest,
|
||||
Peers, Transaction, RpcSettings, Histogram,
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
@@ -409,4 +410,23 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
||||
fn ipfs_cid(&self, content: Bytes) -> Result<String, Error> {
|
||||
ipfs::cid(content)
|
||||
}
|
||||
|
||||
fn call(&self, requests: Vec<CallRequest>, block: Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error> {
|
||||
let requests: Result<Vec<(SignedTransaction, _)>, Error> = requests
|
||||
.into_iter()
|
||||
.map(|request| Ok((
|
||||
fake_sign::sign_call(&self.client, &self.miner, request.into())?,
|
||||
Default::default()
|
||||
)))
|
||||
.collect();
|
||||
|
||||
let block = block.unwrap_or_default();
|
||||
let requests = try_bf!(requests);
|
||||
|
||||
let result = self.client.call_many(&requests, block.into())
|
||||
.map(|res| res.into_iter().map(|res| res.output.into()).collect())
|
||||
.map_err(errors::call);
|
||||
|
||||
future::done(result).boxed()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Trailing;
|
||||
use v1::traits::Traces;
|
||||
use v1::helpers::{errors, fake_sign};
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, TraceOptions, H256};
|
||||
|
||||
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
||||
fn to_call_analytics(flags: TraceOptions) -> CallAnalytics {
|
||||
CallAnalytics {
|
||||
transaction_tracing: flags.contains(&("trace".to_owned())),
|
||||
vm_tracing: flags.contains(&("vmTrace".to_owned())),
|
||||
@@ -79,29 +79,45 @@ impl<C, M> Traces for TracesClient<C, M> where C: MiningBlockChainClient + 'stat
|
||||
.map(LocalizedTrace::from))
|
||||
}
|
||||
|
||||
fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
fn call(&self, request: CallRequest, flags: TraceOptions, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
let block = block.unwrap_or_default();
|
||||
|
||||
let request = CallRequest::into(request);
|
||||
let signed = fake_sign::sign_call(&self.client, &self.miner, request)?;
|
||||
|
||||
self.client.call(&signed, block.into(), to_call_analytics(flags))
|
||||
self.client.call(&signed, to_call_analytics(flags), block.into())
|
||||
.map(TraceResults::from)
|
||||
.map_err(errors::call)
|
||||
}
|
||||
|
||||
fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
fn call_many(&self, requests: Vec<(CallRequest, TraceOptions)>, block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>, Error> {
|
||||
let block = block.unwrap_or_default();
|
||||
|
||||
let requests = requests.into_iter()
|
||||
.map(|(request, flags)| {
|
||||
let request = CallRequest::into(request);
|
||||
let signed = fake_sign::sign_call(&self.client, &self.miner, request)?;
|
||||
Ok((signed, to_call_analytics(flags)))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
self.client.call_many(&requests, block.into())
|
||||
.map(|results| results.into_iter().map(TraceResults::from).collect())
|
||||
.map_err(errors::call)
|
||||
}
|
||||
|
||||
fn raw_transaction(&self, raw_transaction: Bytes, flags: TraceOptions, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
let block = block.unwrap_or_default();
|
||||
|
||||
let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?;
|
||||
let signed = SignedTransaction::new(tx).map_err(errors::transaction)?;
|
||||
|
||||
self.client.call(&signed, block.into(), to_call_analytics(flags))
|
||||
self.client.call(&signed, to_call_analytics(flags), block.into())
|
||||
.map(TraceResults::from)
|
||||
.map_err(errors::call)
|
||||
}
|
||||
|
||||
fn replay_transaction(&self, transaction_hash: H256, flags: Vec<String>) -> Result<TraceResults, Error> {
|
||||
fn replay_transaction(&self, transaction_hash: H256, flags: TraceOptions) -> Result<TraceResults, Error> {
|
||||
self.client.replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags))
|
||||
.map(TraceResults::from)
|
||||
.map_err(errors::call)
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::hash_map::Entry;
|
||||
use util::{Address, H256, Bytes, U256, RwLock, Mutex};
|
||||
use ethcore::error::{Error, CallError};
|
||||
use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics};
|
||||
use ethcore::block::{ClosedBlock, IsBlock};
|
||||
use ethcore::error::Error;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::block::ClosedBlock;
|
||||
use ethcore::header::BlockNumber;
|
||||
use ethcore::transaction::{UnverifiedTransaction, SignedTransaction, PendingTransaction};
|
||||
use ethcore::receipt::{Receipt, RichReceipt};
|
||||
@@ -280,41 +280,6 @@ impl MinerService for TestMinerService {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn balance(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option<U256> {
|
||||
self.latest_closed_block.lock()
|
||||
.as_ref()
|
||||
.map(|b| b.block().fields().state.balance(address))
|
||||
.map(|b| b.ok())
|
||||
.unwrap_or(Some(U256::default()))
|
||||
}
|
||||
|
||||
fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction, _analytics: CallAnalytics) -> Result<Executed, CallError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn storage_at(&self, _chain: &MiningBlockChainClient, address: &Address, position: &H256) -> Option<H256> {
|
||||
self.latest_closed_block.lock()
|
||||
.as_ref()
|
||||
.map(|b| b.block().fields().state.storage_at(address, position))
|
||||
.map(|s| s.ok())
|
||||
.unwrap_or(Some(H256::default()))
|
||||
}
|
||||
|
||||
fn nonce(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option<U256> {
|
||||
// we assume all transactions are in a pending block, ignoring the
|
||||
// reality of gas limits.
|
||||
Some(self.last_nonce(address).unwrap_or(U256::zero()))
|
||||
}
|
||||
|
||||
fn code(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option<Option<Bytes>> {
|
||||
self.latest_closed_block.lock()
|
||||
.as_ref()
|
||||
.map(|b| b.block().fields().state.code(address))
|
||||
.map(|c| c.ok())
|
||||
.unwrap_or(None)
|
||||
.map(|c| c.map(|c| (&*c).clone()))
|
||||
}
|
||||
|
||||
fn sensible_gas_price(&self) -> U256 {
|
||||
20000000000u64.into()
|
||||
}
|
||||
|
||||
@@ -432,10 +432,7 @@ fn rpc_eth_balance_pending() {
|
||||
"id": 1
|
||||
}"#;
|
||||
|
||||
// the TestMinerService doesn't communicate with the the TestBlockChainClient in any way.
|
||||
// if this returns zero, we know that the "pending" call is being properly forwarded to the
|
||||
// miner.
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x0","id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x5","id":1}"#;
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use ethcore_logger::RotatingLogger;
|
||||
use util::Address;
|
||||
use util::{Address, U256};
|
||||
use ethsync::ManageNetwork;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::{TestBlockChainClient};
|
||||
use ethcore::client::{TestBlockChainClient, Executed};
|
||||
use ethcore::miner::LocalTransactionStatus;
|
||||
use ethstore::ethkey::{Generator, Random};
|
||||
|
||||
@@ -504,3 +504,40 @@ fn rpc_parity_cid() {
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_call() {
|
||||
let deps = Dependencies::new();
|
||||
deps.client.set_execution_result(Ok(Executed {
|
||||
exception: None,
|
||||
gas: U256::zero(),
|
||||
gas_used: U256::from(0xff30),
|
||||
refunded: U256::from(0x5),
|
||||
cumulative_gas_used: U256::zero(),
|
||||
logs: vec![],
|
||||
contracts_created: vec![],
|
||||
output: vec![0x12, 0x34, 0xff],
|
||||
trace: vec![],
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
}));
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "parity_call",
|
||||
"params": [[{
|
||||
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": "0x9184e72a",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}],
|
||||
"latest"],
|
||||
"id": 1
|
||||
}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":["0x1234ff"],"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
@@ -170,6 +170,16 @@ fn rpc_trace_call() {
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_trace_multi_call() {
|
||||
let tester = io();
|
||||
|
||||
let request = r#"{"jsonrpc":"2.0","method":"trace_callMany","params":[[[{}, ["stateDiff", "vmTrace", "trace"]]]],"id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":[{"output":"0x010203","stateDiff":null,"trace":[],"vmTrace":null}],"id":1}"#;
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_trace_call_state_pruned() {
|
||||
let tester = io();
|
||||
|
||||
@@ -23,7 +23,7 @@ use jsonrpc_macros::Trailing;
|
||||
use futures::BoxFuture;
|
||||
|
||||
use v1::types::{
|
||||
H160, H256, H512, U256, Bytes,
|
||||
H160, H256, H512, U256, Bytes, CallRequest,
|
||||
Peers, Transaction, RpcSettings, Histogram,
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
@@ -203,5 +203,9 @@ build_rpc_trait! {
|
||||
/// Get IPFS CIDv0 given protobuf encoded bytes.
|
||||
#[rpc(name = "parity_cidV0")]
|
||||
fn ipfs_cid(&self, Bytes) -> Result<String, Error>;
|
||||
|
||||
/// Call contract, returning the output data.
|
||||
#[rpc(async, name = "parity_call")]
|
||||
fn call(&self, Vec<CallRequest>, Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Trailing;
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256, TraceOptions};
|
||||
|
||||
build_rpc_trait! {
|
||||
/// Traces specific rpc interface.
|
||||
@@ -41,14 +41,18 @@ build_rpc_trait! {
|
||||
|
||||
/// Executes the given call and returns a number of possible traces for it.
|
||||
#[rpc(name = "trace_call")]
|
||||
fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
|
||||
fn call(&self, CallRequest, TraceOptions, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
|
||||
|
||||
/// Executes all given calls and returns a number of possible traces for each of it.
|
||||
#[rpc(name = "trace_callMany")]
|
||||
fn call_many(&self, Vec<(CallRequest, TraceOptions)>, Trailing<BlockNumber>) -> Result<Vec<TraceResults>, Error>;
|
||||
|
||||
/// Executes the given raw transaction and returns a number of possible traces for it.
|
||||
#[rpc(name = "trace_rawTransaction")]
|
||||
fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
|
||||
fn raw_transaction(&self, Bytes, TraceOptions, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
|
||||
|
||||
/// Executes the transaction with the given hash and returns a number of possible traces for it.
|
||||
#[rpc(name = "trace_replayTransaction")]
|
||||
fn replay_transaction(&self, H256, Vec<String>) -> Result<TraceResults, Error>;
|
||||
fn replay_transaction(&self, H256, TraceOptions) -> Result<TraceResults, Error>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,3 +78,7 @@ pub use self::transaction_request::TransactionRequest;
|
||||
pub use self::transaction_condition::TransactionCondition;
|
||||
pub use self::uint::{U128, U256};
|
||||
pub use self::work::Work;
|
||||
|
||||
// TODO [ToDr] Refactor to a proper type Vec of enums?
|
||||
/// Expected tracing type.
|
||||
pub type TraceOptions = Vec<String>;
|
||||
|
||||
Reference in New Issue
Block a user