RPC endpoint for VM tracing and ser/de types ready.
This commit is contained in:
parent
42e4c2d51c
commit
c1ed520de0
@ -421,7 +421,7 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<V> BlockChainClient for Client<V> where V: Verifier {
|
impl<V> BlockChainClient for Client<V> where V: Verifier {
|
||||||
fn call(&self, t: &SignedTransaction) -> Result<Executed, ExecutionError> {
|
fn call(&self, t: &SignedTransaction, vm_tracing: bool) -> Result<Executed, ExecutionError> {
|
||||||
let header = self.block_header(BlockID::Latest).unwrap();
|
let header = self.block_header(BlockID::Latest).unwrap();
|
||||||
let view = HeaderView::new(&header);
|
let view = HeaderView::new(&header);
|
||||||
let last_hashes = self.build_last_hashes(view.hash());
|
let last_hashes = self.build_last_hashes(view.hash());
|
||||||
@ -444,7 +444,7 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
|||||||
// give the sender max balance
|
// give the sender max balance
|
||||||
state.sub_balance(&sender, &balance);
|
state.sub_balance(&sender, &balance);
|
||||||
state.add_balance(&sender, &U256::max_value());
|
state.add_balance(&sender, &U256::max_value());
|
||||||
let options = TransactOptions { tracing: false, check_nonce: false };
|
let options = TransactOptions { tracing: false, vm_tracing: vm_tracing, check_nonce: false };
|
||||||
Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options)
|
Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,8 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
fn try_seal(&self, block: LockedBlock, seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock>;
|
fn try_seal(&self, block: LockedBlock, seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock>;
|
||||||
|
|
||||||
/// Makes a non-persistent transaction call.
|
/// Makes a non-persistent transaction call.
|
||||||
fn call(&self, t: &SignedTransaction) -> Result<Executed, ExecutionError>;
|
// TODO: should be able to accept blockchain location for call.
|
||||||
|
fn call(&self, t: &SignedTransaction, vm_tracing: bool) -> Result<Executed, ExecutionError>;
|
||||||
|
|
||||||
/// Returns EvmFactory.
|
/// Returns EvmFactory.
|
||||||
fn vm_factory(&self) -> &EvmFactory;
|
fn vm_factory(&self) -> &EvmFactory;
|
||||||
|
@ -233,7 +233,7 @@ impl TestBlockChainClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BlockChainClient for TestBlockChainClient {
|
impl BlockChainClient for TestBlockChainClient {
|
||||||
fn call(&self, _t: &SignedTransaction) -> Result<Executed, ExecutionError> {
|
fn call(&self, _t: &SignedTransaction, _vm_tracing: bool) -> Result<Executed, ExecutionError> {
|
||||||
Ok(self.execution_result.read().unwrap().clone().unwrap())
|
Ok(self.execution_result.read().unwrap().clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address {
|
|||||||
pub struct TransactOptions {
|
pub struct TransactOptions {
|
||||||
/// Enable call tracing.
|
/// Enable call tracing.
|
||||||
pub tracing: bool,
|
pub tracing: bool,
|
||||||
|
/// Enable VM tracing.
|
||||||
|
pub vm_tracing: bool,
|
||||||
/// Check transaction nonce before execution.
|
/// Check transaction nonce before execution.
|
||||||
pub check_nonce: bool,
|
pub check_nonce: bool,
|
||||||
}
|
}
|
||||||
@ -394,6 +396,7 @@ impl<'a> Executive<'a> {
|
|||||||
contracts_created: vec![],
|
contracts_created: vec![],
|
||||||
output: output,
|
output: output,
|
||||||
trace: trace,
|
trace: trace,
|
||||||
|
vm_trace: None,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@ -406,6 +409,7 @@ impl<'a> Executive<'a> {
|
|||||||
contracts_created: substate.contracts_created,
|
contracts_created: substate.contracts_created,
|
||||||
output: output,
|
output: output,
|
||||||
trace: trace,
|
trace: trace,
|
||||||
|
vm_trace: None,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -913,7 +917,7 @@ mod tests {
|
|||||||
|
|
||||||
let executed = {
|
let executed = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
||||||
let opts = TransactOptions { check_nonce: true, tracing: false };
|
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
|
||||||
ex.transact(&t, opts).unwrap()
|
ex.transact(&t, opts).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -947,7 +951,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
||||||
let opts = TransactOptions { check_nonce: true, tracing: false };
|
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
|
||||||
ex.transact(&t, opts)
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -979,7 +983,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
||||||
let opts = TransactOptions { check_nonce: true, tracing: false };
|
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
|
||||||
ex.transact(&t, opts)
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1013,7 +1017,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
||||||
let opts = TransactOptions { check_nonce: true, tracing: false };
|
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
|
||||||
ex.transact(&t, opts)
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1047,7 +1051,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
|
||||||
let opts = TransactOptions { check_nonce: true, tracing: false };
|
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
|
||||||
ex.transact(&t, opts)
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ impl State {
|
|||||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, vm_factory: &EvmFactory, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, vm_factory: &EvmFactory, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
||||||
// let old = self.to_pod();
|
// let old = self.to_pod();
|
||||||
|
|
||||||
let options = TransactOptions { tracing: tracing, check_nonce: true };
|
let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true };
|
||||||
let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options));
|
let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options));
|
||||||
|
|
||||||
// TODO uncomment once to_pod() works correctly.
|
// TODO uncomment once to_pod() works correctly.
|
||||||
|
@ -31,7 +31,7 @@ pub use self::block::BlockTraces;
|
|||||||
pub use self::config::{Config, Switch};
|
pub use self::config::{Config, Switch};
|
||||||
pub use self::db::TraceDB;
|
pub use self::db::TraceDB;
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
pub use types::trace_types::trace::Trace;
|
pub use types::trace_types::trace::{Trace, VMTrace};
|
||||||
pub use self::noop_tracer::NoopTracer;
|
pub use self::noop_tracer::NoopTracer;
|
||||||
pub use self::executive_tracer::ExecutiveTracer;
|
pub use self::executive_tracer::ExecutiveTracer;
|
||||||
pub use types::trace_types::filter::{Filter, AddressesFilter};
|
pub use types::trace_types::filter::{Filter, AddressesFilter};
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use util::numbers::*;
|
use util::numbers::*;
|
||||||
use util::Bytes;
|
use util::Bytes;
|
||||||
use trace::Trace;
|
use trace::{Trace, VMTrace};
|
||||||
use types::log_entry::LogEntry;
|
use types::log_entry::LogEntry;
|
||||||
use ipc::binary::BinaryConvertError;
|
use ipc::binary::BinaryConvertError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -59,6 +59,8 @@ pub struct Executed {
|
|||||||
pub output: Bytes,
|
pub output: Bytes,
|
||||||
/// The trace of this transaction.
|
/// The trace of this transaction.
|
||||||
pub trace: Option<Trace>,
|
pub trace: Option<Trace>,
|
||||||
|
/// The VM trace of this transaction.
|
||||||
|
pub vm_trace: Option<VMTrace>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of executing the transaction.
|
/// Result of executing the transaction.
|
||||||
|
@ -349,6 +349,94 @@ impl Trace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Binary)]
|
||||||
|
/// A record of the execution of a single VM operation.
|
||||||
|
pub struct VMOperation {
|
||||||
|
/// The program counter.
|
||||||
|
pub pc: usize,
|
||||||
|
/// The instruction executed.
|
||||||
|
pub instruction: u8,
|
||||||
|
/// The gas cost for this instruction.
|
||||||
|
pub gas_cost: U256,
|
||||||
|
/// The total gas used.
|
||||||
|
pub gas_used: U256,
|
||||||
|
/// The stack.
|
||||||
|
pub stack: Vec<U256>,
|
||||||
|
/// Altered storage value. TODO: should be option.
|
||||||
|
// pub storage_diff: Option<(U256, U256)>,
|
||||||
|
/// If altered, the new memory image.
|
||||||
|
pub new_memory: Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for VMOperation {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(6);
|
||||||
|
s.append(&self.pc);
|
||||||
|
s.append(&self.instruction);
|
||||||
|
s.append(&self.gas_cost);
|
||||||
|
s.append(&self.gas_used);
|
||||||
|
s.append(&self.stack);
|
||||||
|
// s.append(&self.storage_diff);
|
||||||
|
s.append(&self.new_memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for VMOperation {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let d = decoder.as_rlp();
|
||||||
|
let res = VMOperation {
|
||||||
|
pc: try!(d.val_at(0)),
|
||||||
|
instruction: try!(d.val_at(1)),
|
||||||
|
gas_cost: try!(d.val_at(2)),
|
||||||
|
gas_used: try!(d.val_at(3)),
|
||||||
|
stack: try!(d.val_at(4)),
|
||||||
|
// storage_diff: try!(d.val_at(5)),
|
||||||
|
new_memory: try!(d.val_at(6)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Binary)]
|
||||||
|
/// A record of a full VM trace for a CALL/CREATE.
|
||||||
|
pub struct VMTrace {
|
||||||
|
/// The number of EVM execution environments active when this action happened; 0 if it's
|
||||||
|
/// the outer action of the transaction.
|
||||||
|
pub depth: usize,
|
||||||
|
/// The code to be executed.
|
||||||
|
pub code: Bytes,
|
||||||
|
/// The operations executed.
|
||||||
|
pub operations: Vec<VMOperation>,
|
||||||
|
/// The sub traces for each interior action performed as part of this call/create.
|
||||||
|
/// Thre is a 1:1 correspondance between these and a CALL/CREATE/CALLCODE/DELEGATECALL instruction.
|
||||||
|
pub subs: Vec<VMTrace>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for VMTrace {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
s.begin_list(4);
|
||||||
|
s.append(&self.depth);
|
||||||
|
s.append(&self.code);
|
||||||
|
s.append(&self.operations);
|
||||||
|
s.append(&self.subs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for VMTrace {
|
||||||
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
|
let d = decoder.as_rlp();
|
||||||
|
let res = VMTrace {
|
||||||
|
depth: try!(d.val_at(0)),
|
||||||
|
code: try!(d.val_at(1)),
|
||||||
|
operations: try!(d.val_at(2)),
|
||||||
|
subs: try!(d.val_at(3)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use util::{Address, U256, FixedHash};
|
use util::{Address, U256, FixedHash};
|
||||||
|
@ -158,7 +158,7 @@ pub trait MinerService : Send + Sync {
|
|||||||
fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256;
|
fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256;
|
||||||
|
|
||||||
/// Call into contract code using pending state.
|
/// Call into contract code using pending state.
|
||||||
fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result<Executed, ExecutionError>;
|
fn call(&self, chain: &BlockChainClient, t: &SignedTransaction, vm_tracing: bool) -> Result<Executed, ExecutionError>;
|
||||||
|
|
||||||
/// Get storage value in pending state.
|
/// Get storage value in pending state.
|
||||||
fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256;
|
fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256;
|
||||||
|
@ -252,7 +252,7 @@ impl MinerService for Miner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result<Executed, ExecutionError> {
|
fn call(&self, chain: &BlockChainClient, t: &SignedTransaction, vm_tracing: bool) -> Result<Executed, ExecutionError> {
|
||||||
let sealing_work = self.sealing_work.lock().unwrap();
|
let sealing_work = self.sealing_work.lock().unwrap();
|
||||||
match sealing_work.peek_last_ref() {
|
match sealing_work.peek_last_ref() {
|
||||||
Some(work) => {
|
Some(work) => {
|
||||||
@ -278,12 +278,13 @@ impl MinerService for Miner {
|
|||||||
// give the sender max balance
|
// give the sender max balance
|
||||||
state.sub_balance(&sender, &balance);
|
state.sub_balance(&sender, &balance);
|
||||||
state.add_balance(&sender, &U256::max_value());
|
state.add_balance(&sender, &U256::max_value());
|
||||||
let options = TransactOptions { tracing: false, check_nonce: false };
|
let options = TransactOptions { tracing: false, vm_tracing: vm_tracing, check_nonce: false };
|
||||||
|
|
||||||
|
// TODO: use vm_trace here.
|
||||||
Executive::new(&mut state, &env_info, self.engine(), chain.vm_factory()).transact(t, options)
|
Executive::new(&mut state, &env_info, self.engine(), chain.vm_factory()).transact(t, options)
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
chain.call(t)
|
chain.call(t, vm_tracing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ pub fn setup_dapps_server(
|
|||||||
server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate());
|
server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate());
|
||||||
server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate());
|
server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate());
|
||||||
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate());
|
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate());
|
||||||
server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate());
|
server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate());
|
||||||
|
|
||||||
let start_result = match auth {
|
let start_result = match auth {
|
||||||
None => {
|
None => {
|
||||||
|
@ -110,7 +110,7 @@ fn setup_rpc_server(apis: Vec<&str>, deps: &Arc<Dependencies>) -> Server {
|
|||||||
},
|
},
|
||||||
"ethcore" => {
|
"ethcore" => {
|
||||||
modules.insert("ethcore".to_owned(), "1.0".to_owned());
|
modules.insert("ethcore".to_owned(), "1.0".to_owned());
|
||||||
server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate())
|
server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate())
|
||||||
},
|
},
|
||||||
"traces" => {
|
"traces" => {
|
||||||
modules.insert("traces".to_owned(), "1.0".to_owned());
|
modules.insert("traces".to_owned(), "1.0".to_owned());
|
||||||
|
@ -26,6 +26,7 @@ extern crate serde;
|
|||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate jsonrpc_core;
|
extern crate jsonrpc_core;
|
||||||
extern crate jsonrpc_http_server;
|
extern crate jsonrpc_http_server;
|
||||||
|
#[macro_use]
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
extern crate ethcore;
|
extern crate ethcore;
|
||||||
extern crate ethsync;
|
extern crate ethsync;
|
||||||
|
@ -522,8 +522,8 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM> where
|
|||||||
.and_then(|(request, block_number,)| {
|
.and_then(|(request, block_number,)| {
|
||||||
let signed = try!(self.sign_call(request));
|
let signed = try!(self.sign_call(request));
|
||||||
let r = match block_number {
|
let r = match block_number {
|
||||||
BlockNumber::Pending => take_weak!(self.miner).call(take_weak!(self.client).deref(), &signed),
|
BlockNumber::Pending => take_weak!(self.miner).call(take_weak!(self.client).deref(), &signed, false),
|
||||||
BlockNumber::Latest => take_weak!(self.client).call(&signed),
|
BlockNumber::Latest => take_weak!(self.client).call(&signed, false),
|
||||||
_ => panic!("{:?}", block_number),
|
_ => panic!("{:?}", block_number),
|
||||||
};
|
};
|
||||||
to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])))
|
to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])))
|
||||||
@ -535,8 +535,8 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM> where
|
|||||||
.and_then(|(request, block_number,)| {
|
.and_then(|(request, block_number,)| {
|
||||||
let signed = try!(self.sign_call(request));
|
let signed = try!(self.sign_call(request));
|
||||||
let r = match block_number {
|
let r = match block_number {
|
||||||
BlockNumber::Pending => take_weak!(self.miner).call(take_weak!(self.client).deref(), &signed),
|
BlockNumber::Pending => take_weak!(self.miner).call(take_weak!(self.client).deref(), &signed, false),
|
||||||
BlockNumber::Latest => take_weak!(self.client).call(&signed),
|
BlockNumber::Latest => take_weak!(self.client).call(&signed, false),
|
||||||
_ => return Err(Error::invalid_params()),
|
_ => return Err(Error::invalid_params()),
|
||||||
};
|
};
|
||||||
to_value(&r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0)))
|
to_value(&r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0)))
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Ethcore-specific rpc implementation.
|
//! Ethcore-specific rpc implementation.
|
||||||
use util::{U256, Address, RotatingLogger};
|
use util::{U256, Address, RotatingLogger, FixedHash, Uint};
|
||||||
use util::network_settings::NetworkSettings;
|
use util::network_settings::NetworkSettings;
|
||||||
use util::misc::version_data;
|
use util::misc::version_data;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
@ -23,29 +23,50 @@ use std::ops::Deref;
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use ethminer::{MinerService};
|
use ethminer::{MinerService};
|
||||||
|
use ethcore::client::{BlockChainClient};
|
||||||
|
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
|
||||||
use v1::traits::Ethcore;
|
use v1::traits::Ethcore;
|
||||||
use v1::types::Bytes;
|
use v1::types::{Bytes, CallRequest};
|
||||||
|
|
||||||
/// Ethcore implementation.
|
/// Ethcore implementation.
|
||||||
pub struct EthcoreClient<M>
|
pub struct EthcoreClient<C, M> where
|
||||||
where M: MinerService {
|
C: BlockChainClient,
|
||||||
|
M: MinerService {
|
||||||
|
|
||||||
|
client: Weak<C>,
|
||||||
miner: Weak<M>,
|
miner: Weak<M>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> EthcoreClient<M> where M: MinerService {
|
impl<C, M> EthcoreClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||||
/// Creates new `EthcoreClient`.
|
/// Creates new `EthcoreClient`.
|
||||||
pub fn new(miner: &Arc<M>, logger: Arc<RotatingLogger>, settings: Arc<NetworkSettings>) -> Self {
|
pub fn new(client: &Arc<C>, miner: &Arc<M>, logger: Arc<RotatingLogger>, settings: Arc<NetworkSettings>) -> Self {
|
||||||
EthcoreClient {
|
EthcoreClient {
|
||||||
|
client: Arc::downgrade(client),
|
||||||
miner: Arc::downgrade(miner),
|
miner: Arc::downgrade(miner),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: share with eth.rs
|
||||||
|
fn sign_call(&self, request: CallRequest) -> Result<SignedTransaction, Error> {
|
||||||
|
let client = take_weak!(self.client);
|
||||||
|
let miner = take_weak!(self.miner);
|
||||||
|
let from = request.from.unwrap_or(Address::zero());
|
||||||
|
Ok(EthTransaction {
|
||||||
|
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
|
||||||
|
action: request.to.map_or(Action::Create, Action::Call),
|
||||||
|
gas: request.gas.unwrap_or(U256::from(50_000_000)),
|
||||||
|
gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()),
|
||||||
|
value: request.value.unwrap_or_else(U256::zero),
|
||||||
|
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
|
||||||
|
}.fake_sign(from))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> Ethcore for EthcoreClient<M> where M: MinerService + 'static {
|
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> {
|
fn set_min_gas_price(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(U256,)>(params).and_then(|(gas_price,)| {
|
from_params::<(U256,)>(params).and_then(|(gas_price,)| {
|
||||||
@ -135,4 +156,19 @@ impl<M> Ethcore for EthcoreClient<M> where M: MinerService + 'static {
|
|||||||
let version = version_data();
|
let version = version_data();
|
||||||
to_value(&Bytes::new(version))
|
to_value(&Bytes::new(version))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//pub type VMTraceFunctionBox = Box<FnMut(usize, u8, U256, U256) + Send>;
|
||||||
|
|
||||||
|
fn vm_trace_call(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
trace!(target: "jsonrpc", "vm_trace_call: {:?}", params);
|
||||||
|
from_params(params)
|
||||||
|
.and_then(|(request,)| {
|
||||||
|
let signed = try!(self.sign_call(request));
|
||||||
|
let _ = take_weak!(self.client).call(&signed, true);
|
||||||
|
// TODO: construct JSON trace from _.vm_trace.
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
ret.push(Value::Object(map!["foo".to_owned() => Value::String("var".to_owned())]));
|
||||||
|
Ok(Value::Array(ret))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,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())
|
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: &BlockChainClient, _t: &SignedTransaction) -> Result<Executed, ExecutionError> {
|
fn call(&self, _chain: &BlockChainClient, _t: &SignedTransaction, _vm_tracing: bool) -> Result<Executed, ExecutionError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,8 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
|||||||
/// Returns default extra data
|
/// Returns default extra data
|
||||||
fn default_extra_data(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
|
fn default_extra_data(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
|
||||||
|
|
||||||
|
/// Executes the given call and returns the VM trace for it.
|
||||||
|
fn vm_trace_call(&self, _: Params) -> Result<Value, Error> { rpc_unimplemented!() }
|
||||||
|
|
||||||
/// Should be used to convert object to io delegate.
|
/// Should be used to convert object to io delegate.
|
||||||
fn to_delegate(self) -> IoDelegate<Self> {
|
fn to_delegate(self) -> IoDelegate<Self> {
|
||||||
@ -95,6 +97,8 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
|||||||
delegate.add_method("ethcore_nodeName", Ethcore::node_name);
|
delegate.add_method("ethcore_nodeName", Ethcore::node_name);
|
||||||
delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data);
|
delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data);
|
||||||
|
|
||||||
|
delegate.add_method("ethcore_vmTraceCall", Ethcore::vm_trace_call);
|
||||||
|
|
||||||
delegate
|
delegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user