amadeus_runtime/consensus/bic/
sol_difficulty.rs

1use std::cmp::{max, min};
2
3const TARGET_SOLS_EPOCH: u64 = 380_000;
4
5const TOL_NUM: u64 = 1;
6const TOL_DEN: u64 = 10;
7
8const MAX_STEP_DOWN: u32 = 3;
9const MAX_STEP_UP: u32 = 2;
10const UP_SLOWDOWN: u32 = 2;
11
12const DIFF_MIN_BITS: u32 = 20;
13const DIFF_MAX_BITS: u32 = 64;
14
15fn clamp_bits(b: u32) -> u32 {
16    max(DIFF_MIN_BITS, min(b, DIFF_MAX_BITS))
17}
18
19fn ceil_div(a: u64, b: u64) -> u64 {
20    (a + b - 1) / b
21}
22
23fn ilog2_floor(n: u64) -> u32 {
24    if n < 1 {
25        return 0;
26    }
27    63 - n.leading_zeros()
28}
29
30fn ceil_log2_ratio(a: u64, b: u64) -> u32 {
31    if a <= b {
32        return 0;
33    }
34    let d0 = ilog2_floor(a) - ilog2_floor(b);
35    if b << d0 >= a { d0 } else { d0 + 1 }
36}
37
38pub fn next(prev_bits: u32, sols: u64) -> u32 {
39    let target = TARGET_SOLS_EPOCH;
40
41    let lo = max(1, (target * (TOL_DEN - TOL_NUM) + TOL_DEN / 2) / TOL_DEN);
42    let hi = (target * (TOL_DEN + TOL_NUM) + TOL_DEN / 2) / TOL_DEN;
43
44    if sols == 0 {
45        clamp_bits(prev_bits.saturating_sub(min(MAX_STEP_DOWN, 3)))
46    } else if sols > hi {
47        let raw = ceil_log2_ratio(sols, target);
48        let delta = max(1, min(MAX_STEP_UP, ceil_div(raw as u64, UP_SLOWDOWN as u64) as u32));
49        clamp_bits(prev_bits + delta)
50    } else if sols < lo {
51        let delta = max(1, min(MAX_STEP_DOWN, ceil_log2_ratio(target, max(sols, 1))));
52        clamp_bits(prev_bits.saturating_sub(delta))
53    } else {
54        prev_bits
55    }
56}