Skip to content

Commit

Permalink
test: Avoid magic constants
Browse files Browse the repository at this point in the history
Co-authored-by: Alan Szepieniec <[email protected]>
  • Loading branch information
Sword-Smith and aszepieniec committed Jan 24, 2025
1 parent 2c45029 commit aa42608
Showing 1 changed file with 41 additions and 24 deletions.
65 changes: 41 additions & 24 deletions src/models/blockchain/block/difficulty_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,12 +468,6 @@ pub(crate) fn max_cumulative_pow_after(
difficulty_start: Difficulty,
num_blocks: usize,
) -> ProofOfWork {
// Avoid spending too much time in below loop and return early on silly
// input values.
if num_blocks > 1_000_000_000 {
return ProofOfWork::MAXIMUM;
}

// If the observed interval between consecutive blocks is the minimum
// allowed by the consensus rules, the clamped relative error is almost -1.
// In this case the PID adjustment factor is
Expand All @@ -485,18 +479,25 @@ pub(crate) fn max_cumulative_pow_after(
/ 16.0;
let mut max_difficulty: f64 = BigUint::from(difficulty_start).to_f64().unwrap();
let mut max_cumpow: f64 = BigUint::from(cumulative_pow_start).to_f64().unwrap();
let cap = BigUint::from(ProofOfWork::MAXIMUM).to_f64().unwrap();
for _ in 0..num_blocks {
max_cumpow += max_difficulty;
max_difficulty *= f;

// Avoid spending more time in loop if we've already reached max.
if max_cumpow >= cap {
return ProofOfWork::MAXIMUM;
}
}

ProofOfWork::try_from(max_cumpow).unwrap_or_else(|_e| panic!("calculated max proof-of-work"))
// This conversion is safe and cannot panic.
ProofOfWork::try_from(max_cumpow).unwrap_or_else(|_e| {
panic!("max_cumpow is within bounds where successful conversion should be guaranteed")
})
}

#[cfg(test)]
mod test {
use std::usize;

use itertools::Itertools;
use num_bigint::BigInt;
use num_bigint::BigUint;
Expand All @@ -515,14 +516,7 @@ mod test {
use rand_distr::Geometric;
use test_strategy::proptest;

use super::difficulty_control;
use super::max_cumulative_pow_after;
use super::ProofOfWork;
use crate::models::blockchain::block::block_header::ADVANCE_DIFFICULTY_CORRECTION_FACTOR;
use crate::models::blockchain::block::block_header::ADVANCE_DIFFICULTY_CORRECTION_WAIT;
use crate::models::blockchain::block::block_height::BlockHeight;
use crate::models::blockchain::block::difficulty_control::Difficulty;
use crate::models::proof_abstractions::timestamp::Timestamp;
use super::*;

impl Difficulty {
pub(crate) fn from_biguint(bi: BigUint) -> Self {
Expand Down Expand Up @@ -820,7 +814,20 @@ mod test {
) -> ProofOfWork {
let mut cumulative_pow = cumulative_pow_start;
let mut difficulty = difficulty_start;
let f = (1u64 << 32) + (115 << 21);

// f = 1 + (MINIMUM_BLOCK_TIME - TARGET_BLOCK_INTERVAL) / TARGET_BLOCK_INTERVAL * P
// let f = (1u64 << 32) + (115 << 21);
// let second_term = (MINIMUM_BLOCK_TIME.to_millis() - TARGET_BLOCK_INTERVAL.to_millis())
// as f64
// / TARGET_BLOCK_INTERVAL.to_millis() as f64;
let f = (1.0_f64
+ (TARGET_BLOCK_INTERVAL.to_millis() - MINIMUM_BLOCK_TIME.to_millis()) as f64
/ TARGET_BLOCK_INTERVAL.to_millis() as f64
/ 16.0)
* (1u64 << 32) as f64;
let f = f as u64;
// let second_term_shift_amount = 32 - second_term.ilog2() - 1;
// let f = (1u64 << 32) + (second_term << second_term_shift_amount);
let lo = f as u32;
let hi = (f >> 32) as u32;
for _ in 0..num_blocks {
Expand Down Expand Up @@ -857,28 +864,38 @@ mod test {
let init_difficulty = Difficulty::from_u64(init_difficulty);
let calculated = max_cumulative_pow_after(init_cumpow, init_difficulty, num_blocks);

let upper_bound = max_cumulative_pow_after_iterative_test_impl(
let approximation = max_cumulative_pow_after_iterative_test_impl(
init_cumpow_upper_bound,
init_difficulty,
num_blocks,
);
println!("upper_bound: {upper_bound}");
println!("upper_bound: {approximation}");
println!("calculated: {calculated}");
println!("num_blocks: {num_blocks}");
prop_assert!(upper_bound >= calculated);
let approximation_as_f64 = BigUint::from(approximation).to_f64().unwrap();
let upper_bound = approximation_as_f64 * 1.01;
let lower_bound = approximation_as_f64 * 0.99;
let calculated_as_f64 = BigUint::from(calculated).to_f64().unwrap();
prop_assert!(upper_bound >= calculated_as_f64);
prop_assert!(lower_bound <= calculated_as_f64);
prop_assert!(calculated < ProofOfWork::MAXIMUM);
}

#[test]
fn test_sanity_max_pow_after() {
fn test_sanity_max_pow_after_unit() {
let init_cumpow = 100u64;
let init_cumpow = ProofOfWork::from_u64(init_cumpow);
let init_difficulty = Difficulty::from_u64(1000u64);
let num_blocks = 1000;
let calculated = max_cumulative_pow_after(init_cumpow, init_difficulty, num_blocks);
let upper_bound =
let approximation =
max_cumulative_pow_after_iterative_test_impl(init_cumpow, init_difficulty, num_blocks);
assert!(upper_bound >= calculated);
let approximation_as_f64 = BigUint::from(approximation).to_f64().unwrap();
let upper_bound = approximation_as_f64 * 1.01;
let lower_bound = approximation_as_f64 * 0.99;
let calculated_as_f64 = BigUint::from(calculated).to_f64().unwrap();
assert!(upper_bound >= calculated_as_f64);
assert!(lower_bound <= calculated_as_f64);
assert!(calculated < ProofOfWork::MAXIMUM);
}
}

0 comments on commit aa42608

Please sign in to comment.