Verify block syncing responses against requests (#9670)
* sync: Validate received BlockHeaders packets against stored request.
* sync: Validate received BlockBodies and BlockReceipts.
* sync: Fix broken tests.
* sync: Unit tests for BlockDownloader::import_headers.
* sync: Unit tests for import_{bodies,receipts}.
* tests: Add missing method doc.
This commit is contained in:
@@ -28,6 +28,7 @@ use network::PeerId;
|
||||
use rlp::Rlp;
|
||||
use snapshot::ChunkType;
|
||||
use std::cmp;
|
||||
use std::mem;
|
||||
use std::collections::HashSet;
|
||||
use std::time::Instant;
|
||||
use sync_io::SyncIo;
|
||||
@@ -296,6 +297,13 @@ impl SyncHandler {
|
||||
trace!(target: "sync", "{}: Ignored unexpected bodies", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
let expected_blocks = match sync.peers.get_mut(&peer_id) {
|
||||
Some(peer) => mem::replace(&mut peer.asking_blocks, Vec::new()),
|
||||
None => {
|
||||
trace!(target: "sync", "{}: Ignored unexpected bodies (peer not found)", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{} -> BlockBodies ({} entries), set = {:?}", peer_id, item_count, block_set);
|
||||
if item_count == 0 {
|
||||
@@ -315,7 +323,7 @@ impl SyncHandler {
|
||||
Some(ref mut blocks) => blocks,
|
||||
}
|
||||
};
|
||||
downloader.import_bodies(r)?;
|
||||
downloader.import_bodies(r, expected_blocks.as_slice())?;
|
||||
}
|
||||
sync.collect_blocks(io, block_set);
|
||||
Ok(())
|
||||
@@ -368,10 +376,23 @@ impl SyncHandler {
|
||||
let expected_hash = sync.peers.get(&peer_id).and_then(|p| p.asking_hash);
|
||||
let allowed = sync.peers.get(&peer_id).map(|p| p.is_allowed()).unwrap_or(false);
|
||||
let block_set = sync.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks);
|
||||
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockHeaders) || expected_hash.is_none() || !allowed {
|
||||
trace!(target: "sync", "{}: Ignored unexpected headers, expected_hash = {:?}", peer_id, expected_hash);
|
||||
|
||||
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockHeaders) {
|
||||
debug!(target: "sync", "{}: Ignored unexpected headers", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
let expected_hash = match expected_hash {
|
||||
Some(hash) => hash,
|
||||
None => {
|
||||
debug!(target: "sync", "{}: Ignored unexpected headers (expected_hash is None)", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
if !allowed {
|
||||
debug!(target: "sync", "{}: Ignored unexpected headers (peer not allowed)", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}, set = {:?}", peer_id, item_count, sync.state, block_set);
|
||||
if (sync.state == SyncState::Idle || sync.state == SyncState::WaitingPeers) && sync.old_blocks.is_none() {
|
||||
@@ -419,6 +440,13 @@ impl SyncHandler {
|
||||
trace!(target: "sync", "{}: Ignored unexpected receipts", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
let expected_blocks = match sync.peers.get_mut(&peer_id) {
|
||||
Some(peer) => mem::replace(&mut peer.asking_blocks, Vec::new()),
|
||||
None => {
|
||||
trace!(target: "sync", "{}: Ignored unexpected bodies (peer not found)", peer_id);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{} -> BlockReceipts ({} entries)", peer_id, item_count);
|
||||
if item_count == 0 {
|
||||
@@ -438,7 +466,7 @@ impl SyncHandler {
|
||||
Some(ref mut blocks) => blocks,
|
||||
}
|
||||
};
|
||||
downloader.import_receipts(io, r)?;
|
||||
downloader.import_receipts(r, expected_blocks.as_slice())?;
|
||||
}
|
||||
sync.collect_blocks(io, block_set);
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user