krabka_verified/consensus/
log_is_up_to_date.rs1#[cfg(creusot)]
2use super::{count_ge, count_ge_prefix, hwm_member_at, valid_hwm_majority};
3use creusot_std::prelude::*;
4
5#[cfg(creusot)]
7#[cfg_attr(test, mutants::skip)]
8#[logic]
9#[requires(0 <= limit && limit <= s.len() + 1)]
10#[requires(low <= high)]
11#[ensures(count_ge_prefix(log_end, s, low, limit, leader_counts)
12 >= count_ge_prefix(log_end, s, high, limit, leader_counts))]
13#[variant(limit)]
14pub fn lemma_count_ge_prefix_monotone(
15 log_end: Int,
16 s: Seq<i64>,
17 low: Int,
18 high: Int,
19 limit: Int,
20 leader_counts: bool,
21) {
22 if limit > 0 {
23 lemma_count_ge_prefix_monotone(log_end, s, low, high, limit - 1, leader_counts);
24 }
25}
26
27#[cfg(creusot)]
29#[cfg_attr(test, mutants::skip)]
30#[logic]
31#[requires(0 <= limit && limit <= s.len() + 1)]
32#[ensures(count_ge_prefix(log_end, s, v, limit, leader_counts) >= 0)]
33#[variant(limit)]
34pub fn lemma_count_ge_prefix_nonnegative(
35 log_end: Int,
36 s: Seq<i64>,
37 v: Int,
38 limit: Int,
39 leader_counts: bool,
40) {
41 if limit > 0 {
42 lemma_count_ge_prefix_nonnegative(log_end, s, v, limit - 1, leader_counts);
43 }
44}
45
46#[cfg(creusot)]
48#[cfg_attr(test, mutants::skip)]
49#[logic]
50#[requires(0 < limit && limit <= s.len() + 1)]
51#[requires(count_ge_prefix(log_end, s, v, limit, leader_counts) >= 1)]
52#[ensures(0 <= result && result < limit)]
53#[ensures(hwm_member_at(log_end, s, result) >= v)]
54#[ensures(count_ge_prefix(log_end, s, hwm_member_at(log_end, s, result), limit, leader_counts)
55 >= count_ge_prefix(log_end, s, v, limit, leader_counts))]
56#[variant(limit)]
57pub fn least_hwm_member_ge_index(
58 log_end: Int,
59 s: Seq<i64>,
60 v: Int,
61 limit: Int,
62 leader_counts: bool,
63) -> Int {
64 if limit <= 1 {
67 0
68 } else {
69 let last_index = limit - 1;
70 let last_member = hwm_member_at(log_end, s, last_index);
71 let previous_count = count_ge_prefix(log_end, s, v, last_index, leader_counts);
72 if last_member >= v {
73 if previous_count >= 1 {
74 let previous_index =
75 least_hwm_member_ge_index(log_end, s, v, last_index, leader_counts);
76 let previous_member = hwm_member_at(log_end, s, previous_index);
77 if last_member <= previous_member {
78 lemma_count_ge_prefix_monotone(
81 log_end,
82 s,
83 last_member,
84 previous_member,
85 last_index,
86 leader_counts,
87 );
88 last_index
89 } else {
90 previous_index
93 }
94 } else {
95 lemma_count_ge_prefix_nonnegative(log_end, s, v, last_index, leader_counts);
99 lemma_count_ge_prefix_nonnegative(
100 log_end,
101 s,
102 last_member,
103 last_index,
104 leader_counts,
105 );
106 last_index
107 }
108 } else {
109 least_hwm_member_ge_index(log_end, s, v, last_index, leader_counts)
111 }
112 }
113}
114
115#[cfg(creusot)]
117#[cfg_attr(test, mutants::skip)]
118#[requires(valid_hwm_majority(majority@, [email protected]()))]
119#[ensures(forall<v: Int> count_ge(log_end@, s@, v, leader_counts) >= majority@
120 ==> exists<k: Int> hwm_member_witness(log_end@, s@, k, v, majority@, leader_counts))]
121pub fn lemma_hwm_threshold_has_member(
122 log_end: i64,
123 s: &[i64],
124 majority: usize,
125 leader_counts: bool,
126) {
127 proof_assert!(forall<v: Int> count_ge(log_end@, s@, v, leader_counts) >= majority@ ==>
128 exists<k: Int> k == least_hwm_member_ge_index(log_end@, s@, v, [email protected]() + 1, leader_counts)
129 && hwm_member_witness(log_end@, s@, k, v, majority@, leader_counts));
130}
131
132#[cfg(creusot)]
134#[cfg_attr(test, mutants::skip)]
135#[requires(valid_hwm_majority(majority@, [email protected]()))]
136#[requires(forall<k: Int> 0 <= k && k < [email protected]() + 1
137 && count_ge(log_end@, s@, hwm_member_at(log_end@, s@, k), leader_counts) >= majority@
138 ==> hwm_member_at(log_end@, s@, k) <= best@)]
139#[ensures(forall<v: Int> count_ge(log_end@, s@, v, leader_counts) >= majority@ ==> v <= best@)]
140pub fn lemma_hwm_member_maximal(
141 log_end: i64,
142 s: &[i64],
143 majority: usize,
144 best: i64,
145 leader_counts: bool,
146) {
147 lemma_hwm_threshold_has_member(log_end, s, majority, leader_counts);
148}
149
150#[ensures(base_ms@ == 0 ==> result@ == 0)]
160#[ensures(base_ms@ > 0 ==> result@ < base_ms@)]
161#[must_use]
162pub fn election_jitter_ms(me: u64, epoch: u32, base_ms: u64) -> u64 {
163 if base_ms == 0 {
164 return 0;
165 }
166 let mix = me.wrapping_mul(0x9E37_79B9_7F4A_7C15)
169 ^ u64::from(epoch).wrapping_mul(0xD1B5_4A32_D192_ED03);
170 mix % base_ms
171}
172
173#[ensures(result == (cand_epoch@ > my_epoch@
178 || (cand_epoch@ == my_epoch@ && cand_offset@ >= my_end@)))]
179#[must_use]
180pub const fn log_is_up_to_date(
181 my_epoch: u32,
182 my_end: i64,
183 cand_epoch: u32,
184 cand_offset: i64,
185) -> bool {
186 cand_epoch > my_epoch || (cand_epoch == my_epoch && cand_offset >= my_end)
187}
188
189#[cfg(creusot)]
191#[cfg_attr(test, mutants::skip)]
192#[logic(open)]
193fn hwm_member_witness(
195 end: Int,
196 offsets: Seq<i64>,
197 index: Int,
198 value: Int,
199 majority: Int,
200 leader_counts: bool,
201) -> bool {
202 pearlite! { 0 <= index && index < offsets.len() + 1 && hwm_member_at(end, offsets, index) >= value
203 && count_ge(end, offsets, hwm_member_at(end, offsets, index), leader_counts) >= majority }
204}