Moved sync::BestBlock to db::BestBlock (#65)

* * moved BestBlock to db package
* use u32 as block index in sync package

* fixed compilation after merge
This commit is contained in:
Svyatoslav Nikolsky 2016-10-31 16:58:48 +03:00 committed by Marek Kotewicz
parent f44d4d18a1
commit 4f9d68cd99
12 changed files with 126 additions and 136 deletions

10
db/src/best_block.rs Normal file
View File

@ -0,0 +1,10 @@
use primitives::hash::H256;
/// Best block information
#[derive(Debug, Clone)]
pub struct BestBlock {
/// Height/number of the best block (genesis block has zero height)
pub number: u32,
/// Hash of the best block
pub hash: H256,
}

View File

@ -14,6 +14,7 @@ extern crate ethcore_devtools as devtools;
#[cfg(test)]
extern crate test_data;
mod best_block;
mod kvdb;
mod storage;
#[cfg(feature="dev")]
@ -25,6 +26,7 @@ pub enum BlockRef {
Hash(primitives::hash::H256),
}
pub use best_block::BestBlock;
pub use storage::{Storage, Store, Error};
pub use kvdb::Database;

View File

@ -6,7 +6,7 @@ use kvdb::{DBTransaction, Database, DatabaseConfig};
use byteorder::{LittleEndian, ByteOrder};
use primitives::hash::H256;
use primitives::bytes::Bytes;
use super::BlockRef;
use super::{BlockRef, BestBlock};
use serialization;
use chain::{self, RepresentH256};
use parking_lot::RwLock;
@ -30,11 +30,8 @@ const DB_VERSION: u32 = 1;
/// Blockchain storage interface
pub trait Store : Send + Sync {
/// get best block number
fn best_block_number(&self) -> Option<u32>;
/// get best block hash
fn best_block_hash(&self) -> Option<H256>;
/// get best block
fn best_block(&self) -> Option<BestBlock>;
/// resolves hash by block number
fn block_hash(&self, number: u32) -> Option<H256>;
@ -69,12 +66,6 @@ pub trait Store : Send + Sync {
fn transaction_meta(&self, hash: &H256) -> Option<TransactionMeta>;
}
#[derive(Debug, Clone)]
pub struct BestBlock {
pub number: u32,
pub hash: H256,
}
/// Blockchain storage with rocksdb database
pub struct Storage {
database: Database,
@ -149,7 +140,9 @@ impl Storage {
let best_number = storage.read_meta_u32(KEY_BEST_BLOCK_NUMBER);
let best_hash = storage.get(COL_META, KEY_BEST_BLOCK_HASH).map(|val| H256::from(&**val));
if best_number.is_some() && best_hash.is_some() {
// both values should be stored
assert!(best_number.is_some() == best_hash.is_some());
if best_number.is_some() {
*storage.best_block.write() = Some(
BestBlock {
number: best_number.expect("is_some() is checked above for block number"),
@ -266,12 +259,8 @@ impl Storage {
}
impl Store for Storage {
fn best_block_number(&self) -> Option<u32> {
self.best_block.read().as_ref().map(|bb| bb.number)
}
fn best_block_hash(&self) -> Option<H256> {
self.best_block.read().as_ref().map(|h| h.hash.clone())
fn best_block(&self) -> Option<BestBlock> {
self.best_block.read().clone()
}
fn block_hash(&self, number: u32) -> Option<H256> {
@ -423,7 +412,7 @@ mod tests {
let block: Block = test_data::genesis();
store.insert_block(&block).unwrap();
assert_eq!(store.best_block_number(), Some(0));
assert_eq!(store.best_block().expect("genesis block inserted").number, 0);
assert_eq!(store.block_hash(0), Some(block.hash()));
}
@ -438,7 +427,7 @@ mod tests {
let block: Block = test_data::block_h1();
store.insert_block(&block).unwrap();
assert_eq!(store.best_block_number(), Some(1));
assert_eq!(store.best_block().expect("genesis block inserted").number, 1);
}
#[test]
@ -453,9 +442,9 @@ mod tests {
store.insert_block(&another_block).unwrap();
// did not update because `another_block` is not child of `block`
assert_eq!(store.best_block_hash(), Some(block.hash()));
assert_eq!(store.best_block().expect("blocks inserted above").hash, block.hash());
// number should not be update also
assert_eq!(store.best_block_number(), Some(0));
assert_eq!(store.best_block().expect("blocks inserted above").number, 0);
}
#[test]
@ -501,7 +490,7 @@ mod tests {
let genesis_meta = store.transaction_meta(&genesis_coinbase).unwrap();
assert!(genesis_meta.is_spent(0));
assert_eq!(store.best_block_number(), Some(1));
assert_eq!(store.best_block().expect("genesis block inserted").number, 1);
}
#[test]

View File

@ -1,6 +1,6 @@
//! Test storage
use super::{BlockRef, Store, Error};
use super::{BlockRef, Store, Error, BestBlock};
use chain::{self, Block, RepresentH256};
use primitives::hash::H256;
use serialization;
@ -18,9 +18,9 @@ pub struct TestStorage {
#[derive(Default)]
struct TestData {
best_block_number: Option<usize>,
best_block: Option<BestBlock>,
blocks: HashMap<H256, chain::Block>,
heights: HashMap<usize, H256>,
heights: HashMap<u32, H256>,
}
impl TestStorage {
@ -37,11 +37,14 @@ impl TestStorage {
{
let mut data = storage.data.write();
if blocks_len != 0 {
data.best_block_number = Some(blocks_len - 1);
data.best_block = Some(BestBlock {
number: blocks_len as u32 - 1,
hash: blocks[blocks_len - 1].hash(),
});
for (idx, block) in blocks.iter().enumerate() {
let hash = block.hash();
data.blocks.insert(hash.clone(), block.clone());
data.heights.insert(idx, hash);
data.heights.insert(idx as u32, hash);
}
}
}
@ -55,17 +58,13 @@ impl TestStorage {
}
impl Store for TestStorage {
fn best_block_number(&self) -> Option<u32> {
self.data.read().best_block_number.map(|b| b as u32)
}
fn best_block_hash(&self) -> Option<H256> {
unimplemented!()
fn best_block(&self) -> Option<BestBlock> {
self.data.read().best_block.clone()
}
fn block_hash(&self, number: u32) -> Option<H256> {
let data = self.data.read();
data.heights.get(&(number as usize)).cloned()
data.heights.get(&number).cloned()
}
fn block_header_bytes(&self, block_ref: BlockRef) -> Option<Bytes> {
@ -119,13 +118,19 @@ impl Store for TestStorage {
entry.insert(block.clone());
},
}
match data.best_block_number {
Some(best_block_number) => {
data.best_block_number = Some(best_block_number + 1);
match data.best_block {
Some(BestBlock { number: best_block_number, hash: _ }) => {
data.best_block = Some(BestBlock {
number: best_block_number + 1,
hash: hash.clone(),
});
data.heights.insert(best_block_number + 1, hash);
},
None => {
data.best_block_number = Some(0);
data.best_block = Some(BestBlock {
number: 0,
hash: hash.clone(),
});
data.heights.insert(0, hash);
},
}

View File

@ -47,7 +47,7 @@ fn open_db(use_disk_database: bool) -> Arc<db::Store> {
fn init_db(db: &Arc<db::Store>) {
// insert genesis block if db is empty
if db.best_block_number().is_none() {
if db.best_block().is_none() {
// TODO: move to config
let genesis_block: Block = "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into();
db.insert_block(&genesis_block)

View File

@ -1,7 +0,0 @@
use primitives::hash::H256;
#[derive(Debug, Clone)]
pub struct BestBlock {
pub height: u64,
pub hash: H256,
}

View File

@ -35,8 +35,8 @@ impl HashQueue {
}
/// Returns len of the given queue.
pub fn len(&self) -> usize {
self.queue.len()
pub fn len(&self) -> u32 {
self.queue.len() as u32
}
/// Returns true if queue is empty.
@ -93,7 +93,7 @@ impl HashQueue {
}
/// Removes n elements from the front of the queue.
pub fn pop_front_n(&mut self, n: usize) -> Vec<H256> {
pub fn pop_front_n(&mut self, n: u32) -> Vec<H256> {
let mut result: Vec<H256> = Vec::new();
for _ in 0..n {
match self.pop_front() {
@ -148,11 +148,11 @@ impl HashQueue {
}
}
impl Index<usize> for HashQueue {
impl Index<u32> for HashQueue {
type Output = H256;
fn index(&self, index: usize) -> &Self::Output {
&self.queue[index]
fn index(&self, index: u32) -> &Self::Output {
&self.queue[index as usize]
}
}
@ -166,29 +166,29 @@ impl HashQueueChain {
}
/// Returns length of the whole chain.
pub fn len(&self) -> usize {
pub fn len(&self) -> u32 {
self.chain.iter().fold(0, |total, chain| total + chain.len())
}
/// Returns length of the given queue.
pub fn len_of(&self, chain_index: usize) -> usize {
self.chain[chain_index].len()
pub fn len_of(&self, queue_index: usize) -> u32 {
self.chain[queue_index].len()
}
/// Returns true if given queue is empty.
pub fn is_empty_at(&self, chain_index: usize) -> bool {
self.chain[chain_index].is_empty()
pub fn is_empty_at(&self, queue_index: usize) -> bool {
self.chain[queue_index].is_empty()
}
/// Returns element at the front of the given queue.
pub fn front_at(&self, chain_index: usize) -> Option<H256> {
let ref queue = self.chain[chain_index];
pub fn front_at(&self, queue_index: usize) -> Option<H256> {
let ref queue = self.chain[queue_index];
queue.front()
}
/// Returns element at the back of the given queue.
pub fn back_at(&self, chain_index: usize) -> Option<H256> {
let ref queue = self.chain[chain_index];
/// Returns element at the front of the given queue.
pub fn back_at(&self, queue_index: usize) -> Option<H256> {
let ref queue = self.chain[queue_index];
queue.back()
}
@ -238,7 +238,7 @@ impl HashQueueChain {
}
/// Remove a number of hashes from the front of the given queue.
pub fn pop_front_n_at(&mut self, queue_index: usize, n: usize) -> Vec<H256> {
pub fn pop_front_n_at(&mut self, queue_index: usize, n: u32) -> Vec<H256> {
self.chain[queue_index].pop_front_n(n)
}
@ -263,10 +263,10 @@ impl HashQueueChain {
}
}
impl Index<usize> for HashQueueChain {
impl Index<u32> for HashQueueChain {
type Output = H256;
fn index<'a>(&'a self, mut index: usize) -> &'a Self::Output {
fn index<'a>(&'a self, mut index: u32) -> &'a Self::Output {
for queue in self.chain.iter() {
let queue_len = queue.len();
if index < queue_len {

View File

@ -18,7 +18,7 @@ impl InboundConnectionFactory {
impl LocalSyncNode for InboundConnectionFactory {
fn start_height(&self) -> i32 {
self.local_node.best_block().height as i32
self.local_node.best_block().number as i32
}
fn create_sync_session(&self, best_block_height: i32, outbound_connection: OutboundSyncConnectionRef) -> InboundSyncConnectionRef {

View File

@ -9,7 +9,6 @@ extern crate primitives;
extern crate time;
extern crate verification;
mod best_block;
mod hash_queue;
mod inbound_connection;
pub mod inbound_connection_factory;

View File

@ -10,7 +10,6 @@ use message::types;
use synchronization::{Synchronization, SynchronizationRef, Config as SynchronizationConfig, Task as SynchronizationTask, TaskExecutor as SynchronizationTaskExecutor};
use synchronization_chain::{Chain, ChainRef};
use synchronization_executor::LocalSynchronizationTaskExecutor;
use best_block::BestBlock;
/// Thread-safe reference to the `LocalNode`.
/// Locks order:
@ -46,7 +45,7 @@ impl LocalNode {
}
/// Best block hash (including non-verified, requested && non-requested blocks)
pub fn best_block(&self) -> BestBlock {
pub fn best_block(&self) -> db::BestBlock {
self.chain.read().best_block()
}

View File

@ -67,15 +67,15 @@ use time;
///! TODO: check + optimize algorithm for Saturated state
/// Approximate maximal number of blocks hashes in scheduled queue.
const MAX_SCHEDULED_HASHES: u64 = 4 * 1024;
const MAX_SCHEDULED_HASHES: u32 = 4 * 1024;
/// Approximate maximal number of blocks hashes in requested queue.
const MAX_REQUESTED_BLOCKS: u64 = 512;
const MAX_REQUESTED_BLOCKS: u32 = 512;
/// Approximate maximal number of blocks in verifying queue.
const MAX_VERIFYING_BLOCKS: u64 = 512;
const MAX_VERIFYING_BLOCKS: u32 = 512;
/// Minimum number of blocks to request from peer
const MIN_BLOCKS_IN_REQUEST: u64 = 32;
const MIN_BLOCKS_IN_REQUEST: u32 = 32;
/// Maximum number of blocks to request from peer
const MAX_BLOCKS_IN_REQUEST: u64 = 512;
const MAX_BLOCKS_IN_REQUEST: u32 = 512;
/// Thread-safe reference to the `Synchronization`
pub type SynchronizationRef<T> = Arc<Mutex<Synchronization<T>>>;
@ -93,7 +93,7 @@ pub enum Task {
#[derive(Debug, Clone, Copy)]
pub enum State {
Synchronizing(f64, u64),
Synchronizing(f64, u32),
Saturated,
}
@ -237,7 +237,7 @@ impl<T> Synchronization<T> where T: TaskExecutor + Send + 'static {
// TODO: reset verification queue
let mut chain = self.chain.write();
self.state = State::Synchronizing(time::precise_time_s(), chain.best_block().height);
self.state = State::Synchronizing(time::precise_time_s(), chain.best_block().number);
chain.remove_blocks_with_state(BlockState::Requested);
chain.remove_blocks_with_state(BlockState::Scheduled);
chain.remove_blocks_with_state(BlockState::Verifying);
@ -263,7 +263,7 @@ impl<T> Synchronization<T> where T: TaskExecutor + Send + 'static {
// new block is scheduled => move to synchronizing state
if !self.state.is_synchronizing() {
self.state = State::Synchronizing(time::precise_time_s(), chain.best_block().height);
self.state = State::Synchronizing(time::precise_time_s(), chain.best_block().number);
}
// when synchronization is idling
@ -378,7 +378,7 @@ impl<T> Synchronization<T> where T: TaskExecutor + Send + 'static {
fn execute_synchronization_tasks(&mut self) {
let mut tasks: Vec<Task> = Vec::new();
let idle_peers = self.peers.idle_peers();
let idle_peers_len = idle_peers.len() as u64;
let idle_peers_len = idle_peers.len() as u32;
// prepare synchronization tasks
if idle_peers_len != 0 {
@ -387,7 +387,7 @@ impl<T> Synchronization<T> where T: TaskExecutor + Send + 'static {
if let State::Synchronizing(timestamp, num_of_blocks) = self.state {
let new_timestamp = time::precise_time_s();
let timestamp_diff = new_timestamp - timestamp;
let new_num_of_blocks = chain.best_block().height;
let new_num_of_blocks = chain.best_block().number;
let blocks_diff = if new_num_of_blocks > num_of_blocks { new_num_of_blocks - num_of_blocks} else { 0 };
if timestamp_diff >= 60.0 || blocks_diff > 1000 {
self.state = State::Synchronizing(new_timestamp, new_num_of_blocks);

View File

@ -4,7 +4,6 @@ use parking_lot::RwLock;
use chain::{Block, RepresentH256};
use db;
use primitives::hash::H256;
use best_block::BestBlock;
use hash_queue::{HashQueueChain, HashPosition};
/// Thread-safe reference to `Chain`
@ -38,13 +37,13 @@ pub enum BlockState {
#[derive(Debug)]
pub struct Information {
/// Number of blocks currently scheduled for requesting
pub scheduled: u64,
pub scheduled: u32,
/// Number of blocks currently requested from peers
pub requested: u64,
pub requested: u32,
/// Number of blocks currently verifying
pub verifying: u64,
pub verifying: u32,
/// Number of blocks in the storage
pub stored: u64,
pub stored: u32,
}
/// Blockchain from synchroniation point of view, consisting of:
@ -89,14 +88,12 @@ impl Chain {
// we only work with storages with genesis block
let genesis_block_hash = storage.block_hash(0)
.expect("storage with genesis block is required");
let best_storage_block_number = storage.best_block_number()
let best_storage_block = storage.best_block()
.expect("non-empty storage is required");
let best_storage_block_hash = storage.block_hash(best_storage_block_number)
.expect("checked above");
Chain {
genesis_block_hash: genesis_block_hash,
best_storage_block_hash: best_storage_block_hash,
best_storage_block_hash: best_storage_block.hash,
storage: storage,
hash_chain: HashQueueChain::with_number_of_queues(NUMBER_OF_QUEUES),
}
@ -105,10 +102,10 @@ impl Chain {
/// Get information on current blockchain state
pub fn information(&self) -> Information {
Information {
scheduled: self.hash_chain.len_of(SCHEDULED_QUEUE) as u64,
requested: self.hash_chain.len_of(REQUESTED_QUEUE) as u64,
verifying: self.hash_chain.len_of(VERIFYING_QUEUE) as u64,
stored: self.storage.best_block_number().map_or(0, |number| number as u64 + 1),
scheduled: self.hash_chain.len_of(SCHEDULED_QUEUE),
requested: self.hash_chain.len_of(REQUESTED_QUEUE),
verifying: self.hash_chain.len_of(VERIFYING_QUEUE),
stored: self.storage.best_block().map_or(0, |block| block.number + 1),
}
}
@ -118,8 +115,8 @@ impl Chain {
}
/// Get number of blocks in given state
pub fn length_of_state(&self, state: BlockState) -> u64 {
self.hash_chain.len_of(state.to_queue_index()) as u64
pub fn length_of_state(&self, state: BlockState) -> u32 {
self.hash_chain.len_of(state.to_queue_index())
}
/// Returns true if has blocks of given type
@ -128,50 +125,46 @@ impl Chain {
}
/// Get best block
pub fn best_block(&self) -> BestBlock {
let storage_best_block_number = self.storage.best_block_number().expect("storage with genesis block is required");
pub fn best_block(&self) -> db::BestBlock {
let storage_best_block = self.storage.best_block().expect("storage with genesis block is required");
match self.hash_chain.back() {
Some(hash) => BestBlock {
height: storage_best_block_number as u64 + self.hash_chain.len() as u64,
Some(hash) => db::BestBlock {
number: storage_best_block.number + self.hash_chain.len(),
hash: hash.clone(),
},
None => BestBlock {
height: storage_best_block_number as u64,
hash: self.storage.block_hash(storage_best_block_number).expect("storage with genesis block is required"),
None => db::BestBlock {
number: storage_best_block.number,
hash: storage_best_block.hash,
}
}
}
/// Get best block of given state
pub fn best_block_of_state(&self, state: BlockState) -> Option<BestBlock> {
pub fn best_block_of_state(&self, state: BlockState) -> Option<db::BestBlock> {
match state {
BlockState::Scheduled => self.hash_chain.back_at(SCHEDULED_QUEUE)
.map(|hash| BestBlock {
.map(|hash| db::BestBlock {
hash: hash,
height: self.storage.best_block_number().expect("storage with genesis block is required") as u64 + 1
+ self.hash_chain.len_of(VERIFYING_QUEUE) as u64
+ self.hash_chain.len_of(REQUESTED_QUEUE) as u64
+ self.hash_chain.len_of(SCHEDULED_QUEUE) as u64
number: self.storage.best_block().expect("storage with genesis block is required").number + 1
+ self.hash_chain.len_of(VERIFYING_QUEUE)
+ self.hash_chain.len_of(REQUESTED_QUEUE)
+ self.hash_chain.len_of(SCHEDULED_QUEUE)
}),
BlockState::Requested => self.hash_chain.back_at(REQUESTED_QUEUE)
.map(|hash| BestBlock {
.map(|hash| db::BestBlock {
hash: hash,
height: self.storage.best_block_number().expect("storage with genesis block is required") as u64 + 1
+ self.hash_chain.len_of(VERIFYING_QUEUE) as u64
+ self.hash_chain.len_of(REQUESTED_QUEUE) as u64
number: self.storage.best_block().expect("storage with genesis block is required").number + 1
+ self.hash_chain.len_of(VERIFYING_QUEUE)
+ self.hash_chain.len_of(REQUESTED_QUEUE)
}),
BlockState::Verifying => self.hash_chain.back_at(VERIFYING_QUEUE)
.map(|hash| BestBlock {
.map(|hash| db::BestBlock {
hash: hash,
height: self.storage.best_block_number().expect("storage with genesis block is required") as u64 + 1
+ self.hash_chain.len_of(VERIFYING_QUEUE) as u64
number: self.storage.best_block().expect("storage with genesis block is required").number + 1
+ self.hash_chain.len_of(VERIFYING_QUEUE)
}),
BlockState::Stored => {
let storage_best_block_number = self.storage.best_block_number().expect("storage with genesis block is required");
Some(BestBlock {
height: storage_best_block_number as u64,
hash: self.storage.block_hash(storage_best_block_number).expect("storage with genesis block is required"),
})
self.storage.best_block()
},
_ => panic!("not supported"),
}
@ -225,9 +218,9 @@ impl Chain {
let (local_index, step) = self.block_locator_hashes_for_queue(&mut block_locator_hashes);
// calculate for storage
let storage_best_block_number = self.storage.best_block_number().expect("storage with genesis block is required");
let storage_index = if (storage_best_block_number as u64) < local_index { 0 } else { (storage_best_block_number as u64) - local_index };
self.block_locator_hashes_for_storage(storage_index as u64, step, &mut block_locator_hashes);
let storage_best_block_number = self.storage.best_block().expect("storage with genesis block is required").number;
let storage_index = if storage_best_block_number < local_index { 0 } else { storage_best_block_number - local_index };
self.block_locator_hashes_for_storage(storage_index, step, &mut block_locator_hashes);
block_locator_hashes
}
@ -237,8 +230,8 @@ impl Chain {
}
/// Moves n blocks from scheduled queue to requested queue
pub fn request_blocks_hashes(&mut self, n: u64) -> Vec<H256> {
let scheduled = self.hash_chain.pop_front_n_at(SCHEDULED_QUEUE, n as usize);
pub fn request_blocks_hashes(&mut self, n: u32) -> Vec<H256> {
let scheduled = self.hash_chain.pop_front_n_at(SCHEDULED_QUEUE, n);
self.hash_chain.push_back_n_at(REQUESTED_QUEUE, scheduled.clone());
scheduled
}
@ -250,8 +243,8 @@ impl Chain {
/// Moves n blocks from requested queue to verifying queue
#[cfg(test)]
pub fn verify_blocks_hashes(&mut self, n: u64) -> Vec<H256> {
let requested = self.hash_chain.pop_front_n_at(REQUESTED_QUEUE, n as usize);
pub fn verify_blocks_hashes(&mut self, n: u32) -> Vec<H256> {
let requested = self.hash_chain.pop_front_n_at(REQUESTED_QUEUE, n);
self.hash_chain.push_back_n_at(VERIFYING_QUEUE, requested.clone());
requested
}
@ -280,16 +273,16 @@ impl Chain {
}
/// Calculate block locator hashes for hash queue
fn block_locator_hashes_for_queue(&self, hashes: &mut Vec<H256>) -> (u64, u64) {
let queue_len = self.hash_chain.len() as u64;
fn block_locator_hashes_for_queue(&self, hashes: &mut Vec<H256>) -> (u32, u32) {
let queue_len = self.hash_chain.len();
if queue_len == 0 {
return (0, 1);
}
let mut index = queue_len - 1;
let mut step = 1u64;
let mut step = 1u32;
loop {
let block_hash = self.hash_chain[index as usize].clone();
let block_hash = self.hash_chain[index].clone();
hashes.push(block_hash);
if hashes.len() >= 10 {
@ -303,9 +296,9 @@ impl Chain {
}
/// Calculate block locator hashes for storage
fn block_locator_hashes_for_storage(&self, mut index: u64, mut step: u64, hashes: &mut Vec<H256>) {
fn block_locator_hashes_for_storage(&self, mut index: u32, mut step: u32, hashes: &mut Vec<H256>) {
loop {
let block_hash = self.storage.block_hash(index as u32)
let block_hash = self.storage.block_hash(index)
.expect("private function; index calculated in `block_locator_hashes`; qed");
hashes.push(block_hash);
@ -329,9 +322,9 @@ impl fmt::Debug for Chain {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "chain: ["));
{
let mut num = self.storage.best_block_number().unwrap() as usize;
let mut num = self.storage.best_block().expect("Storage with genesis block is required").number;
try!(writeln!(f, "\tworse(stored): {} {:?}", 0, self.storage.block_hash(0)));
try!(writeln!(f, "\tbest(stored): {} {:?}", num, self.storage.block_hash(num as u32)));
try!(writeln!(f, "\tbest(stored): {} {:?}", num, self.storage.block_hash(num)));
let queues = vec![
("verifying", VERIFYING_QUEUE),