mirror of
https://github.com/luxfi/warp.git
synced 2026-10-30 15:13:04 +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.
78 lines
3.1 KiB
Go
78 lines
3.1 KiB
Go
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// resolver_distinctness_test.go — proves the THREE per-lane key registries are
|
|
// structurally DISTINCT types, so no implementation can ever serve two roles
|
|
// and Pulsar ↔ Corona ↔ P3Q key material can never be aliased. This lives in
|
|
// package pulsar because it is the only place that can see all three at once:
|
|
// warp.PulsarKeyEraResolver (one threshold ML-DSA group key),
|
|
// pulsar.CoronaGroupKeyResolver (one threshold lattice group key), and
|
|
// warp.SignerSetAuthority (independent per-validator keys for P3Q / cert-set).
|
|
|
|
package pulsar
|
|
|
|
import (
|
|
"testing"
|
|
|
|
corona "github.com/luxfi/corona/threshold"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/warp"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// Each fake implements EXACTLY ONE of the three resolver interfaces.
|
|
|
|
type onlyPulsarEra struct{}
|
|
|
|
func (onlyPulsarEra) ResolvePulsarKeyEra(ids.ID, uint64, uint64) (warp.PulsarKeyEra, error) {
|
|
return warp.PulsarKeyEra{}, nil
|
|
}
|
|
|
|
type onlyCoronaResolver struct{}
|
|
|
|
func (onlyCoronaResolver) ResolveGroupKey([32]byte, uint64, uint64) (*corona.GroupKey, string, error) {
|
|
return nil, "", nil
|
|
}
|
|
|
|
type onlySignerSet struct{}
|
|
|
|
func (onlySignerSet) ResolveSignerSet(ids.ID, uint64) ([]warp.ValidatorMLDSAKey, uint64, error) {
|
|
return nil, 0, nil
|
|
}
|
|
|
|
// TestPulsarAndCoronaUseDistinctKeyResolvers proves an implementation of one
|
|
// lane's key registry can NEVER satisfy another lane's registry interface.
|
|
func TestPulsarAndCoronaUseDistinctKeyResolvers(t *testing.T) {
|
|
var pulsarEra any = onlyPulsarEra{}
|
|
var coronaRes any = onlyCoronaResolver{}
|
|
var signerSet any = onlySignerSet{}
|
|
|
|
// Each satisfies its OWN interface.
|
|
_, ok := pulsarEra.(warp.PulsarKeyEraResolver)
|
|
require.True(t, ok, "Pulsar fake must implement PulsarKeyEraResolver")
|
|
_, ok = coronaRes.(CoronaGroupKeyResolver)
|
|
require.True(t, ok, "Corona fake must implement CoronaGroupKeyResolver")
|
|
_, ok = signerSet.(warp.SignerSetAuthority)
|
|
require.True(t, ok, "SignerSet fake must implement SignerSetAuthority")
|
|
|
|
// A Pulsar key-era resolver is NEITHER a Corona resolver NOR a signer-set
|
|
// authority — the registries cannot be confused.
|
|
_, ok = pulsarEra.(CoronaGroupKeyResolver)
|
|
require.False(t, ok, "Pulsar resolver must not alias the Corona resolver")
|
|
_, ok = pulsarEra.(warp.SignerSetAuthority)
|
|
require.False(t, ok, "Pulsar resolver must not alias the signer-set authority")
|
|
|
|
// A Corona resolver is NEITHER a Pulsar key-era resolver NOR a signer-set
|
|
// authority.
|
|
_, ok = coronaRes.(warp.PulsarKeyEraResolver)
|
|
require.False(t, ok, "Corona resolver must not alias the Pulsar resolver")
|
|
_, ok = coronaRes.(warp.SignerSetAuthority)
|
|
require.False(t, ok, "Corona resolver must not alias the signer-set authority")
|
|
|
|
// A signer-set authority (P3Q / cert-set) is NEITHER threshold resolver.
|
|
_, ok = signerSet.(warp.PulsarKeyEraResolver)
|
|
require.False(t, ok, "signer-set authority must not alias the Pulsar resolver")
|
|
_, ok = signerSet.(CoronaGroupKeyResolver)
|
|
require.False(t, ok, "signer-set authority must not alias the Corona resolver")
|
|
}
|