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
+2 -2
View File
@@ -1287,7 +1287,7 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
}
let is_best = self.context_data.chain.info().best_hash == hash;
debug!(target: "sync", "Reannouncing block {:?}", hash);
debug!(target: "sync", "Reannouncing block {:?} is_best: {}", hash, is_best);
self.send_announcement(&header, data, is_best, true)
}
@@ -2160,7 +2160,7 @@ mod tests {
reserved_only: false,
priority_groups: Vec::new(),
},
Box::new(DefaultBlockAnnounceValidator::new(client.clone())),
Box::new(DefaultBlockAnnounceValidator),
None,
Default::default(),
None,
+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(
@@ -104,7 +104,7 @@ fn build_test_full_node(config: config::NetworkConfiguration)
protocol_id: config::ProtocolId::from(&b"/test-protocol-name"[..]),
import_queue,
block_announce_validator: Box::new(
sp_consensus::block_validation::DefaultBlockAnnounceValidator::new(client.clone()),
sp_consensus::block_validation::DefaultBlockAnnounceValidator,
),
metrics_registry: None,
})