mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
Replaces every direct import of luxfi/corona/* and luxfi/pulsar/ref/go
in consensus with the canonical luxfi/threshold/protocols/{corona,pulsar}
alias surface. Pure import swap + go.mod bump; no behaviour change.
Files touched (16):
bench/pq_modes_bench_test.go
engine/pq/crypto.go
engine/pq/engine.go
pkg/wire/policies.go
protocol/quasar/cert_size_compare_test.go
protocol/quasar/corona_gob.go
protocol/quasar/dual_threshold_test.go
protocol/quasar/epoch.go
protocol/quasar/epoch_test.go
protocol/quasar/gpu_accel.go
protocol/quasar/grouped_threshold.go
protocol/quasar/quasar.go
protocol/quasar/types.go
protocol/quasar/wave_signer.go
protocol/quasar/wave_signer_test.go
protocol/quasar/witness.go
protocol/quasar/witness_pulsar_test.go
Import path swaps:
luxfi/corona/threshold -> luxfi/threshold/protocols/corona
luxfi/corona/keyera -> luxfi/threshold/protocols/corona/keyera
luxfi/corona/primitives -> luxfi/threshold/protocols/corona/primitives
luxfi/corona/reshare -> luxfi/threshold/protocols/corona/reshare
luxfi/corona/sign -> luxfi/threshold/protocols/corona/sign
luxfi/corona/gpu -> luxfi/threshold/protocols/corona/gpu
luxfi/pulsar/ref/go/pkg/pulsar -> luxfi/threshold/protocols/pulsar
The aliased package name "coronaThreshold" used by quasar / engine/pq /
pkg/wire identifiers is preserved at the call sites (it now refers to
the threshold/protocols/corona alias package). engine/pq/crypto.go is
the only file where the package was bare-imported as `threshold`; that
identifier was renamed to `corona` to match the new alias path.
go.mod:
- luxfi/threshold bumped to a branch pseudo-version that carries the
new alias subpackages; will pin to a stable tag once threshold's
companion commit lands and a release is cut.
- luxfi/corona and luxfi/pulsar drop to indirect (consensus now
reaches them only via threshold/protocols).
- luxfi/math v1.4.0 -> v1.4.1 and luxfi/metric v1.5.0 -> v1.5.7 are
transitive minimum-version bumps pulled by the new threshold
requirement; they are no-op for consensus call sites.
Comment-only references to "github.com/luxfi/corona/..." in bls.go,
round_digest.go, reshare_epoch.go, comprehensive_test.go,
engine_test.go, quasar_bench_test.go and config/pq_mode.go are
documentation pointers to where the underlying implementation lives;
they are accurate either way and are left unchanged (out of refactor
scope).
Layering shape after:
consensus -> threshold/protocols/{corona,pulsar} (stable alias)
|
v
luxfi/corona, luxfi/pulsar (primitive implementations)
Closes the 22-file layering violation flagged by the 2026-05-31
integration audit. Tests pass: ./engine/pq/..., ./pkg/wire/...,
./protocol/quasar/... (all key cases — TestEpochManager*,
TestRoundSigner*, TestVerifyPQFinality*, TestBLSThreshold*,
TestDualSigningFlow, TestCoronaCertSize* — green; the pre-existing
TestGroupedEpochManager_ParallelKeygen perf-bound flake on slow
machines was reproduced on unmodified main, so it is not a
regression).
128 lines
3.6 KiB
Go
128 lines
3.6 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package quasar
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/rand"
|
|
"testing"
|
|
|
|
"github.com/luxfi/consensus/protocol/prism"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/threshold/protocols/pulsar"
|
|
)
|
|
|
|
// TestRoundSigner_RunRound_ProducesFIPS204Verifiable runs a
|
|
// minimal Lux round at (K, T) = (3, 2): three sampled validators
|
|
// produce one FIPS 204 ML-DSA signature on a round item, which
|
|
// verifies under unmodified pulsar.VerifyCtx (i.e. FIPS 204
|
|
// ML-DSA.Verify with the precompile ctx).
|
|
func TestRoundSigner_RunRound_ProducesFIPS204Verifiable(t *testing.T) {
|
|
params := pulsar.MustParamsFor(pulsar.ModeP65)
|
|
|
|
// Build a (3, 2) DKG using pulsar directly to set up the
|
|
// per-validator KeyShares. This mirrors what a real Lux
|
|
// validator-set DKG ceremony would produce at the start of an
|
|
// epoch.
|
|
committee := []pulsar.NodeID{
|
|
{0x01, 0x00, 'V'}, {0x02, 0x00, 'V'}, {0x03, 0x00, 'V'},
|
|
}
|
|
const n, threshold = 3, 2
|
|
|
|
// Per-party long-term identity keys (v1.0.7 mandatory CR-6/8 closure).
|
|
identities := make(map[pulsar.NodeID]*pulsar.IdentityKey, n)
|
|
dirEntries := make(map[pulsar.NodeID]*pulsar.IdentityPublicKey, n)
|
|
for i := 0; i < n; i++ {
|
|
ik, err := pulsar.GenerateIdentity(rand.Reader)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
identities[committee[i]] = ik
|
|
dirEntries[committee[i]] = ik.PublicKey()
|
|
}
|
|
directory, err := pulsar.NewIdentityDirectory(dirEntries)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
dkg := make([]*pulsar.DKGSession, n)
|
|
for i := 0; i < n; i++ {
|
|
rng := bytes.NewReader(append([]byte{byte(i)}, bytes.Repeat([]byte{0xDE, 0xAD}, 32)...))
|
|
s, err := pulsar.NewDKGSession(params, committee, threshold, committee[i], identities[committee[i]], directory, rng)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
dkg[i] = s
|
|
}
|
|
r1 := make([]*pulsar.DKGRound1Msg, n)
|
|
for i, s := range dkg {
|
|
m, err := s.Round1()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r1[i] = m
|
|
}
|
|
r2 := make([]*pulsar.DKGRound2Msg, n)
|
|
for i, s := range dkg {
|
|
m, err := s.Round2(r1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r2[i] = m
|
|
}
|
|
outs := make([]*pulsar.DKGOutput, n)
|
|
for i, s := range dkg {
|
|
out, err := s.Round3(r1, r2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
outs[i] = out
|
|
}
|
|
groupPK := outs[0].GroupPubkey
|
|
|
|
// Build the RoundSigner's share map keyed by ids.NodeID.
|
|
shares := make(map[ids.NodeID]*pulsar.KeyShare, n)
|
|
pool := make([]ids.NodeID, n)
|
|
for i := 0; i < n; i++ {
|
|
var id ids.NodeID
|
|
copy(id[:], committee[i][:])
|
|
pool[i] = id
|
|
shares[id] = outs[i].SecretShare
|
|
}
|
|
|
|
ctxBytes := []byte("lux-evm-precompile-pulsar-v1")
|
|
signer := &RoundSigner{
|
|
Params: params,
|
|
Cut: prism.NewUniformCut(pool),
|
|
K: 3,
|
|
Threshold: 2,
|
|
Shares: shares,
|
|
PrecompileCtx: ctxBytes,
|
|
}
|
|
|
|
// Drive one Lux round.
|
|
item := []byte("lux-round smoke test item")
|
|
res, err := signer.RunRound(context.Background(), item)
|
|
if err != nil {
|
|
t.Fatalf("RunRound: %v", err)
|
|
}
|
|
|
|
// The result must verify under unmodified FIPS 204 ML-DSA.Verify
|
|
// with the precompile ctx -- this is the Class N1 manifesto in
|
|
// effect end-to-end through the Wave-driver adapter.
|
|
if err := pulsar.VerifyCtx(params, groupPK, item, ctxBytes, res.Signature); err != nil {
|
|
t.Fatalf("FIPS 204 verify (with precompile ctx) on RoundSigner output: %v", err)
|
|
}
|
|
|
|
// Signature must NOT verify under a different ctx -- proves ctx
|
|
// is load-bearing end-to-end.
|
|
if err := pulsar.VerifyCtx(params, groupPK, item, nil, res.Signature); err == nil {
|
|
t.Fatalf("expected verify failure under ctx=nil; got nil error")
|
|
}
|
|
|
|
// Suppress the unused rand import in case the test ever reverts.
|
|
_ = rand.Reader
|
|
}
|