Unknown block error for RPC (#3965)

This commit is contained in:
Robert Habermeier 2016-12-23 18:46:17 +01:00 committed by Gav Wood
parent 612f14188f
commit 546246c56b
5 changed files with 55 additions and 16 deletions

View File

@ -619,7 +619,8 @@ impl Client {
/// Attempt to get a copy of a specific block's final state.
///
/// This will not fail if given BlockId::Latest.
/// Otherwise, this can fail (but may not) if the DB prunes state.
/// Otherwise, this can fail (but may not) if the DB prunes state or the block
/// is unknown.
pub fn state_at(&self, id: BlockId) -> Option<State> {
// fast path for latest state.
match id.clone() {

View File

@ -523,7 +523,8 @@ impl BlockChainClient for TestBlockChainClient {
match id {
BlockId::Number(number) if (number as usize) < self.blocks.read().len() => BlockStatus::InChain,
BlockId::Hash(ref hash) if self.blocks.read().get(hash).is_some() => BlockStatus::InChain,
_ => BlockStatus::Unknown
BlockId::Latest | BlockId::Pending | BlockId::Earliest => BlockStatus::InChain,
_ => BlockStatus::Unknown,
}
}

View File

@ -290,3 +290,11 @@ pub fn from_call_error(error: CallError) -> Error {
CallError::TransactionNotFound => internal("{}, this should not be the case with eth_call, most likely a bug.", CallError::TransactionNotFound),
}
}
pub fn unknown_block() -> Error {
Error {
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Unknown block number".into(),
data: None,
}
}

View File

@ -238,6 +238,15 @@ pub fn pending_logs<M>(miner: &M, best_block: EthBlockNumber, filter: &EthcoreFi
result
}
fn check_known<C>(client: &C, number: BlockNumber) -> Result<(), Error> where C: MiningBlockChainClient {
use ethcore::block_status::BlockStatus;
match client.block_status(number.into()) {
BlockStatus::InChain => Ok(()),
_ => Err(errors::unknown_block()),
}
}
const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6.
impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
@ -359,12 +368,17 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let address = address.into();
match num.0 {
BlockNumber::Pending => Ok(take_weak!(self.miner).balance(&*take_weak!(self.client), &address).into()),
id => match take_weak!(self.client).balance(&address, id.into()) {
id => {
let client = take_weak!(self.client);
check_known(&*client, id.clone())?;
match client.balance(&address, id.into()) {
Some(balance) => Ok(balance.into()),
None => Err(errors::state_pruned()),
}
}
}
}
fn storage_at(&self, address: RpcH160, pos: RpcU256, num: Trailing<BlockNumber>) -> Result<RpcH256, Error> {
try!(self.active());
@ -372,12 +386,17 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let position: U256 = RpcU256::into(pos);
match num.0 {
BlockNumber::Pending => Ok(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position)).into()),
id => match take_weak!(self.client).storage_at(&address, &H256::from(position), id.into()) {
id => {
let client = take_weak!(self.client);
check_known(&*client, id.clone())?;
match client.storage_at(&address, &H256::from(position), id.into()) {
Some(s) => Ok(s.into()),
None => Err(errors::state_pruned()),
}
}
}
}
fn transaction_count(&self, address: RpcH160, num: Trailing<BlockNumber>) -> Result<RpcU256, Error> {
try!(self.active());
@ -385,12 +404,17 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let address: Address = RpcH160::into(address);
match num.0 {
BlockNumber::Pending => Ok(take_weak!(self.miner).nonce(&*take_weak!(self.client), &address).into()),
id => match take_weak!(self.client).nonce(&address, id.into()) {
id => {
let client = take_weak!(self.client);
check_known(&*client, id.clone())?;
match client.nonce(&address, id.into()) {
Some(nonce) => Ok(nonce.into()),
None => Err(errors::state_pruned()),
}
}
}
}
fn block_transaction_count_by_hash(&self, hash: RpcH256) -> Result<Option<RpcU256>, Error> {
try!(self.active());
@ -441,10 +465,15 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let address: Address = RpcH160::into(address);
match num.0 {
BlockNumber::Pending => Ok(take_weak!(self.miner).code(&*take_weak!(self.client), &address).map_or_else(Bytes::default, Bytes::new)),
_ => match take_weak!(self.client).code(&address, num.0.into()) {
id => {
let client = take_weak!(self.client);
check_known(&*client, id.clone())?;
match client.code(&address, id.into()) {
Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
None => Err(errors::state_pruned()),
},
}
}
}
}