Support synching of blocks that are not new_best (#6508)

* Start

* Remove debug println

* Add tests
This commit is contained in:
Bastian Köcher
2020-06-30 16:44:52 +02:00
committed by GitHub
parent 4fd770dcf9
commit 53be6ec510
9 changed files with 172 additions and 53 deletions
+30 -18
View File
@@ -48,6 +48,7 @@ use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion, Hash, HashFor}
};
use sp_arithmetic::traits::Saturating;
use std::{fmt, ops::Range, collections::{HashMap, HashSet, VecDeque}, sync::Arc};
mod blocks;
@@ -388,7 +389,7 @@ impl<B: BlockT> ChainSync<B> {
/// Returns the current sync status.
pub fn status(&self) -> Status<B> {
let best_seen = self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number);
let best_seen = self.peers.values().map(|p| p.best_number).max();
let sync_state =
if let Some(n) = best_seen {
// A chain is classified as downloading if the provided best block is
@@ -1186,6 +1187,21 @@ impl<B: BlockT> ChainSync<B> {
peer.recently_announced.pop_front();
}
peer.recently_announced.push_back(hash.clone());
// Let external validator check the block announcement.
let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice());
let is_best = match self.block_announce_validator.validate(&header, assoc_data) {
Ok(Validation::Success { is_new_best }) => is_new_best || is_best,
Ok(Validation::Failure) => {
debug!(target: "sync", "Block announcement validation of block {} from {} failed", hash, who);
return OnBlockAnnounce::Nothing
}
Err(e) => {
error!(target: "sync", "💔 Block announcement validation errored: {}", e);
return OnBlockAnnounce::Nothing
}
};
if is_best {
// update their best block
peer.best_number = number;
@@ -1216,20 +1232,6 @@ impl<B: BlockT> ChainSync<B> {
return OnBlockAnnounce::Nothing
}
// Let external validator check the block announcement.
let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice());
match self.block_announce_validator.validate(&header, assoc_data) {
Ok(Validation::Success) => (),
Ok(Validation::Failure) => {
debug!(target: "sync", "Block announcement validation of block {} from {} failed", hash, who);
return OnBlockAnnounce::Nothing
}
Err(e) => {
error!(target: "sync", "💔 Block announcement validation errored: {}", e);
return OnBlockAnnounce::Nothing
}
}
if ancient_parent {
trace!(target: "sync", "Ignored ancient block announced from {}: {} {:?}", who, hash, header);
return OnBlockAnnounce::Nothing
@@ -1428,14 +1430,24 @@ fn peer_block_request<B: BlockT>(
max_parallel_downloads,
MAX_DOWNLOAD_AHEAD,
) {
// The end is not part of the range.
let last = range.end.saturating_sub(One::one());
let from = if peer.best_number == last {
message::FromBlock::Hash(peer.best_hash)
} else {
message::FromBlock::Number(last)
};
let request = message::generic::BlockRequest {
id: 0,
fields: attrs.clone(),
from: message::FromBlock::Number(range.start),
from,
to: None,
direction: message::Direction::Ascending,
direction: message::Direction::Descending,
max: Some((range.end - range.start).saturated_into::<u32>())
};
Some((range, request))
} else {
None
@@ -1558,7 +1570,7 @@ mod test {
let client = Arc::new(TestClientBuilder::new().build());
let info = client.info();
let block_announce_validator = Box::new(DefaultBlockAnnounceValidator::new(client.clone()));
let block_announce_validator = Box::new(DefaultBlockAnnounceValidator);
let peer_id = PeerId::random();
let mut sync = ChainSync::new(