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 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<T: ChainDataFetcher> ::ethcore::client::EngineClient for Client<T> {
Client::chain_info(self)
}
fn call_contract(&self, _id: BlockId, _address: Address, _data: Vec<u8>) -> Result<Vec<u8>, String> {
Err("Contract calling not supported by light client".into())
}
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 as_full_client(&self) -> Option<&::ethcore::client::BlockChainClient> {
None
}
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {

View File

@ -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<Bytes, String> {
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 as_full_client(&self) -> Option<&BlockChainClient> { Some(self) }
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
BlockChainClient::block_number(self, id)

View File

@ -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<Bytes, String> {
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 as_full_client(&self) -> Option<&BlockChainClient> { Some(self) }
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
BlockChainClient::block_number(self, id)

View File

@ -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<Bytes, String>;
/// Import a transaction: used for misbehaviour reporting.
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError>;
/// 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<BlockNumber>;
}

View File

@ -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;

View File

@ -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()))
}
}

View File

@ -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
}

View File

@ -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<Ethash> {
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 {
filter.register_client(client as Weak<BlockChainClient>);
filter.register_client(client);
}
}

View File

@ -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<Option<Contract>>,
client: RwLock<Option<Weak<BlockChainClient>>>,
client: RwLock<Option<Weak<EngineClient>>>,
contract_address: Address,
permission_cache: Mutex<HashMap<(H256, Address), u32>>,
}
@ -66,7 +67,7 @@ impl TransactionFilter {
}
/// 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);
}
@ -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) {