allow optional casting of engine client to full client

This commit is contained in:
Robert Habermeier 2017-09-05 17:24:35 +02:00
parent ad39446e87
commit 7d1c7a0474
9 changed files with 37 additions and 43 deletions

View File

@ -19,9 +19,9 @@
use std::sync::{Weak, Arc}; use std::sync::{Weak, Arc};
use ethcore::block_status::BlockStatus; 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::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::ids::BlockId;
use ethcore::header::{BlockNumber, Header}; use ethcore::header::{BlockNumber, Header};
use ethcore::verification::queue::{self, HeaderQueue}; use ethcore::verification::queue::{self, HeaderQueue};
@ -35,7 +35,6 @@ use bigint::prelude::U256;
use bigint::hash::H256; use bigint::hash::H256;
use futures::{IntoFuture, Future}; use futures::{IntoFuture, Future};
use util::Address;
use util::kvdb::{KeyValueDB, CompactionProfile}; use util::kvdb::{KeyValueDB, CompactionProfile};
use self::fetch::ChainDataFetcher; use self::fetch::ChainDataFetcher;
@ -619,17 +618,8 @@ impl<T: ChainDataFetcher> ::ethcore::client::EngineClient for Client<T> {
Client::chain_info(self) Client::chain_info(self)
} }
fn call_contract(&self, _id: BlockId, _address: Address, _data: Vec<u8>) -> Result<Vec<u8>, String> { fn as_full_client(&self) -> Option<&::ethcore::client::BlockChainClient> {
Err("Contract calling not supported by light client".into()) None
}
fn transact_contract(&self, _address: Address, _data: Vec<u8>)
-> Result<TransactionImportResult, EthcoreError>
{
// 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 block_number(&self, id: BlockId) -> Option<BlockNumber> { fn block_number(&self, id: BlockId) -> Option<BlockNumber> {

View File

@ -1960,13 +1960,7 @@ impl super::traits::EngineClient for Client {
BlockChainClient::chain_info(self) BlockChainClient::chain_info(self)
} }
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String> { fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) }
BlockChainClient::call_contract(self, id, address, data)
}
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError> {
BlockChainClient::transact_contract(self, address, data)
}
fn block_number(&self, id: BlockId) -> Option<BlockNumber> { fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
BlockChainClient::block_number(self, id) BlockChainClient::block_number(self, id)

View File

@ -828,13 +828,7 @@ impl super::traits::EngineClient for TestBlockChainClient {
BlockChainClient::chain_info(self) BlockChainClient::chain_info(self)
} }
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String> { fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) }
BlockChainClient::call_contract(self, id, address, data)
}
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError> {
BlockChainClient::transact_contract(self, address, data)
}
fn block_number(&self, id: BlockId) -> Option<BlockNumber> { fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
BlockChainClient::block_number(self, id) BlockChainClient::block_number(self, id)

View File

@ -337,12 +337,10 @@ pub trait EngineClient: Sync + Send {
/// Get block chain info. /// Get block chain info.
fn chain_info(&self) -> BlockChainInfo; fn chain_info(&self) -> BlockChainInfo;
/// Like `call`, but with various defaults. Designed to be used for calling contracts. /// Attempt to cast the engine client to a full client.
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>; fn as_full_client(&self) -> Option<&BlockChainClient>;
/// Import a transaction: used for misbehaviour reporting.
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError>;
/// Get a block number by ID.
fn block_number(&self, id: BlockId) -> Option<BlockNumber>; fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
} }

View File

@ -35,7 +35,7 @@ use bigint::hash::{H256, H520};
use parking_lot::RwLock; use parking_lot::RwLock;
use util::*; use util::*;
use unexpected::{OutOfBounds, Mismatch}; use unexpected::{OutOfBounds, Mismatch};
use client::{Client, EngineClient}; use client::EngineClient;
use error::{Error, BlockError}; use error::{Error, BlockError};
use header::{Header, BlockNumber}; use header::{Header, BlockNumber};
use builtin::Builtin; use builtin::Builtin;

View File

@ -58,7 +58,13 @@ impl ValidatorContract {
Box::new(move |a, d| client.as_ref() Box::new(move |a, d| client.as_ref()
.and_then(Weak::upgrade) .and_then(Weak::upgrade)
.ok_or("No client!".into()) .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())) .map(|_| Default::default()))
} }
} }

View File

@ -311,7 +311,12 @@ impl ValidatorSet for ValidatorSafeContract {
Box::new(move |addr, data| client.as_ref() Box::new(move |addr, data| client.as_ref()
.and_then(Weak::upgrade) .and_then(Weak::upgrade)
.ok_or("No client!".into()) .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 .map(|out| (out, Vec::new()))) // generate no proofs in general
} }

View File

@ -40,7 +40,7 @@ use rlp::{self, UntrustedRlp};
use vm::LastHashes; use vm::LastHashes;
use semantic_version::SemanticVersion; use semantic_version::SemanticVersion;
use tx_filter::{TransactionFilter}; use tx_filter::{TransactionFilter};
use client::{Client, BlockChainClient}; use client::EngineClient;
/// Parity tries to round block.gas_limit to multiple of this constant /// Parity tries to round block.gas_limit to multiple of this constant
pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
@ -460,9 +460,9 @@ impl Engine for Arc<Ethash> {
Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS))) Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS)))
} }
fn register_client(&self, client: Weak<Client>) { fn register_client(&self, client: Weak<EngineClient>) {
if let Some(ref filter) = self.tx_filter { if let Some(ref filter) = self.tx_filter {
filter.register_client(client as Weak<BlockChainClient>); filter.register_client(client);
} }
} }

View File

@ -19,9 +19,10 @@
use std::sync::Weak; use std::sync::Weak;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use bigint::hash::H256;
use native_contracts::TransactAcl as Contract; use native_contracts::TransactAcl as Contract;
use client::{BlockChainClient, BlockId, ChainNotify}; use client::{EngineClient, BlockId, ChainNotify};
use util::{Address, H256, Bytes}; use util::{Address, Bytes};
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use futures::{self, Future}; use futures::{self, Future};
use spec::CommonParams; use spec::CommonParams;
@ -42,7 +43,7 @@ mod tx_permissions {
/// Connection filter that uses a contract to manage permissions. /// Connection filter that uses a contract to manage permissions.
pub struct TransactionFilter { pub struct TransactionFilter {
contract: Mutex<Option<Contract>>, contract: Mutex<Option<Contract>>,
client: RwLock<Option<Weak<BlockChainClient>>>, client: RwLock<Option<Weak<EngineClient>>>,
contract_address: Address, contract_address: Address,
permission_cache: Mutex<HashMap<(H256, Address), u32>>, permission_cache: Mutex<HashMap<(H256, Address), u32>>,
} }
@ -66,7 +67,7 @@ impl TransactionFilter {
} }
/// Set client reference to be used for contract call. /// Set client reference to be used for contract call.
pub fn register_client(&self, client: Weak<BlockChainClient>) { pub fn register_client(&self, client: Weak<EngineClient>) {
*self.client.write() = Some(client); *self.client.write() = Some(client);
} }
@ -78,6 +79,12 @@ impl TransactionFilter {
Some(client) => client, Some(client) => client,
_ => return false, _ => 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 { let tx_type = match transaction.action {
Action::Create => tx_permissions::CREATE, Action::Create => tx_permissions::CREATE,
Action::Call(address) => if client.code_hash(&address, BlockId::Hash(*parent_hash)).map_or(false, |c| c != KECCAK_EMPTY) { Action::Call(address) => if client.code_hash(&address, BlockId::Hash(*parent_hash)).map_or(false, |c| c != KECCAK_EMPTY) {