Supporting blockid in eth_call and trace_call/trace_raw (#1837)
* Supporting blockid in eth_call and trace_call/trace_raw * Nicer state diff handling * Purging deref.deref
This commit is contained in:
@@ -44,8 +44,7 @@ use self::ethash::SeedHashCompute;
|
||||
use v1::traits::Eth;
|
||||
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
|
||||
use v1::helpers::CallRequest as CRequest;
|
||||
use v1::impls::{default_gas_price, dispatch_transaction, error_codes};
|
||||
use serde;
|
||||
use v1::impls::{default_gas_price, dispatch_transaction, error_codes, from_params_default_second, from_params_default_third};
|
||||
|
||||
/// Eth RPC options
|
||||
pub struct EthClientOptions {
|
||||
@@ -215,27 +214,6 @@ pub fn pending_logs<M>(miner: &M, filter: &EthcoreFilter) -> Vec<Log> where M: M
|
||||
|
||||
const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6.
|
||||
|
||||
fn params_len(params: &Params) -> usize {
|
||||
match params {
|
||||
&Params::Array(ref vec) => vec.len(),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_params_default_second<F>(params: Params) -> Result<(F, BlockNumber, ), Error> where F: serde::de::Deserialize {
|
||||
match params_len(¶ms) {
|
||||
1 => from_params::<(F, )>(params).map(|(f,)| (f, BlockNumber::Latest)),
|
||||
_ => from_params::<(F, BlockNumber)>(params),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_params_default_third<F1, F2>(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize {
|
||||
match params_len(¶ms) {
|
||||
2 => from_params::<(F1, F2, )>(params).map(|(f1, f2)| (f1, f2, BlockNumber::Latest)),
|
||||
_ => from_params::<(F1, F2, BlockNumber)>(params)
|
||||
}
|
||||
}
|
||||
|
||||
fn make_unsupported_err() -> Error {
|
||||
Error {
|
||||
code: ErrorCode::ServerError(error_codes::UNSUPPORTED_REQUEST_CODE),
|
||||
@@ -656,8 +634,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
||||
let signed = try!(self.sign_call(request));
|
||||
let r = match block_number {
|
||||
BlockNumber::Pending => take_weak!(self.miner).call(take_weak!(self.client).deref(), &signed, Default::default()),
|
||||
BlockNumber::Latest => take_weak!(self.client).call(&signed, Default::default()),
|
||||
_ => panic!("{:?}", block_number),
|
||||
block_number => take_weak!(self.client).call(&signed, block_number.into(), Default::default()),
|
||||
};
|
||||
to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])))
|
||||
})
|
||||
@@ -671,8 +648,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
||||
let signed = try!(self.sign_call(request));
|
||||
let r = match block_number {
|
||||
BlockNumber::Pending => take_weak!(self.miner).call(take_weak!(self.client).deref(), &signed, Default::default()),
|
||||
BlockNumber::Latest => take_weak!(self.client).call(&signed, Default::default()),
|
||||
_ => return Err(Error::invalid_params()),
|
||||
block => take_weak!(self.client).call(&signed, block.into(), Default::default()),
|
||||
};
|
||||
to_value(&RpcU256::from(r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0))))
|
||||
})
|
||||
|
||||
@@ -53,8 +53,9 @@ pub use self::ethcore_set::EthcoreSetClient;
|
||||
pub use self::traces::TracesClient;
|
||||
pub use self::rpc::RpcClient;
|
||||
|
||||
use serde;
|
||||
use v1::helpers::TransactionRequest;
|
||||
use v1::types::{H256 as RpcH256, H520 as RpcH520};
|
||||
use v1::types::{H256 as RpcH256, H520 as RpcH520, BlockNumber};
|
||||
use ethcore::error::Error as EthcoreError;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
@@ -63,7 +64,7 @@ use ethcore::account_provider::{AccountProvider, Error as AccountError};
|
||||
use util::numbers::*;
|
||||
use util::rlp::encode;
|
||||
use util::bytes::ToPretty;
|
||||
use jsonrpc_core::{Error, ErrorCode, Value, to_value};
|
||||
use jsonrpc_core::{Error, ErrorCode, Value, to_value, from_params, Params};
|
||||
|
||||
mod error_codes {
|
||||
// NOTE [ToDr] Codes from [-32099, -32000]
|
||||
@@ -79,6 +80,30 @@ mod error_codes {
|
||||
pub const REQUEST_NOT_FOUND: i64 = -32041;
|
||||
}
|
||||
|
||||
fn params_len(params: &Params) -> usize {
|
||||
match params {
|
||||
&Params::Array(ref vec) => vec.len(),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize request parameters with optional second parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
|
||||
pub fn from_params_default_second<F>(params: Params) -> Result<(F, BlockNumber, ), Error> where F: serde::de::Deserialize {
|
||||
match params_len(¶ms) {
|
||||
1 => from_params::<(F, )>(params).map(|(f,)| (f, BlockNumber::Latest)),
|
||||
_ => from_params::<(F, BlockNumber)>(params),
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize request parameters with optional third parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
|
||||
pub fn from_params_default_third<F1, F2>(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize {
|
||||
match params_len(¶ms) {
|
||||
2 => from_params::<(F1, F2, )>(params).map(|(f1, f2)| (f1, f2, BlockNumber::Latest)),
|
||||
_ => from_params::<(F1, F2, BlockNumber)>(params)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result<Value, Error>
|
||||
where C: MiningBlockChainClient, M: MinerService {
|
||||
let hash = RpcH256::from(signed_transaction.hash());
|
||||
|
||||
@@ -25,6 +25,7 @@ use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Act
|
||||
use v1::traits::Traces;
|
||||
use v1::helpers::CallRequest as CRequest;
|
||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
||||
use v1::impls::from_params_default_third;
|
||||
|
||||
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
||||
CallAnalytics {
|
||||
@@ -122,11 +123,11 @@ impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M:
|
||||
|
||||
fn call(&self, params: Params) -> Result<Value, Error> {
|
||||
try!(self.active());
|
||||
from_params(params)
|
||||
.and_then(|(request, flags)| {
|
||||
from_params_default_third(params)
|
||||
.and_then(|(request, flags, block)| {
|
||||
let request = CallRequest::into(request);
|
||||
let signed = try!(self.sign_call(request));
|
||||
match take_weak!(self.client).call(&signed, to_call_analytics(flags)) {
|
||||
match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) {
|
||||
Ok(e) => to_value(&TraceResults::from(e)),
|
||||
_ => Ok(Value::Null),
|
||||
}
|
||||
@@ -135,11 +136,11 @@ impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M:
|
||||
|
||||
fn raw_transaction(&self, params: Params) -> Result<Value, Error> {
|
||||
try!(self.active());
|
||||
from_params::<(Bytes, _)>(params)
|
||||
.and_then(|(raw_transaction, flags)| {
|
||||
let raw_transaction = raw_transaction.to_vec();
|
||||
from_params_default_third(params)
|
||||
.and_then(|(raw_transaction, flags, block)| {
|
||||
let raw_transaction = Bytes::to_vec(raw_transaction);
|
||||
match UntrustedRlp::new(&raw_transaction).as_val() {
|
||||
Ok(signed) => match take_weak!(self.client).call(&signed, to_call_analytics(flags)) {
|
||||
Ok(signed) => match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) {
|
||||
Ok(e) => to_value(&TraceResults::from(e)),
|
||||
_ => Ok(Value::Null),
|
||||
},
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use util::{Address, H256, Bytes, U256, FixedHash, Uint};
|
||||
use util::standard::*;
|
||||
use ethcore::error::{Error, ExecutionError};
|
||||
use ethcore::error::{Error, CallError};
|
||||
use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics};
|
||||
use ethcore::block::{ClosedBlock, IsBlock};
|
||||
use ethcore::transaction::SignedTransaction;
|
||||
@@ -220,7 +220,7 @@ impl MinerService for TestMinerService {
|
||||
self.latest_closed_block.lock().as_ref().map_or_else(U256::zero, |b| b.block().fields().state.balance(address).clone())
|
||||
}
|
||||
|
||||
fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction, _analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
|
||||
fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction, _analytics: CallAnalytics) -> Result<Executed, CallError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
|
||||
@@ -423,9 +423,9 @@ fn rpc_eth_code() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_eth_call() {
|
||||
fn rpc_eth_call_latest() {
|
||||
let tester = EthTester::default();
|
||||
tester.client.set_execution_result(Executed {
|
||||
tester.client.set_execution_result(Ok(Executed {
|
||||
gas: U256::zero(),
|
||||
gas_used: U256::from(0xff30),
|
||||
refunded: U256::from(0x5),
|
||||
@@ -436,7 +436,7 @@ fn rpc_eth_call() {
|
||||
trace: vec![],
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
}));
|
||||
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
@@ -458,9 +458,9 @@ fn rpc_eth_call() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_eth_call_default_block() {
|
||||
fn rpc_eth_call() {
|
||||
let tester = EthTester::default();
|
||||
tester.client.set_execution_result(Executed {
|
||||
tester.client.set_execution_result(Ok(Executed {
|
||||
gas: U256::zero(),
|
||||
gas_used: U256::from(0xff30),
|
||||
refunded: U256::from(0x5),
|
||||
@@ -471,7 +471,42 @@ fn rpc_eth_call_default_block() {
|
||||
trace: vec![],
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
}));
|
||||
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_call",
|
||||
"params": [{
|
||||
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
|
||||
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
|
||||
"gas": "0x76c0",
|
||||
"gasPrice": "0x9184e72a000",
|
||||
"value": "0x9184e72a",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
},
|
||||
"0x0"],
|
||||
"id": 1
|
||||
}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#;
|
||||
|
||||
assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_eth_call_default_block() {
|
||||
let tester = EthTester::default();
|
||||
tester.client.set_execution_result(Ok(Executed {
|
||||
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 request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
@@ -494,7 +529,7 @@ fn rpc_eth_call_default_block() {
|
||||
#[test]
|
||||
fn rpc_eth_estimate_gas() {
|
||||
let tester = EthTester::default();
|
||||
tester.client.set_execution_result(Executed {
|
||||
tester.client.set_execution_result(Ok(Executed {
|
||||
gas: U256::zero(),
|
||||
gas_used: U256::from(0xff30),
|
||||
refunded: U256::from(0x5),
|
||||
@@ -505,7 +540,7 @@ fn rpc_eth_estimate_gas() {
|
||||
trace: vec![],
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
}));
|
||||
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
@@ -529,7 +564,7 @@ fn rpc_eth_estimate_gas() {
|
||||
#[test]
|
||||
fn rpc_eth_estimate_gas_default_block() {
|
||||
let tester = EthTester::default();
|
||||
tester.client.set_execution_result(Executed {
|
||||
tester.client.set_execution_result(Ok(Executed {
|
||||
gas: U256::zero(),
|
||||
gas_used: U256::from(0xff30),
|
||||
refunded: U256::from(0x5),
|
||||
@@ -540,7 +575,7 @@ fn rpc_eth_estimate_gas_default_block() {
|
||||
trace: vec![],
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
}));
|
||||
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
|
||||
Reference in New Issue
Block a user