diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 2b77685bd..2b2514d0a 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -19,9 +19,9 @@ use std::sync::{Weak, Arc}; use ethcore::block_status::BlockStatus; -use ethcore::client::{TransactionImportResult, ClientReport, EnvInfo}; +use ethcore::client::{ClientReport, EnvInfo}; use ethcore::engines::{epoch, Engine, EpochChange, EpochTransition, Proof, Unsure}; -use ethcore::error::{TransactionError, BlockImportError, Error as EthcoreError}; +use ethcore::error::BlockImportError; use ethcore::ids::BlockId; use ethcore::header::{BlockNumber, Header}; use ethcore::verification::queue::{self, HeaderQueue}; @@ -35,7 +35,6 @@ use bigint::prelude::U256; use bigint::hash::H256; use futures::{IntoFuture, Future}; -use util::Address; use util::kvdb::{KeyValueDB, CompactionProfile}; use self::fetch::ChainDataFetcher; @@ -619,17 +618,8 @@ impl ::ethcore::client::EngineClient for Client { Client::chain_info(self) } - fn call_contract(&self, _id: BlockId, _address: Address, _data: Vec) -> Result, String> { - Err("Contract calling not supported by light client".into()) - } - - fn transact_contract(&self, _address: Address, _data: Vec) - -> Result - { - // TODO: these are only really used for misbehavior reporting. - // no relevant clients will be running light clients, but maybe - // they could be at some point? - Err(TransactionError::LimitReached.into()) + fn as_full_client(&self) -> Option<&::ethcore::client::BlockChainClient> { + None } fn block_number(&self, id: BlockId) -> Option { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 0eda5048e..02682ece2 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1960,13 +1960,7 @@ impl super::traits::EngineClient for Client { BlockChainClient::chain_info(self) } - fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result { - BlockChainClient::call_contract(self, id, address, data) - } - - fn transact_contract(&self, address: Address, data: Bytes) -> Result { - BlockChainClient::transact_contract(self, address, data) - } + fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) } fn block_number(&self, id: BlockId) -> Option { BlockChainClient::block_number(self, id) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 0cd9fedc8..f39932f82 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -828,13 +828,7 @@ impl super::traits::EngineClient for TestBlockChainClient { BlockChainClient::chain_info(self) } - fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result { - BlockChainClient::call_contract(self, id, address, data) - } - - fn transact_contract(&self, address: Address, data: Bytes) -> Result { - BlockChainClient::transact_contract(self, address, data) - } + fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) } fn block_number(&self, id: BlockId) -> Option { BlockChainClient::block_number(self, id) diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 45736e2c5..5a619a95e 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -337,12 +337,10 @@ pub trait EngineClient: Sync + Send { /// Get block chain info. fn chain_info(&self) -> BlockChainInfo; - /// Like `call`, but with various defaults. Designed to be used for calling contracts. - fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result; - - /// Import a transaction: used for misbehaviour reporting. - fn transact_contract(&self, address: Address, data: Bytes) -> Result; + /// Attempt to cast the engine client to a full client. + fn as_full_client(&self) -> Option<&BlockChainClient>; + /// Get a block number by ID. fn block_number(&self, id: BlockId) -> Option; } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index dff678c92..ce0a0da24 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -35,7 +35,7 @@ use bigint::hash::{H256, H520}; use parking_lot::RwLock; use util::*; use unexpected::{OutOfBounds, Mismatch}; -use client::{Client, EngineClient}; +use client::EngineClient; use error::{Error, BlockError}; use header::{Header, BlockNumber}; use builtin::Builtin; diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index 9a3705b63..24e396c10 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -58,7 +58,13 @@ impl ValidatorContract { Box::new(move |a, d| client.as_ref() .and_then(Weak::upgrade) .ok_or("No client!".into()) - .and_then(|c| c.transact_contract(a, d).map_err(|e| format!("Transaction import error: {}", e))) + .and_then(|c| { + match c.as_full_client() { + Some(c) => c.transact_contract(a, d) + .map_err(|e| format!("Transaction import error: {}", e)), + None => Err("No full client!".into()), + } + }) .map(|_| Default::default())) } } diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index 1d4f9b0be..c3f82e181 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -311,7 +311,12 @@ impl ValidatorSet for ValidatorSafeContract { Box::new(move |addr, data| client.as_ref() .and_then(Weak::upgrade) .ok_or("No client!".into()) - .and_then(|c| c.call_contract(id, addr, data)) + .and_then(|c| { + match c.as_full_client() { + Some(c) => c.call_contract(id, addr, data), + None => Err("No full client!".into()), + } + }) .map(|out| (out, Vec::new()))) // generate no proofs in general } diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index b11700e09..11c04b628 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -40,7 +40,7 @@ use rlp::{self, UntrustedRlp}; use vm::LastHashes; use semantic_version::SemanticVersion; use tx_filter::{TransactionFilter}; -use client::{Client, BlockChainClient}; +use client::EngineClient; /// Parity tries to round block.gas_limit to multiple of this constant pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); @@ -460,9 +460,9 @@ impl Engine for Arc { Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS))) } - fn register_client(&self, client: Weak) { + fn register_client(&self, client: Weak) { if let Some(ref filter) = self.tx_filter { - filter.register_client(client as Weak); + filter.register_client(client); } } diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index f39b92451..bd6a0b6bd 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -19,9 +19,10 @@ use std::sync::Weak; use std::collections::HashMap; use std::collections::hash_map::Entry; +use bigint::hash::H256; use native_contracts::TransactAcl as Contract; -use client::{BlockChainClient, BlockId, ChainNotify}; -use util::{Address, H256, Bytes}; +use client::{EngineClient, BlockId, ChainNotify}; +use util::{Address, Bytes}; use parking_lot::{Mutex, RwLock}; use futures::{self, Future}; use spec::CommonParams; @@ -42,7 +43,7 @@ mod tx_permissions { /// Connection filter that uses a contract to manage permissions. pub struct TransactionFilter { contract: Mutex>, - client: RwLock>>, + client: RwLock>>, contract_address: Address, permission_cache: Mutex>, } @@ -66,7 +67,7 @@ impl TransactionFilter { } /// Set client reference to be used for contract call. - pub fn register_client(&self, client: Weak) { + pub fn register_client(&self, client: Weak) { *self.client.write() = Some(client); } @@ -78,6 +79,12 @@ impl TransactionFilter { Some(client) => client, _ => return false, }; + + let client = match client.as_full_client() { + Some(client) => client, + _ => return false, // TODO: how to handle verification for light clients? + }; + let tx_type = match transaction.action { Action::Create => tx_permissions::CREATE, Action::Call(address) => if client.code_hash(&address, BlockId::Hash(*parent_hash)).map_or(false, |c| c != KECCAK_EMPTY) {