Merge pull request #1206 from ethcore/diffing
Integrate state diffing into the ethcore JSONRPC
This commit is contained in:
@@ -511,8 +511,8 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM> where
|
||||
.and_then(|(request, block_number,)| {
|
||||
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, false),
|
||||
BlockNumber::Latest => take_weak!(self.client).call(&signed, false),
|
||||
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),
|
||||
};
|
||||
to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])))
|
||||
@@ -524,8 +524,8 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM> where
|
||||
.and_then(|(request, block_number,)| {
|
||||
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, false),
|
||||
BlockNumber::Latest => take_weak!(self.client).call(&signed, false),
|
||||
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()),
|
||||
};
|
||||
to_value(&r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0)))
|
||||
|
||||
@@ -22,9 +22,12 @@ use std::sync::{Arc, Weak};
|
||||
use std::ops::Deref;
|
||||
use std::collections::BTreeMap;
|
||||
use jsonrpc_core::*;
|
||||
use serde;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::state_diff::StateDiff;
|
||||
use ethcore::account_diff::{Diff, Existance};
|
||||
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
|
||||
use ethcore::client::BlockChainClient;
|
||||
use ethcore::client::{BlockChainClient, CallAnalytics};
|
||||
use ethcore::trace::VMTrace;
|
||||
use v1::traits::Ethcore;
|
||||
use v1::types::{Bytes, CallRequest};
|
||||
@@ -115,6 +118,47 @@ fn vm_trace_to_object(t: &VMTrace) -> Value {
|
||||
Value::Object(ret)
|
||||
}
|
||||
|
||||
fn diff_to_object<T>(d: &Diff<T>) -> Value where T: serde::Serialize + Eq {
|
||||
let mut ret = BTreeMap::new();
|
||||
match *d {
|
||||
Diff::Same => {
|
||||
ret.insert("diff".to_owned(), Value::String("=".to_owned()));
|
||||
}
|
||||
Diff::Born(ref x) => {
|
||||
ret.insert("diff".to_owned(), Value::String("+".to_owned()));
|
||||
ret.insert("+".to_owned(), to_value(x).unwrap());
|
||||
}
|
||||
Diff::Died(ref x) => {
|
||||
ret.insert("diff".to_owned(), Value::String("-".to_owned()));
|
||||
ret.insert("-".to_owned(), to_value(x).unwrap());
|
||||
}
|
||||
Diff::Changed(ref from, ref to) => {
|
||||
ret.insert("diff".to_owned(), Value::String("*".to_owned()));
|
||||
ret.insert("-".to_owned(), to_value(from).unwrap());
|
||||
ret.insert("+".to_owned(), to_value(to).unwrap());
|
||||
}
|
||||
};
|
||||
Value::Object(ret)
|
||||
}
|
||||
|
||||
fn state_diff_to_object(t: &StateDiff) -> Value {
|
||||
Value::Object(t.iter().map(|(address, account)| {
|
||||
(address.hex(), Value::Object(map![
|
||||
"existance".to_owned() => Value::String(match account.existance() {
|
||||
Existance::Born => "+",
|
||||
Existance::Alive => ".",
|
||||
Existance::Died => "-",
|
||||
}.to_owned()),
|
||||
"balance".to_owned() => diff_to_object(&account.balance),
|
||||
"nonce".to_owned() => diff_to_object(&account.nonce),
|
||||
"code".to_owned() => diff_to_object(&account.code),
|
||||
"storage".to_owned() => Value::Object(account.storage.iter().map(|(key, val)| {
|
||||
(key.hex(), diff_to_object(&val))
|
||||
}).collect::<BTreeMap<_, _>>())
|
||||
]))
|
||||
}).collect::<BTreeMap<_, _>>())
|
||||
}
|
||||
|
||||
impl<C, M> Ethcore for EthcoreClient<C, M> where C: BlockChainClient + 'static, M: MinerService + 'static {
|
||||
|
||||
fn set_min_gas_price(&self, params: Params) -> Result<Value, Error> {
|
||||
@@ -211,7 +255,7 @@ impl<C, M> Ethcore for EthcoreClient<C, M> where C: BlockChainClient + 'static,
|
||||
from_params(params)
|
||||
.and_then(|(request,)| {
|
||||
let signed = try!(self.sign_call(request));
|
||||
let r = take_weak!(self.client).call(&signed, true);
|
||||
let r = take_weak!(self.client).call(&signed, CallAnalytics{ vm_tracing: true, state_diffing: false });
|
||||
if let Ok(executed) = r {
|
||||
if let Some(vm_trace) = executed.vm_trace {
|
||||
return Ok(vm_trace_to_object(&vm_trace));
|
||||
@@ -220,4 +264,19 @@ impl<C, M> Ethcore for EthcoreClient<C, M> where C: BlockChainClient + 'static,
|
||||
Ok(Value::Null)
|
||||
})
|
||||
}
|
||||
|
||||
fn state_diff_call(&self, params: Params) -> Result<Value, Error> {
|
||||
trace!(target: "jsonrpc", "state_diff_call: {:?}", params);
|
||||
from_params(params)
|
||||
.and_then(|(request,)| {
|
||||
let signed = try!(self.sign_call(request));
|
||||
let r = take_weak!(self.client).call(&signed, CallAnalytics{ vm_tracing: false, state_diffing: true });
|
||||
if let Ok(executed) = r {
|
||||
if let Some(state_diff) = executed.state_diff {
|
||||
return Ok(state_diff_to_object(&state_diff));
|
||||
}
|
||||
}
|
||||
Ok(Value::Null)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use util::{Address, H256, Bytes, U256, FixedHash, Uint};
|
||||
use util::standard::*;
|
||||
use ethcore::error::{Error, ExecutionError};
|
||||
use ethcore::client::{MiningBlockChainClient, Executed};
|
||||
use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics};
|
||||
use ethcore::block::{ClosedBlock, IsBlock};
|
||||
use ethcore::transaction::SignedTransaction;
|
||||
use ethcore::receipt::Receipt;
|
||||
@@ -202,7 +202,7 @@ impl MinerService for TestMinerService {
|
||||
self.latest_closed_block.lock().unwrap().as_ref().map_or_else(U256::zero, |b| b.block().fields().state.balance(address).clone())
|
||||
}
|
||||
|
||||
fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction, _vm_tracing: bool) -> Result<Executed, ExecutionError> {
|
||||
fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction, _analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
|
||||
@@ -431,6 +431,7 @@ fn rpc_eth_call() {
|
||||
output: vec![0x12, 0x34, 0xff],
|
||||
trace: None,
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
|
||||
let request = r#"{
|
||||
@@ -465,6 +466,7 @@ fn rpc_eth_call_default_block() {
|
||||
output: vec![0x12, 0x34, 0xff],
|
||||
trace: None,
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
|
||||
let request = r#"{
|
||||
@@ -498,6 +500,7 @@ fn rpc_eth_estimate_gas() {
|
||||
output: vec![0x12, 0x34, 0xff],
|
||||
trace: None,
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
|
||||
let request = r#"{
|
||||
@@ -532,6 +535,7 @@ fn rpc_eth_estimate_gas_default_block() {
|
||||
output: vec![0x12, 0x34, 0xff],
|
||||
trace: None,
|
||||
vm_trace: None,
|
||||
state_diff: None,
|
||||
});
|
||||
|
||||
let request = r#"{
|
||||
|
||||
@@ -75,6 +75,9 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
||||
/// Executes the given call and returns the VM trace for it.
|
||||
fn vm_trace_call(&self, _: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Executes the given call and returns the diff for it.
|
||||
fn state_diff_call(&self, params: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Should be used to convert object to io delegate.
|
||||
fn to_delegate(self) -> IoDelegate<Self> {
|
||||
let mut delegate = IoDelegate::new(Arc::new(self));
|
||||
@@ -98,6 +101,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
||||
delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data);
|
||||
|
||||
delegate.add_method("ethcore_vmTraceCall", Ethcore::vm_trace_call);
|
||||
delegate.add_method("ethcore_stateDiffCall", Ethcore::state_diff_call);
|
||||
|
||||
delegate
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user