few client methods use BlockId instead of hash and BlockNumber

This commit is contained in:
debris 2016-02-10 19:29:27 +01:00
parent 2c360d6c9b
commit db35e21bcd
4 changed files with 81 additions and 113 deletions

View File

@ -23,24 +23,6 @@ use extras::*;
use transaction::*; use transaction::*;
use views::*; use views::*;
/// Uniquely identifies block.
pub enum BlockId {
/// Block's sha3.
/// Querying by hash is always faster.
Hash(H256),
/// Block number within canon blockchain.
Number(BlockNumber)
}
/// Uniquely identifies transaction.
pub enum TransactionId {
/// Transaction's sha3.
Hash(H256),
/// Block id and transaction index within this block.
/// Querying by block position is always faster.
Location(BlockId, usize)
}
/// Represents a tree route between `from` block and `to` block: /// Represents a tree route between `from` block and `to` block:
pub struct TreeRoute { pub struct TreeRoute {
/// A vector of hashes of all blocks, ordered from `from` to `to`. /// A vector of hashes of all blocks, ordered from `from` to `to`.
@ -129,18 +111,8 @@ pub trait BlockProvider {
} }
/// Get transaction with given transaction hash. /// Get transaction with given transaction hash.
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> { fn transaction(&self, address: &TransactionAddress) -> Option<LocalizedTransaction> {
match id { self.block(&address.block_hash).and_then(|bytes| BlockView::new(&bytes).localized_transaction_at(address.index))
TransactionId::Hash(ref hash) => self.transaction_address(hash),
TransactionId::Location(BlockId::Hash(hash), index) => Some(TransactionAddress {
block_hash: hash,
index: index
}),
TransactionId::Location(BlockId::Number(number), index) => self.block_hash(number).map(|hash| TransactionAddress {
block_hash: hash,
index: index
})
}.and_then(|address| self.block(&address.block_hash).and_then(|bytes| BlockView::new(&bytes).localized_transaction_at(address.index)))
} }
/// Get a list of transactions for a given block. /// Get a list of transactions for a given block.

View File

@ -18,7 +18,7 @@
use util::*; use util::*;
use rocksdb::{Options, DB, DBCompactionStyle}; use rocksdb::{Options, DB, DBCompactionStyle};
use blockchain::{BlockChain, BlockProvider, CacheSize, TransactionId}; use blockchain::{BlockChain, BlockProvider, CacheSize};
use views::BlockView; use views::BlockView;
use error::*; use error::*;
use header::BlockNumber; use header::BlockNumber;
@ -32,8 +32,27 @@ use env_info::LastHashes;
use verification::*; use verification::*;
use block::*; use block::*;
use transaction::LocalizedTransaction; use transaction::LocalizedTransaction;
use extras::TransactionAddress;
pub use blockchain::TreeRoute; pub use blockchain::TreeRoute;
/// Uniquely identifies block.
pub enum BlockId {
/// Block's sha3.
/// Querying by hash is always faster.
Hash(H256),
/// Block number within canon blockchain.
Number(BlockNumber)
}
/// Uniquely identifies transaction.
pub enum TransactionId {
/// Transaction's sha3.
Hash(H256),
/// Block id and transaction index within this block.
/// Querying by block position is always faster.
Location(BlockId, usize)
}
/// General block status /// General block status
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum BlockStatus { pub enum BlockStatus {
@ -70,41 +89,25 @@ impl fmt::Display for BlockChainInfo {
/// Blockchain database client. Owns and manages a blockchain and a block queue. /// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send { pub trait BlockChainClient : Sync + Send {
/// Get raw block header data by block header hash. /// Get raw block header data by block id.
fn block_header(&self, hash: &H256) -> Option<Bytes>; fn block_header(&self, id: BlockId) -> Option<Bytes>;
/// Get raw block body data by block header hash. /// Get raw block body data by block id.
/// Block body is an RLP list of two items: uncles and transactions. /// Block body is an RLP list of two items: uncles and transactions.
fn block_body(&self, hash: &H256) -> Option<Bytes>; fn block_body(&self, id: BlockId) -> Option<Bytes>;
/// Get raw block data by block header hash. /// Get raw block data by block header hash.
fn block(&self, hash: &H256) -> Option<Bytes>; fn block(&self, id: BlockId) -> Option<Bytes>;
/// Get block status by block header hash. /// Get block status by block header hash.
fn block_status(&self, hash: &H256) -> BlockStatus; fn block_status(&self, id: BlockId) -> BlockStatus;
/// Get block total difficulty. /// Get block total difficulty.
fn block_total_difficulty(&self, hash: &H256) -> Option<U256>; fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
/// Get address code. /// Get address code.
fn code(&self, address: &Address) -> Option<Bytes>; fn code(&self, address: &Address) -> Option<Bytes>;
/// Get raw block header data by block number.
fn block_header_at(&self, n: BlockNumber) -> Option<Bytes>;
/// Get raw block body data by block number.
/// Block body is an RLP list of two items: uncles and transactions.
fn block_body_at(&self, n: BlockNumber) -> Option<Bytes>;
/// Get raw block data by block number.
fn block_at(&self, n: BlockNumber) -> Option<Bytes>;
/// Get block status by block number.
fn block_status_at(&self, n: BlockNumber) -> BlockStatus;
/// Get block total difficulty.
fn block_total_difficulty_at(&self, n: BlockNumber) -> Option<U256>;
/// Get transaction with given hash. /// Get transaction with given hash.
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>; fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>;
@ -132,7 +135,7 @@ pub trait BlockChainClient : Sync + Send {
/// Get the best block header. /// Get the best block header.
fn best_block_header(&self) -> Bytes { fn best_block_header(&self) -> Bytes {
self.block_header(&self.chain_info().best_block_hash).unwrap() self.block_header(BlockId::Hash(self.chain_info().best_block_hash)).unwrap()
} }
} }
@ -332,68 +335,62 @@ impl Client {
pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) { pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) {
self.chain.write().unwrap().configure_cache(pref_cache_size, max_cache_size); self.chain.write().unwrap().configure_cache(pref_cache_size, max_cache_size);
} }
fn block_hash(&self, id: BlockId) -> Option<H256> {
match id {
BlockId::Hash(hash) => Some(hash),
BlockId::Number(number) => self.chain.read().unwrap().block_hash(number)
}
}
} }
impl BlockChainClient for Client { impl BlockChainClient for Client {
fn block_header(&self, hash: &H256) -> Option<Bytes> { fn block_header(&self, id: BlockId) -> Option<Bytes> {
self.chain.read().unwrap().block(hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec()) self.block_hash(id).and_then(|hash| self.chain.read().unwrap().block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec()))
} }
fn block_body(&self, hash: &H256) -> Option<Bytes> { fn block_body(&self, id: BlockId) -> Option<Bytes> {
self.chain.read().unwrap().block(hash).map(|bytes| { self.block_hash(id).and_then(|hash| {
self.chain.read().unwrap().block(&hash).map(|bytes| {
let rlp = Rlp::new(&bytes); let rlp = Rlp::new(&bytes);
let mut body = RlpStream::new(); let mut body = RlpStream::new();
body.append_raw(rlp.at(1).as_raw(), 1); body.append_raw(rlp.at(1).as_raw(), 1);
body.append_raw(rlp.at(2).as_raw(), 1); body.append_raw(rlp.at(2).as_raw(), 1);
body.out() body.out()
}) })
})
} }
fn block(&self, hash: &H256) -> Option<Bytes> { fn block(&self, id: BlockId) -> Option<Bytes> {
self.chain.read().unwrap().block(hash) self.block_hash(id).and_then(|hash| {
self.chain.read().unwrap().block(&hash)
})
} }
fn block_status(&self, hash: &H256) -> BlockStatus { fn block_status(&self, id: BlockId) -> BlockStatus {
if self.chain.read().unwrap().is_known(&hash) { match self.block_hash(id) {
BlockStatus::InChain Some(ref hash) if self.chain.read().unwrap().is_known(hash) => BlockStatus::InChain,
} else { Some(hash) => self.block_queue.read().unwrap().block_status(&hash),
self.block_queue.read().unwrap().block_status(hash) None => BlockStatus::Unknown
} }
} }
fn block_total_difficulty(&self, hash: &H256) -> Option<U256> { fn block_total_difficulty(&self, id: BlockId) -> Option<U256> {
self.chain.read().unwrap().block_details(hash).map(|d| d.total_difficulty) self.block_hash(id).and_then(|hash| self.chain.read().unwrap().block_details(&hash)).map(|d| d.total_difficulty)
} }
fn code(&self, address: &Address) -> Option<Bytes> { fn code(&self, address: &Address) -> Option<Bytes> {
self.state().code(address) self.state().code(address)
} }
fn block_header_at(&self, n: BlockNumber) -> Option<Bytes> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_header(&h))
}
fn block_body_at(&self, n: BlockNumber) -> Option<Bytes> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_body(&h))
}
fn block_at(&self, n: BlockNumber) -> Option<Bytes> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block(&h))
}
fn block_status_at(&self, n: BlockNumber) -> BlockStatus {
match self.chain.read().unwrap().block_hash(n) {
Some(h) => self.block_status(&h),
None => BlockStatus::Unknown
}
}
fn block_total_difficulty_at(&self, n: BlockNumber) -> Option<U256> {
self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_total_difficulty(&h))
}
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> { fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction> {
self.chain.read().unwrap().transaction(id) match id {
TransactionId::Hash(ref hash) => self.chain.read().unwrap().transaction_address(hash),
TransactionId::Location(id, index) => self.block_hash(id).map(|hash| TransactionAddress {
block_hash: hash,
index: index
})
}.and_then(|address| self.chain.read().unwrap().transaction(&address))
} }
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> { fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
@ -413,7 +410,7 @@ impl BlockChainClient for Client {
if self.chain.read().unwrap().is_known(&header.hash()) { if self.chain.read().unwrap().is_known(&header.hash()) {
return Err(ImportError::AlreadyInChain); return Err(ImportError::AlreadyInChain);
} }
if self.block_status(&header.parent_hash) == BlockStatus::Unknown { if self.block_status(BlockId::Hash(header.parent_hash)) == BlockStatus::Unknown {
return Err(ImportError::UnknownParent); return Err(ImportError::UnknownParent);
} }
self.block_queue.write().unwrap().import_block(bytes) self.block_queue.write().unwrap().import_block(bytes)

View File

@ -23,7 +23,6 @@ use util::uint::*;
use util::sha3::*; use util::sha3::*;
use ethcore::client::*; use ethcore::client::*;
use ethcore::views::*; use ethcore::views::*;
use ethcore::blockchain::{BlockId, TransactionId};
use ethcore::ethereum::denominations::shannon; use ethcore::ethereum::denominations::shannon;
use v1::traits::{Eth, EthFilter}; use v1::traits::{Eth, EthFilter};
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index}; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index};
@ -110,7 +109,7 @@ impl Eth for EthClient {
fn block_transaction_count(&self, params: Params) -> Result<Value, Error> { fn block_transaction_count(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256,)>(params) from_params::<(H256,)>(params)
.and_then(|(hash,)| match self.client.block(&hash) { .and_then(|(hash,)| match self.client.block(BlockId::Hash(hash)) {
Some(bytes) => to_value(&BlockView::new(&bytes).transactions_count()), Some(bytes) => to_value(&BlockView::new(&bytes).transactions_count()),
None => Ok(Value::Null) None => Ok(Value::Null)
}) })
@ -118,7 +117,7 @@ impl Eth for EthClient {
fn block_uncles_count(&self, params: Params) -> Result<Value, Error> { fn block_uncles_count(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256,)>(params) from_params::<(H256,)>(params)
.and_then(|(hash,)| match self.client.block(&hash) { .and_then(|(hash,)| match self.client.block(BlockId::Hash(hash)) {
Some(bytes) => to_value(&BlockView::new(&bytes).uncles_count()), Some(bytes) => to_value(&BlockView::new(&bytes).uncles_count()),
None => Ok(Value::Null) None => Ok(Value::Null)
}) })
@ -132,7 +131,7 @@ impl Eth for EthClient {
fn block(&self, params: Params) -> Result<Value, Error> { fn block(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256, bool)>(params) from_params::<(H256, bool)>(params)
.and_then(|(hash, include_txs)| match (self.client.block(&hash), self.client.block_total_difficulty(&hash)) { .and_then(|(hash, include_txs)| match (self.client.block(BlockId::Hash(hash.clone())), self.client.block_total_difficulty(BlockId::Hash(hash))) {
(Some(bytes), Some(total_difficulty)) => { (Some(bytes), Some(total_difficulty)) => {
let block_view = BlockView::new(&bytes); let block_view = BlockView::new(&bytes);
let view = block_view.header_view(); let view = block_view.header_view();

View File

@ -33,7 +33,7 @@ use util::*;
use std::mem::{replace}; use std::mem::{replace};
use ethcore::views::{HeaderView}; use ethcore::views::{HeaderView};
use ethcore::header::{BlockNumber, Header as BlockHeader}; use ethcore::header::{BlockNumber, Header as BlockHeader};
use ethcore::client::{BlockChainClient, BlockStatus}; use ethcore::client::{BlockChainClient, BlockStatus, BlockId};
use range_collection::{RangeCollection, ToUsize, FromUsize}; use range_collection::{RangeCollection, ToUsize, FromUsize};
use ethcore::error::*; use ethcore::error::*;
use ethcore::block::Block; use ethcore::block::Block;
@ -331,7 +331,7 @@ impl ChainSync {
self.highest_block = Some(number); self.highest_block = Some(number);
} }
let hash = info.hash(); let hash = info.hash();
match io.chain().block_status(&hash) { match io.chain().block_status(BlockId::Hash(hash.clone())) {
BlockStatus::InChain => { BlockStatus::InChain => {
self.have_common_block = true; self.have_common_block = true;
self.last_imported_block = Some(number); self.last_imported_block = Some(number);
@ -491,7 +491,7 @@ impl ChainSync {
for (rh, rd) in hashes { for (rh, rd) in hashes {
let h = try!(rh); let h = try!(rh);
let d = try!(rd); let d = try!(rd);
match io.chain().block_status(&h) { match io.chain().block_status(BlockId::Hash(h.clone())) {
BlockStatus::InChain => { BlockStatus::InChain => {
trace!(target: "sync", "New block hash already in chain {:?}", h); trace!(target: "sync", "New block hash already in chain {:?}", h);
}, },
@ -877,7 +877,7 @@ impl ChainSync {
// id is a hash // id is a hash
let hash: H256 = try!(r.val_at(0)); let hash: H256 = try!(r.val_at(0));
trace!(target: "sync", "-> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", hash, max_headers, skip, reverse); trace!(target: "sync", "-> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", hash, max_headers, skip, reverse);
match io.chain().block_header(&hash) { match io.chain().block_header(BlockId::Hash(hash)) {
Some(hdr) => From::from(HeaderView::new(&hdr).number()), Some(hdr) => From::from(HeaderView::new(&hdr).number()),
None => last None => last
} }
@ -897,7 +897,7 @@ impl ChainSync {
let mut data = Bytes::new(); let mut data = Bytes::new();
let inc = (skip + 1) as BlockNumber; let inc = (skip + 1) as BlockNumber;
while number <= last && number > 0 && count < max_count { while number <= last && number > 0 && count < max_count {
if let Some(mut hdr) = io.chain().block_header_at(number) { if let Some(mut hdr) = io.chain().block_header(BlockId::Number(number)) {
data.append(&mut hdr); data.append(&mut hdr);
count += 1; count += 1;
} }
@ -929,7 +929,7 @@ impl ChainSync {
let mut added = 0usize; let mut added = 0usize;
let mut data = Bytes::new(); let mut data = Bytes::new();
for i in 0..count { for i in 0..count {
if let Some(mut hdr) = io.chain().block_body(&try!(r.val_at::<H256>(i))) { if let Some(mut hdr) = io.chain().block_body(BlockId::Hash(try!(r.val_at::<H256>(i)))) {
data.append(&mut hdr); data.append(&mut hdr);
added += 1; added += 1;
} }
@ -1060,7 +1060,7 @@ impl ChainSync {
let mut rlp_stream = RlpStream::new_list(route.blocks.len()); let mut rlp_stream = RlpStream::new_list(route.blocks.len());
for block_hash in route.blocks { for block_hash in route.blocks {
let mut hash_rlp = RlpStream::new_list(2); let mut hash_rlp = RlpStream::new_list(2);
let difficulty = chain.block_total_difficulty(&block_hash).expect("Mallformed block without a difficulty on the chain!"); let difficulty = chain.block_total_difficulty(BlockId::Hash(block_hash.clone())).expect("Mallformed block without a difficulty on the chain!");
hash_rlp.append(&block_hash); hash_rlp.append(&block_hash);
hash_rlp.append(&difficulty); hash_rlp.append(&difficulty);
rlp_stream.append_raw(&hash_rlp.out(), 1); rlp_stream.append_raw(&hash_rlp.out(), 1);
@ -1076,7 +1076,7 @@ impl ChainSync {
/// creates latest block rlp for the given client /// creates latest block rlp for the given client
fn create_latest_block_rlp(chain: &BlockChainClient) -> Bytes { fn create_latest_block_rlp(chain: &BlockChainClient) -> Bytes {
let mut rlp_stream = RlpStream::new_list(2); let mut rlp_stream = RlpStream::new_list(2);
rlp_stream.append_raw(&chain.block(&chain.chain_info().best_block_hash).expect("Creating latest block when there is none"), 1); rlp_stream.append_raw(&chain.block(BlockId::Hash(chain.chain_info().best_block_hash)).expect("Creating latest block when there is none"), 1);
rlp_stream.append(&chain.chain_info().total_difficulty); rlp_stream.append(&chain.chain_info().total_difficulty);
rlp_stream.out() rlp_stream.out()
} }
@ -1088,10 +1088,10 @@ impl ChainSync {
let latest_hash = chain_info.best_block_hash; let latest_hash = chain_info.best_block_hash;
let latest_number = chain_info.best_block_number; let latest_number = chain_info.best_block_number;
self.peers.iter().filter(|&(_, peer_info)| self.peers.iter().filter(|&(_, peer_info)|
match io.chain().block_status(&peer_info.latest) match io.chain().block_status(BlockId::Hash(peer_info.latest.clone()))
{ {
BlockStatus::InChain => { BlockStatus::InChain => {
let peer_number = HeaderView::new(&io.chain().block_header(&peer_info.latest).unwrap()).number(); let peer_number = HeaderView::new(&io.chain().block_header(BlockId::Hash(peer_info.latest.clone())).unwrap()).number();
peer_info.latest != latest_hash && latest_number > peer_number && latest_number - peer_number < MAX_PEER_LAG_PROPAGATION peer_info.latest != latest_hash && latest_number > peer_number && latest_number - peer_number < MAX_PEER_LAG_PROPAGATION
}, },
_ => false _ => false