fixed sync tests
This commit is contained in:
parent
98803d6afe
commit
964d013042
|
@ -40,10 +40,6 @@ impl HashQueue {
|
|||
self.queue.is_empty()
|
||||
}
|
||||
|
||||
pub fn front<'a>(&'a self) -> Option<&'a H256> {
|
||||
self.queue.front()
|
||||
}
|
||||
|
||||
pub fn back<'a>(&'a self) -> Option<&'a H256> {
|
||||
self.queue.back()
|
||||
}
|
||||
|
@ -52,10 +48,6 @@ impl HashQueue {
|
|||
self.set.contains(hash)
|
||||
}
|
||||
|
||||
pub fn queue<'a>(&'a self) -> &'a VecDeque<H256> {
|
||||
&self.queue
|
||||
}
|
||||
|
||||
pub fn pop_front(&mut self) -> Option<H256> {
|
||||
match self.queue.pop_front() {
|
||||
Some(hash) => {
|
||||
|
@ -140,17 +132,20 @@ impl HashQueueChain {
|
|||
self.chain[chain_index].is_empty()
|
||||
}
|
||||
|
||||
pub fn front<'a>(&'a self) -> Option<&'a H256> {
|
||||
self.chain[0].front()
|
||||
}
|
||||
pub fn back(&self) -> Option<H256> {
|
||||
let mut queue_index = self.chain.len() - 1;
|
||||
loop {
|
||||
let ref queue = self.chain[queue_index];
|
||||
let queue_back = queue.back();
|
||||
if queue_back.is_some() {
|
||||
return queue_back.cloned();
|
||||
}
|
||||
|
||||
pub fn front_of<'a>(&'a self, queue_index: usize) -> Option<&'a H256> {
|
||||
self.chain[queue_index].front()
|
||||
}
|
||||
|
||||
pub fn back<'a>(&'a self) -> Option<&'a H256> {
|
||||
let queue_index = self.chain.len() - 1;
|
||||
self.chain[queue_index].back()
|
||||
queue_index = queue_index - 1;
|
||||
if queue_index == 0 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_contained_in(&self, queue_index: usize, hash: &H256) -> bool {
|
||||
|
@ -166,24 +161,10 @@ impl HashQueueChain {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn queue_at<'a>(&'a self, queue_index: usize) -> &'a VecDeque<H256> {
|
||||
self.chain[queue_index].queue()
|
||||
}
|
||||
|
||||
pub fn pop_front_at(&mut self, queue_index: usize) -> H256 {
|
||||
self.chain[queue_index].pop_front()
|
||||
.expect("must be checked by caller")
|
||||
}
|
||||
|
||||
pub fn pop_front_n_at(&mut self, queue_index: usize, n: usize) -> Vec<H256> {
|
||||
self.chain[queue_index].pop_front_n(n)
|
||||
}
|
||||
|
||||
pub fn push_back(&mut self, hash: H256) {
|
||||
let queue_index = self.chain.len() - 1;
|
||||
self.chain[queue_index].push_back(hash)
|
||||
}
|
||||
|
||||
pub fn push_back_n_at(&mut self, queue_index: usize, hashes: Vec<H256>) {
|
||||
self.chain[queue_index].push_back_n(hashes)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::cmp::{min, max};
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use chain::{Block, RepresentH256};
|
||||
use primitives::hash::H256;
|
||||
use hash_queue::HashPosition;
|
||||
use synchronization_peers::Peers;
|
||||
use synchronization_peers::{Peers, Information as PeersInformation};
|
||||
use synchronization_chain::{ChainRef, Information as ChainInformation, BlockState};
|
||||
|
||||
///! Blocks synchronization process:
|
||||
|
@ -88,6 +88,8 @@ pub enum State {
|
|||
pub struct Information {
|
||||
/// Current synchronization state.
|
||||
pub state: State,
|
||||
/// Information on synchronization peers.
|
||||
pub peers: PeersInformation,
|
||||
/// Current synchronization chain inormation.
|
||||
pub chain: ChainInformation,
|
||||
/// Number of currently orphaned blocks.
|
||||
|
@ -121,6 +123,7 @@ impl Synchronization {
|
|||
pub fn information(&self) -> Information {
|
||||
Information {
|
||||
state: self.state,
|
||||
peers: self.peers.information(),
|
||||
chain: self.chain.read().information(),
|
||||
orphaned: self.orphaned_blocks.len(),
|
||||
}
|
||||
|
@ -274,201 +277,89 @@ impl Synchronization {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use parking_lot::RwLock;
|
||||
use chain::{Block, RepresentH256};
|
||||
use primitives::hash::H256;
|
||||
use local_chain::LocalChain;
|
||||
use super::{Synchronization, State, Task};
|
||||
use synchronization_chain::{Chain, ChainRef};
|
||||
|
||||
#[test]
|
||||
fn synchronization_saturated_on_start() {
|
||||
let sync = Synchronization::new();
|
||||
let chain = ChainRef::new(RwLock::new(Chain::with_test_storage()));
|
||||
let sync = Synchronization::new(chain);
|
||||
let info = sync.information();
|
||||
assert_eq!(info.state, State::Saturated);
|
||||
assert_eq!(info.requested, 0);
|
||||
assert_eq!(info.queued, 0);
|
||||
assert_eq!(info.orphaned, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn synchronization_in_order_block_path() {
|
||||
let mut chain = LocalChain::with_test_storage();
|
||||
let mut sync = Synchronization::new();
|
||||
let chain = ChainRef::new(RwLock::new(Chain::with_test_storage()));
|
||||
let mut sync = Synchronization::new(chain);
|
||||
|
||||
let block1: Block = "010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000".into();
|
||||
let block2: Block = "010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010bffffffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac00000000".into();
|
||||
|
||||
sync.on_unknown_blocks(5, vec![block1.hash()]);
|
||||
assert_eq!(sync.information().state, State::Synchronizing);
|
||||
assert_eq!(sync.information().requested, 0);
|
||||
assert_eq!(sync.information().queued, 1);
|
||||
assert_eq!(sync.information().orphaned, 0);
|
||||
assert_eq!(sync.peers().information().idle, 1);
|
||||
assert_eq!(sync.peers().information().active, 0);
|
||||
assert_eq!(sync.information().chain.scheduled, 1);
|
||||
assert_eq!(sync.information().chain.requested, 0);
|
||||
assert_eq!(sync.information().chain.stored, 1);
|
||||
assert_eq!(sync.information().peers.idle, 1);
|
||||
assert_eq!(sync.information().peers.active, 0);
|
||||
|
||||
let tasks = sync.get_synchronization_tasks();
|
||||
assert_eq!(tasks.len(), 2);
|
||||
assert_eq!(tasks[0], Task::RequestBestInventory(5));
|
||||
assert_eq!(tasks[1], Task::RequestBlocks(5, vec![block1.hash()]));
|
||||
assert_eq!(sync.information().state, State::Synchronizing);
|
||||
assert_eq!(sync.information().requested, 1);
|
||||
assert_eq!(sync.information().queued, 0);
|
||||
assert_eq!(sync.information().orphaned, 0);
|
||||
assert_eq!(sync.peers().information().idle, 0);
|
||||
assert_eq!(sync.peers().information().active, 1);
|
||||
assert_eq!(sync.information().chain.scheduled, 0);
|
||||
assert_eq!(sync.information().chain.requested, 1);
|
||||
assert_eq!(sync.information().chain.stored, 1);
|
||||
assert_eq!(sync.information().peers.idle, 0);
|
||||
assert_eq!(sync.information().peers.active, 1);
|
||||
|
||||
// push unknown block => nothing should change
|
||||
sync.on_peer_block(&mut chain, 5, block2);
|
||||
sync.on_peer_block(5, block2);
|
||||
assert_eq!(sync.information().state, State::Synchronizing);
|
||||
assert_eq!(sync.information().requested, 1);
|
||||
assert_eq!(sync.information().queued, 0);
|
||||
assert_eq!(sync.information().orphaned, 0);
|
||||
assert_eq!(sync.peers().information().idle, 0);
|
||||
assert_eq!(sync.peers().information().active, 1);
|
||||
assert_eq!(sync.information().chain.scheduled, 0);
|
||||
assert_eq!(sync.information().chain.requested, 1);
|
||||
assert_eq!(sync.information().chain.stored, 1);
|
||||
assert_eq!(sync.information().peers.idle, 0);
|
||||
assert_eq!(sync.information().peers.active, 1);
|
||||
|
||||
// push requested block => nothing should change
|
||||
sync.on_peer_block(&mut chain, 5, block1);
|
||||
sync.on_peer_block(5, block1);
|
||||
assert_eq!(sync.information().state, State::Saturated);
|
||||
assert_eq!(sync.information().requested, 0);
|
||||
assert_eq!(sync.information().queued, 0);
|
||||
assert_eq!(sync.information().orphaned, 0);
|
||||
assert_eq!(sync.peers().information().idle, 1);
|
||||
assert_eq!(sync.peers().information().active, 0);
|
||||
assert_eq!(chain.information().length, 2);
|
||||
assert_eq!(sync.information().chain.scheduled, 0);
|
||||
assert_eq!(sync.information().chain.requested, 0);
|
||||
assert_eq!(sync.information().chain.stored, 2);
|
||||
assert_eq!(sync.information().peers.idle, 1);
|
||||
assert_eq!(sync.information().peers.active, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn synchronization_out_of_order_block_path() {
|
||||
let mut chain = LocalChain::with_test_storage();
|
||||
let mut sync = Synchronization::new();
|
||||
let chain = ChainRef::new(RwLock::new(Chain::with_test_storage()));
|
||||
let mut sync = Synchronization::new(chain);
|
||||
|
||||
let block2: Block = "010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010bffffffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac00000000".into();
|
||||
|
||||
sync.on_unknown_blocks(5, vec![block2.hash()]);
|
||||
sync.get_synchronization_tasks();
|
||||
sync.on_peer_block(&mut chain, 5, block2);
|
||||
sync.on_peer_block(5, block2);
|
||||
|
||||
// out-of-order block was presented by the peer
|
||||
assert_eq!(sync.information().state, State::Saturated);
|
||||
assert_eq!(sync.information().requested, 0);
|
||||
assert_eq!(sync.information().queued, 0);
|
||||
assert_eq!(sync.information().orphaned, 0);
|
||||
assert_eq!(sync.peers().information().idle, 1);
|
||||
assert_eq!(sync.peers().information().active, 0);
|
||||
assert_eq!(chain.information().length, 1);
|
||||
assert_eq!(sync.information().chain.scheduled, 0);
|
||||
assert_eq!(sync.information().chain.requested, 0);
|
||||
assert_eq!(sync.information().chain.stored, 1);
|
||||
assert_eq!(sync.information().peers.idle, 1);
|
||||
assert_eq!(sync.information().peers.active, 0);
|
||||
// TODO: check that peer is penalized
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn synchronization_block_locator_hashes() {
|
||||
let mut chain = LocalChain::with_test_storage();
|
||||
let genesis_hash = chain.best_block().hash;
|
||||
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(0, 100, &mut hashes);
|
||||
assert_eq!(hashes, vec![genesis_hash.clone()]);
|
||||
|
||||
let block1: Block = "010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000".into();
|
||||
let block1_hash = block1.hash();
|
||||
|
||||
chain.insert_block(block1);
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(0, 1, &mut hashes);
|
||||
assert_eq!(hashes, vec![genesis_hash.clone()]);
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(1, 1, &mut hashes);
|
||||
assert_eq!(hashes, vec![block1_hash.clone(), genesis_hash.clone()]);
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(1, 10, &mut hashes);
|
||||
assert_eq!(hashes, vec![block1_hash.clone(), genesis_hash.clone()]);
|
||||
|
||||
let block2: Block = "010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010bffffffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac00000000".into();
|
||||
let block2_hash = block2.hash();
|
||||
|
||||
chain.insert_block(block2);
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(2, 1, &mut hashes);
|
||||
assert_eq!(hashes, vec![block2_hash.clone(), block1_hash.clone(), genesis_hash.clone()]);
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(2, 10, &mut hashes);
|
||||
assert_eq!(hashes, vec![block2_hash.clone(), genesis_hash.clone()]);
|
||||
let mut hashes: Vec<H256> = Vec::new(); chain.block_locator_hashes(2, 2, &mut hashes);
|
||||
assert_eq!(hashes, vec![block2_hash.clone(), genesis_hash.clone()]);
|
||||
|
||||
let mut sync = Synchronization::new();
|
||||
{
|
||||
let verifying_hashes = sync.verifying_hashes_mut();
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000000".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000001".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000002".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000003".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000004".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000005".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000006".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000007".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000008".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000009".into());
|
||||
verifying_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000010".into());
|
||||
}
|
||||
|
||||
assert_eq!(sync.best_block_locator_hashes(&chain), vec!["0000000000000000000000000000000000000000000000000000000000000010".into()]);
|
||||
assert_eq!(sync.block_locator_hashes(&chain), vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000009".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000007".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000006".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000005".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000004".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000003".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000002".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000001".into(),
|
||||
block2_hash.clone(),
|
||||
genesis_hash.clone(),
|
||||
]);
|
||||
|
||||
{
|
||||
let requested_hashes = sync.requested_hashes_mut();
|
||||
requested_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000011".into());
|
||||
requested_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000012".into());
|
||||
requested_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000013".into());
|
||||
requested_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000014".into());
|
||||
requested_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000015".into());
|
||||
requested_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000016".into());
|
||||
}
|
||||
|
||||
assert_eq!(sync.best_block_locator_hashes(&chain), vec!["0000000000000000000000000000000000000000000000000000000000000016".into()]);
|
||||
assert_eq!(sync.block_locator_hashes(&chain), vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000016".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000015".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000014".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000013".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000012".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000011".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000009".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000007".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000005".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000001".into(),
|
||||
genesis_hash.clone(),
|
||||
]);
|
||||
|
||||
{
|
||||
let queued_hashes = sync.queued_hashes_mut();
|
||||
queued_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000020".into());
|
||||
queued_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000021".into());
|
||||
queued_hashes.push_back("0000000000000000000000000000000000000000000000000000000000000022".into());
|
||||
}
|
||||
|
||||
assert_eq!(sync.best_block_locator_hashes(&chain), vec!["0000000000000000000000000000000000000000000000000000000000000022".into()]);
|
||||
assert_eq!(sync.block_locator_hashes(&chain), vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000022".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000021".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000020".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000016".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000015".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000014".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000013".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000012".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000011".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000004".into(),
|
||||
genesis_hash.clone(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use chain::Block;
|
|||
use db;
|
||||
use primitives::hash::H256;
|
||||
use best_block::BestBlock;
|
||||
use hash_queue::{HashQueue, HashQueueChain, HashPosition};
|
||||
use hash_queue::{HashQueueChain, HashPosition};
|
||||
use verification;
|
||||
|
||||
/// Thread-safe reference to `Chain`
|
||||
|
@ -112,6 +112,8 @@ impl Chain {
|
|||
#[cfg(test)]
|
||||
/// Create new `Chain` with in-memory test storage
|
||||
pub fn with_test_storage() -> Self {
|
||||
use db::Store;
|
||||
|
||||
// we only work with storages with genesis block
|
||||
let storage = Arc::new(db::TestStorage::with_genesis_block());
|
||||
let genesis_block_hash = storage.block_hash(0)
|
||||
|
@ -144,12 +146,6 @@ impl Chain {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get total blockchain length
|
||||
pub fn length(&self) -> u64 {
|
||||
self.storage.best_block_number().expect("storage with genesis block is required") + 1
|
||||
+ self.hash_chain.len() as u64
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -209,9 +205,8 @@ impl Chain {
|
|||
let mut block_locator_hashes: Vec<H256> = Vec::new();
|
||||
|
||||
// calculate for hash_queue
|
||||
let (local_index, step) = self.block_locator_hashes_for(0, 1, SCHEDULED_QUEUE, &mut block_locator_hashes);
|
||||
let (local_index, step) = self.block_locator_hashes_for(local_index, step, REQUESTED_QUEUE, &mut block_locator_hashes);
|
||||
let (local_index, step) = self.block_locator_hashes_for(local_index, step, VERIFYING_QUEUE, &mut block_locator_hashes);
|
||||
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 < local_index { 0 } else { storage_best_block_number - local_index };
|
||||
|
@ -224,13 +219,21 @@ impl Chain {
|
|||
self.hash_chain.push_back_n_at(SCHEDULED_QUEUE, hashes)
|
||||
}
|
||||
|
||||
/// Pops block with givent state
|
||||
pub fn request_blocks_hashes(&mut self, num_blocks: u64) -> Vec<H256> {
|
||||
let scheduled = self.hash_chain.pop_front_n_at(SCHEDULED_QUEUE, num_blocks as usize);
|
||||
/// 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);
|
||||
self.hash_chain.push_back_n_at(REQUESTED_QUEUE, scheduled.clone());
|
||||
scheduled
|
||||
}
|
||||
|
||||
/// 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);
|
||||
self.hash_chain.push_back_n_at(VERIFYING_QUEUE, requested.clone());
|
||||
requested
|
||||
}
|
||||
|
||||
/// Schedule block for verification
|
||||
pub fn verify_and_insert_block(&mut self, hash: H256, block: Block) {
|
||||
// TODO: add another basic verifications here (use verification package)
|
||||
|
@ -244,10 +247,7 @@ impl Chain {
|
|||
return;
|
||||
}
|
||||
|
||||
self.storage.insert_block(&block);
|
||||
self.best_storage_block_hash = hash;
|
||||
|
||||
/* TODO: fails on first 500 blocks
|
||||
// TODO: currently verification fails on first ~500 blocks
|
||||
// TODO: async verification
|
||||
match self.verification_queue.push(block) {
|
||||
Err(err) => {
|
||||
|
@ -275,7 +275,7 @@ impl Chain {
|
|||
trace!(target: "sync", "Error verifying block {:?}: {:?}", hash, self.verification_queue.block_status(&hash));
|
||||
unimplemented!();
|
||||
},
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove block by hash if it is currently in given state
|
||||
|
@ -283,33 +283,26 @@ impl Chain {
|
|||
self.hash_chain.remove_at(state.to_queue_index(), hash)
|
||||
}
|
||||
|
||||
/// Calculate block locator hashes for qiven hash queue
|
||||
fn block_locator_hashes_for(&self, local_index: u64, mut step: u64, queue_index: usize, hashes: &mut Vec<H256>) -> (u64, u64) {
|
||||
let queue = self.hash_chain.queue_at(queue_index);
|
||||
let queue_len = queue.len() as u64;
|
||||
|
||||
// no items in queue => proceed to next storage
|
||||
/// 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;
|
||||
if queue_len == 0 {
|
||||
return (local_index, step);
|
||||
return (0, 1);
|
||||
}
|
||||
|
||||
// there are less items in the queue than we need to skip => proceed to next storage
|
||||
if queue_len - 1 < local_index {
|
||||
return (local_index - queue_len - 1, step);
|
||||
}
|
||||
|
||||
let mut local_index = queue_len - 1 - local_index;
|
||||
let mut index = queue_len - 1;
|
||||
let mut step = 1u64;
|
||||
loop {
|
||||
let hash = queue[local_index as usize].clone();
|
||||
hashes.push(hash);
|
||||
let block_hash = self.hash_chain[index as usize].clone();
|
||||
hashes.push(block_hash);
|
||||
|
||||
if hashes.len() >= 10 {
|
||||
step <<= 1;
|
||||
}
|
||||
if local_index < step {
|
||||
return (step - local_index - 1, step);
|
||||
if index < step {
|
||||
return (step - index - 1, step);
|
||||
}
|
||||
local_index -= step;
|
||||
index -= step;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,3 +328,110 @@ impl Chain {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chain::{Block, RepresentH256};
|
||||
use super::Chain;
|
||||
|
||||
#[test]
|
||||
fn chain_block_locator_hashes() {
|
||||
let mut chain = Chain::with_test_storage();
|
||||
let genesis_hash = chain.best_block().hash;
|
||||
assert_eq!(chain.block_locator_hashes(), vec![genesis_hash.clone()]);
|
||||
|
||||
let block1: Block = "010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000".into();
|
||||
let block1_hash = block1.hash();
|
||||
|
||||
chain.verify_and_insert_block(block1.hash(), block1);
|
||||
assert_eq!(chain.block_locator_hashes(), vec![block1_hash.clone(), genesis_hash.clone()]);
|
||||
|
||||
let block2: Block = "010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010bffffffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac00000000".into();
|
||||
let block2_hash = block2.hash();
|
||||
|
||||
chain.verify_and_insert_block(block2.hash(), block2);
|
||||
assert_eq!(chain.block_locator_hashes(), vec![block2_hash.clone(), block1_hash.clone(), genesis_hash.clone()]);
|
||||
|
||||
chain.schedule_blocks_hashes(vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000000".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000001".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000002".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000003".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000004".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000005".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000006".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000007".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000009".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
]);
|
||||
chain.request_blocks_hashes(10);
|
||||
chain.verify_blocks_hashes(10);
|
||||
|
||||
assert_eq!(chain.best_block_locator_hashes(), vec!["0000000000000000000000000000000000000000000000000000000000000010".into()]);
|
||||
assert_eq!(chain.block_locator_hashes(), vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000009".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000007".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000006".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000005".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000004".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000003".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000002".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000001".into(),
|
||||
block2_hash.clone(),
|
||||
genesis_hash.clone(),
|
||||
]);
|
||||
|
||||
chain.schedule_blocks_hashes(vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000011".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000012".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000013".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000014".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000015".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000016".into(),
|
||||
]);
|
||||
chain.request_blocks_hashes(10);
|
||||
|
||||
assert_eq!(chain.best_block_locator_hashes(), vec!["0000000000000000000000000000000000000000000000000000000000000016".into()]);
|
||||
assert_eq!(chain.block_locator_hashes(), vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000016".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000015".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000014".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000013".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000012".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000011".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000009".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000007".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000005".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000001".into(),
|
||||
genesis_hash.clone(),
|
||||
]);
|
||||
|
||||
chain.schedule_blocks_hashes(vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000020".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000021".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000022".into(),
|
||||
]);
|
||||
|
||||
assert_eq!(chain.best_block_locator_hashes(), vec!["0000000000000000000000000000000000000000000000000000000000000022".into()]);
|
||||
assert_eq!(chain.block_locator_hashes(), vec![
|
||||
"0000000000000000000000000000000000000000000000000000000000000022".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000021".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000020".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000016".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000015".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000014".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000013".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000012".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000011".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000010".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000008".into(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000004".into(),
|
||||
genesis_hash.clone(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct Peers {
|
|||
}
|
||||
|
||||
/// Information on synchronization peers
|
||||
#[cfg(test)]
|
||||
#[derive(Debug)]
|
||||
pub struct Information {
|
||||
/// Number of currently idle synchronization peers.
|
||||
pub idle: usize,
|
||||
|
@ -31,7 +31,6 @@ impl Peers {
|
|||
}
|
||||
|
||||
/// Get information on synchronization peers
|
||||
#[cfg(test)]
|
||||
pub fn information(&self) -> Information {
|
||||
Information {
|
||||
idle: self.idle_peers.len(),
|
||||
|
@ -84,11 +83,6 @@ impl Peers {
|
|||
pub fn on_inventory_requested(&mut self, _peer_index: usize) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// Wrong block was received from peer.
|
||||
pub fn on_wrong_block_received(&mut self, _peer_index: usize) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
Loading…
Reference in New Issue