1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
crate::ix!();
pub fn get_next_work_required(
pindex_last: Arc<BlockIndex>,
pblock: Arc<BlockHeader>,
params: &ChainConsensusParams) -> u32 {
let n_proof_of_work_limit: u32 = uint_to_arith256(¶ms.pow_limit).get_compact(None);
if (((*pindex_last).n_height + 1) as i64) % params.difficulty_adjustment_interval() != 0 {
if params.pow_allow_min_difficulty_blocks {
if (*pblock).get_block_time() > (*pindex_last).get_block_time() + params.n_pow_target_spacing * 2 {
return n_proof_of_work_limit;
} else {
let mut pindex: Arc<BlockIndex> = pindex_last;;
while (*pindex).pprev.is_some()
&& ((*pindex).n_height as i64) % params.difficulty_adjustment_interval() != 0
&& (*pindex).n_bits == n_proof_of_work_limit
{
pindex = (*pindex).pprev.as_ref().unwrap().clone();
}
return (*pindex).n_bits;
}
}
return (*pindex_last).n_bits;
}
let n_height_first: i32 = (((*pindex_last).n_height as i64) - (params.difficulty_adjustment_interval() - 1)).try_into().unwrap();
assert!(n_height_first >= 0);
let pindex_first = pindex_last.clone().get_ancestor(n_height_first);
assert!(pindex_first.is_some());
calculate_next_work_required(
pindex_last.clone(),
pindex_first.unwrap().get_block_time(),
params
)
}
pub fn calculate_next_work_required(
pindex_last: Arc<BlockIndex>,
n_first_block_time: i64,
params: &ChainConsensusParams) -> u32 {
if params.pow_no_retargeting {
return (*pindex_last).n_bits;
}
let mut n_actual_timespan: i64 = (*pindex_last).get_block_time() - n_first_block_time;;
if n_actual_timespan < params.n_pow_target_timespan / 4 {
n_actual_timespan = params.n_pow_target_timespan / 4;
}
if n_actual_timespan > params.n_pow_target_timespan * 4 {
n_actual_timespan = params.n_pow_target_timespan * 4;
}
let bn_pow_limit: ArithU256 = uint_to_arith256(¶ms.pow_limit);;
let mut bn_new = ArithU256::default();
bn_new.set_compact((*pindex_last).n_bits, null_mut(), null_mut());
bn_new *= n_actual_timespan;
bn_new /= params.n_pow_target_timespan;
if bn_new > bn_pow_limit {
bn_new = bn_pow_limit;
}
bn_new.get_compact(None)
}
pub fn check_proof_of_work(
hash: u256,
n_bits: u32,
params: &ChainConsensusParams) -> bool {
let mut negative = bool::default();
let mut overflow = bool::default();
let mut bn_target = ArithU256::default();
bn_target.set_compact(n_bits, &mut negative, &mut overflow);
if negative || bn_target == ArithU256::from(0) || overflow || bn_target > uint_to_arith256(¶ms.pow_limit) {
return false;
}
if uint_to_arith256(&hash) > bn_target {
return false;
}
true
}