diff --git a/zebra-consensus/src/block.rs b/zebra-consensus/src/block.rs index b170d0a3..c341906c 100644 --- a/zebra-consensus/src/block.rs +++ b/zebra-consensus/src/block.rs @@ -135,18 +135,7 @@ where // Do the difficulty checks first, to raise the threshold for // attacks that use any other fields. - let difficulty_threshold = block - .header - .difficulty_threshold - .to_expanded() - .ok_or(BlockError::InvalidDifficulty(height, hash))?; - if hash > difficulty_threshold { - Err(BlockError::DifficultyFilter( - height, - hash, - difficulty_threshold, - ))?; - } + check::difficulty_is_valid(&block.header, &height, &hash)?; check::equihash_solution_is_valid(&block.header)?; // Since errors cause an early exit, try to do the diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index ece3453e..5d7f8e02 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -3,6 +3,8 @@ use chrono::{DateTime, Utc}; use zebra_chain::{ + block::Hash, + block::Height, block::{Block, Header}, parameters::NetworkUpgrade, work::equihash, @@ -39,6 +41,35 @@ pub fn coinbase_is_first(block: &Block) -> Result<(), BlockError> { Ok(()) } +/// Returns `Ok(())` if `hash` passes the difficulty filter and PoW limit, +/// based on the fields in `header`. +/// +/// If the block is invalid, returns an error containing `height` and `hash`. +pub fn difficulty_is_valid( + header: &Header, + height: &Height, + hash: &Hash, +) -> Result<(), BlockError> { + // TODO: + // - PoW limit + + let difficulty_threshold = header + .difficulty_threshold + .to_expanded() + .ok_or(BlockError::InvalidDifficulty(*height, *hash))?; + + // Difficulty filter + if hash > &difficulty_threshold { + Err(BlockError::DifficultyFilter( + *height, + *hash, + difficulty_threshold, + ))?; + } + + Ok(()) +} + /// Returns `Ok(())` if the `EquihashSolution` is valid for `header` pub fn equihash_solution_is_valid(header: &Header) -> Result<(), equihash::Error> { header.solution.check(&header)