Coherence pass 3: post-apex accuracy sweep, hygiene, guard ladder

- README: the pyramid diagram claimed the cofactored ZIP-215 equation,
  which is NOT the proven statement - corrected to the actual theorem
  (accepted IFF compress([s]B-[k]A) = R, byte-for-byte) and the signature
  row now names verify_accepts_iff; new "The signature apex (phase 1)"
  section states the theorem, this repo's glue architecture, the exact
  button-enforced axiom cone, and the phase-2 deferral.
- TRUSTED-BASE: item 5 rewritten from an aspirational hash paragraph to
  the structural boundary - certificate name, exact allowed cone, and the
  Phase 3b enforcement that fails the build on any deviation.
- Dead pre-merge artifacts removed: gen/CurveScalar, CurveScalar.llbc,
  extract-scalar.sh (the merged gen/CurveField universe is the single
  model; check-scalar.sh remains the scalar button, header updated).
- lean-guard: Guard 3a retry ladder (LEAN_MEM_WAIT_SEC) - a clamped run
  that dies on memory retries as headroom improves, converting ambient
  memory pressure from a deterministic abort into a delayed pass.

Fresh green buttons after these changes: check.sh (incl. Phase 3b apex
audit) + check-scalar.sh, both at shipped defaults, coherence pass 3
sweep 2026-07-05.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mrwulf 2026-07-05 11:48:17 +02:00
parent b7f3934dbd
commit e22e8a12ad
12 changed files with 110 additions and 1018 deletions

View file

@ -5,7 +5,7 @@ coherent proof pyramid in Lean 4 via the Charon/Aeneas transpilation pipeline:
``` ```
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ Signature (EdDSA verify) │ accepted ⇒ [8][S]B = [8]R + [8][k]A │ Signature (EdDSA verify) │ accepted ⇔ compress([s]B[k]A) = R
├──────────────────────────────┤ ├──────────────────────────────┤
│ Scalar arithmetic mod │ Scalar52 ops correct mod │ Scalar arithmetic mod │ Scalar52 ops correct mod
├──────────────────────────────┤ ├──────────────────────────────┤
@ -28,11 +28,42 @@ in this repository.
| Field 𝔽_p | `fieldImplementation` | ✅ proven | `[propext, Classical.choice, Quot.sound]` | | Field 𝔽_p | `fieldImplementation` | ✅ proven | `[propext, Classical.choice, Quot.sound]` |
| Group law (Edwards) | `edwardsImplementation` | ✅ proven | `[propext, Classical.choice, Quot.sound]` | | Group law (Edwards) | `edwardsImplementation` | ✅ proven | `[propext, Classical.choice, Quot.sound]` |
| Scalar mod | `scalarImplementation` (add ✅ sub ✅ mul ✅) | ✅ proven | `[propext, Classical.choice, Quot.sound]` | | Scalar mod | `scalarImplementation` (add ✅ sub ✅ mul ✅) | ✅ proven | `[propext, Classical.choice, Quot.sound]` |
| Signature (EdDSA) | `verifyEquation` (planned) | ⏳ planned | — | | Signature (EdDSA) | `verify_accepts_iff` | ✅ proven (phase 1) | standard three + the button-enforced SHA-512/wire-format boundary — see [The signature apex](#the-signature-apex-phase-1) |
Status legend: ✅ proven & axiom-audited · ⏳ in progress · ❌ not started. Status legend: ✅ proven & axiom-audited · ⏳ in progress · ❌ not started.
This table is updated only when `verification/check.sh` passes for the layer. This table is updated only when `verification/check.sh` passes for the layer.
## The signature apex (phase 1)
The apex certificate `CurveFieldProofs.verify_accepts_iff` is the literal EdDSA
acceptance criterion, proven about the extracted verifier:
> For a signature that parses, the verifier returns `Ok(())` **iff** the
> recomputed compressed point `compress([s]·B [k]·A)` equals the signature's
> `R`, byte-for-byte — where `k` is whatever scalar the opaque SHA-512 oracle
> produces from `(R, A, msg)`.
The recomputation runs entirely through the **proven** model: the vendored `ed25519-dalek` verify glue is extracted as `gen/CurveSig`, whose
hand-maintained externals import `gen/CurveField` — every curve and scalar call
resolves by fully-qualified name to a **proven** definition. Only SHA-512 (three
stateful wrapper calls) and the wire-format types stay opaque.
`check.sh` has a dedicated audit phase (Phase 3b) that fails the build unless
the apex certificate's axiom cone is **exactly**
`[propext, Classical.choice, Quot.sound]` + `{ed25519.Signature, sha2.Sha512, verifying.sha512_new, verifying.sha512_update, verifying.sha512_finalize_bytes, ed25519.Signature.to_bytes, signature.error.Error, signature.error.Error.new}`
— i.e. the three Lean foundations plus the documented SHA-512/wire-format
boundary. Zero curve, scalar, or backend axioms. The companion certificate
`verify_loop_full` (the 32-byte comparison loop computes array equality)
carries the standard three axioms only.
**Phase 2 (deferred, documented):** lifting the byte-level equation to the
point level (`[s]B [k]A = decompress R`) additionally needs `compress`
canonicity and a verified `decompress`; it is deliberately out of scope for
this milestone, mirroring the layer-by-layer phase split used below the apex.
## Source ## Source
- **Upstream**: [dalek-cryptography/curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek), commit `4cf8db2` - **Upstream**: [dalek-cryptography/curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek), commit `4cf8db2`
@ -58,13 +89,15 @@ cd verification
./check.sh # compiles EVERY shipped file + axiom-audits EVERY certificate ./check.sh # compiles EVERY shipped file + axiom-audits EVERY certificate
``` ```
The scalar layer has its own pair of buttons: The gen model is ONE merged universe (`gen/CurveField`: field + curve +
scalar + the verify path's reachable code), regenerated in full by
`extract.sh`. The scalar layer keeps its own check button:
```bash ```bash
./extract-scalar.sh # regenerates gen/CurveScalar (Scalar52 limb arithmetic) ./check-scalar.sh # compiles the merged gen + all scalar proofs (add, sub,
./check-scalar.sh # compiles the scalar gen + all scalar proofs (add, sub, # Montgomery mul, byte-parsing) and kernel-audits the
# Montgomery mul) and kernel-audits 10 certificates, # scalar certificates, incl. the scalarImplementation
# including the scalarImplementation aggregate # aggregate
``` ```

View file

@ -15,11 +15,18 @@ running Rust code. Everything else is machine-checked.
plumbing, formatting) are axiomatized as opaque symbols. The axiom audit plumbing, formatting) are axiomatized as opaque symbols. The axiom audit
proves none of these axioms enters the dependency cone of any certificate, proves none of these axioms enters the dependency cone of any certificate,
except where a model is explicitly listed below. except where a model is explicitly listed below.
5. **SHA-512 (signature layer only)**: the hash is modeled as an opaque 5. **The signature-apex boundary (signature layer only)**: the apex
function * → ℬ⁶⁴ with no algebraic properties assumed. The signature certificate `CurveFieldProofs.verify_accepts_iff` ("the verifier accepts
certificate has the shape "IF the hash model computes SHA-512, THEN an iff compress([s]·B [k]·A) = R byte-for-byte") is `#print axioms`-audited
accepted signature satisfies the EdDSA verification equation". The hash by check.sh Phase 3b against EXACTLY the standard three plus this
implementation itself is NOT verified. documented set, and the build fails on any deviation:
`ed25519.Signature` (wire-format type), the three SHA-512 wrapper
oracles `verifying.sha512_new/update/finalize_bytes` (+ the opaque
`sha2.Sha512` state type), `ed25519.Signature.to_bytes`, and
`signature.error.Error`/`Error.new` (opaque error type). The hash is an
oracle with no algebraic properties assumed — the theorem holds for
whatever bytes it produces; the SHA-512 implementation itself is NOT
verified. Zero curve, scalar, or backend axioms are in the cone.
6. **Compilation of Rust to machine code** (rustc backend) is out of scope, 6. **Compilation of Rust to machine code** (rustc backend) is out of scope,
as is side-channel behaviour (timing, speculation). The proofs are about as is side-channel behaviour (timing, speculation). The proofs are about
functional correctness at the MIR/LLBC level. functional correctness at the MIR/LLBC level.

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Scalar-layer check (Scalar52 arithmetic mod ). Compiles the gen model + the # Scalar-layer check (Scalar52 arithmetic mod ) — the layer is COMPLETE:
# proven foundation. add/sub (Range-loop reductions) and the Montgomery mul # add, sub, Montgomery mul, and the byte-parsing chain, all kernel-audited.
# path are in progress — see README. Guarded compiles throughout. # Runs against the merged gen/CurveField universe (the scalar module lives
# there since the merge; see extract.sh). Guarded compiles throughout.
set -uo pipefail set -uo pipefail
source ~/aeneas-toolchain/env.sh source ~/aeneas-toolchain/env.sh
HERE="$(cd "$(dirname "$0")" && pwd)" HERE="$(cd "$(dirname "$0")" && pwd)"

View file

@ -1,34 +0,0 @@
#!/usr/bin/env bash
# Regenerate the SCALAR-layer Lean model (gen/CurveScalar) from Rust.
#
# SCOPE: the Scalar52 limb backend (backend::serial::u64::scalar) — the
# iterator-free ARITHMETIC core: add/sub/mul/square/montgomery_reduce/
# from_bytes/to_bytes mod = 2²⁵² + 27742317777372353535851937790883648493.
# The high-level crate::scalar wrapper (Sum/Product/NAF/radix/byte-parsing,
# all iterator-heavy) is brought in only for the signature layer.
set -euo pipefail
source ~/aeneas-toolchain/env.sh
HERE="$(cd "$(dirname "$0")" && pwd)"
CRATE=~/GitClone/FormalVerification/sources/curve25519-dalek-source/curve25519-dalek
echo "[1/2] charon: Rust -> LLBC (scalar + Scalar52)"
cd "$CRATE"
charon cargo --preset=aeneas \
--start-from 'crate::backend::serial::u64::scalar::_::add' \
--start-from 'crate::backend::serial::u64::scalar::_::sub' \
--start-from 'crate::backend::serial::u64::scalar::_::mul' \
--start-from 'crate::backend::serial::u64::scalar::_::square' \
--start-from 'crate::backend::serial::u64::scalar::_::montgomery_mul' \
--start-from 'crate::backend::serial::u64::scalar::_::montgomery_square' \
--start-from 'crate::backend::serial::u64::scalar::_::montgomery_reduce' \
--start-from 'crate::backend::serial::u64::scalar::_::montgomery_invert' \
--start-from 'crate::backend::serial::u64::scalar::_::as_montgomery' \
--start-from 'crate::backend::serial::u64::scalar::_::from_montgomery' \
--start-from 'crate::backend::serial::u64::scalar::_::from_bytes_wide' \
--dest-file "$HERE/CurveScalar.llbc" \
-- --no-default-features
echo "[2/2] aeneas: LLBC -> Lean (split files, CurveScalar.* modules)"
cd "$HERE"
aeneas -backend lean -split-files -subdir CurveScalar -dest gen CurveScalar.llbc
echo "Done."

View file

@ -1,826 +0,0 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [curve25519_dalek]: function definitions
import Aeneas
import CurveScalar.Types
import CurveScalar.FunsExternal
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
/- You can remove the following line by using the CLI option `-all-computable`: -/
noncomputable section
namespace curve25519_dalek
/-- [curve25519_dalek::backend::serial::u64::constants::L]
Source: 'curve25519-dalek/src/backend/serial/u64/constants.rs', lines 129:0-135:3 -/
@[global_simps, irreducible]
def backend.serial.u64.constants.L : backend.serial.u64.scalar.Scalar52 :=
Array.make 5#usize [
671914833335277#u64, 3916664325105025#u64, 1367801#u64, 0#u64,
17592186044416#u64
]
/-- [curve25519_dalek::backend::serial::u64::constants::LFACTOR]
Source: 'curve25519-dalek/src/backend/serial/u64/constants.rs', lines 138:0-138:48 -/
@[global_simps, irreducible]
def backend.serial.u64.constants.LFACTOR : Std.U64 := 1439961107955227#u64
/-- [curve25519_dalek::backend::serial::u64::constants::R]
Source: 'curve25519-dalek/src/backend/serial/u64/constants.rs', lines 141:0-147:3 -/
@[global_simps, irreducible]
def backend.serial.u64.constants.R : backend.serial.u64.scalar.Scalar52 :=
Array.make 5#usize [
4302102966953709#u64, 1049714374468698#u64, 4503599278581019#u64,
4503599627370495#u64, 17592186044415#u64
]
/-- [curve25519_dalek::backend::serial::u64::constants::RR]
Source: 'curve25519-dalek/src/backend/serial/u64/constants.rs', lines 150:0-156:3 -/
@[global_simps, irreducible]
def backend.serial.u64.constants.RR : backend.serial.u64.scalar.Scalar52 :=
Array.make 5#usize [
2764609938444603#u64, 3768881411696287#u64, 1616719297148420#u64,
1087343033131391#u64, 10175238647962#u64
]
/-- [curve25519_dalek::backend::serial::u64::scalar::{impl core::ops::index::Index<usize, u64> for curve25519_dalek::backend::serial::u64::scalar::Scalar52}::index]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 43:4-45:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
(self : backend.serial.u64.scalar.Scalar52) (_index : Std.Usize) :
Result Std.U64
:= do
Array.index_usize self _index
/-- [curve25519_dalek::backend::serial::u64::scalar::{impl core::ops::index::IndexMut<usize, u64> for curve25519_dalek::backend::serial::u64::scalar::Scalar52}::index_mut]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 49:4-51:5
Visibility: public -/
def
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexMutUsizeU64.index_mut
(self : backend.serial.u64.scalar.Scalar52) (_index : Std.Usize) :
Result (Std.U64 × (Std.U64 → backend.serial.u64.scalar.Scalar52))
:= do
let (i, index_mut_back) ← Array.index_mut_usize self _index
let back := fun i1 => let a := index_mut_back i1
a
ok (i, back)
/-- [curve25519_dalek::backend::serial::u64::scalar::m]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 56:0-58:1 -/
def backend.serial.u64.scalar.m
(x : Std.U64) (y : Std.U64) : Result Std.U128 := do
let i ← lift (UScalar.cast .U128 x)
let i1 ← lift (UScalar.cast .U128 y)
i * i1
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::ZERO]
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 62:4-62:57
Visibility: public -/
@[global_simps, irreducible]
def backend.serial.u64.scalar.Scalar52.ZERO
: backend.serial.u64.scalar.Scalar52 :=
let a := Array.repeat 5#usize 0#u64
a
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::split_words_lo]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 96:4-105:5 -/
def backend.serial.u64.scalar.Scalar52.split_words_lo
(words : Array Std.U64 8#usize) :
Result backend.serial.u64.scalar.Scalar52
:= do
let i ← 1#u64 <<< 52#i32
let mask ← i - 1#u64
let i1 ← Array.index_usize words 0#usize
let i2 ← lift (i1 &&& mask)
let i3 ← i1 >>> 52#i32
let i4 ← Array.index_usize words 1#usize
let i5 ← i4 <<< 12#i32
let i6 ← lift (i3 ||| i5)
let i7 ← lift (i6 &&& mask)
let i8 ← i4 >>> 40#i32
let i9 ← Array.index_usize words 2#usize
let i10 ← i9 <<< 24#i32
let i11 ← lift (i8 ||| i10)
let i12 ← lift (i11 &&& mask)
let i13 ← i9 >>> 28#i32
let i14 ← Array.index_usize words 3#usize
let i15 ← i14 <<< 36#i32
let i16 ← lift (i13 ||| i15)
let i17 ← lift (i16 &&& mask)
let i18 ← i14 >>> 16#i32
let i19 ← Array.index_usize words 4#usize
let i20 ← i19 <<< 48#i32
let i21 ← lift (i18 ||| i20)
let i22 ← lift (i21 &&& mask)
ok (Array.make 5#usize [ i2, i7, i12, i17, i22 ])
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::split_words_hi]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 108:4-117:5 -/
def backend.serial.u64.scalar.Scalar52.split_words_hi
(words : Array Std.U64 8#usize) :
Result backend.serial.u64.scalar.Scalar52
:= do
let i ← 1#u64 <<< 52#i32
let mask ← i - 1#u64
let i1 ← Array.index_usize words 4#usize
let i2 ← i1 >>> 4#i32
let i3 ← lift (i2 &&& mask)
let i4 ← i1 >>> 56#i32
let i5 ← Array.index_usize words 5#usize
let i6 ← i5 <<< 8#i32
let i7 ← lift (i4 ||| i6)
let i8 ← lift (i7 &&& mask)
let i9 ← i5 >>> 44#i32
let i10 ← Array.index_usize words 6#usize
let i11 ← i10 <<< 20#i32
let i12 ← lift (i9 ||| i11)
let i13 ← lift (i12 &&& mask)
let i14 ← i10 >>> 32#i32
let i15 ← Array.index_usize words 7#usize
let i16 ← i15 <<< 32#i32
let i17 ← lift (i14 ||| i16)
let i18 ← lift (i17 &&& mask)
let i19 ← i15 >>> 20#i32
let i20 ← lift (i19 &&& mask)
ok (Array.make 5#usize [ i3, i8, i13, i18, i20 ])
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_bytes_wide_parts]: loop body 1:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 130:12-132:13 -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0_loop0.body
(bytes : Array Std.U8 64#usize) (i : Std.Usize)
(iter : core.ops.range.Range Std.Usize) (words : Array Std.U64 8#usize) :
Result (ControlFlow ((core.ops.range.Range Std.Usize) × (Array Std.U64
8#usize)) (Array Std.U64 8#usize))
:= do
let (o, iter1) ←
core.iter.range.IteratorRange.next core.iter.range.StepUsize iter
match o with
| none => ok (done words)
| some j =>
let i1 ← i * 8#usize
let i2 ← i1 + j
let i3 ← Array.index_usize bytes i2
let i4 ← lift (UScalar.cast .U64 i3)
let i5 ← j * 8#usize
let i6 ← i4 <<< i5
let i7 ← Array.index_usize words i
let i8 ← lift (i7 ||| i6)
let a ← Array.update words i i8
ok (cont (iter1, a))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_bytes_wide_parts]: loop 1:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 130:12-132:13 -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0_loop0
(iter : core.ops.range.Range Std.Usize) (bytes : Array Std.U8 64#usize)
(words : Array Std.U64 8#usize) (i : Std.Usize) :
Result (Array Std.U64 8#usize)
:= do
loop
(fun (iter1, words1) =>
backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0_loop0.body
bytes i iter1 words1)
(iter, words)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_bytes_wide_parts]: loop body 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 129:8-133:9 -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0.body
(bytes : Array Std.U8 64#usize) (iter : core.ops.range.Range Std.Usize)
(words : Array Std.U64 8#usize) :
Result (ControlFlow ((core.ops.range.Range Std.Usize) × (Array Std.U64
8#usize)) (Array Std.U64 8#usize))
:= do
let (o, iter1) ←
core.iter.range.IteratorRange.next core.iter.range.StepUsize iter
match o with
| none => ok (done words)
| some i =>
let words1 ←
backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0_loop0
{ start := 0#usize, «end» := 8#usize } bytes words i
ok (cont (iter1, words1))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_bytes_wide_parts]: loop 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 129:8-133:9 -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0
(iter : core.ops.range.Range Std.Usize) (bytes : Array Std.U8 64#usize)
(words : Array Std.U64 8#usize) :
Result (Array Std.U64 8#usize)
:= do
loop
(fun (iter1, words1) =>
backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0.body bytes
iter1 words1)
(iter, words)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_bytes_wide_parts]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 127:4-135:5 -/
def backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts
(bytes : Array Std.U8 64#usize) :
Result (backend.serial.u64.scalar.Scalar52 ×
backend.serial.u64.scalar.Scalar52)
:= do
let words := Array.repeat 8#usize 0#u64
let words1 ←
backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts_loop0
{ start := 0#usize, «end» := 8#usize } bytes words
let s ← backend.serial.u64.scalar.Scalar52.split_words_lo words1
let s1 ← backend.serial.u64.scalar.Scalar52.split_words_hi words1
ok (s, s1)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::montgomery_reduce::part2]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 300:8-303:9 -/
def backend.serial.u64.scalar.Scalar52.montgomery_reduce.part2
(sum : Std.U128) : Result (Std.U128 × Std.U64) := do
let i ← lift (UScalar.cast .U64 sum)
let i1 ← 1#u64 <<< 52#i32
let i2 ← i1 - 1#u64
let w ← lift (i &&& i2)
let i3 ← sum >>> 52#i32
ok (i3, w)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::montgomery_reduce::part1]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 294:8-297:9 -/
def backend.serial.u64.scalar.Scalar52.montgomery_reduce.part1
(sum : Std.U128) : Result (Std.U128 × Std.U64) := do
let i ← lift (UScalar.cast .U64 sum)
let i1 ←
lift (core.num.U64.wrapping_mul i backend.serial.u64.constants.LFACTOR)
let i2 ← 1#u64 <<< 52#i32
let i3 ← i2 - 1#u64
let p ← lift (i1 &&& i3)
let i4 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
backend.serial.u64.constants.L 0#usize
let i5 ← backend.serial.u64.scalar.m p i4
let i6 ← sum + i5
let i7 ← i6 >>> 52#i32
ok (i7, p)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::conditional_add_l]: loop body 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 0:0-227:9 -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.conditional_add_l_loop.body
(condition : subtle.Choice) (mask : Std.U64)
(iter : core.ops.range.Range Std.Usize)
(self : backend.serial.u64.scalar.Scalar52) (carry : Std.U64) :
Result (ControlFlow ((core.ops.range.Range Std.Usize) ×
backend.serial.u64.scalar.Scalar52 × Std.U64) (Std.U64 ×
backend.serial.u64.scalar.Scalar52))
:= do
let (o, iter1) ←
core.iter.range.IteratorRange.next core.iter.range.StepUsize iter
match o with
| none => ok (done (carry, self))
| some i =>
let i1 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
backend.serial.u64.constants.L i
let addend ←
U64.Insts.SubtleConditionallySelectable.conditional_select 0#u64 i1
condition
let i2 ← carry >>> 52#i32
let i3 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
self i
let i4 ← i2 + i3
let carry1 ← i4 + addend
let (_, index_mut_back) ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexMutUsizeU64.index_mut
self i
let i5 ← lift (carry1 &&& mask)
let self1 := index_mut_back i5
ok (cont (iter1, self1, carry1))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::conditional_add_l]: loop 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 0:0-227:9 -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.conditional_add_l_loop
(iter : core.ops.range.Range Std.Usize)
(self : backend.serial.u64.scalar.Scalar52) (condition : subtle.Choice)
(carry : Std.U64) (mask : Std.U64) :
Result (Std.U64 × backend.serial.u64.scalar.Scalar52)
:= do
loop
(fun (iter1, self1, carry1) =>
backend.serial.u64.scalar.Scalar52.conditional_add_l_loop.body condition
mask iter1 self1 carry1)
(iter, self, carry)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::conditional_add_l]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 219:4-230:5 -/
def backend.serial.u64.scalar.Scalar52.conditional_add_l
(self : backend.serial.u64.scalar.Scalar52) (condition : subtle.Choice) :
Result (Std.U64 × backend.serial.u64.scalar.Scalar52)
:= do
let i ← 1#u64 <<< 52#i32
let mask ← i - 1#u64
backend.serial.u64.scalar.Scalar52.conditional_add_l_loop
{ start := 0#usize, «end» := 5#usize } self condition 0#u64 mask
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub]: loop body 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 209:8-212:9
Visibility: public -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.sub_loop.body
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) (mask : Std.U64)
(iter : core.ops.range.Range Std.Usize)
(difference : backend.serial.u64.scalar.Scalar52) (borrow : Std.U64) :
Result (ControlFlow ((core.ops.range.Range Std.Usize) ×
backend.serial.u64.scalar.Scalar52 × Std.U64)
(backend.serial.u64.scalar.Scalar52 × Std.U64))
:= do
let (o, iter1) ←
core.iter.range.IteratorRange.next core.iter.range.StepUsize iter
match o with
| none => ok (done (difference, borrow))
| some i =>
let i1 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
a i
let i2 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
b i
let i3 ← borrow >>> 63#i32
let i4 ← i2 + i3
let borrow1 ← lift (core.num.U64.wrapping_sub i1 i4)
let (_, index_mut_back) ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexMutUsizeU64.index_mut
difference i
let i5 ← lift (borrow1 &&& mask)
let difference1 := index_mut_back i5
ok (cont (iter1, difference1, borrow1))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub]: loop 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 209:8-212:9
Visibility: public -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.sub_loop
(iter : core.ops.range.Range Std.Usize)
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52)
(difference : backend.serial.u64.scalar.Scalar52) (mask : Std.U64)
(borrow : Std.U64) :
Result (backend.serial.u64.scalar.Scalar52 × Std.U64)
:= do
loop
(fun (iter1, difference1, borrow1) =>
backend.serial.u64.scalar.Scalar52.sub_loop.body a b mask iter1
difference1 borrow1)
(iter, difference, borrow)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 203:4-217:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.sub
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let i ← 1#u64 <<< 52#i32
let mask ← i - 1#u64
let (difference, borrow) ←
backend.serial.u64.scalar.Scalar52.sub_loop
{ start := 0#usize, «end» := 5#usize } a b
backend.serial.u64.scalar.Scalar52.ZERO mask 0#u64
let i1 ← borrow >>> 63#i32
let i2 ← lift (UScalar.cast .U8 i1)
let c ← subtle.Choice.Insts.CoreConvertFromU8.from i2
let (_, difference1) ←
backend.serial.u64.scalar.Scalar52.conditional_add_l difference c
ok difference1
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::montgomery_reduce]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 291:4-324:5 -/
def backend.serial.u64.scalar.Scalar52.montgomery_reduce
(limbs : Array Std.U128 9#usize) :
Result backend.serial.u64.scalar.Scalar52
:= do
let i ← Array.index_usize limbs 0#usize
let (carry, n0) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part1 i
let i1 ← Array.index_usize limbs 1#usize
let i2 ← carry + i1
let i3 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
backend.serial.u64.constants.L 1#usize
let i4 ← backend.serial.u64.scalar.m n0 i3
let i5 ← i2 + i4
let (carry1, n1) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part1 i5
let i6 ← Array.index_usize limbs 2#usize
let i7 ← carry1 + i6
let i8 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
backend.serial.u64.constants.L 2#usize
let i9 ← backend.serial.u64.scalar.m n0 i8
let i10 ← i7 + i9
let i11 ← backend.serial.u64.scalar.m n1 i3
let i12 ← i10 + i11
let (carry2, n2) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part1 i12
let i13 ← Array.index_usize limbs 3#usize
let i14 ← carry2 + i13
let i15 ← backend.serial.u64.scalar.m n1 i8
let i16 ← i14 + i15
let i17 ← backend.serial.u64.scalar.m n2 i3
let i18 ← i16 + i17
let (carry3, n3) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part1 i18
let i19 ← Array.index_usize limbs 4#usize
let i20 ← carry3 + i19
let i21 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
backend.serial.u64.constants.L 4#usize
let i22 ← backend.serial.u64.scalar.m n0 i21
let i23 ← i20 + i22
let i24 ← backend.serial.u64.scalar.m n2 i8
let i25 ← i23 + i24
let i26 ← backend.serial.u64.scalar.m n3 i3
let i27 ← i25 + i26
let (carry4, n4) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part1 i27
let i28 ← Array.index_usize limbs 5#usize
let i29 ← carry4 + i28
let i30 ← backend.serial.u64.scalar.m n1 i21
let i31 ← i29 + i30
let i32 ← backend.serial.u64.scalar.m n3 i8
let i33 ← i31 + i32
let i34 ← backend.serial.u64.scalar.m n4 i3
let i35 ← i33 + i34
let (carry5, r0) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part2 i35
let i36 ← Array.index_usize limbs 6#usize
let i37 ← carry5 + i36
let i38 ← backend.serial.u64.scalar.m n2 i21
let i39 ← i37 + i38
let i40 ← backend.serial.u64.scalar.m n4 i8
let i41 ← i39 + i40
let (carry6, r1) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part2 i41
let i42 ← Array.index_usize limbs 7#usize
let i43 ← carry6 + i42
let i44 ← backend.serial.u64.scalar.m n3 i21
let i45 ← i43 + i44
let (carry7, r2) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part2 i45
let i46 ← Array.index_usize limbs 8#usize
let i47 ← carry7 + i46
let i48 ← backend.serial.u64.scalar.m n4 i21
let i49 ← i47 + i48
let (carry8, r3) ←
backend.serial.u64.scalar.Scalar52.montgomery_reduce.part2 i49
let r4 ← lift (UScalar.cast .U64 carry8)
backend.serial.u64.scalar.Scalar52.sub
(Array.make 5#usize [ r0, r1, r2, r3, r4 ]) backend.serial.u64.constants.L
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::mul_internal]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 248:4-262:5 -/
def backend.serial.u64.scalar.Scalar52.mul_internal
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) :
Result (Array Std.U128 9#usize)
:= do
let z := Array.repeat 9#usize 0#u128
let i ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
0#usize
let i1 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index b
0#usize
let i2 ← backend.serial.u64.scalar.m i i1
let z1 ← Array.update z 0#usize i2
let i3 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index b
1#usize
let i4 ← backend.serial.u64.scalar.m i i3
let i5 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
1#usize
let i6 ← backend.serial.u64.scalar.m i5 i1
let i7 ← i4 + i6
let z2 ← Array.update z1 1#usize i7
let i8 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index b
2#usize
let i9 ← backend.serial.u64.scalar.m i i8
let i10 ← backend.serial.u64.scalar.m i5 i3
let i11 ← i9 + i10
let i12 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
2#usize
let i13 ← backend.serial.u64.scalar.m i12 i1
let i14 ← i11 + i13
let z3 ← Array.update z2 2#usize i14
let i15 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index b
3#usize
let i16 ← backend.serial.u64.scalar.m i i15
let i17 ← backend.serial.u64.scalar.m i5 i8
let i18 ← i16 + i17
let i19 ← backend.serial.u64.scalar.m i12 i3
let i20 ← i18 + i19
let i21 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
3#usize
let i22 ← backend.serial.u64.scalar.m i21 i1
let i23 ← i20 + i22
let z4 ← Array.update z3 3#usize i23
let i24 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index b
4#usize
let i25 ← backend.serial.u64.scalar.m i i24
let i26 ← backend.serial.u64.scalar.m i5 i15
let i27 ← i25 + i26
let i28 ← backend.serial.u64.scalar.m i12 i8
let i29 ← i27 + i28
let i30 ← backend.serial.u64.scalar.m i21 i3
let i31 ← i29 + i30
let i32 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
4#usize
let i33 ← backend.serial.u64.scalar.m i32 i1
let i34 ← i31 + i33
let z5 ← Array.update z4 4#usize i34
let i35 ← backend.serial.u64.scalar.m i5 i24
let i36 ← backend.serial.u64.scalar.m i12 i15
let i37 ← i35 + i36
let i38 ← backend.serial.u64.scalar.m i21 i8
let i39 ← i37 + i38
let i40 ← backend.serial.u64.scalar.m i32 i3
let i41 ← i39 + i40
let z6 ← Array.update z5 5#usize i41
let i42 ← backend.serial.u64.scalar.m i12 i24
let i43 ← backend.serial.u64.scalar.m i21 i15
let i44 ← i42 + i43
let i45 ← backend.serial.u64.scalar.m i32 i8
let i46 ← i44 + i45
let z7 ← Array.update z6 6#usize i46
let i47 ← backend.serial.u64.scalar.m i21 i24
let i48 ← backend.serial.u64.scalar.m i32 i15
let i49 ← i47 + i48
let z8 ← Array.update z7 7#usize i49
let i50 ← backend.serial.u64.scalar.m i32 i24
Array.update z8 8#usize i50
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::montgomery_mul]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 343:4-345:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.montgomery_mul
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let a1 ← backend.serial.u64.scalar.Scalar52.mul_internal a b
backend.serial.u64.scalar.Scalar52.montgomery_reduce a1
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::add]: loop body 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 193:8-196:9
Visibility: public -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.add_loop.body
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) (mask : Std.U64)
(iter : core.ops.range.Range Std.Usize)
(sum : backend.serial.u64.scalar.Scalar52) (carry : Std.U64) :
Result (ControlFlow ((core.ops.range.Range Std.Usize) ×
backend.serial.u64.scalar.Scalar52 × Std.U64)
backend.serial.u64.scalar.Scalar52)
:= do
let (o, iter1) ←
core.iter.range.IteratorRange.next core.iter.range.StepUsize iter
match o with
| none => ok (done sum)
| some i =>
let i1 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
a i
let i2 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
b i
let i3 ← i1 + i2
let i4 ← carry >>> 52#i32
let carry1 ← i3 + i4
let (_, index_mut_back) ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexMutUsizeU64.index_mut
sum i
let i5 ← lift (carry1 &&& mask)
let sum1 := index_mut_back i5
ok (cont (iter1, sum1, carry1))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::add]: loop 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 193:8-196:9
Visibility: public -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.add_loop
(iter : core.ops.range.Range Std.Usize)
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52)
(sum : backend.serial.u64.scalar.Scalar52) (mask : Std.U64) (carry : Std.U64)
:
Result backend.serial.u64.scalar.Scalar52
:= do
loop
(fun (iter1, sum1, carry1) =>
backend.serial.u64.scalar.Scalar52.add_loop.body a b mask iter1 sum1
carry1)
(iter, sum, carry)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::add]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 187:4-200:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.add
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let i ← 1#u64 <<< 52#i32
let mask ← i - 1#u64
let sum ←
backend.serial.u64.scalar.Scalar52.add_loop
{ start := 0#usize, «end» := 5#usize } a b
backend.serial.u64.scalar.Scalar52.ZERO mask 0#u64
backend.serial.u64.scalar.Scalar52.sub sum backend.serial.u64.constants.L
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_bytes_wide]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 137:4-142:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.from_bytes_wide
(bytes : Array Std.U8 64#usize) :
Result backend.serial.u64.scalar.Scalar52
:= do
let (lo, hi) ←
backend.serial.u64.scalar.Scalar52.from_bytes_wide_parts bytes
let lo1 ←
backend.serial.u64.scalar.Scalar52.montgomery_mul lo
backend.serial.u64.constants.R
let hi1 ←
backend.serial.u64.scalar.Scalar52.montgomery_mul hi
backend.serial.u64.constants.RR
backend.serial.u64.scalar.Scalar52.add hi1 lo1
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::square_internal]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 267:4-286:5 -/
def backend.serial.u64.scalar.Scalar52.square_internal
(a : backend.serial.u64.scalar.Scalar52) :
Result (Array Std.U128 9#usize)
:= do
let i ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
0#usize
let i1 ← i * 2#u64
let i2 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
1#usize
let i3 ← i2 * 2#u64
let i4 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
2#usize
let i5 ← i4 * 2#u64
let i6 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
3#usize
let i7 ← i6 * 2#u64
let i8 ← backend.serial.u64.scalar.m i i
let i9 ← Array.index_usize (Array.make 4#usize [ i1, i3, i5, i7 ]) 0#usize
let i10 ← backend.serial.u64.scalar.m i9 i2
let i11 ← backend.serial.u64.scalar.m i9 i4
let i12 ← backend.serial.u64.scalar.m i2 i2
let i13 ← i11 + i12
let i14 ← backend.serial.u64.scalar.m i9 i6
let i15 ← Array.index_usize (Array.make 4#usize [ i1, i3, i5, i7 ]) 1#usize
let i16 ← backend.serial.u64.scalar.m i15 i4
let i17 ← i14 + i16
let i18 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index a
4#usize
let i19 ← backend.serial.u64.scalar.m i9 i18
let i20 ← backend.serial.u64.scalar.m i15 i6
let i21 ← i19 + i20
let i22 ← backend.serial.u64.scalar.m i4 i4
let i23 ← i21 + i22
let i24 ← backend.serial.u64.scalar.m i15 i18
let i25 ← Array.index_usize (Array.make 4#usize [ i1, i3, i5, i7 ]) 2#usize
let i26 ← backend.serial.u64.scalar.m i25 i6
let i27 ← i24 + i26
let i28 ← backend.serial.u64.scalar.m i25 i18
let i29 ← backend.serial.u64.scalar.m i6 i6
let i30 ← i28 + i29
let i31 ← Array.index_usize (Array.make 4#usize [ i1, i3, i5, i7 ]) 3#usize
let i32 ← backend.serial.u64.scalar.m i31 i18
let i33 ← backend.serial.u64.scalar.m i18 i18
ok (Array.make 9#usize [ i8, i10, i13, i17, i23, i27, i30, i32, i33 ])
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::mul]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 328:4-331:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.mul
(a : backend.serial.u64.scalar.Scalar52)
(b : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let a1 ← backend.serial.u64.scalar.Scalar52.mul_internal a b
let ab ← backend.serial.u64.scalar.Scalar52.montgomery_reduce a1
let a2 ←
backend.serial.u64.scalar.Scalar52.mul_internal ab
backend.serial.u64.constants.RR
backend.serial.u64.scalar.Scalar52.montgomery_reduce a2
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::square]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 336:4-339:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.square
(self : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let a ← backend.serial.u64.scalar.Scalar52.square_internal self
let aa ← backend.serial.u64.scalar.Scalar52.montgomery_reduce a
let a1 ←
backend.serial.u64.scalar.Scalar52.mul_internal aa
backend.serial.u64.constants.RR
backend.serial.u64.scalar.Scalar52.montgomery_reduce a1
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::montgomery_square]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 349:4-351:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.montgomery_square
(self : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let a ← backend.serial.u64.scalar.Scalar52.square_internal self
backend.serial.u64.scalar.Scalar52.montgomery_reduce a
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::as_montgomery]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 355:4-357:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.as_montgomery
(self : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
backend.serial.u64.scalar.Scalar52.montgomery_mul self
backend.serial.u64.constants.RR
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_montgomery]: loop body 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 364:8-366:9
Visibility: public -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.from_montgomery_loop.body
(self : backend.serial.u64.scalar.Scalar52)
(iter : core.ops.range.Range Std.Usize) (limbs : Array Std.U128 9#usize) :
Result (ControlFlow ((core.ops.range.Range Std.Usize) × (Array Std.U128
9#usize)) (Array Std.U128 9#usize))
:= do
let (o, iter1) ←
core.iter.range.IteratorRange.next core.iter.range.StepUsize iter
match o with
| none => ok (done limbs)
| some i =>
let i1 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
self i
let i2 ← lift (UScalar.cast .U128 i1)
let a ← Array.update limbs i i2
ok (cont (iter1, a))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_montgomery]: loop 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 364:8-366:9
Visibility: public -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.from_montgomery_loop
(iter : core.ops.range.Range Std.Usize)
(self : backend.serial.u64.scalar.Scalar52) (limbs : Array Std.U128 9#usize)
:
Result (Array Std.U128 9#usize)
:= do
loop
(fun (iter1, limbs1) =>
backend.serial.u64.scalar.Scalar52.from_montgomery_loop.body self iter1
limbs1)
(iter, limbs)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::from_montgomery]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 362:4-368:5
Visibility: public -/
def backend.serial.u64.scalar.Scalar52.from_montgomery
(self : backend.serial.u64.scalar.Scalar52) :
Result backend.serial.u64.scalar.Scalar52
:= do
let limbs := Array.repeat 9#usize 0#u128
let limbs1 ←
backend.serial.u64.scalar.Scalar52.from_montgomery_loop
{ start := 0#usize, «end» := 5#usize } self limbs
backend.serial.u64.scalar.Scalar52.montgomery_reduce limbs1
end curve25519_dalek

View file

@ -1,36 +0,0 @@
-- Hand-written external function models for the Scalar52 arithmetic extraction.
-- The two subtle items reuse the field extraction's proven models verbatim.
import Aeneas
import CurveScalar.Types
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
set_option maxHeartbeats 1000000
set_option maxRecDepth 2048
open curve25519_dalek
/-- [subtle::{impl core::convert::From<u8> for subtle::Choice}::from]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 238:4-238:32
Name pattern: [subtle::{core::convert::From<subtle::Choice, u8>}::from]
MODEL (faithful): Rust body is `Choice(black_box(input))`; the volatile
read in `black_box` is semantically the identity. -/
@[rust_fun "subtle::{core::convert::From<subtle::Choice, u8>}::from"]
def subtle.Choice.Insts.CoreConvertFromU8.from
(b : Std.U8) : Result subtle.Choice :=
ok b
/-- [subtle::{impl subtle::ConditionallySelectable for u64}::conditional_select]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 513:12-513:77
Name pattern: [subtle::{subtle::ConditionallySelectable<u64>}::conditional_select]
MODEL: `a` if choice = 0, else `b`. The Rust mask trick
`a ^ (-(choice as i64) as u64 & (a ^ b))` agrees with this on the Choice
invariant {0,1} (mask = 0 or all-ones). -/
@[rust_fun
"subtle::{subtle::ConditionallySelectable<u64>}::conditional_select"]
def U64.Insts.SubtleConditionallySelectable.conditional_select
(a b : Std.U64) (choice : subtle.Choice) : Result Std.U64 :=
ok (if choice.val = 0 then a else b)

View file

@ -1,34 +0,0 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [curve25519_dalek]: external functions.
-- This is a template file: rename it to "FunsExternal.lean" and fill the holes.
import Aeneas
import CurveScalar.Types
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
open curve25519_dalek
/-- [subtle::{impl core::convert::From<u8> for subtle::Choice}::from]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 238:4-238:32
Name pattern: [subtle::{core::convert::From<subtle::Choice, u8>}::from]
Visibility: public -/
@[rust_fun "subtle::{core::convert::From<subtle::Choice, u8>}::from"]
axiom subtle.Choice.Insts.CoreConvertFromU8.from
: Std.U8 → Result subtle.Choice
/-- [subtle::{impl subtle::ConditionallySelectable for u64}::conditional_select]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 513:12-513:77
Name pattern: [subtle::{subtle::ConditionallySelectable<u64>}::conditional_select]
Visibility: public -/
@[rust_fun
"subtle::{subtle::ConditionallySelectable<u64>}::conditional_select"]
axiom U64.Insts.SubtleConditionallySelectable.conditional_select
: Std.U64 → Std.U64 → subtle.Choice → Result Std.U64

View file

@ -1,24 +0,0 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [curve25519_dalek]: type definitions
import Aeneas
import CurveScalar.TypesExternal
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
namespace curve25519_dalek
/-- [curve25519_dalek::backend::serial::u64::scalar::Scalar52]
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 26:0-26:34
Visibility: public -/
@[reducible]
def backend.serial.u64.scalar.Scalar52 := Array Std.U64 5#usize
end curve25519_dalek

View file

@ -1,13 +0,0 @@
-- Hand-written external types for the Scalar52 arithmetic extraction.
-- Self-contained; subtle.Choice modeled as the {0,1} u8 (same as the field layer).
import Aeneas
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
set_option maxHeartbeats 1000000
set_option maxRecDepth 2048
/-- [subtle::Choice] — MODEL: a u8 carrying the {0,1} invariant. -/
@[reducible, rust_type "subtle::Choice"]
def subtle.Choice : Type := Std.U8

View file

@ -1,22 +0,0 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [curve25519_dalek]: external types.
-- This is a template file: rename it to "TypesExternal.lean" and fill the holes.
import Aeneas
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
/-- [subtle::Choice]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 120:0-120:17
Name pattern: [subtle::Choice]
Visibility: public -/
@[rust_type "subtle::Choice"]
axiom subtle.Choice : Type

View file

@ -94,6 +94,7 @@ if [ "$AVAIL_MB" -lt "$MIN_FREE_MB" ]; then
exit 1 exit 1
fi fi
# ── Guard 3b: global-headroom clamp (2026-07-03 swap-pressure incident) ───── # ── Guard 3b: global-headroom clamp (2026-07-03 swap-pressure incident) ─────
# A cap is a PROMISE of memory to lean; never promise more than the machine # A cap is a PROMISE of memory to lean; never promise more than the machine
# can afford right now. Requested caps that exceed (available floor) are # can afford right now. Requested caps that exceed (available floor) are
@ -101,11 +102,14 @@ fi
# into swap even when lean itself stays within its cap. Clamp, don't fail: # into swap even when lean itself stays within its cap. Clamp, don't fail:
# most compiles peak far below their cap (measure before raising — the # most compiles peak far below their cap (measure before raising — the
# incident's 9G scopes served a file whose true peak was 753MB). # incident's 9G scopes served a file whose true peak was 753MB).
REQ_MEM_MB=$MEM_MB
WAS_CLAMPED=0
MAX_AFFORD_MB=$(( AVAIL_MB - MIN_FREE_MB )) MAX_AFFORD_MB=$(( AVAIL_MB - MIN_FREE_MB ))
if [ "$MEM_MB" -gt "$MAX_AFFORD_MB" ]; then if [ "$MEM_MB" -gt "$MAX_AFFORD_MB" ]; then
echo "lean-guard: clamping -M ${MEM_MB} -> ${MAX_AFFORD_MB}MB (avail=${AVAIL_MB}MB, floor=${MIN_FREE_MB}MB)" echo "lean-guard: clamping -M ${MEM_MB} -> ${MAX_AFFORD_MB}MB (avail=${AVAIL_MB}MB, floor=${MIN_FREE_MB}MB)"
MEM_MB=$MAX_AFFORD_MB MEM_MB=$MAX_AFFORD_MB
CGROUP_MB=$(( MEM_MB + 1024 )) CGROUP_MB=$(( MEM_MB + 1024 ))
WAS_CLAMPED=1
fi fi
if [ "$MEM_MB" -lt 1024 ]; then if [ "$MEM_MB" -lt 1024 ]; then
echo "FATAL: headroom clamp would leave lean < 1024MB — machine too loaded to compile safely" echo "FATAL: headroom clamp would leave lean < 1024MB — machine too loaded to compile safely"
@ -120,19 +124,56 @@ run_leancmd() {
timeout --signal=TERM --kill-after=15 "$TIMEOUT_SEC" \ timeout --signal=TERM --kill-after=15 "$TIMEOUT_SEC" \
lean -M "$MEM_MB" -o "$OLEAN_FILE" "$LEAN_FILE" "$@" lean -M "$MEM_MB" -o "$OLEAN_FILE" "$LEAN_FILE" "$@"
} }
if systemd-run --user --scope -p MemoryMax=10M --quiet -- /bin/true 2>/dev/null; then do_compile() {
# --scope runs the command as a child of THIS shell (env inherited), if systemd-run --user --scope -p MemoryMax=10M --quiet -- /bin/true 2>/dev/null; then
# merely placing it in a fresh cgroup with the hard caps below. # --scope runs the command as a child of THIS shell (env inherited),
systemd-run --user --scope --quiet \ # merely placing it in a fresh cgroup with the hard caps below.
-p MemoryMax="${CGROUP_MB}M" -p MemorySwapMax=256M \ systemd-run --user --scope --quiet \
-- taskset -c "$CORES" \ -p MemoryMax="${CGROUP_MB}M" -p MemorySwapMax=256M \
timeout --signal=TERM --kill-after=15 "$TIMEOUT_SEC" \ -- taskset -c "$CORES" \
lean -M "$MEM_MB" -o "$OLEAN_FILE" "$LEAN_FILE" "$@" timeout --signal=TERM --kill-after=15 "$TIMEOUT_SEC" \
EXIT_CODE=$? lean -M "$MEM_MB" -o "$OLEAN_FILE" "$LEAN_FILE" "$@"
else else
echo " (systemd-run unavailable — falling back to lean -M only)" >> "$LOG_FILE" echo " (systemd-run unavailable — falling back to lean -M only)" >> "$LOG_FILE"
run_leancmd "$@" run_leancmd "$@"
EXIT_CODE=$? fi
}
do_compile "$@"
EXIT_CODE=$?
# ── Guard 3a: lazy wait-and-retry after a clamped memory abort (pass 3) ─────
# The clamp above protects the host, but under ambient memory pressure it
# can cut a KNOWN-NEEDED cap (ReduceSpec peaks ~6.5G) and guarantee an
# interpreter abort that reads like a proof regression. Lazy semantics keep
# light files free: only when a CLAMPED run dies on memory (134 abort /
# 137 cgroup kill) and LEAN_MEM_WAIT_SEC>0, wait — still under the
# single-flight lock — until the ORIGINAL request is affordable, then retry
# once at full cap. Default 0: behavior unchanged.
MEM_WAIT_SEC=${LEAN_MEM_WAIT_SEC:-0}
if [ "$WAS_CLAMPED" -eq 1 ] && [ "$MEM_WAIT_SEC" -gt 0 ]; then
WAITED=0
# Retry ladder: whenever headroom improves MATERIALLY (>= +1536MB over
# the cap that just died, or reaches the full request), retry at the
# new clamp. The full request may never be affordable on a loaded host
# even though the true peak is — climbing the ladder finds the passing
# clamp without knowing the peak. Monotone caps + deadline => bounded.
while { [ "$EXIT_CODE" -eq 134 ] || [ "$EXIT_CODE" -eq 137 ]; } \
&& [ "$WAITED" -lt "$MEM_WAIT_SEC" ] && [ "$MEM_MB" -lt "$REQ_MEM_MB" ]; do
sleep 20; WAITED=$(( WAITED + 20 ))
AVAIL_MB=$(free -m | awk '/Mem:/{print $7}')
NEW_AFFORD=$(( AVAIL_MB - MIN_FREE_MB ))
if [ "$NEW_AFFORD" -ge "$REQ_MEM_MB" ] || [ "$NEW_AFFORD" -ge $(( MEM_MB + 1536 )) ]; then
MEM_MB=$(( NEW_AFFORD < REQ_MEM_MB ? NEW_AFFORD : REQ_MEM_MB ))
CGROUP_MB=$(( MEM_MB + 1024 ))
echo "lean-guard: clamped run died (rc=$EXIT_CODE); retrying at -M ${MEM_MB}MB after ${WAITED}s (avail=${AVAIL_MB}MB, request=${REQ_MEM_MB}MB)"
echo "[$(date -u +%F' '%T)] RETRY $LEAN_FILE (M=${MEM_MB}MB cg=${CGROUP_MB}MB avail=${AVAIL_MB}MB after ${WAITED}s)" >> "$LOG_FILE"
do_compile "$@"
EXIT_CODE=$?
fi
done
if [ "$EXIT_CODE" -eq 134 ] || [ "$EXIT_CODE" -eq 137 ]; then
echo "lean-guard: memory-death persists after ${WAITED}s of ladder retries (last -M ${MEM_MB}MB, request ${REQ_MEM_MB}MB) — keeping the failure"
fi
fi fi
case $EXIT_CODE in case $EXIT_CODE in