fixed verify_uncles error type (#11276)

* fixed verify_uncles error type

* cleanup and document fn verify_uncles bounds checking

* find_uncle_headers and find_uncle_hashes take u64 instead of u32 as an input param

* Update ethcore/verification/src/verification.rs

Co-Authored-By: David <dvdplm@gmail.com>
This commit is contained in:
Marek Kotewicz 2019-11-22 17:26:50 +08:00 committed by Andronik Ordian
parent df1c5ac616
commit 1986c4ee79
4 changed files with 21 additions and 31 deletions

View File

@ -1323,13 +1323,14 @@ impl BlockChain {
} }
/// Given a block's `parent`, find every block header which represents a valid possible uncle. /// Given a block's `parent`, find every block header which represents a valid possible uncle.
pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: usize) -> Option<Vec<encoded::Header>> { pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: u64) -> Option<Vec<encoded::Header>> {
self.find_uncle_hashes(parent, uncle_generations) self.find_uncle_hashes(parent, uncle_generations)
.map(|v| v.into_iter().filter_map(|h| self.block_header_data(&h)).collect()) .map(|v| v.into_iter().filter_map(|h| self.block_header_data(&h)).collect())
} }
/// Given a block's `parent`, find every block hash which represents a valid possible uncle. /// Given a block's `parent`, find every block hash which represents a valid possible uncle.
pub fn find_uncle_hashes(&self, parent: &H256, uncle_generations: usize) -> Option<Vec<H256>> { pub fn find_uncle_hashes(&self, parent: &H256, uncle_generations: u64) -> Option<Vec<H256>> {
let uncle_generations = uncle_generations as usize;
if !self.is_known(parent) { if !self.is_known(parent) {
return None; return None;
} }

View File

@ -92,7 +92,7 @@ pub enum SealingState {
} }
/// The number of generations back that uncles can be. /// The number of generations back that uncles can be.
pub const MAX_UNCLE_AGE: usize = 6; pub const MAX_UNCLE_AGE: u64 = 6;
/// Default EIP-210 contract code. /// Default EIP-210 contract code.
/// As defined in https://github.com/ethereum/EIPs/pull/210 /// As defined in https://github.com/ethereum/EIPs/pull/210

View File

@ -44,12 +44,9 @@ pub enum BlockError {
/// Uncles hash in header is invalid. /// Uncles hash in header is invalid.
#[display(fmt = "Block has invalid uncles hash: {}", _0)] #[display(fmt = "Block has invalid uncles hash: {}", _0)]
InvalidUnclesHash(Mismatch<H256>), InvalidUnclesHash(Mismatch<H256>),
/// An uncle is from a generation too old. /// An uncle is from a wrong generation.
#[display(fmt = "Uncle block is too old. {}", _0)] #[display(fmt = "Uncle block is too old. {}", _0)]
UncleTooOld(OutOfBounds<BlockNumber>), UncleOutOfBounds(OutOfBounds<BlockNumber>),
/// An uncle is from the same generation as the block.
#[display(fmt = "Uncle from same generation as block. {}", _0)]
UncleIsBrother(OutOfBounds<BlockNumber>),
/// An uncle is already in the chain. /// An uncle is already in the chain.
#[display(fmt = "Uncle {} already in chain", _0)] #[display(fmt = "Uncle {} already in chain", _0)]
UncleInChain(H256), UncleInChain(H256),

View File

@ -179,30 +179,22 @@ fn verify_uncles(block: &PreverifiedBlock, bc: &dyn BlockProvider, engine: &dyn
return Err(From::from(BlockError::DuplicateUncle(uncle.hash()))) return Err(From::from(BlockError::DuplicateUncle(uncle.hash())))
} }
// m_currentBlock.number() - uncle.number() m_cB.n - uP.n() // uncle.number() needs to be within specific number range which is
// 1 2 // [header.number() - MAX_UNCLE_AGE, header.number() - 1]
// 2 //
// 3 // depth is the difference between uncle.number() and header.number()
// 4 // and the previous condition implies that it is always in range
// 5 // [1, MAX_UNCLE_AGE]
// 6 7 let depth = if header.number() > uncle.number() &&
// (8 Invalid) uncle.number() + MAX_UNCLE_AGE >= header.number() {
header.number() - uncle.number()
let depth = if header.number() > uncle.number() { header.number() - uncle.number() } else { 0 }; } else {
if depth > MAX_UNCLE_AGE as u64 { return Err(BlockError::UncleOutOfBounds(OutOfBounds {
return Err(From::from(BlockError::UncleTooOld(OutOfBounds { min: Some(header.number() - MAX_UNCLE_AGE),
min: Some(header.number() - depth),
max: Some(header.number() - 1), max: Some(header.number() - 1),
found: uncle.number() found: uncle.number()
}))); }).into());
} };
else if depth < 1 {
return Err(From::from(BlockError::UncleIsBrother(OutOfBounds {
min: Some(header.number() - depth),
max: Some(header.number() - 1),
found: uncle.number()
})));
}
// cB // cB
// cB.p^1 1 depth, valid uncle // cB.p^1 1 depth, valid uncle
@ -215,7 +207,7 @@ fn verify_uncles(block: &PreverifiedBlock, bc: &dyn BlockProvider, engine: &dyn
// cB.p^8 // cB.p^8
let mut expected_uncle_parent = header.parent_hash().clone(); let mut expected_uncle_parent = header.parent_hash().clone();
let uncle_parent = bc.block_header_data(&uncle.parent_hash()) let uncle_parent = bc.block_header_data(&uncle.parent_hash())
.ok_or_else(|| Error::from(BlockError::UnknownUncleParent(*uncle.parent_hash())))?; .ok_or_else(|| BlockError::UnknownUncleParent(*uncle.parent_hash()))?;
for _ in 0..depth { for _ in 0..depth {
match bc.block_details(&expected_uncle_parent) { match bc.block_details(&expected_uncle_parent) {
Some(details) => { Some(details) => {