Refactor return type of BlockChainClient::code #7098 (#11102)

* fix: refactor return type of `BlockChainClient::code`

* Add TODO move to `common-types`

Co-Authored-By: David <dvdplm@gmail.com>
This commit is contained in:
Juan Aguilar 2019-10-03 13:21:26 +02:00 committed by Niklas Adolfsson
parent 0bd2979c04
commit 0c0f965354
5 changed files with 31 additions and 15 deletions

View File

@ -67,6 +67,16 @@ pub enum StateOrBlock {
Block(BlockId)
}
/// Result to be used during get address code at given block's state
// todo[botika] move to `common-types`
pub enum StateResult<T> {
/// State is missing
Missing,
/// State is some
Some(T),
}
impl From<Box<dyn StateInfo>> for StateOrBlock {
fn from(info: Box<dyn StateInfo>) -> StateOrBlock {
StateOrBlock::State(info)
@ -231,12 +241,14 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
fn block_hash(&self, id: BlockId) -> Option<H256>;
/// Get address code at given block's state.
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>>;
fn code(&self, address: &Address, state: StateOrBlock) -> StateResult<Option<Bytes>>;
/// Get address code at the latest block's state.
fn latest_code(&self, address: &Address) -> Option<Bytes> {
self.code(address, BlockId::Latest.into())
.expect("code will return Some if given BlockId::Latest; qed")
match self.code(address, BlockId::Latest.into()) {
StateResult::Missing => panic!("code will return Some if given BlockId::Latest; qed"),
StateResult::Some(t) => t,
}
}
/// Get a reference to the `BlockProvider`.

View File

@ -77,6 +77,7 @@ use client_traits::{
ScheduleInfo,
StateClient,
StateOrBlock,
StateResult,
Tick,
TransactionInfo
};
@ -1758,14 +1759,14 @@ impl BlockChainClient for Client {
Self::block_hash(&chain, id)
}
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>> {
fn code(&self, address: &Address, state: StateOrBlock) -> StateResult<Option<Bytes>> {
let result = match state {
StateOrBlock::State(s) => s.code(address).ok(),
StateOrBlock::Block(id) => self.state_at(id).and_then(|s| s.code(address).ok())
};
// Converting from `Option<Option<Arc<Bytes>>>` to `Option<Option<Bytes>>`
result.map(|c| c.map(|c| (&*c).clone()))
// Converting from `Option<Option<Arc<Bytes>>>` to `StateResult<Option<Bytes>>`
result.map_or(StateResult::Missing, |c| StateResult::Some(c.map(|c| (&*c).clone())))
}
fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option<H256> {

View File

@ -71,7 +71,7 @@ use client::{
use client_traits::{
BlockInfo, Nonce, Balance, ChainInfo, TransactionInfo, BlockChainClient, ImportBlock,
AccountData, BlockChain, IoClient, BadBlocks, ScheduleInfo, StateClient, ProvingBlockChainClient,
StateOrBlock
StateOrBlock, StateResult
};
use engine::Engine;
use machine::executed::Executed;
@ -702,10 +702,10 @@ impl BlockChainClient for TestBlockChainClient {
None
}
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>> {
fn code(&self, address: &Address, state: StateOrBlock) -> StateResult<Option<Bytes>> {
match state {
StateOrBlock::Block(BlockId::Latest) => Some(self.code.read().get(address).cloned()),
_ => None,
StateOrBlock::Block(BlockId::Latest) => StateResult::Some(self.code.read().get(address).cloned()),
_ => StateResult::Missing,
}
}

View File

@ -26,7 +26,7 @@ use hash::{keccak, KECCAK_NULL_RLP};
use ethereum_types::{U256, H256, Address};
use bytes::ToPretty;
use rlp::PayloadInfo;
use client_traits::{BlockChainReset, Nonce, Balance, BlockChainClient, ImportExportBlocks};
use client_traits::{BlockChainReset, Nonce, Balance, BlockChainClient, ImportExportBlocks, StateResult};
use ethcore::{
client::{DatabaseCompactionProfile, VMType},
miner::Miner,
@ -592,7 +592,10 @@ fn execute_export_state(cmd: ExportState) -> Result<(), String> {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!("\n\"0x{:x}\": {{\"balance\": \"{:x}\", \"nonce\": \"{:x}\"", account, balance, client.nonce(&account, at).unwrap_or_else(U256::zero))).expect("Write error");
let code = client.code(&account, at.into()).unwrap_or(None).unwrap_or_else(Vec::new);
let code = match client.code(&account, at.into()) {
StateResult::Missing => Vec::new(),
StateResult::Some(t) => t.unwrap_or_else(Vec::new),
};
if !code.is_empty() {
out.write_fmt(format_args!(", \"code_hash\": \"0x{:x}\"", keccak(&code))).expect("Write error");
if cmd.code {

View File

@ -25,7 +25,7 @@ use ethereum_types::{Address, H64, H160, H256, U64, U256, BigEndianHash};
use parking_lot::Mutex;
use account_state::state::StateInfo;
use client_traits::{BlockChainClient, StateClient, ProvingBlockChainClient, StateOrBlock};
use client_traits::{BlockChainClient, StateClient, ProvingBlockChainClient, StateOrBlock, StateResult};
use ethash::{self, SeedHashCompute};
use ethcore::client::{Call, EngineInfo};
use ethcore::miner::{self, MinerService};
@ -742,8 +742,8 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
try_bf!(check_known(&*self.client, num.clone()));
let res = match self.client.code(&address, self.get_state(num)) {
Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
None => Err(errors::state_pruned()),
StateResult::Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
StateResult::Missing => Err(errors::state_pruned()),
};
Box::new(future::done(res))