Files
zooqueenandHanzo Dev ac9676a47a proofs: drive formal/lean library to 0 errors
The formal/lean library (53 files — a separate formalization from lean/) had
~110 type-check errors across 38 files and had never had its Mathlib oleans
built. It now verifies at 0 errors under the project's strict setting:
`lake env lean -D autoImplicit=false`, all 53 files.

Fixed the same families as the sibling lean/ tree (the content is diverged, so
each was repaired directly):
- Crypto (BLS/FROST/Corona/Hybrid/threshold/FHE/Verkle): omega needs in-scope
  structure invariants; Nat-division bounds; noncomputable over opaque verifiers;
  Fin n index → Nat; deriving Inhabited.
- DeFi (AMM/staking/fees/flashloan/HFT/router): constant-product invariant and
  fee bounds via Nat.div_mul_le_self / Nat.div_le_of_le_mul; dead tactics.
- Protocol/Consensus/Warp/Bridge: BFT quorum theorems tightened to n=3f+1;
  pipe-projection parse fixes; split-after-simp; dead tactics; built the
  Consensus/Safety + ThresholdProof dependency oleans from clean source.
- Network/Compute/Trust/Build: record-projection opacity (unfold+split),
  foldl-min monotonicity, BEq parse parens.
- autoImplicit=false: declared previously auto-bound variables (explicit binders
  / variable blocks); the lakefile sets autoImplicit:=false.

Integrity: no sorry/admit/native_decide; no proof-by-assumption axiom cheats.
Statement changes only tightened false/trivial draft theorems to true
invariants. Remaining axioms are trusted-base only (opaque crypto primitives,
protocol modeling / honesty-static, build determinism).

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-02 09:31:40 -07:00

127 lines
4.3 KiB
Lean4

/-
BLS Signature Aggregation Correctness
Models the BLS signature scheme used in Quasar (quasar/bls.go).
BLS signatures have the aggregation property:
- Individual: verify(pk_i, msg, sig_i) = true
- Aggregate: verify(agg_pk, msg, agg_sig) = true
where agg_pk = sum(pk_i), agg_sig = sum(sig_i)
This file proves aggregation correctness abstractly
(bilinear pairing properties assumed as axioms).
Maps to:
- quasar/bls.go: BLS struct, Aggregate, Verify
- luxfi/crypto/bls: Signature, PublicKey, AggregateSignatures
Properties:
- Aggregation soundness: aggregate verifies iff all individuals verify
- Rogue key resistance: with proof-of-possession
- Quorum: 2f+1 valid signatures from n=3f+1 validators
-/
import Mathlib.Data.Nat.Defs
import Mathlib.Tactic
namespace Crypto.BLS
/-- Abstract group elements (G1, G2, GT in BLS12-381) -/
axiom G1 : Type
axiom G2 : Type
axiom GT : Type
/-- Bilinear pairing -/
axiom e : G1 → G2 → GT
/-- Group operations (abstract) -/
axiom G1.add : G1 → G1 → G1
axiom G2.add : G2 → G2 → G2
axiom GT.mul : GT → GT → GT
/-- Bilinearity axiom: e(a+b, c) = e(a,c) * e(b,c) -/
axiom bilinear_left :
∀ (a b : G1) (c : G2),
e (G1.add a b) c = GT.mul (e a c) (e b c)
/-- Bilinearity axiom: e(a, b+c) = e(a,b) * e(a,c) -/
axiom bilinear_right :
∀ (a : G1) (b c : G2),
e a (G2.add b c) = GT.mul (e a b) (e a c)
/-- BLS signature model -/
structure Signature where
sig : G1 -- signature in G1
pk : G2 -- public key in G2
msg : G1 -- message hash to G1
/-- BLS verify: e(sig, g2) = e(msg, pk) -/
axiom g2_generator : G2
def verify (s : Signature) : Prop :=
e s.sig g2_generator = e s.msg s.pk
/-- Aggregate signature.
Takes a non-empty list represented as a head signature `first` plus the
remaining signatures `rest`; this avoids needing an `Inhabited` instance on
the opaque group-element types. The aggregate sums all signature points and
all public-key points, keeping the common message (all signers sign the same
message, as required by `hmsg` callers). Marked `noncomputable` because the
group operations `G1.add`/`G2.add` are abstract axioms with no executable
code. -/
noncomputable def aggregate (first : Signature) (rest : List Signature) :
Signature :=
{ sig := rest.foldl (fun acc s => G1.add acc s.sig) first.sig
, pk := rest.foldl (fun acc s => G2.add acc s.pk) first.pk
, msg := first.msg }
/-- Aggregation soundness (2 signatures case):
If verify(sig1) and verify(sig2) on same message,
then verify(aggregate(sig1, sig2)) holds.
By bilinearity:
e(sig1 + sig2, g2) = e(sig1, g2) * e(sig2, g2)
= e(msg, pk1) * e(msg, pk2)
= e(msg, pk1 + pk2) -/
theorem aggregate_two_sound
(s1 s2 : Signature)
(hmsg : s1.msg = s2.msg)
(hv1 : verify s1)
(hv2 : verify s2) :
e (G1.add s1.sig s2.sig) g2_generator =
e s1.msg (G2.add s1.pk s2.pk) := by
rw [bilinear_left]
rw [bilinear_right]
rw [verify] at hv1 hv2
rw [hv1, hv2, hmsg]
/-- Rogue key resistance: proof-of-possession prevents
an attacker from choosing a key that cancels honest keys -/
axiom proof_of_possession :
∀ (pk : G2) (sig : G1),
-- Each validator must prove knowledge of their secret key
-- by signing their own public key
e sig g2_generator = e (G1.add sig sig) pk → True
/-- Quorum threshold: 2f+1 of n=3f+1 validators is a strict majority.
The optimal BFT bound pins `n = 3f+1` via `3f < n ≤ 3f+1`
(same invariant as `Consensus.BFT`). -/
theorem bls_quorum_sufficient (n f : Nat) (hf : 3 * f < n) (hn : n ≤ 3 * f + 1)
(sigs : Nat) (h : sigs ≥ 2 * f + 1) :
sigs > n / 2 := by omega
/-- Aggregate signature size is constant: one G1 point regardless of signer count -/
theorem aggregate_constant_size (_sigs : List Signature) :
-- 48 bytes (BLS12-381 G1 compressed) no matter how many signers
(1 : Nat) = 1 := rfl
/-- Two quorums overlap: any two sets of 2f+1 from n=3f+1 share a member,
since their sizes sum to more than n. The optimal BFT bound pins
`n = 3f+1` via `3f < n ≤ 3f+1` (same invariant as `Consensus.BFT`). -/
theorem quorum_overlap (n f : Nat) (hf : 3 * f < n) (hn : n ≤ 3 * f + 1)
(q1 q2 : Nat) (hq1 : q1 ≥ 2 * f + 1) (hq2 : q2 ≥ 2 * f + 1) :
q1 + q2 > n := by omega
end Crypto.BLS