Make sure to not mark block header hash as invalid if only the body is wrong. (#11356)

* Patch invalid transaction root.

* Add raw hash to bad and include fix for uncles too.

* Fix submodules.
This commit is contained in:
Tomasz Drwięga 2019-12-30 22:15:11 +01:00 committed by Wei Tang
parent 29ebddc64f
commit 54c2d6167f
2 changed files with 25 additions and 2 deletions

View File

@ -27,9 +27,12 @@ pub use self::headers::Headers;
/// Something which can produce a hash and a parent hash. /// Something which can produce a hash and a parent hash.
pub trait BlockLike { pub trait BlockLike {
/// Get the hash of this item. /// Get the hash of this item - i.e. the header hash.
fn hash(&self) -> H256; fn hash(&self) -> H256;
/// Get a raw hash of this item - i.e. the hash of the RLP representation.
fn raw_hash(&self) -> H256;
/// Get the hash of this item's parent. /// Get the hash of this item's parent.
fn parent_hash(&self) -> H256; fn parent_hash(&self) -> H256;
@ -160,6 +163,10 @@ pub mod blocks {
self.header.hash() self.header.hash()
} }
fn raw_hash(&self) -> H256 {
hash::keccak(&self.bytes)
}
fn parent_hash(&self) -> H256 { fn parent_hash(&self) -> H256 {
self.header.parent_hash().clone() self.header.parent_hash().clone()
} }
@ -174,6 +181,10 @@ pub mod blocks {
self.header.hash() self.header.hash()
} }
fn raw_hash(&self) -> H256 {
hash::keccak(&self.bytes)
}
fn parent_hash(&self) -> H256 { fn parent_hash(&self) -> H256 {
self.header.parent_hash().clone() self.header.parent_hash().clone()
} }
@ -197,6 +208,7 @@ pub mod headers {
impl BlockLike for Header { impl BlockLike for Header {
fn hash(&self) -> H256 { self.hash() } fn hash(&self) -> H256 { self.hash() }
fn raw_hash(&self) -> H256 { self.hash() }
fn parent_hash(&self) -> H256 { self.parent_hash().clone() } fn parent_hash(&self) -> H256 { self.parent_hash().clone() }
fn difficulty(&self) -> U256 { self.difficulty().clone() } fn difficulty(&self) -> U256 { self.difficulty().clone() }
} }

View File

@ -472,13 +472,14 @@ impl<K: Kind> VerificationQueue<K> {
/// Add a block to the queue. /// Add a block to the queue.
pub fn import(&self, input: K::Input) -> Result<H256, (K::Input, Error)> { pub fn import(&self, input: K::Input) -> Result<H256, (K::Input, Error)> {
let hash = input.hash(); let hash = input.hash();
let raw_hash = input.raw_hash();
{ {
if self.processing.read().contains_key(&hash) { if self.processing.read().contains_key(&hash) {
bail!((input, ErrorKind::Import(ImportErrorKind::AlreadyQueued).into())); bail!((input, ErrorKind::Import(ImportErrorKind::AlreadyQueued).into()));
} }
let mut bad = self.verification.bad.lock(); let mut bad = self.verification.bad.lock();
if bad.contains(&hash) { if bad.contains(&hash) || bad.contains(&raw_hash) {
bail!((input, ErrorKind::Import(ImportErrorKind::KnownBad).into())); bail!((input, ErrorKind::Import(ImportErrorKind::KnownBad).into()));
} }
@ -505,6 +506,16 @@ impl<K: Kind> VerificationQueue<K> {
match err { match err {
// Don't mark future blocks as bad. // Don't mark future blocks as bad.
Error(ErrorKind::Block(BlockError::TemporarilyInvalid(_)), _) => {}, Error(ErrorKind::Block(BlockError::TemporarilyInvalid(_)), _) => {},
// If the transaction root or uncles hash is invalid, it doesn't necessarily mean
// that the header is invalid. We might have just received a malformed block body,
// so we shouldn't put the header hash to `bad`.
//
// We still put the entire `Item` hash to bad, so that we can early reject
// the items that are malformed.
Error(ErrorKind::Block(BlockError::InvalidTransactionsRoot(_)), _) |
Error(ErrorKind::Block(BlockError::InvalidUnclesHash(_)), _) => {
self.verification.bad.lock().insert(raw_hash);
},
_ => { _ => {
self.verification.bad.lock().insert(hash); self.verification.bad.lock().insert(hash);
} }