Skip to content

Commit

Permalink
Validate block bodies when syncing (paritytech#5894)
Browse files Browse the repository at this point in the history
  • Loading branch information
arkpar authored May 5, 2020
1 parent 32aeccb commit ba4eec2
Showing 1 changed file with 41 additions and 2 deletions.
43 changes: 41 additions & 2 deletions client/network/src/protocol/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
//! order to update it.
//!
use codec::Encode;
use blocks::BlockCollection;
use sp_blockchain::{Error as ClientError, Info as BlockchainInfo, HeaderMetadata};
use sp_consensus::{BlockOrigin, BlockStatus,
Expand All @@ -45,7 +46,7 @@ use log::{debug, trace, warn, info, error};
use sp_runtime::{
Justification,
generic::BlockId,
traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion}
traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion, Hash, HashFor}
};
use std::{fmt, ops::Range, collections::{HashMap, HashSet, VecDeque}, sync::Arc};

Expand Down Expand Up @@ -727,8 +728,10 @@ impl<B: BlockT> ChainSync<B> {
match &mut peer.state {
PeerSyncState::DownloadingNew(start_block) => {
self.blocks.clear_peer_download(&who);
self.blocks.insert(*start_block, blocks, who.clone());
let start_block = *start_block;
peer.state = PeerSyncState::Available;
validate_blocks::<B>(&blocks, &who)?;
self.blocks.insert(start_block, blocks, who.clone());
self.blocks
.drain(self.best_queued_number + One::one())
.into_iter()
Expand All @@ -750,6 +753,7 @@ impl<B: BlockT> ChainSync<B> {
debug!(target: "sync", "Empty block response from {}", who);
return Err(BadPeer(who, rep::NO_BLOCK));
}
validate_blocks::<B>(&blocks, &who)?;
blocks.into_iter().map(|b| {
IncomingBlock {
hash: b.hash,
Expand Down Expand Up @@ -834,6 +838,7 @@ impl<B: BlockT> ChainSync<B> {
}
} else {
// When request.is_none() this is a block announcement. Just accept blocks.
validate_blocks::<B>(&blocks, &who)?;
blocks.into_iter().map(|b| {
IncomingBlock {
hash: b.hash,
Expand Down Expand Up @@ -1500,6 +1505,40 @@ fn is_descendent_of<Block, T>(client: &T, base: &Block::Hash, block: &Block::Has
Ok(ancestor.hash == *base)
}

fn validate_blocks<Block: BlockT>(blocks: &Vec<message::BlockData<Block>>, who: &PeerId) -> Result<(), BadPeer> {
for b in blocks {
if let Some(header) = &b.header {
let hash = header.hash();
if hash != b.hash {
debug!(
target:"sync",
"Bad header received from {}. Expected hash {:?}, got {:?}",
who,
b.hash,
hash,
);
return Err(BadPeer(who.clone(), rep::BAD_BLOCK))
}
}
if let (Some(header), Some(body)) = (&b.header, &b.body) {
let expected = *header.extrinsics_root();
let got = HashFor::<Block>::ordered_trie_root(body.iter().map(Encode::encode).collect());
if expected != got {
debug!(
target:"sync",
"Bad extrinsic root for a block {} received from {}. Expected {:?}, got {:?}",
b.hash,
who,
expected,
got,
);
return Err(BadPeer(who.clone(), rep::BAD_BLOCK))
}
}
}
Ok(())
}

#[cfg(test)]
mod test {
use super::*;
Expand Down

0 comments on commit ba4eec2

Please sign in to comment.