mirror of
https://github.com/luxfi/warp.git
synced 2026-07-27 03:37:46 +00:00
Decomplect the PQ finality lanes into a typed, impossible-to-confuse model where
KIND chooses the verifier and SUITE only chooses parameterization (fail-closed on
mismatch). Kills the prior conflation where the corona-backed lattice lane was
mislabeled "Pulse/Pulsar-SHA3".
Four strict evidence kinds — each its own verifier + suite + key registry:
beam-bls BLS12-381 aggregate (fast classical)
pulsar-threshold-mldsa threshold ML-DSA, verified as a STANDARD FIPS-204
ML-DSA signature under a group public key; the TALUS
dealerless machinery is entirely offline (VerifyPulsar
imports only mldsa65 — enforced by an import-hygiene test)
corona-ringtail Ringtail/Module-LWE lattice threshold (the corona kernel)
p3q-mldsa-rollup succinct rollup of independent ML-DSA-65 sigs; strict
ONLY when its proof system is PQ (classical SNARK gated)
Plus the raw mldsa-cert-set as a NON-strict availability/audit artifact.
Subject-agnostic verifiers take (subject, evidence, keyEra): one dispatch serves
the warp cross-chain digest D and the consensus finality subject
M = keccak256("QUASAR_FINALITY_V1" || chainID || height || round || blockID ||
stateRoot || signerSetID || keyEraID || generation || pChainHeight || policyID)
folding generation + pChainHeight + policyID so a signature binds its era, its
validator snapshot, and its tier (tier-downgrade replay fails closed).
Policy tiers (BLS_FAST / HYBRID_PQ_CHECKPOINT / STRICT_QUASAR / RECOVERY) select
which lanes are required — orthogonal to verification and to keys. PulsarKeyEra
and CoronaKeyEra are symmetric but DISTINCT registry types; P3Q/cert-set resolve a
per-validator SignerSetAuthority — no resolver can alias another's key material.
Offline signers (pulsard, coronad, P3Q prover) are interfaces only, never imported
by the verify path.
Wire unchanged: D, the Message c14n, messageDST, the ZAP magic and kind bytes are
byte-identical (forge Go<->Solidity equality holds; golden envelope SHA unchanged).
The corona lane DST is renamed pulseDST->coronaDST (no deployed corona sigs;
envelope KAT regenerated).
22 tests green: non-confusable dispatch, suite/kind fail-closed, Pulsar import
hygiene, subject-identity across lanes, policyID downgrade, key-era distinctness,
P3Q-classical-root strict gate.
112 lines
4.2 KiB
Go
112 lines
4.2 KiB
Go
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// quasar_cert.go — the QuasarCert: the consensus FINALITY object.
|
|
//
|
|
// A QuasarCert carries TYPED finality evidence over the consensus subject M —
|
|
// NOT a thousand raw validator signatures. Each lane is one compact object:
|
|
//
|
|
// Beam one BLS aggregate over M (always present; the fast lane)
|
|
// Pulsar one threshold ML-DSA sig over M (optional; the PQ quorum lane)
|
|
// Corona one Ringtail threshold sig over M (optional; the PQ lattice lane)
|
|
// P3QRoot one succinct ML-DSA-65 rollup root (optional; recovery/compression)
|
|
// CertSet raw per-validator ML-DSA-65 certs (optional; AVAILABILITY only —
|
|
// never a strict finality root, but auditable + the P3Q input)
|
|
//
|
|
// The cert is a CARRIER, exactly like the warp Envelope: it computes the
|
|
// subject (M) and hands typed lane evidence to the same subject-agnostic
|
|
// verifiers. Admissibility under a finality tier is decided by AcceptQuasarCert
|
|
// (finality_tier.go); this file only models the value and enumerates it.
|
|
|
|
package warp
|
|
|
|
// QuasarCert is the consensus finality certificate for a single decided block.
|
|
// Subject is the QuasarFinalitySubject params; Subject.* and the lane evidence
|
|
// together are what a receiver verifies and admits.
|
|
type QuasarCert struct {
|
|
// Subject identifies the finalized decision. M = QuasarFinalitySubject(Subject)
|
|
// is the digest every present lane signs.
|
|
Subject QuasarFinalityParams
|
|
|
|
// Lanes. Beam is structurally always present (the BLS aggregate). The PQ
|
|
// lanes are optional; which combination is REQUIRED is a policy-tier
|
|
// decision (AcceptQuasarCert), not a structural one.
|
|
Beam BitSetSignature
|
|
Pulsar *PulsarEvidence
|
|
Corona *CoronaEvidence
|
|
P3QRoot *P3QRoot
|
|
|
|
// CertSet is the optional raw ML-DSA-65 availability artifact. It is the
|
|
// INPUT a P3Q rollup compresses and an accountable audit trail. It is
|
|
// NEVER admissible as a strict finality root (IsStrictFinalityKind ==
|
|
// false), so AcceptQuasarCert never counts it toward a required lane.
|
|
CertSet *CertSetEvidence
|
|
}
|
|
|
|
// SubjectBytes returns M, the 32-byte consensus finality digest every present
|
|
// lane is verified over.
|
|
func (c *QuasarCert) SubjectBytes() [32]byte {
|
|
return QuasarFinalitySubject(c.Subject)
|
|
}
|
|
|
|
// HasPulsar reports whether the cert carries a Pulsar threshold-ML-DSA lane.
|
|
func (c *QuasarCert) HasPulsar() bool { return c != nil && c.Pulsar != nil }
|
|
|
|
// HasCorona reports whether the cert carries a Corona Ringtail lane.
|
|
func (c *QuasarCert) HasCorona() bool { return c != nil && c.Corona != nil }
|
|
|
|
// HasP3Q reports whether the cert carries a P3Q rollup root.
|
|
func (c *QuasarCert) HasP3Q() bool { return c != nil && c.P3QRoot != nil }
|
|
|
|
// HasCertSet reports whether the cert carries a raw ML-DSA cert-set
|
|
// availability artifact.
|
|
func (c *QuasarCert) HasCertSet() bool { return c != nil && c.CertSet != nil }
|
|
|
|
// Evidence enumerates the typed finality-evidence lanes this cert carries,
|
|
// correct-by-construction (each lane paired with the suite its kind demands),
|
|
// mirroring Envelope.Evidence. The subject for these lanes is M
|
|
// (c.SubjectBytes()). Lanes appear only when present; the Beam is always
|
|
// present. The raw cert-set IS enumerated (it is recognized evidence), but
|
|
// IsStrictFinalityKind(EvidenceMLDSACertSet) is false so policy never admits it
|
|
// as a strict root.
|
|
func (c *QuasarCert) Evidence() []FinalityEvidence {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
out := make([]FinalityEvidence, 0, 5)
|
|
out = append(out, FinalityEvidence{
|
|
Kind: EvidenceBeamBLS,
|
|
Suite: SuiteBeamBLS12381,
|
|
Beam: &c.Beam,
|
|
})
|
|
if c.HasPulsar() {
|
|
out = append(out, FinalityEvidence{
|
|
Kind: EvidencePulsarThresholdMLDSA,
|
|
Suite: c.Pulsar.SuiteID,
|
|
Pulsar: c.Pulsar,
|
|
})
|
|
}
|
|
if c.HasCorona() {
|
|
out = append(out, FinalityEvidence{
|
|
Kind: EvidenceCoronaRingtail,
|
|
Suite: SuiteCoronaRingtailSHA3,
|
|
Corona: c.Corona,
|
|
})
|
|
}
|
|
if c.HasP3Q() {
|
|
out = append(out, FinalityEvidence{
|
|
Kind: EvidenceP3QMLDSARollup,
|
|
Suite: c.P3QRoot.SuiteID,
|
|
P3Q: c.P3QRoot,
|
|
})
|
|
}
|
|
if c.HasCertSet() {
|
|
out = append(out, FinalityEvidence{
|
|
Kind: EvidenceMLDSACertSet,
|
|
Suite: SuiteMLDSA65CertSetSHA3,
|
|
CertSet: c.CertSet,
|
|
})
|
|
}
|
|
return out
|
|
}
|