From 521f2a14331e60b0f40f4cd64b31b3b2fada7665 Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 21:37:11 +0100 Subject: [PATCH] implemented eth_call --- ethcore/src/client/client.rs | 25 +++++++++++++++++++++++++ ethcore/src/client/mod.rs | 5 ++++- ethcore/src/client/test_client.rs | 6 ++++++ ethcore/src/views.rs | 3 +++ rpc/src/v1/impls/eth.rs | 20 ++++++++++++++++++++ util/bigint/src/uint.rs | 11 +++++++++++ 6 files changed, 69 insertions(+), 1 deletion(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index c62364dce..a0538d8de 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -37,6 +37,8 @@ use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; use client::{BlockId, TransactionId, ClientConfig, BlockChainClient}; +use env_info::EnvInfo; +use executive::{Executive, Executed}; pub use blockchain::CacheSize as BlockChainCacheSize; /// General block status @@ -385,6 +387,29 @@ impl Client where V: Verifier { } impl BlockChainClient for Client where V: Verifier { + fn call(&self, t: &SignedTransaction) -> Result { + let header = self.block_header(BlockId::Latest).unwrap(); + let view = HeaderView::new(&header); + let last_hashes = self.build_last_hashes(view.hash()); + let env_info = EnvInfo { + number: view.number(), + author: view.author(), + timestamp: view.timestamp(), + difficulty: view.difficulty(), + last_hashes: last_hashes, + gas_used: U256::zero(), + gas_limit: U256::max_value(), + }; + // that's just a copy of the state. + let mut state = self.state(); + let sender = try!(t.sender()); + let balance = state.balance(&sender); + // give the sender max balance + state.sub_balance(&sender, &balance); + state.add_balance(&sender, &U256::max_value()); + Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t) + } + // TODO [todr] Should be moved to miner crate eventually. fn try_seal(&self, block: ClosedBlock, seal: Vec) -> Result { block.try_seal(self.engine.deref().deref(), seal) diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 198e918f7..4a3208eb8 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -37,7 +37,8 @@ use header::BlockNumber; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; -use error::{ImportResult}; +use error::{ImportResult, Error}; +use executive::Executed; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -118,5 +119,7 @@ pub trait BlockChainClient : Sync + Send { /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. fn try_seal(&self, block: ClosedBlock, seal: Vec) -> Result; + /// Makes a non-persistent transaction call. + fn call(&self, t: &SignedTransaction) -> Result; } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 9150a5f55..5d51368de 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -29,6 +29,8 @@ use error::{ImportResult}; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock}; +use executive::Executed; +use error::Error; /// Test client. pub struct TestBlockChainClient { @@ -182,6 +184,10 @@ impl TestBlockChainClient { } impl BlockChainClient for TestBlockChainClient { + fn call(&self, t: &SignedTransaction) -> Result { + unimplemented!() + } + fn block_total_difficulty(&self, _id: BlockId) -> Option { Some(U256::zero()) } diff --git a/ethcore/src/views.rs b/ethcore/src/views.rs index 745cbff2c..11e26eb5f 100644 --- a/ethcore/src/views.rs +++ b/ethcore/src/views.rs @@ -256,6 +256,9 @@ impl<'a> HeaderView<'a> { } } + /// Returns header hash. + pub fn hash(&self) -> H256 { self.sha3() } + /// Returns raw rlp. pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5cd1b2966..7fa12295d 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -397,6 +397,26 @@ impl Eth for EthClient } }) } + + fn call(&self, params: Params) -> Result { + from_params::<(TransactionRequest, BlockNumber)>(params) + .and_then(|(transaction_request, _block_number)| { + let accounts = take_weak!(self.accounts); + match accounts.account_secret(&transaction_request.from) { + Ok(secret) => { + let client = take_weak!(self.client); + + let transaction: EthTransaction = transaction_request.into(); + let signed_transaction = transaction.sign(&secret); + + to_value(&client.call(&signed_transaction) + .map(|e| Bytes::new(e.output)) + .unwrap_or(Bytes::default())) + }, + Err(_) => { to_value(&Bytes::default()) } + } + }) + } } /// Eth filter rpc implementation. diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index d185750c2..7bc6007ed 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -490,6 +490,8 @@ pub trait Uint: Sized + Default + FromStr + From + fmt::Debug + fmt::Displa fn zero() -> Self; /// Returns new instance equalling one. fn one() -> Self; + /// Returns the largest value that can be represented by this integer type. + fn max_value() -> Self; /// Error type for converting from a decimal string. type FromDecStrErr; @@ -647,6 +649,15 @@ macro_rules! construct_uint { From::from(1u64) } + #[inline] + fn max_value() -> Self { + let mut result = [0; $n_words]; + for i in 0..$n_words { + result[i] = u64::max_value(); + } + $name(result) + } + /// Fast exponentation by squaring /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring fn pow(self, expon: Self) -> Self {