Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
90d077e
Update Readme
clementblaudeau Aug 4, 2025
eaf198d
Add rewriting lemmas
clementblaudeau Aug 4, 2025
8eca698
Add the Lean Barrett example
clementblaudeau Aug 4, 2025
1ef0334
Add the Lean Chacha20 example
clementblaudeau Aug 4, 2025
64737f0
Update README
clementblaudeau Aug 4, 2025
5fe0411
Turn the proof-libs/lean into a proper lean library package
clementblaudeau Aug 5, 2025
4daaeae
Extract pure facts out of preconditions on specification theorems
clementblaudeau Aug 5, 2025
f80e1f2
Finish panic freedom proof of Chacha20
clementblaudeau Aug 5, 2025
899a794
Update lib import for lean barrett
clementblaudeau Aug 5, 2025
a33b7fd
Add run instructions
clementblaudeau Aug 5, 2025
040452b
Update makefiles in examples
clementblaudeau Aug 6, 2025
6c36477
proof-lib/lean Add Xor + fix bug in gt/ge
clementblaudeau Aug 6, 2025
ee782a3
proof-lib/lean Move scoped attributes into a shared namespace
clementblaudeau Aug 6, 2025
b438ad6
Lean_chacha20 add proof of hacspec helpers
clementblaudeau Aug 6, 2025
19afead
Update Readme
clementblaudeau Aug 6, 2025
2aa10c6
Update testcase
clementblaudeau Aug 6, 2025
a0f0196
Update Readme and lakefile
clementblaudeau Aug 6, 2025
65f3961
Add Apache Standard License Header
clementblaudeau Aug 7, 2025
2eff826
Changed relative path to hax library
clementblaudeau Aug 13, 2025
70cb738
Merge branch 'main' into lean-dev-examples
clementblaudeau Aug 14, 2025
0705e68
Update examples/README.md
clementblaudeau Aug 20, 2025
0287b2d
Merge branch 'main' into lean-dev-examples
clementblaudeau Aug 20, 2025
1d60924
Merge remote-tracking branch 'origin/main' into lean-dev-examples
clementblaudeau Aug 20, 2025
e1686c6
Update CI to install lean before running the examples
clementblaudeau Aug 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions examples/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[workspace]
members = [
"chacha20",
"lean_chacha20",
"lean_barrett",
"limited-order-book",
"sha256",
"barrett",
Expand All @@ -13,4 +15,3 @@ resolver = "2"
[workspace.dependencies]
hax-lib = { path = "../hax-lib" }
hax-bounded-integers = { path = "../hax-bounded-integers" }

4 changes: 4 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ default:
make -C barrett
make -C kyber_compress
make -C proverif-psk
make -C lean_chacha20
make -C lean_barrett

clean:
make -C limited-order-book clean
Expand All @@ -14,3 +16,5 @@ clean:
make -C barrett clean
make -C kyber_compress clean
make -C proverif-psk clean
make -C lean_chacha20 clean
make -C lean_barrett clean
54 changes: 51 additions & 3 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

<details>
<summary><b>Requirements</b></summary>

First, make sure to have hax installed in PATH. Then:

* With Nix, `nix develop .#examples` setups a shell automatically for you.

* Without Nix:
1. install F* `v2025.03.25`<!---FSTAR_VERSION--> manually (see https://github.com/FStarLang/FStar/blob/master/INSTALL.md);
1. make sure to have `fstar.exe` in PATH;
Expand All @@ -39,3 +39,51 @@ Note the generated modules live in the

For those examples, we generated Coq modules without typechecking them.
The `<EXAMPLE>/proofs/coq/extraction` folders contain the generated Coq modules.

## Lean

Two examples are fine-tuned to showcase the Lean backend: `lean_barrett` and
`lean_chacha20`. For both, the lean extraction can be obtained by running `cargo
hax into lean`

### Barrett

The *Barrett reduction* allows to compute remainders without using divisions. It
showcases arithmetic operations, conversions between integer types (namely `i32`
and `i64`). The Lean backend provides *panicking* arithmetic operations `+?`,
`-?`, etc, that panic on overflows.

For the Lean extracted code, we prove panic freedom with regards to those
arithmetic operations, and then we prove that the result is indeed the modulus
(as long as the absolute value of the input is lower than the bound
`BARRETT_R`). The proof is made via bit-blasting (using Lean's `bv_decide`). To
limit the computation time, the bound `BARRETT_R` was lowered compared to the
normal example in the `barrett` folder.

The proofs are backported in the rust code (in `lean_barrett/src/lib.rs`): doing
`cargo hax into lean` extracts a valid lean file that contains the proof.

The proof can be run by doing (requires `lake`):

```sh
cd lean_barrett/
make
```

### Chacha20

The Chacha20 example extracts to Lean, but requires a manual edit to be
wellformed. It showcases array, vector and slices accesses, as well as loops
(with loop invariants). For the Lean extracted code, we prove panic freedom,
which involves arithmetic on size of arrays.

This edit and the proofs of panic freedom can be found in
`lean_chacha20/proofs/lean/extraction/lean_chacha20_manual_edit.lean`.

The extraction (in `lean_chacha20.lean`) and rerun of the proofs (in
`lean_chacha20_manual_edit.lean`) can be done by doing (requires `lake`):

```sh
cd lean_chacha20/
make
```
9 changes: 9 additions & 0 deletions examples/lean_barrett/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "lean_barrett"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hax-lib.workspace = true
8 changes: 8 additions & 0 deletions examples/lean_barrett/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.PHONY: default lean clean
default:
cargo hax into lean
cd proofs/lean/extraction && lake build

clean:
rm -f proofs/lean/extraction/lean_barrett.lean
cd proofs/lean/extraction && lake clean
10 changes: 10 additions & 0 deletions examples/lean_barrett/proofs/lean/extraction/lakefile.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "lean_barrett"
version = "0.1.0"
defaultTargets = ["lean_barrett"]

[[lean_lib]]
name = "lean_barrett"

[[require]]
name = "Hax"
path = "../../../../../hax-lib/proof-libs/lean"
73 changes: 73 additions & 0 deletions examples/lean_barrett/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use hax_lib as hax;
use hax_lib::lean;

/// Values having this type hold a representative 'x' of the Kyber field.
/// We use 'fe' as a shorthand for this type.
pub(crate) type FieldElement = i32;

#[hax_lib::lean::before("@[simp, spec]")]
const BARRETT_R: i64 = 0x400000; // is 0x4000000 in the normal barrett example

#[hax_lib::lean::before("@[simp, spec]")]
const BARRETT_SHIFT: i64 = 26;

#[hax_lib::lean::before("@[simp, spec]")]
const BARRETT_MULTIPLIER: i64 = 20159;

#[hax_lib::lean::before("@[simp, spec]")]
pub(crate) const FIELD_MODULUS: i32 = 3329;

/// Signed Barrett Reduction
///
/// Given an input `value`, `barrett_reduce` outputs a representative `result`
/// such that:
///
/// - result ≡ value (mod FIELD_MODULUS)
/// - the absolute value of `result` is bound as follows:
///
/// `|result| ≤ FIELD_MODULUS / 2 · (|value|/BARRETT_R + 1)
///
/// In particular, if `|value| < BARRETT_R`, then `|result| < FIELD_MODULUS`.
#[hax::requires((i64::from(value) >= -BARRETT_R && i64::from(value) <= BARRETT_R))]
#[hax::ensures(|result| {
let valid_result = value % FIELD_MODULUS;
result > -FIELD_MODULUS
&& result < FIELD_MODULUS
&& (result == valid_result ||
result == valid_result + FIELD_MODULUS ||
result == valid_result - FIELD_MODULUS)
})]
#[hax_lib::lean::before("@[simp, spec]")]
#[hax_lib::lean::after("
theorem barrett_spec (value: i32) :
⦃ __requires (value) = pure true ⦄
(barrett_reduce value)
⦃ ⇓ result => __ensures value result = pure true ⦄
:= by
mvcgen [__requires, __ensures]
hax_bv_decide
simp [__requires, __ensures] at *
rw [Int32.HaxRem_spec_bv_rw] ; simp ;
rw [Int32.HaxAdd_spec_bv_rw] ; simp ;
rw [Int32.HaxSub_spec_bv_rw] ; simp
hax_bv_decide
expose_names
have ⟨ h1, h2 ⟩ := h; clear h
simp [Int32.eq_iff_toBitVec_eq,
Int32.lt_iff_toBitVec_slt,
Int32.le_iff_toBitVec_sle,
Int64.eq_iff_toBitVec_eq,
Int64.lt_iff_toBitVec_slt,
Int64.le_iff_toBitVec_sle,
] at *
generalize Int32.toBitVec value = bv_value at * ; clear value
bv_decide (config := {timeout := 120})
")]
pub fn barrett_reduce(value: FieldElement) -> FieldElement {
let t = i64::from(value) * BARRETT_MULTIPLIER;
let t = t + (BARRETT_R >> 1);
let quotient = t >> BARRETT_SHIFT;
let quotient = quotient as i32;
let sub = quotient * FIELD_MODULUS;
value - sub
}
9 changes: 9 additions & 0 deletions examples/lean_chacha20/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "lean_chacha20"
version = "0.1.0"
authors = ["Clement Blaudeau <[email protected]>"]
edition = "2021"

[dependencies]
hax-lib.workspace = true
hax-bounded-integers.workspace = true
7 changes: 7 additions & 0 deletions examples/lean_chacha20/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.PHONY: default clean
default:
cargo hax into lean
cd proofs/lean/extraction && lake build

clean:
rm -f proofs/lean/extraction/lean_chacha20.lean
13 changes: 13 additions & 0 deletions examples/lean_chacha20/proofs/lean/extraction/lakefile.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name = "lean_chacha20"
version = "0.1.0"
defaultTargets = ["lean_chacha20_manual_edit"]

[[lean_lib]]
name = "lean_chacha20"

[[lean_lib]]
name = "lean_chacha20_manual_edit"

[[require]]
name = "Hax"
path = "../../../../../hax-lib/proof-libs/lean"
Loading
Loading