From d168479a85f5f18f6fc75510ea8a81996a1ce808 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 19 Jun 2017 16:24:07 +0200 Subject: [PATCH] blacklist bad manifest hashes upon failure --- sync/src/chain.rs | 13 +++++++++++-- sync/src/snapshot.rs | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index edf6f13d2..badd784a4 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -521,7 +521,8 @@ impl ChainSync { sn > fork_block && self.highest_block.map_or(true, |highest| highest >= sn && (highest - sn) <= SNAPSHOT_RESTORE_THRESHOLD) )) - .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))); + .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))) + .filter(|&(_, ref hash)| !self.snapshot.is_known_bad(hash)); let mut snapshot_peers = HashMap::new(); let mut max_peers: usize = 0; @@ -1075,10 +1076,18 @@ impl ChainSync { } // check service status - match io.snapshot_service().status() { + let status = io.snapshot_service().status(); + match status { RestorationStatus::Inactive | RestorationStatus::Failed => { trace!(target: "sync", "{}: Snapshot restoration aborted", peer_id); self.state = SyncState::WaitingPeers; + + // only note bad if restoration failed. + if let (Some(hash), RestorationStatus::Failed) = (self.snapshot.snapshot_hash(), status) { + trace!(target: "sync", "Noting snapshot hash {} as bad", hash); + self.snapshot.note_bad(hash); + } + self.snapshot.clear(); self.continue_sync(io); return Ok(()); diff --git a/sync/src/snapshot.rs b/sync/src/snapshot.rs index 727991caa..ffdaecd79 100644 --- a/sync/src/snapshot.rs +++ b/sync/src/snapshot.rs @@ -31,6 +31,7 @@ pub struct Snapshot { downloading_chunks: HashSet, completed_chunks: HashSet, snapshot_hash: Option, + bad_hashes: HashSet, } impl Snapshot { @@ -42,6 +43,7 @@ impl Snapshot { downloading_chunks: HashSet::new(), completed_chunks: HashSet::new(), snapshot_hash: None, + bad_hashes: HashSet::new(), } } @@ -109,6 +111,16 @@ impl Snapshot { self.downloading_chunks.remove(hash); } + // note snapshot hash as bad. + pub fn note_bad(&mut self, hash: H256) { + self.bad_hashes.insert(hash); + } + + // whether snapshot hash is known to be bad. + pub fn is_known_bad(&self, hash: &H256) -> bool { + self.bad_hashes.contains(hash) + } + pub fn snapshot_hash(&self) -> Option { self.snapshot_hash } @@ -205,5 +217,15 @@ mod test { assert_eq!(snapshot.done_chunks(), snapshot.total_chunks()); assert_eq!(snapshot.snapshot_hash(), Some(manifest.into_rlp().sha3())); } + + #[test] + fn tracks_known_bad() { + let mut snapshot = Snapshot::new(); + let hash = H256::random(); + + assert_eq!(snapshot.is_known_bad(&hash), false); + snapshot.note_bad(hash); + assert_eq!(snapshot.is_known_bad(&hash), true); + } }