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:19 +02:00
parent 78c8acec0f
commit a6e32a41a6
11 changed files with 113 additions and 964 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,44 @@ 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 (a
single monomorphic `sha512_hash3(R, A, m)` oracle — this fork's sha2-0.10 stack
makes the incremental-hasher types untranslatable) 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, verifying.sha512_hash3, 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**: [risc0/curve25519-dalek](https://github.com/risc0/curve25519-dalek), commit `385adda` - **Upstream**: [risc0/curve25519-dalek](https://github.com/risc0/curve25519-dalek), commit `385adda`
@ -58,11 +91,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 + the proven scalar foundation # Montgomery mul, byte-parsing) and kernel-audits the
# scalar certificates, incl. the scalarImplementation
# aggregate
``` ```

View file

@ -15,16 +15,23 @@ 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 single SHA-512 oracle
`verifying.sha512_hash3` (semantically `Sha512(R ‖ A ‖ msg)`),
`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. **`Scalar52::sub::black_box` (scalar layer)**: this fork's v4.1.3 code 6. **`Scalar52::sub::black_box` (scalar layer)**: this fork's v4.1.3 code
implements the constant-time conditional via a local `black_box` = implements the constant-time conditional via a local `black_box` =
`unsafe { core::ptr::read_volatile(&value) }`. The volatile read is an `unsafe { core::ptr::read_volatile(&value) }`. The volatile read is an
optimization fence whose VALUE semantics is the identity; it is modeled as optimization fence whose VALUE semantics is the identity; it is modeled as
`id` in `gen/CurveScalar/FunsExternal.lean`. (Upstream v5 uses `subtle` `id` in `gen/CurveField/FunsExternal.lean` (merged gen). (Upstream v5 uses `subtle`
here; betrusted v4.1.2 uses a pure arithmetic mask — each fork is verified here; betrusted v4.1.2 uses a pure arithmetic mask — each fork is verified
against its own strategy.) against its own strategy.)
7. **Compilation of Rust to machine code** (rustc backend) is out of scope, 7. **Compilation of Rust to machine code** (rustc backend) is out of scope,

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,35 +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/risc0-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' \
--opaque 'crate::backend::serial::u64::scalar::_::sub::black_box' \
--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,816 +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 117:0-123: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 126:0-126: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 129:0-135: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 138:0-144: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 42:4-44: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 48:4-50: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 55:0-57: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 61:4-61: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 95:4-104: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 107:4-116: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 129:12-131: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 129:12-131: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 128:8-132: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 128:8-132: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 126:4-134: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 289:8-292: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 283:8-286: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}::sub]: loop body 0:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 216:8-219:9
Visibility: public -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.sub_loop0.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 216:8-219:9
Visibility: public -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.sub_loop0
(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_loop0.body a b mask iter1
difference1 borrow1)
(iter, difference, borrow)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub]: loop body 1:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 0:0-229:9
Visibility: public -/
@[rust_loop_body]
def backend.serial.u64.scalar.Scalar52.sub_loop1.body
(mask : Std.U64) (underflow_mask : Std.U64)
(iter : core.ops.range.Range Std.Usize)
(difference : 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 difference)
| some i =>
let i1 ← carry >>> 52#i32
let i2 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
difference i
let i3 ← i1 + i2
let i4 ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexUsizeU64.index
backend.serial.u64.constants.L i
let i5 ← backend.serial.u64.scalar.Scalar52.sub.black_box underflow_mask
let i6 ← lift (i4 &&& i5)
let carry1 ← i3 + i6
let (_, index_mut_back) ←
backend.serial.u64.scalar.Scalar52.Insts.CoreOpsIndexIndexMutUsizeU64.index_mut
difference i
let i7 ← lift (carry1 &&& mask)
let difference1 := index_mut_back i7
ok (cont (iter1, difference1, carry1))
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub]: loop 1:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 0:0-229:9
Visibility: public -/
@[rust_loop]
def backend.serial.u64.scalar.Scalar52.sub_loop1
(iter : core.ops.range.Range Std.Usize)
(difference : backend.serial.u64.scalar.Scalar52) (mask : Std.U64)
(underflow_mask : Std.U64) (carry : Std.U64) :
Result backend.serial.u64.scalar.Scalar52
:= do
loop
(fun (iter1, difference1, carry1) =>
backend.serial.u64.scalar.Scalar52.sub_loop1.body mask underflow_mask
iter1 difference1 carry1)
(iter, difference, carry)
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 202:4-232: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_loop0
{ 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 (i1 ^^^ 1#u64)
let underflow_mask ← lift (core.num.U64.wrapping_sub i2 1#u64)
backend.serial.u64.scalar.Scalar52.sub_loop1
{ start := 0#usize, «end» := 5#usize } difference mask underflow_mask
0#u64
/-- [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 280:4-313: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 237:4-251: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 332:4-334: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 192:8-195: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 192:8-195: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 186:4-199: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 136:4-141: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 256:4-275: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 317:4-320: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 325:4-328: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 338:4-340: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 344:4-346: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 353:8-355: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 353:8-355: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 351:4-357: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,28 +0,0 @@
-- Hand-written external function models for the Scalar52 arithmetic extraction.
-- This fork (curve25519-dalek v4.1.3) implements Scalar52::sub's constant-time
-- conditional add directly with a local `black_box` optimization barrier rather
-- than routing through subtle::ConditionallySelectable (as the v5 dalek does).
-- The sole external item is that `black_box`.
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
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub::black_box]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 179:8-183:9
MODEL (faithful): the Rust body is
`unsafe { core::ptr::read_volatile(&value) }`
— a volatile read of the `u64` `value` living on the stack. The `volatile`
qualifier only forbids the compiler from eliding/reordering the read (an
optimization barrier to keep the constant-time path branch-free); the VALUE
read back is exactly the value written, so semantically this is the identity
on `u64`. -/
def backend.serial.u64.scalar.Scalar52.sub.black_box
(value : Std.U64) : Result Std.U64 :=
ok value

View file

@ -1,22 +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
/-- [curve25519_dalek::backend::serial::u64::scalar::{curve25519_dalek::backend::serial::u64::scalar::Scalar52}::sub::black_box]:
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 205:8-209:9 -/
axiom backend.serial.u64.scalar.Scalar52.sub.black_box
: Std.U64 → Result Std.U64

View file

@ -1,23 +0,0 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [curve25519_dalek]: type definitions
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
namespace curve25519_dalek
/-- [curve25519_dalek::backend::serial::u64::scalar::Scalar52]
Source: 'curve25519-dalek/src/backend/serial/u64/scalar.rs', lines 25:0-25:34
Visibility: public -/
@[reducible]
def backend.serial.u64.scalar.Scalar52 := Array Std.U64 5#usize
end curve25519_dalek

View file

@ -1,12 +0,0 @@
-- Hand-written external types for the Scalar52 arithmetic extraction.
-- This fork's function-level scalar extraction pulls in NO external types
-- (unlike the v5 dalek template, whose sub/conditional_select route through
-- subtle::Choice). Kept as a (decl-free) module so the check manifest is
-- uniform across forks.
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

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