snarkvm_ledger/
is_solution_limit_reached.rs1use super::*;
17
18pub const STAKE_REQUIREMENTS_PER_SOLUTION: [(i64, u64); 9] = [
27 (1754006399i64, 100_000_000_000u64), (1761955199i64, 250_000_000_000u64), (1769903999i64, 500_000_000_000u64), (1777593599i64, 750_000_000_000u64), (1785542399i64, 1_000_000_000_000u64), (1793491199i64, 1_250_000_000_000u64), (1801439999i64, 1_500_000_000_000u64), (1809129599i64, 2_000_000_000_000u64), (1817078399i64, 2_500_000_000_000u64), ];
37
38pub fn maximum_allowed_solutions_per_epoch(prover_stake: u64, current_time: i64) -> u64 {
40 if current_time < STAKE_REQUIREMENTS_PER_SOLUTION.first().map(|(t, _)| *t).unwrap_or(i64::MAX) {
42 return u64::MAX;
43 }
44
45 let minimum_stake_per_solution_per_epoch =
47 match STAKE_REQUIREMENTS_PER_SOLUTION.binary_search_by_key(¤t_time, |(t, _)| *t) {
48 Ok(index) => STAKE_REQUIREMENTS_PER_SOLUTION[index].1,
50 Err(index) => STAKE_REQUIREMENTS_PER_SOLUTION[index.saturating_sub(1)].1,
52 };
53
54 prover_stake.saturating_div(minimum_stake_per_solution_per_epoch)
56}
57
58impl<N: Network, C: ConsensusStorage<N>> Ledger<N, C> {
59 pub fn num_remaining_solutions(&self, prover_address: &Address<N>, additional_solutions_in_block: u64) -> u64 {
61 let prover_stake = self.get_bonded_amount(prover_address).unwrap_or(0);
63
64 let maximum_allowed_solutions = maximum_allowed_solutions_per_epoch(prover_stake, self.latest_timestamp());
66
67 let prover_num_solutions_in_epoch = *self.epoch_provers_cache.read().get(prover_address).unwrap_or(&0);
69
70 let num_solutions = (prover_num_solutions_in_epoch as u64).saturating_add(additional_solutions_in_block);
72
73 maximum_allowed_solutions.saturating_sub(num_solutions)
75 }
76
77 pub fn is_solution_limit_reached(&self, prover_address: &Address<N>, additional_solutions_in_block: u64) -> bool {
79 let num_remaining_solutions = self.num_remaining_solutions(prover_address, additional_solutions_in_block);
81
82 num_remaining_solutions == 0
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 const ITERATIONS: u64 = 100;
92
93 #[test]
94 fn test_solution_limit_per_epoch() {
95 let mut rng = TestRng::default();
96
97 for _ in 0..ITERATIONS {
98 for window in STAKE_REQUIREMENTS_PER_SOLUTION.windows(2) {
99 let (prev_time, stake_per_solution) = window[0];
100 let (next_time, _) = window[1];
101
102 let timestamp = rng.gen_range(prev_time..next_time);
104 let prover_stake: u64 = rng.gen();
106 let expected_num_solutions = prover_stake / stake_per_solution;
107
108 assert_eq!(maximum_allowed_solutions_per_epoch(prover_stake, timestamp), expected_num_solutions,);
109 }
110 }
111 }
112
113 #[test]
114 fn test_solution_limit_before_enforcement() {
115 let mut rng = TestRng::default();
116
117 let first_timestamp = STAKE_REQUIREMENTS_PER_SOLUTION.first().unwrap().0;
119 let time_before_first = first_timestamp - 1;
120
121 let prover_stake = 0;
123 assert_eq!(maximum_allowed_solutions_per_epoch(prover_stake, time_before_first), u64::MAX);
124
125 for _ in 0..ITERATIONS {
127 assert_eq!(maximum_allowed_solutions_per_epoch(rng.gen(), rng.gen_range(0..time_before_first)), u64::MAX);
128 }
129 }
130
131 #[test]
132 fn test_solution_limit_after_final_timestamp() {
133 let mut rng = TestRng::default();
134 let (last_timestamp, stake_per_solution) = *STAKE_REQUIREMENTS_PER_SOLUTION.last().unwrap();
135
136 for _ in 0..ITERATIONS {
138 let prover_stake: u64 = rng.gen();
139 let time_after_last = rng.gen_range(last_timestamp..i64::MAX);
140 let expected_num_solutions = prover_stake / stake_per_solution;
141
142 assert_eq!(maximum_allowed_solutions_per_epoch(prover_stake, time_after_last), expected_num_solutions);
143 }
144 }
145
146 #[test]
147 fn test_solution_limit_exact_timestamps() {
148 let mut rng = TestRng::default();
149 for &(timestamp, stake_per_solution) in STAKE_REQUIREMENTS_PER_SOLUTION.iter() {
151 let expected_num_solutions = rng.gen_range(1..=100);
152 let prover_stake = expected_num_solutions * stake_per_solution;
153
154 assert_eq!(maximum_allowed_solutions_per_epoch(prover_stake, timestamp), expected_num_solutions,);
155 }
156 }
157}