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:
Tomasz Drwięga
2017-08-04 15:58:14 +02:00
committed by Marek Kotewicz
parent 62153b1ff0
commit f157461ee1
22 changed files with 308 additions and 271 deletions

View File

@@ -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()
}

View File

@@ -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()));
}

View File

@@ -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()));
}

View File

@@ -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();