Files
zooqueen dca3110ddb fix(quasar): make BLS optional on QuasarCert.VerifyWithRealKeys (fully-PQ finality)
FULLY-PQ AUDIT FINDING (critical, finality path): VerifyWithRealKeys
unconditionally required a valid BLS-12-381 aggregate (types.go: 'if
len(c.BLS)==0 return false' + mandatory bls.Verify), wired into production
at engine/pq/engine.go and pkg/wire/policies.go. This contradicted the
cert's own contract ('empty in pure-PQ', HasClassicalFastPath) and the
sibling VerkleWitness verifier, and meant a quantum break of BLS-12-381
could forge ANY cert that passed verification, regardless of the PQ legs.
No pure-PQ QuasarCert could finalise through this surface.

Fix (decomplected, mirrors VerkleWitness + the field's documented contract):
- BLS is now ONE OPTIONAL leg, verified iff the cert carries BLS bytes,
  exactly like the Corona/ML-DSA legs.
- Fail-closed guard: count verified legs; accept only if >=1 leg actually
  verified, so removing the mandatory-BLS gate can never let an
  evidence-free cert pass (no fail-open).
- engine/pq pre-check relaxed from 'BLS key required' to '>=1 verify key
  (BLS, Corona, or ML-DSA) required'.
- QuantumPolicy SigQuasar wire format keeps its by-design BLS+Corona dual
  shape; pure-PQ finality runs through the WeightedQuorumCert / Polaris
  path, not SigQuasar.

Regression tests (pure_pq_cert_test.go, both pass):
- TestVerifyWithRealKeys_PurePQ_NoBLS: pure-PQ cert (BLS empty, real
  ML-DSA-65 leg) verifies with a nil BLS key; tampered leg rejected.
- TestVerifyWithRealKeys_FailClosed_NoLeg: empty cert + rollup-without-keys
  both rejected.

Full protocol/quasar suite green; engine/pq green; full consensus build clean.
2026-06-21 15:25:13 -07:00
..