diff --git a/base_layer/core/src/validation/block_validators/body_only.rs b/base_layer/core/src/validation/block_validators/body_only.rs index 0b2fbf0fd0..bfee04b11b 100644 --- a/base_layer/core/src/validation/block_validators/body_only.rs +++ b/base_layer/core/src/validation/block_validators/body_only.rs @@ -26,11 +26,15 @@ use tari_utilities::hex::Hex; use super::LOG_TARGET; use crate::{ - blocks::ChainBlock, + blocks::{BlockHeader, ChainBlock}, chain_storage, - chain_storage::BlockchainBackend, - consensus::ConsensusManager, - validation::{helpers, PostOrphanBodyValidation, ValidationError}, + chain_storage::{fetch_headers, BlockchainBackend}, + consensus::{ConsensusConstants, ConsensusManager}, + validation::{ + helpers::{self, check_header_timestamp_greater_than_median}, + PostOrphanBodyValidation, + ValidationError, + }, }; /// This validator tests whether a candidate block is internally consistent. @@ -46,6 +50,31 @@ impl BodyOnlyValidator { pub fn new(rules: ConsensusManager) -> Self { Self { rules } } + + /// This function tests that the block timestamp is greater than the median timestamp at the specified height. + fn check_median_timestamp( + &self, + db: &B, + constants: &ConsensusConstants, + block_header: &BlockHeader, + ) -> Result<(), ValidationError> { + if block_header.height == 0 { + return Ok(()); // Its the genesis block, so we dont have to check median + } + + let height = block_header.height - 1; + let min_height = block_header + .height + .saturating_sub(constants.get_median_timestamp_count() as u64); + let timestamps = fetch_headers(db, min_height, height)? + .iter() + .map(|h| h.timestamp) + .collect::>(); + + check_header_timestamp_greater_than_median(block_header, ×tamps)?; + + Ok(()) + } } impl PostOrphanBodyValidation for BodyOnlyValidator { @@ -61,6 +90,8 @@ impl PostOrphanBodyValidation for BodyOnlyValidator { block: &ChainBlock, metadata: &ChainMetadata, ) -> Result<(), ValidationError> { + let constants = self.rules.consensus_constants(block.header().height); + if block.header().prev_hash != *metadata.best_block() { return Err(ValidationError::IncorrectPreviousHash { expected: metadata.best_block().to_hex(), @@ -74,6 +105,8 @@ impl PostOrphanBodyValidation for BodyOnlyValidator { }); } + self.check_median_timestamp(backend, constants, block.header())?; + let block_id = format!("block #{} ({})", block.header().height, block.hash().to_hex()); helpers::check_inputs_are_utxos(backend, &block.block().body)?; helpers::check_outputs( diff --git a/base_layer/core/src/validation/header_validator.rs b/base_layer/core/src/validation/header_validator.rs index 97858bcd04..79e6d21e2b 100644 --- a/base_layer/core/src/validation/header_validator.rs +++ b/base_layer/core/src/validation/header_validator.rs @@ -33,31 +33,6 @@ impl HeaderValidator { pub fn new(rules: ConsensusManager) -> Self { Self { rules } } - - /// This function tests that the block timestamp is greater than the median timestamp at the specified height. - fn check_median_timestamp( - &self, - db: &B, - constants: &ConsensusConstants, - block_header: &BlockHeader, - ) -> Result<(), ValidationError> { - if block_header.height == 0 { - return Ok(()); // Its the genesis block, so we dont have to check median - } - - let height = block_header.height - 1; - let min_height = block_header - .height - .saturating_sub(constants.get_median_timestamp_count() as u64); - let timestamps = fetch_headers(db, min_height, height)? - .iter() - .map(|h| h.timestamp) - .collect::>(); - - check_header_timestamp_greater_than_median(block_header, ×tamps)?; - - Ok(()) - } } impl HeaderValidation for HeaderValidator { @@ -82,12 +57,6 @@ impl HeaderValidation for HeaderValidator "BlockHeader validation: FTL timestamp is ok for {} ", header_id ); - self.check_median_timestamp(backend, constants, header)?; - trace!( - target: LOG_TARGET, - "BlockHeader validation: Median timestamp is ok for {} ", - header_id - ); check_pow_data(header, &self.rules, backend)?; let achieved_target = difficulty_calculator.check_achieved_and_target_difficulty(backend, header)?; check_not_bad_block(backend, header.hash())?;