amadeus_runtime/consensus/bic/
sol_difficulty.rs1use 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}