pub fn check_achieved_and_target_difficulty<B: BlockchainBackend>(
    db: &B,
    block_header: &BlockHeader,
    height: u64,
    rules: ConsensusManager,
) -> Result<(), ValidationError>
{
    let pow_algo = block_header.pow.pow_algo;
    // Monero has extra data to check.
    if pow_algo == PowAlgorithm::Monero {
        MoneroData::new(&block_header).map_err(|e| ValidationError::CustomError(e.to_string()))?;
        // TODO: We need some way of getting the seed height and or count.
        // Current proposals are to either store the height of first seed use, or count the seed use.
        let seed_height = 0;
        if (seed_height != 0) &&
            (block_header.height - seed_height >
                rules.consensus_constants(block_header.height).max_randomx_seed_height())
        {
            return Err(ValidationError::BlockHeaderError(
                BlockHeaderValidationError::OldSeedHash,
            ));
        }
    }
    let achieved = block_header.achieved_difficulty()?;
    // This tests the target diff.
    let target = if block_header.height > 0 || rules.get_genesis_block_hash() != block_header.hash() {
        let constants = rules.consensus_constants(block_header.height);
        let block_window = constants.get_difficulty_block_window() as usize;
        let target_difficulties = db.fetch_target_difficulties(pow_algo, height, block_window)?;
        get_target_difficulty(
            target_difficulties,
            block_window,
            constants.get_diff_target_block_interval(pow_algo),
            constants.min_pow_difficulty(pow_algo),
            constants.max_pow_difficulty(pow_algo),
            constants.get_difficulty_max_block_interval(pow_algo),
        )
        .map_err(|e| {
            error!(target: LOG_TARGET, "Validation could not get target difficulty: {}", e);
            ValidationError::BlockHeaderError(BlockHeaderValidationError::ProofOfWorkError(
                PowError::InvalidProofOfWork,
            ))
        })?
    } else {
        1.into()
    };
    if block_header.pow.target_difficulty != target {
        warn!(
            target: LOG_TARGET,
            "Recorded header target difficulty {} was incorrect: {}", block_header.pow.target_difficulty, target
        );
        return Err(ValidationError::BlockHeaderError(
            BlockHeaderValidationError::ProofOfWorkError(PowError::InvalidTargetDifficulty),
        ));
    }
    // Now lets compare the achieved and target.
    if achieved < target {
        warn!(
            target: LOG_TARGET,
            "Proof of work for {} was below the target difficulty. Achieved: {}, Target:{}",
            block_header.hash().to_hex(),
            achieved,
            target
        );
        return Err(ValidationError::BlockHeaderError(
            BlockHeaderValidationError::ProofOfWorkError(PowError::AchievedDifficultyTooLow { achieved, target }),
        ));
    }
    Ok(())
}
/// Calculates the achieved and target difficulties at the specified height and compares them.
Calculates the achieved and target difficulties at the specified height and compares them.
Calculates the achieved and target difficulties at the specified height and compares them .
pub fn check_achieved_and_target_difficulty<B: BlockchainBackend>(
    db: &B,
    block_header: &BlockHeader,
    height: u64,
    rules: ConsensusManager,
) -> Result<(), ValidationError>
{
    let pow_algo = block_header.pow.pow_algo;
    // Monero has extra data to check.
    if pow_algo == PowAlgorithm::Monero {
        MoneroData::new(&block_header).map_err(|e| ValidationError::CustomError(e.to_string()))?;
        // TODO: We need some way of getting the seed height and or count.
        // Current proposals are to either store the height of first seed use, or count the seed use.
        let seed_height = 0;
        if (seed_height != 0) &&
            (block_header.height - seed_height >
                rules.consensus_constants(block_header.height).max_randomx_seed_height())
        {
            return Err(ValidationError::BlockHeaderError(
                BlockHeaderValidationError::OldSeedHash,
            ));
        }
    }
    let achieved = block_header.achieved_difficulty()?;
    // This tests the target diff.
    let target = if block_header.height > 0 || rules.get_genesis_block_hash() != block_header.hash() {
        let constants = rules.consensus_constants(block_header.height);
        let block_window = constants.get_difficulty_block_window() as usize;
        let target_difficulties = db.fetch_target_difficulties(pow_algo, height, block_window)?;
        get_target_difficulty(
            target_difficulties,
            block_window,
            constants.get_diff_target_block_interval(pow_algo),
            constants.min_pow_difficulty(pow_algo),
            constants.max_pow_difficulty(pow_algo),
            constants.get_difficulty_max_block_interval(pow_algo),
        )
        .map_err(|e| {
            error!(target: LOG_TARGET, "Validation could not get target difficulty: {}", e);
            ValidationError::BlockHeaderError(BlockHeaderValidationError::ProofOfWorkError(
                PowError::InvalidProofOfWork,
            ))
        })?
    } else {
        1.into()
    };
    if block_header.pow.target_difficulty != target {
        warn!(
            target: LOG_TARGET,
            "Recorded header target difficulty {} was incorrect: {}", block_header.pow.target_difficulty, target
        );
        return Err(ValidationError::BlockHeaderError(
            BlockHeaderValidationError::ProofOfWorkError(PowError::InvalidTargetDifficulty),
        ));
    }
    // Now lets compare the achieved and target.
    if achieved < target {
        warn!(
            target: LOG_TARGET,
            "Proof of work for {} was below the target difficulty. Achieved: {}, Target:{}",
            block_header.hash().to_hex(),
            achieved,
            target
        );
        return Err(ValidationError::BlockHeaderError(
            BlockHeaderValidationError::ProofOfWorkError(PowError::AchievedDifficultyTooLow { achieved, target }),
        ));
    }
    Ok(())
}
pub fn check_achieved_and_target_difficulty < B : BlockchainBackend > ( db : & B , block_header : & BlockHeader , height : u64 , rules : ConsensusManager , ) -> Result < ( ) , ValidationError > { let pow_algo = block_header . pow . pow_algo ; // Monero has extra data to check. if pow_algo == PowAlgorithm :: Monero { MoneroData :: new ( & block_header ) . map_err ( | e | ValidationError :: CustomError ( e . to_string ( ) ) ) ? ; // TODO: We need some way of getting the seed height and or count. // Current proposals are to either store the height of first seed use, or count the seed use. let seed_height = 0 ; if ( seed_height != 0 ) && ( block_header . height - seed_height > rules . consensus_constants ( block_header . height ) . max_randomx_seed_height ( ) ) { return Err ( ValidationError :: BlockHeaderError ( BlockHeaderValidationError :: OldSeedHash , ) ) ; } } let achieved = block_header . achieved_difficulty ( ) ? ; // This tests the target diff. let target = if block_header . height > 0 || rules . get_genesis_block_hash ( ) != block_header . hash ( ) { let constants = rules . consensus_constants ( block_header . height ) ; let block_window = constants . get_difficulty_block_window ( ) as usize ; let target_difficulties = db . fetch_target_difficulties ( pow_algo , height , block_window ) ? ; get_target_difficulty ( target_difficulties , block_window , constants . get_diff_target_block_interval ( pow_algo ) , constants . min_pow_difficulty ( pow_algo ) , constants . max_pow_difficulty ( pow_algo ) , constants . get_difficulty_max_block_interval ( pow_algo ) , ) . map_err ( | e | { error ! ( target LOG_TARGET " " e ) ; ValidationError :: BlockHeaderError ( BlockHeaderValidationError :: ProofOfWorkError ( PowError :: InvalidProofOfWork , ) ) } ) ? } else { 1 . into ( ) } ; if block_header . pow . target_difficulty != target { warn ! ( target LOG_TARGET " " block_header pow target_difficulty target ) ; return Err ( ValidationError :: BlockHeaderError ( BlockHeaderValidationError :: ProofOfWorkError ( PowError :: InvalidTargetDifficulty ) , ) ) ; } // Now lets compare the achieved and target. if achieved < target { warn ! ( target LOG_TARGET " " block_header hash ( ) to_hex ( ) achieved target ) ; return Err ( ValidationError :: BlockHeaderError ( BlockHeaderValidationError :: ProofOfWorkError ( PowError :: AchievedDifficultyTooLow { achieved , target } ) , ) ) ; } Ok ( ( ) ) }
Calculates the achieved and target difficulties at the specified height and compares them.
Calculates the achieved and target difficulties at the specified height and compares them .
db
&B
block_header
&BlockHeader
height
u64
rules
ConsensusManager
db
&B
block_header
&BlockHeader
height
u64
rules
ConsensusManager