zebrad: treat duplicate downloads as an error

We should error if we notice that we're attempting to download the same
blocks multiple times, because that indicates that peers reported bad
information to us, or we got confused trying to interpret their
responses.
This commit is contained in:
Henry de Valence 2020-10-24 17:31:41 -07:00
parent 4127d086ea
commit 4c960c4e6d
2 changed files with 6 additions and 8 deletions

View File

@ -544,10 +544,7 @@ where
async fn request_blocks(&mut self, hashes: HashSet<block::Hash>) -> Result<(), Report> { async fn request_blocks(&mut self, hashes: HashSet<block::Hash>) -> Result<(), Report> {
tracing::debug!(hashes.len = hashes.len(), "requesting blocks"); tracing::debug!(hashes.len = hashes.len(), "requesting blocks");
for hash in hashes.into_iter() { for hash in hashes.into_iter() {
self.downloads self.downloads.download_and_verify(hash).await?;
.download_and_verify(hash)
.await
.map_err(|e| eyre!(e))?;
} }
Ok(()) Ok(())

View File

@ -5,6 +5,7 @@ use std::{
task::{Context, Poll}, task::{Context, Poll},
}; };
use color_eyre::eyre::{eyre, Report};
use futures::{ use futures::{
future::TryFutureExt, future::TryFutureExt,
ready, ready,
@ -110,10 +111,9 @@ where
/// only if the network service fails. It returns immediately after queuing /// only if the network service fails. It returns immediately after queuing
/// the request. /// the request.
#[instrument(skip(self))] #[instrument(skip(self))]
pub async fn download_and_verify(&mut self, hash: block::Hash) -> Result<(), BoxError> { pub async fn download_and_verify(&mut self, hash: block::Hash) -> Result<(), Report> {
if self.cancel_handles.contains_key(&hash) { if self.cancel_handles.contains_key(&hash) {
tracing::debug!("skipping hash already queued for download"); return Err(eyre!("duplicate hash queued for download"));
return Ok(());
} }
// We construct the block requests sequentially, waiting for the peer // We construct the block requests sequentially, waiting for the peer
@ -127,7 +127,8 @@ where
let block_req = self let block_req = self
.network .network
.ready_and() .ready_and()
.await? .await
.map_err(|e| eyre!(e))?
.call(zn::Request::BlocksByHash(std::iter::once(hash).collect())); .call(zn::Request::BlocksByHash(std::iter::once(hash).collect()));
tracing::debug!("requested block"); tracing::debug!("requested block");