@@ -48,6 +48,7 @@ const BARRETT_SHIFT: i64 = 26;
4848const BARRETT_R: i64 = 0x4000000; // 2^26
4949const BARRETT_MULTIPLIER: i64 = 20159; // ⌊(BARRETT_R / FIELD_MODULUS) + 1/2⌋
5050
51+ #[hax_lib::fstar::options("--z3rlimit 100")]
5152#[hax_lib::requires((i64::from(value) >= -BARRETT_R && i64::from(value) <= BARRETT_R))]
5253#[hax_lib::ensures(|result| result > -FIELD_MODULUS && result < FIELD_MODULUS
5354 && result % FIELD_MODULUS == value % FIELD_MODULUS)]
@@ -60,9 +61,6 @@ fn barrett_reduce(value: i32) -> i32 {
6061
6162 let sub = quotient * FIELD_MODULUS;
6263
63- // Here a lemma to prove that `(quotient * 3329) % 3329 = 0`
64- // may have to be called in F*.
65-
6664 value - sub
6765}
6866```
@@ -71,13 +69,26 @@ fn barrett_reduce(value: i32) -> i32 {
7169effect, but in F*, that establishes that `(quotient * 3329) % 3329` is
7270zero. -->
7371
74- Before returning, a lemma may have to be called in F* to prove the correctness
75- of the reduction.
76- The lemma is ` Math.Lemmas.cancel_mul_mod (v quotient) 3329; ` , which establishes
77- that ` (quotient * 3329) % 3329 ` is zero.
78- With the help of that one lemma, F\* is able to prove the
79- reduction computes the expected result.
80- (We may expose lemmas like this to call from Rust directly in future.)
72+ The proof for the code above uses the Z3 SMT solver to prive the
73+ post-condition. Since the SMT solver needs to reason about non-linear
74+ arithmetic (multiplication, modulus, division) it needs more
75+ resources, hence we bump up the ` rlimit ` to 100 in an annotation above
76+ the function. With this annotation F* and Z3 are able to automatically
77+ verify this function. However, it is worth noting that the heuristic
78+ strategies used by Z3 for non-linear arithmetic may sometimes fail to
79+ complete in the given ` rlimit ` depending on the solver version or random
80+ number generator, so we often give Z3 a generous resource limit.
81+
82+ Conversely, instead of relying on the SMT solver, we can also
83+ elaborate the proof of this function by hand to make it more
84+ predictable. For example, before the final line of the function,
85+ we could call a mathematical lemma may have to help F* prove
86+ the correctness of the reduction. The lemma call would be:
87+ ```
88+ fstar!("Math.Lemmas.cancel_mul_mod (v quotient) 3329");
89+ ```
90+ This lemma establishes that ` (quotient * 3329) % 3329 ` is zero. We often use lemmas like
91+ these to limit our dependence on Z3.
8192
8293This Barrett reduction examples is taken from
8394[ libcrux] ( https://github.com/cryspen/libcrux/tree/main ) 's proof of
0 commit comments