quasar: kill all remaining Ringtail identifiers; rename test/bench helpers

Final identifier sweep. After this commit zero 'Ringtail' / 'RINGTAIL'
references remain in any Go file in the consensus repo. Surface
changes (compound-identifier camelCase):

  bench:
    pqModesRingtailCounts → pqModesCoronaCounts
    ringtailMaxRetries    → coronaMaxRetries
    ringtailFixture       → coronaFixture
    newRingtailFixture    → newCoronaFixture
    BenchmarkPQModes_BLSPlusRingtail → BenchmarkPQModes_BLSPlusCorona

  protocol/quasar:
    RingtailSignature  → CoronaSignature
    RingtailRound1Data → CoronaRound1Data
    RingtailRound1State→ CoronaRound1State
    RingtailBits       → CoronaBits
    RingtailProof      → CoronaProof
    RingtailAggregated → CoronaAggregated
    verifyRingtailThreshold → verifyCoronaThreshold
    ringtailCount/Bits/ShareMap → coronaCount/Bits/ShareMap
    TestQuantumFinalityWithRingtail → TestQuantumFinalityWithCorona
    TestGenerateCert_RefusesPartialTriple_WithSigner_NoRingtail
        → TestGenerateCert_RefusesPartialTriple_WithSigner_NoCorona
    TestQuasarCert_Verify_RejectsMissingRingtail
        → TestQuasarCert_Verify_RejectsMissingCorona
    TestVerkleWitness_VerifyRingtailThreshold
        → TestVerkleWitness_VerifyCoronaThreshold
    TestVerkleWitness_FullVerification_RingtailThresholdNotMet
        → TestVerkleWitness_FullVerification_CoronaThresholdNotMet
    TestRingtailCertSize_BinaryVsGob → TestCoronaCertSize_BinaryVsGob
    TestNoRingtailDirectImport → TestNoCoronaDirectImport
    file rename: ringtail_death_test.go → corona_death_test.go
    TestQuasar_ValidatorSetSync_BLSAndRingtail
        → TestQuasar_ValidatorSetSync_BLSAndCorona

  engine/pq:
    CompleteRingtailRound2 → CompleteCoronaRound2
    GetRingtailGroupKey    → GetCoronaGroupKey
    TestGetRingtailGroupKey → TestGetCoronaGroupKey
    ringtailShare/Signer/Group → coronaShare/Signer/Group

  pkg/wire:
    SigRingtail → SigCorona
    TestQuantumPolicyRingtailOnlyRTNotRequired
        → TestQuantumPolicyCoronaOnlyRTNotRequired
    ringtailHash → coronaHash

Parallel Ring+Module Double-Lattice PQ posture stands: QuasarCert
carries both Corona (Ring-LWE) and Pulsar (Module-LWE) bytes,
checkable independently. Pure-PQ profile drops BLS entirely.

Tests green: quasar 42s, engine/pq 2s, bench 1s, wire 2s, config 1s.
This commit is contained in:
2026-05-12 09:41:44 -07:00
parent dc7e4ed0fc
commit 6f8f8a2268
20 changed files with 131 additions and 131 deletions
+18 -18
View File
@@ -45,17 +45,17 @@ import (
// per-validator linear paths (notably ML-DSA-65 = 3309 B per validator).
var pqModesValidatorCounts = []int{4, 21, 64, 100}
// pqModesRingtailCounts is the validator-set sizes used for Corona-bearing
// pqModesCoronaCounts is the validator-set sizes used for Corona-bearing
// modes. n=4 is excluded because the Ring-LWE rejection sampler is known
// flaky at that group size (see consensus CLAUDE.md). n=100 is excluded
// because a single full 2-round Corona signing pass takes 5+ minutes
// at that group size; the bench instead measures n in {21, 64} which is
// where the shape of the cost curve is informative.
var pqModesRingtailCounts = []int{21, 64}
var pqModesCoronaCounts = []int{21, 64}
// ringtailMaxRetries bounds how many times we re-run Round1/Round2/Finalize
// coronaMaxRetries bounds how many times we re-run Round1/Round2/Finalize
// when verify fails (Corona rejection-sampling is nondeterministic).
const ringtailMaxRetries = 4
const coronaMaxRetries = 4
// modeMetrics is the per-mode per-n result row aggregated by the suite.
type modeMetrics struct {
@@ -302,11 +302,11 @@ func BenchmarkPQModes_BLSPlusMLDSA(b *testing.B) {
// Mode 3: BLS + Corona (lattice threshold, O(1) cert in N)
// =============================================================================
// ringtailFixture holds a fully-keyed Corona group plus a parallel BLS
// coronaFixture holds a fully-keyed Corona group plus a parallel BLS
// keyset. We re-use the dual_threshold_test.go flow: GenerateDualKeys
// gives us BLS-threshold + Corona-threshold shares for a (t, n) group,
// and we drive Round1 / Round2 / Finalize to produce a real signature.
type ringtailFixture struct {
type coronaFixture struct {
cfg *quasar.SignerConfig
signer *quasar.Signer
rtSigners []*coronaThreshold.Signer
@@ -317,7 +317,7 @@ type ringtailFixture struct {
n int
}
func newRingtailFixture(t, n int) (*ringtailFixture, error) {
func newCoronaFixture(t, n int) (*coronaFixture, error) {
cfg, err := quasar.GenerateDualKeys(t, n)
if err != nil {
return nil, fmt.Errorf("GenerateDualKeys(%d,%d): %w", t, n, err)
@@ -338,7 +338,7 @@ func newRingtailFixture(t, n int) (*ringtailFixture, error) {
rtIDs[i] = i
}
return &ringtailFixture{
return &coronaFixture{
cfg: cfg,
signer: s,
rtSigners: rtSigners,
@@ -359,11 +359,11 @@ type signResult struct {
}
// signWithRetry re-runs signOnce until the produced Corona signature
// verifies, up to ringtailMaxRetries attempts. Returns (result, attempts,
// verifies, up to coronaMaxRetries attempts. Returns (result, attempts,
// error). Used because Corona rejection sampling is nondeterministic.
func (f *ringtailFixture) signWithRetry(msg []byte, prfKey []byte, groupKey *coronaThreshold.GroupKey) (*signResult, int, error) {
func (f *coronaFixture) signWithRetry(msg []byte, prfKey []byte, groupKey *coronaThreshold.GroupKey) (*signResult, int, error) {
var lastErr error
for i := 0; i < ringtailMaxRetries; i++ {
for i := 0; i < coronaMaxRetries; i++ {
res, err := f.signOnce(msg, i+1, prfKey)
if err != nil {
lastErr = err
@@ -374,12 +374,12 @@ func (f *ringtailFixture) signWithRetry(msg []byte, prfKey []byte, groupKey *cor
}
lastErr = fmt.Errorf("Corona verify failed on attempt %d", i+1)
}
return nil, ringtailMaxRetries, lastErr
return nil, coronaMaxRetries, lastErr
}
// signOnce runs the Corona 2-round flow once and returns the resulting
// signature alongside the BLS aggregate over the same message.
func (f *ringtailFixture) signOnce(msg []byte, sessionID int, prfKey []byte) (*signResult, error) {
func (f *coronaFixture) signOnce(msg []byte, sessionID int, prfKey []byte) (*signResult, error) {
round1 := make(map[int]*coronaThreshold.Round1Data, f.n)
for _, s := range f.rtSigners {
d := s.Round1(sessionID, prfKey, f.rtSignerIDs)
@@ -409,8 +409,8 @@ func (f *ringtailFixture) signOnce(msg []byte, sessionID int, prfKey []byte) (*s
return &signResult{rtSig: rtSig, rtBytes: rtBytes, blsAgg: blsAgg, blsAggPK: blsAggPK}, nil
}
func BenchmarkPQModes_BLSPlusRingtail(b *testing.B) {
for _, n := range pqModesRingtailCounts {
func BenchmarkPQModes_BLSPlusCorona(b *testing.B) {
for _, n := range pqModesCoronaCounts {
n := n
b.Run(fmt.Sprintf("n%d", n), func(b *testing.B) {
t := (2*n + 2) / 3 // ~2/3 threshold (BFT)
@@ -420,7 +420,7 @@ func BenchmarkPQModes_BLSPlusRingtail(b *testing.B) {
if t >= n {
t = n - 1
}
fix, err := newRingtailFixture(t, n)
fix, err := newCoronaFixture(t, n)
if err != nil {
b.Skipf("Corona fixture for n=%d failed: %v", n, err)
return
@@ -539,7 +539,7 @@ func BenchmarkPQModes_BLSPlusGroth16(b *testing.B) {
// =============================================================================
func BenchmarkPQModes_TripleQuantum(b *testing.B) {
for _, n := range pqModesRingtailCounts {
for _, n := range pqModesCoronaCounts {
n := n
b.Run(fmt.Sprintf("n%d", n), func(b *testing.B) {
t := (2*n + 2) / 3
@@ -549,7 +549,7 @@ func BenchmarkPQModes_TripleQuantum(b *testing.B) {
if t >= n {
t = n - 1
}
fix, err := newRingtailFixture(t, n)
fix, err := newCoronaFixture(t, n)
if err != nil {
b.Skipf("Corona fixture for n=%d failed: %v", n, err)
return
+1 -1
View File
@@ -63,7 +63,7 @@ func (p Parameters) PostQuantum() bool {
// true -> PQModeTripleQuantum // strongest available
// false -> PQModeBLSOnly // classical fast path
//
// For middle-ground modes (BLSPlusMLDSA, BLSPlusRingtail, BLSPlusGroth16),
// For middle-ground modes (BLSPlusMLDSA, BLSPlusCorona, BLSPlusGroth16),
// call WithPQMode directly with the desired constant.
func (p Parameters) WithPostQuantum(on bool) Parameters {
p.PQMode = PQModeFromBool(on)
+22 -22
View File
@@ -23,9 +23,9 @@ type CertificateGenerator struct {
blsPublicKey *bls.PublicKey
// Corona threshold signing
ringtailShare *threshold.KeyShare
ringtailSigner *threshold.Signer
ringtailGroup *threshold.GroupKey
coronaShare *threshold.KeyShare
coronaSigner *threshold.Signer
coronaGroup *threshold.GroupKey
// ML-DSA-65 identity key (FIPS 204).
mldsaSecret *mldsa.PrivateKey
@@ -54,9 +54,9 @@ func NewCertificateGenerator(blsKey, pqKey []byte) *CertificateGenerator {
// The pqKey seeds the random generation
shares, groupKey, err := threshold.GenerateKeys(2, 3, nil)
if err == nil && len(shares) > 0 {
cg.ringtailShare = shares[0]
cg.ringtailGroup = groupKey
cg.ringtailSigner = threshold.NewSigner(shares[0])
cg.coronaShare = shares[0]
cg.coronaGroup = groupKey
cg.coronaSigner = threshold.NewSigner(shares[0])
}
}
@@ -78,9 +78,9 @@ func (cg *CertificateGenerator) InitializeThreshold(share *threshold.KeyShare) {
cg.mu.Lock()
defer cg.mu.Unlock()
cg.ringtailShare = share
cg.ringtailGroup = share.GroupKey
cg.ringtailSigner = threshold.NewSigner(share)
cg.coronaShare = share
cg.coronaGroup = share.GroupKey
cg.coronaSigner = threshold.NewSigner(share)
}
// GenerateBLSSignature generates a real BLS signature for a block.
@@ -171,16 +171,16 @@ func (cg *CertificateGenerator) GeneratePQCertificate(blockID ids.ID, sessionID
cg.mu.RLock()
defer cg.mu.RUnlock()
if cg.ringtailSigner == nil {
if cg.coronaSigner == nil {
return nil, fmt.Errorf("Corona signer not initialized")
}
round1 := cg.ringtailSigner.Round1(sessionID, prfKey, signers)
round1 := cg.coronaSigner.Round1(sessionID, prfKey, signers)
return round1, nil
}
// CompleteRingtailRound2 performs round 2 of Corona signing.
func (cg *CertificateGenerator) CompleteRingtailRound2(
// CompleteCoronaRound2 performs round 2 of Corona signing.
func (cg *CertificateGenerator) CompleteCoronaRound2(
sessionID int,
message string,
prfKey []byte,
@@ -190,23 +190,23 @@ func (cg *CertificateGenerator) CompleteRingtailRound2(
cg.mu.RLock()
defer cg.mu.RUnlock()
if cg.ringtailSigner == nil {
if cg.coronaSigner == nil {
return nil, fmt.Errorf("Corona signer not initialized")
}
return cg.ringtailSigner.Round2(sessionID, message, prfKey, signers, round1Data)
return cg.coronaSigner.Round2(sessionID, message, prfKey, signers, round1Data)
}
// FinalizeRingtailSignature aggregates round 2 data into final signature.
func (cg *CertificateGenerator) FinalizeRingtailSignature(round2Data map[int]*threshold.Round2Data) (*threshold.Signature, error) {
// FinalizeCoronaSignature aggregates round 2 data into final signature.
func (cg *CertificateGenerator) FinalizeCoronaSignature(round2Data map[int]*threshold.Round2Data) (*threshold.Signature, error) {
cg.mu.RLock()
defer cg.mu.RUnlock()
if cg.ringtailSigner == nil {
if cg.coronaSigner == nil {
return nil, fmt.Errorf("Corona signer not initialized")
}
return cg.ringtailSigner.Finalize(round2Data)
return cg.coronaSigner.Finalize(round2Data)
}
// GetBLSPublicKey returns the BLS public key bytes.
@@ -220,11 +220,11 @@ func (cg *CertificateGenerator) GetBLSPublicKey() []byte {
return bls.PublicKeyToCompressedBytes(cg.blsPublicKey)
}
// GetRingtailGroupKey returns the Corona group public key.
func (cg *CertificateGenerator) GetRingtailGroupKey() *threshold.GroupKey {
// GetCoronaGroupKey returns the Corona group public key.
func (cg *CertificateGenerator) GetCoronaGroupKey() *threshold.GroupKey {
cg.mu.RLock()
defer cg.mu.RUnlock()
return cg.ringtailGroup
return cg.coronaGroup
}
// VerifyBLSAggregate verifies a BLS aggregate signature against public keys.
+9 -9
View File
@@ -25,7 +25,7 @@ func TestNewCertificateGenerator(t *testing.T) {
// Keys are now internal - verify they were initialized by checking derived values
require.NotNil(t, cg.blsSecretKey)
require.NotNil(t, cg.blsPublicKey)
require.NotNil(t, cg.ringtailGroup)
require.NotNil(t, cg.coronaGroup)
}
func TestNewCertificateGenerator_ShortKeys(t *testing.T) {
@@ -37,7 +37,7 @@ func TestNewCertificateGenerator_ShortKeys(t *testing.T) {
require.NotNil(t, cg)
require.Nil(t, cg.blsSecretKey) // Too short to initialize
require.Nil(t, cg.ringtailGroup)
require.Nil(t, cg.coronaGroup)
}
func TestGenerateBLSSignature(t *testing.T) {
@@ -255,19 +255,19 @@ func TestGetBLSPublicKey_NoKey(t *testing.T) {
require.Nil(t, pubKey)
}
func TestGetRingtailGroupKey(t *testing.T) {
func TestGetCoronaGroupKey(t *testing.T) {
blsKey, pqKey := GenerateTestKeys()
cg := NewCertificateGenerator(blsKey, pqKey)
groupKey := cg.GetRingtailGroupKey()
groupKey := cg.GetCoronaGroupKey()
require.NotNil(t, groupKey)
}
func TestGetRingtailGroupKey_NoKey(t *testing.T) {
func TestGetCoronaGroupKey_NoKey(t *testing.T) {
cg := NewCertificateGenerator(nil, nil)
groupKey := cg.GetRingtailGroupKey()
groupKey := cg.GetCoronaGroupKey()
require.Nil(t, groupKey)
}
@@ -377,12 +377,12 @@ func TestInitializeThreshold(t *testing.T) {
cg := NewCertificateGenerator(blsKey, pqKey)
// Get the existing share
existingGroup := cg.GetRingtailGroupKey()
existingGroup := cg.GetCoronaGroupKey()
require.NotNil(t, existingGroup)
// The internal share should exist after construction
require.NotNil(t, cg.ringtailShare)
require.NotNil(t, cg.ringtailSigner)
require.NotNil(t, cg.coronaShare)
require.NotNil(t, cg.coronaSigner)
}
func BenchmarkGenerateBLSSignature(b *testing.B) {
+1 -1
View File
@@ -128,7 +128,7 @@ const (
SigNone byte = 0x00
SigEd25519 byte = 0x01
SigBLS byte = 0x02
SigRingtail byte = 0x03
SigCorona byte = 0x03
SigQuasar byte = 0x04 // BLS + Corona (Quasar protocol)
)
+2 -2
View File
@@ -128,9 +128,9 @@ func TestCertificate_TranscriptHash_BindsHashSuiteID(t *testing.T) {
corona := NewCertificateWithSuite(candidateID, 100, PolicyPQ, HashSuiteBLAKE3Legacy, []byte("p"))
pulsarHash := pulsar.TranscriptHash()
ringtailHash := corona.TranscriptHash()
coronaHash := corona.TranscriptHash()
if pulsarHash == ringtailHash {
if pulsarHash == coronaHash {
t.Fatalf("transcript hash collides across HashSuiteID: Pulsar(SHA3-NIST) and Corona(BLAKE3-legacy) share PolicyPQ; F1 fix requires HashSuiteID to break the digest")
}
+3 -3
View File
@@ -534,7 +534,7 @@ func (p *QuantumPolicy) OnVote(ctx context.Context, vote *Vote) error {
p.blsVotes[vote.CandidateID] = make(map[VoterID][]byte)
}
p.blsVotes[vote.CandidateID][vote.VoterID] = vote.Signature[1:] // Skip scheme byte
case SigRingtail:
case SigCorona:
// Only allowed if requireRT is false
if p.pqVotes[vote.CandidateID] == nil {
p.pqVotes[vote.CandidateID] = make(map[VoterID][]byte)
@@ -585,8 +585,8 @@ func sigSchemeToString(scheme byte) string {
return "SigEd25519"
case SigBLS:
return "SigBLS"
case SigRingtail:
return "SigRingtail"
case SigCorona:
return "SigCorona"
case SigQuasar:
return "SigQuasar"
default:
+3 -3
View File
@@ -662,14 +662,14 @@ func TestQuantumPolicyUnknownSchemeRTNotRequired(t *testing.T) {
}
}
func TestQuantumPolicyRingtailOnlyRTNotRequired(t *testing.T) {
func TestQuantumPolicyCoronaOnlyRTNotRequired(t *testing.T) {
policy := NewQuantumPolicyWithOptions(1, false)
ctx := context.Background()
c := NewCandidate([]byte("d"), []byte("p"), EmptyCandidateID, 1)
policy.OnCandidate(ctx, c)
vote := NewVote(c.ID, DeriveVoterID("a", []byte("v")), 0, true)
vote.Signature = []byte{SigRingtail, 4, 5, 6}
vote.Signature = []byte{SigCorona, 4, 5, 6}
err := policy.OnVote(ctx, vote)
if err != nil {
t.Errorf("RT-only vote should be accepted when RT not required: %v", err)
@@ -686,7 +686,7 @@ func TestSigSchemeToString(t *testing.T) {
{SigNone, "SigNone"},
{SigEd25519, "SigEd25519"},
{SigBLS, "SigBLS"},
{SigRingtail, "SigRingtail"},
{SigCorona, "SigCorona"},
{SigQuasar, "SigQuasar"},
{0xFF, "Unknown"},
}
+1 -1
View File
@@ -426,7 +426,7 @@ func TestQuantumPolicyRTEnforcement(t *testing.T) {
// Test 2: Corona-only vote should also be rejected
rtVote := NewVote(candidate.ID, voter1, 0, true)
rtVote.Signature = []byte{SigRingtail, 4, 5, 6} // Corona only
rtVote.Signature = []byte{SigCorona, 4, 5, 6} // Corona only
err = policy.OnVote(ctx, rtVote)
if err == nil {
+2 -2
View File
@@ -10,12 +10,12 @@ import (
coronaThreshold "github.com/luxfi/corona/threshold"
)
// TestRingtailCertSize_BinaryVsGob measures the on-wire Pulsar/Corona
// TestCoronaCertSize_BinaryVsGob measures the on-wire Pulsar/Corona
// signature size produced by the native binary encoder vs the legacy gob
// encoder, for the production parameter set (M=8, N=7, LogN=8 -> ring
// degree 256, Q=0x1000000004A01 48-bit prime). Reports per-cert and
// 10K-cert storage so we can see the gob -> native delta.
func TestRingtailCertSize_BinaryVsGob(t *testing.T) {
func TestCoronaCertSize_BinaryVsGob(t *testing.T) {
cfg, err := GenerateDualKeys(2, 3)
if err != nil {
t.Fatalf("GenerateDualKeys: %v", err)
+20 -20
View File
@@ -1052,7 +1052,7 @@ func TestWitnessProof_Size(t *testing.T) {
Path: make([]byte, 16),
OpeningProof: make([]byte, 32),
BLSAggregate: make([]byte, 96),
RingtailBits: make([]byte, 4),
CoronaBits: make([]byte, 4),
ValidatorSet: make([]byte, 32),
BlockHeight: 100,
StateRoot: make([]byte, 32),
@@ -1093,7 +1093,7 @@ func TestWitnessProof_Compress(t *testing.T) {
w := &WitnessProof{
Commitment: make([]byte, 32),
OpeningProof: make([]byte, 32),
RingtailBits: []byte{0xFF, 0x0F, 0x00, 0x01},
CoronaBits: []byte{0xFF, 0x0F, 0x00, 0x01},
BlockHeight: 0x12345678,
Timestamp: 0xFEDCBA98,
}
@@ -1195,7 +1195,7 @@ func TestVerkleWitness_CheckPQFinality(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
witness := &WitnessProof{RingtailBits: tt.bits}
witness := &WitnessProof{CoronaBits: tt.bits}
got := w.checkPQFinality(witness)
if got != tt.want {
t.Errorf("checkPQFinality() = %v, want %v", got, tt.want)
@@ -1204,7 +1204,7 @@ func TestVerkleWitness_CheckPQFinality(t *testing.T) {
}
}
func TestVerkleWitness_VerifyRingtailThreshold(t *testing.T) {
func TestVerkleWitness_VerifyCoronaThreshold(t *testing.T) {
w := NewVerkleWitness(2)
tests := []struct {
@@ -1217,9 +1217,9 @@ func TestVerkleWitness_VerifyRingtailThreshold(t *testing.T) {
}
for _, tt := range tests {
got := w.verifyRingtailThreshold(tt.bits)
got := w.verifyCoronaThreshold(tt.bits)
if got != tt.want {
t.Errorf("verifyRingtailThreshold(%v) = %v, want %v", tt.bits, got, tt.want)
t.Errorf("verifyCoronaThreshold(%v) = %v, want %v", tt.bits, got, tt.want)
}
}
}
@@ -1307,14 +1307,14 @@ func TestVerkleWitness_CreateWitness(t *testing.T) {
t.Error("expected non-empty opening proof")
}
if len(witness.RingtailBits) == 0 {
if len(witness.CoronaBits) == 0 {
t.Error("expected non-empty corona bits")
}
// Check corona bits match signers
expectedBits := compressToBitfield(signers)
for i := range expectedBits {
if witness.RingtailBits[i] != expectedBits[i] {
if witness.CoronaBits[i] != expectedBits[i] {
t.Error("corona bits mismatch")
}
}
@@ -1346,7 +1346,7 @@ func TestVerkleWitness_VerifyStateTransition(t *testing.T) {
Commitment: commitmentBytes[:],
Path: path,
OpeningProof: openingProof,
RingtailBits: []byte{0x01}, // 1 signer meets threshold of 1
CoronaBits: []byte{0x01}, // 1 signer meets threshold of 1
BlockHeight: 100,
StateRoot: stateRoot,
}
@@ -1364,7 +1364,7 @@ func TestVerkleWitness_VerifyStateTransition_InvalidCommitment(t *testing.T) {
Commitment: []byte{1, 2, 3}, // Invalid commitment bytes
Path: []byte{4, 5, 6},
OpeningProof: []byte{7, 8, 9},
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
}
err := w.VerifyStateTransition(witness)
@@ -1393,7 +1393,7 @@ func TestVerkleWitness_BatchVerify(t *testing.T) {
Commitment: commitmentBytes[:],
Path: path,
OpeningProof: openingProof,
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
StateRoot: stateRoot,
}
}
@@ -1421,7 +1421,7 @@ func TestVerkleWitness_BatchVerify_WithInvalid(t *testing.T) {
Commitment: commitmentBytes[:],
Path: path,
OpeningProof: openingProof,
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
StateRoot: stateRoot,
}
@@ -1430,7 +1430,7 @@ func TestVerkleWitness_BatchVerify_WithInvalid(t *testing.T) {
Commitment: []byte{1, 2, 3}, // Invalid
Path: []byte{4, 5, 6},
OpeningProof: []byte{7, 8, 9},
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
}
witnesses := []*WitnessProof{validWitness, invalidWitness}
@@ -1471,7 +1471,7 @@ func TestVerkleWitness_FullVerification(t *testing.T) {
Path: path,
OpeningProof: openingProof,
BLSAggregate: blsSigBytes,
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
ValidatorSet: []byte{5, 6, 7, 8},
BlockHeight: 100,
StateRoot: stateRoot,
@@ -1507,7 +1507,7 @@ func TestVerkleWitness_FullVerification_InsufficientThreshold(t *testing.T) {
Path: path,
OpeningProof: openingProof,
BLSAggregate: blsSig, // Valid-length signature
RingtailBits: []byte{0x01}, // Only 1 signer, need 5
CoronaBits: []byte{0x01}, // Only 1 signer, need 5
ValidatorSet: []byte{5, 6, 7, 8},
StateRoot: stateRoot,
}
@@ -2355,7 +2355,7 @@ func TestVerkleWitness_VerifyVerkleCommitment_InvalidOpeningProof(t *testing.T)
Commitment: commitmentBytes[:],
Path: path,
OpeningProof: []byte{1, 2, 3, 4, 5}, // Wrong proof
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
StateRoot: stateRoot,
}
@@ -2656,7 +2656,7 @@ func TestSigner_VerifyAggregatedSignature_BLSSignatureTamperedFail(t *testing.T)
}
}
func TestVerkleWitness_FullVerification_RingtailThresholdNotMet(t *testing.T) {
func TestVerkleWitness_FullVerification_CoronaThresholdNotMet(t *testing.T) {
w := NewVerkleWitness(10) // High threshold
w.assumePQFinal = false // Force full verification path
@@ -2684,7 +2684,7 @@ func TestVerkleWitness_FullVerification_RingtailThresholdNotMet(t *testing.T) {
Path: path,
OpeningProof: openingProof,
BLSAggregate: blsSig, // Valid-length signature
RingtailBits: []byte{0x01}, // Only 1 signer, need 10
CoronaBits: []byte{0x01}, // Only 1 signer, need 10
ValidatorSet: []byte{5, 6, 7, 8},
StateRoot: stateRoot,
}
@@ -2866,7 +2866,7 @@ func TestVerkleWitness_VerifyStateTransition_FastPath(t *testing.T) {
Commitment: commitmentBytes[:],
Path: path,
OpeningProof: openingProof,
RingtailBits: []byte{0x01}, // 1 signer meets threshold
CoronaBits: []byte{0x01}, // 1 signer meets threshold
StateRoot: stateRoot,
}
@@ -2898,7 +2898,7 @@ func TestVerkleWitness_VerifyStateTransition_SlowPath(t *testing.T) {
Path: path,
OpeningProof: openingProof,
BLSAggregate: blsSigBytes,
RingtailBits: []byte{0x01}, // 1 signer meets threshold
CoronaBits: []byte{0x01}, // 1 signer meets threshold
ValidatorSet: []byte{5, 6, 7, 8},
StateRoot: stateRoot,
}
+3 -3
View File
@@ -69,7 +69,7 @@ type QuantumBlock struct {
SourceBlocks []*Block
QuantumHash string
BLSSignature []byte
RingtailProof []byte // ML-DSA signature
CoronaProof []byte // ML-DSA signature
Timestamp time.Time
CreatedAt time.Time // When this block entered the pending set
ValidatorSigs map[string]*QuasarSig
@@ -870,12 +870,12 @@ func (q *Quasar) VerifyQuasarSig(message []byte, sig *QuasarSig) bool {
}
// CoronaRound1 executes Round 1 of the Corona threshold signing protocol.
func (q *Quasar) CoronaRound1(validatorID string, sessionID int, prfKey []byte) (*RingtailRound1Data, error) {
func (q *Quasar) CoronaRound1(validatorID string, sessionID int, prfKey []byte) (*CoronaRound1Data, error) {
data, err := q.signer.CoronaRound1(validatorID, sessionID, prfKey)
if err != nil {
return nil, err
}
return &RingtailRound1Data{PartyID: data.PartyID}, nil
return &CoronaRound1Data{PartyID: data.PartyID}, nil
}
// Internal helpers
+1 -1
View File
@@ -95,7 +95,7 @@ func TestQuasar(t *testing.T) {
processed, proofs, height)
}
func TestQuantumFinalityWithRingtail(t *testing.T) {
func TestQuantumFinalityWithCorona(t *testing.T) {
// Test that Corona and BLS signatures work in parallel
qa, err := NewQuasar(2)
if err != nil {
@@ -26,7 +26,7 @@ import (
"testing"
)
// TestNoRingtailDirectImport — fails if any non-test .go file in this
// TestNoCoronaDirectImport — fails if any non-test .go file in this
// package imports `github.com/luxfi/nasua/...` or invokes
// corona.GenerateKeys (matched as a selector expression
// `corona.GenerateKeys(...)` regardless of the package alias).
@@ -34,7 +34,7 @@ import (
// Test files (*_test.go) are scanned too — the corona kernel is
// equally forbidden from package tests so the cutover doesn't slip
// back through a "just for the test" import.
func TestNoRingtailDirectImport(t *testing.T) {
func TestNoCoronaDirectImport(t *testing.T) {
pkgDir, err := os.Getwd()
if err != nil {
t.Fatalf("os.Getwd: %v", err)
@@ -57,7 +57,7 @@ func TestNoRingtailDirectImport(t *testing.T) {
// literals as part of the death-test guard — the regex /
// fixture below would match itself otherwise.
base := filepath.Base(f)
if base == "ringtail_death_test.go" {
if base == "corona_death_test.go" {
continue
}
@@ -86,7 +86,7 @@ func TestNoRingtailDirectImport(t *testing.T) {
// dot-imported alias, which we reject below by name.
for _, f := range matches {
base := filepath.Base(f)
if base == "ringtail_death_test.go" {
if base == "corona_death_test.go" {
continue
}
src, err := os.ReadFile(f)
+1 -1
View File
@@ -522,7 +522,7 @@ func TestQuasar_UpdateValidatorSet(t *testing.T) {
t.Log("Updated validator set: v2->inactive, added v3, v4")
}
func TestQuasar_ValidatorSetSync_BLSAndRingtail(t *testing.T) {
func TestQuasar_ValidatorSetSync_BLSAndCorona(t *testing.T) {
q, err := NewQuasar(2)
require.NoError(t, err)
+14 -14
View File
@@ -111,8 +111,8 @@ type SignerConfig struct {
CoronaGroupKey *coronaThreshold.GroupKey
}
// RingtailRound1State holds Round 1 data for all parties in a signing session.
type RingtailRound1State struct {
// CoronaRound1State holds Round 1 data for all parties in a signing session.
type CoronaRound1State struct {
SessionID int
PRFKey []byte
SignerIDs []int
@@ -225,12 +225,12 @@ func GenerateDualKeys(t, n int) (*SignerConfig, error) {
// Convert to maps keyed by validator ID
blsShareMap := make(map[string]threshold.KeyShare)
ringtailShareMap := make(map[string]*coronaThreshold.KeyShare)
coronaShareMap := make(map[string]*coronaThreshold.KeyShare)
for i := 0; i < n; i++ {
id := fmt.Sprintf("v%d", i)
blsShareMap[id] = blsShares[i]
ringtailShareMap[id] = coronaShares[i]
coronaShareMap[id] = coronaShares[i]
}
return &SignerConfig{
@@ -238,7 +238,7 @@ func GenerateDualKeys(t, n int) (*SignerConfig, error) {
TotalParties: n,
BLSKeyShares: blsShareMap,
BLSGroupKey: blsGroupKey,
CoronaShares: ringtailShareMap,
CoronaShares: coronaShareMap,
CoronaGroupKey: coronaGroupKey,
}, nil
}
@@ -301,8 +301,8 @@ func (s *signer) CoronaFinalize(validatorID string, round2Data map[int]*coronaTh
return signer.Finalize(round2Data)
}
// VerifyRingtailSignature verifies a Corona threshold signature.
func (s *signer) VerifyRingtailSignature(message string, sig *coronaThreshold.Signature) bool {
// VerifyCoronaSignature verifies a Corona threshold signature.
func (s *signer) VerifyCoronaSignature(message string, sig *coronaThreshold.Signature) bool {
if s.coronaGroupKey == nil || sig == nil {
return false
}
@@ -319,10 +319,10 @@ func (s *signer) VerifyRingtailSignature(message string, sig *coronaThreshold.Si
func (s *signer) DualSignRound1(ctx context.Context, validatorID string, message []byte, sessionID int, prfKey []byte) (*QuasarSig, *coronaThreshold.Round1Data, error) {
s.mu.RLock()
blsSigner, hasBLS := s.blsSigners[validatorID]
_, hasRingtail := s.coronaSigners[validatorID]
_, hasCorona := s.coronaSigners[validatorID]
s.mu.RUnlock()
if !hasBLS || !hasRingtail {
if !hasBLS || !hasCorona {
return nil, nil, errors.New("validator not configured for dual signing")
}
@@ -389,7 +389,7 @@ func (s *signer) DualSignRound2(validatorID string, sessionID int, message strin
func (s *signer) TripleSignRound1(ctx context.Context, validatorID string, message []byte, sessionID int, prfKey []byte) (*QuasarSig, *coronaThreshold.Round1Data, error) {
s.mu.RLock()
blsSigner, hasBLS := s.blsSigners[validatorID]
_, hasRingtail := s.coronaSigners[validatorID]
_, hasCorona := s.coronaSigners[validatorID]
mldsaSK, hasMLDSA := s.mldsaKeys[validatorID]
s.mu.RUnlock()
@@ -409,7 +409,7 @@ func (s *signer) TripleSignRound1(ctx context.Context, validatorID string, messa
}
paths := 1 // BLS always
if hasRingtail {
if hasCorona {
paths++
}
if hasMLDSA {
@@ -424,7 +424,7 @@ func (s *signer) TripleSignRound1(ctx context.Context, validatorID string, messa
}()
// Path 2: Corona Round 1 (PQ lattice threshold)
if hasRingtail {
if hasCorona {
go func() {
defer wg.Done()
round1Data, rtErr = s.CoronaRound1(validatorID, sessionID, prfKey)
@@ -598,7 +598,7 @@ func (s *signer) VerifyQuasarSig(message []byte, sig *QuasarSig) bool {
// VerifyQuasarSigWithContext verifies a signature.
// Verifies all present paths: BLS (always), ML-DSA (when sig.MLDSA is non-empty).
// Corona threshold verification is handled separately via VerifyRingtailSignature.
// Corona threshold verification is handled separately via VerifyCoronaSignature.
func (s *signer) VerifyQuasarSigWithContext(ctx context.Context, message []byte, sig *QuasarSig) bool {
if ctx.Err() != nil {
return false
@@ -787,7 +787,7 @@ type QuasarSig struct {
// AggregatedSignature contains aggregated signatures.
type AggregatedSignature struct {
BLSAggregated []byte
RingtailAggregated []byte
CoronaAggregated []byte
ValidatorIDs []string
SignerCount int
IsThreshold bool
+4 -4
View File
@@ -38,12 +38,12 @@ func TestGenerateCert_RefusesPartialTriple(t *testing.T) {
}
}
// TestGenerateCert_RefusesPartialTriple_WithSigner_NoRingtail proves
// TestGenerateCert_RefusesPartialTriple_WithSigner_NoCorona proves
// the realCert fallback path is also closed: a signer can produce a
// BLS+MLDSA cert (Corona empty because aggregation is at the
// BundleSigner layer), and under a triple-mode profile we MUST refuse
// that single-layer artefact.
func TestGenerateCert_RefusesPartialTriple_WithSigner_NoRingtail(t *testing.T) {
func TestGenerateCert_RefusesPartialTriple_WithSigner_NoCorona(t *testing.T) {
c, err := newCertifier(1)
if err != nil {
t.Fatalf("newCertifier: %v", err)
@@ -127,11 +127,11 @@ func TestGenerateCert_NilProfile_AcceptsPlaceholder(t *testing.T) {
}
}
// TestQuasarCert_Verify_RejectsMissingRingtail proves the structural
// TestQuasarCert_Verify_RejectsMissingCorona proves the structural
// gate at the vote-acceptance layer: cert.Verify() refuses a cert that
// doesn't carry every layer, so a single-layer cert is rejected even
// if generateCert somehow emits it.
func TestQuasarCert_Verify_RejectsMissingRingtail(t *testing.T) {
func TestQuasarCert_Verify_RejectsMissingCorona(t *testing.T) {
cert := &QuasarCert{
BLS: []byte("bls"),
Corona: nil, // missing
+6 -6
View File
@@ -414,7 +414,7 @@ type Stats struct {
}
// BLSSignature contains a classical BLS threshold signature.
// Fast path for consensus - used in parallel with RingtailSignature.
// Fast path for consensus - used in parallel with CoronaSignature.
type BLSSignature struct {
Signature []byte // BLS signature bytes
ValidatorID string // Signing validator
@@ -422,9 +422,9 @@ type BLSSignature struct {
SignerIndex int // Signer index in committee
}
// RingtailSignature contains a post-quantum Corona threshold signature.
// CoronaSignature contains a post-quantum Corona threshold signature.
// Quantum-safe path - used in parallel with BLSSignature.
type RingtailSignature struct {
type CoronaSignature struct {
Signature []byte // Corona (Ring-LWE) signature bytes
ValidatorID string // Signing validator
IsThreshold bool // True if threshold signature
@@ -447,12 +447,12 @@ type RingtailSignature struct {
// PQ proof: variable (aggregated Corona + ML-DSA, or future SNARK)
type QuasarSignature struct {
BLS *BLSSignature // Classical fast path (aggregatable)
Corona *RingtailSignature // PQ anonymous path (ring-LWE threshold)
Corona *CoronaSignature // PQ anonymous path (ring-LWE threshold)
MLDSA []byte // PQ identity proof (ML-DSA-65, FIPS 204)
}
// RingtailRound1Data contains the output of Corona Round 1.
type RingtailRound1Data struct {
// CoronaRound1Data contains the output of Corona Round 1.
type CoronaRound1Data struct {
PartyID int
}
+12 -12
View File
@@ -85,7 +85,7 @@ type VerkleWitness struct {
//
// PQSignature is the load-bearing field: an ML-DSA-65 signature over
// SigningDigest(witness) produced by the group key the verifier holds.
// BLSAggregate / RingtailBits / ValidatorSet are legacy fields kept
// BLSAggregate / CoronaBits / ValidatorSet are legacy fields kept
// for wire compatibility with classical-compat deployments; under
// strict-PQ the verifier ignores them.
type WitnessProof struct {
@@ -100,9 +100,9 @@ type WitnessProof struct {
PQSignature []byte
// Legacy fields (classical-compat deployments). Strict-PQ
// verifiers refuse to consult RingtailBits / BLSAggregate.
// verifiers refuse to consult CoronaBits / BLSAggregate.
BLSAggregate []byte // Aggregated BLS signature
RingtailBits []byte // Bitfield of Corona signers
CoronaBits []byte // Bitfield of Corona signers
ValidatorSet []byte // Compressed validator set hash
// Block metadata
@@ -334,8 +334,8 @@ func (v *VerkleWitness) checkPQFinality(witness *WitnessProof) bool {
if witness == nil {
return false
}
ringtailCount := countSetBits(witness.RingtailBits)
return ringtailCount >= v.minThreshold
coronaCount := countSetBits(witness.CoronaBits)
return coronaCount >= v.minThreshold
}
// verifyVerkleCommitment does ultra-fast Verkle proof verification
@@ -381,7 +381,7 @@ func (v *VerkleWitness) fullVerification(witness *WitnessProof) error {
}
// Verify Corona threshold
if !v.verifyRingtailThreshold(witness.RingtailBits) {
if !v.verifyCoronaThreshold(witness.CoronaBits) {
return errors.New("corona threshold not met")
}
@@ -406,7 +406,7 @@ func (v *VerkleWitness) CreateWitness(
openingProof := createIPAProof(commitment, stateRoot)
// Compress Corona signers to bitfield
ringtailBits := compressToBitfield(coronaSigners)
coronaBits := compressToBitfield(coronaSigners)
// Create witness
commitmentBytes := commitment.Bytes()
@@ -415,7 +415,7 @@ func (v *VerkleWitness) CreateWitness(
Path: compressPath(stateRoot),
OpeningProof: openingProof,
BLSAggregate: bls.SignatureToBytes(blsAgg),
RingtailBits: ringtailBits,
CoronaBits: coronaBits,
ValidatorSet: hashValidatorSet(),
BlockHeight: height,
StateRoot: stateRoot,
@@ -615,7 +615,7 @@ func (v *VerkleWitness) verifyBLSAggregate(aggSig []byte, validatorSet []byte) e
return nil
}
func (v *VerkleWitness) verifyRingtailThreshold(bits []byte) bool {
func (v *VerkleWitness) verifyCoronaThreshold(bits []byte) bool {
count := countSetBits(bits)
return count >= v.minThreshold
}
@@ -633,7 +633,7 @@ func (v *VerkleWitness) GetCachedWitness(stateRoot []byte) (*WitnessProof, bool)
func (w *WitnessProof) Size() int {
return len(w.Commitment) + len(w.Path) + len(w.OpeningProof) +
len(w.PQSignature) +
len(w.BLSAggregate) + len(w.RingtailBits) + len(w.ValidatorSet) +
len(w.BLSAggregate) + len(w.CoronaBits) + len(w.ValidatorSet) +
8 + len(w.StateRoot) + 8 // BlockHeight + StateRoot + Timestamp
}
@@ -659,8 +659,8 @@ func (w *WitnessProof) Compress() *CompressedWitness {
// Compress validator bits to uint32 (supports up to 32 validators)
var validatorBits uint32
for i := 0; i < len(w.RingtailBits) && i < 4; i++ {
validatorBits |= uint32(w.RingtailBits[i]) << (i * 8)
for i := 0; i < len(w.CoronaBits) && i < 4; i++ {
validatorBits |= uint32(w.CoronaBits[i]) << (i * 8)
}
return &CompressedWitness{
+4 -4
View File
@@ -35,7 +35,7 @@ func TestVerifyPQFinality_PulsarM_RealVerifyAccepts(t *testing.T) {
Commitment: make([]byte, 32),
Path: make([]byte, 16),
OpeningProof: make([]byte, 48),
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
BlockHeight: 100,
StateRoot: make([]byte, 32),
Timestamp: 1700000000,
@@ -73,7 +73,7 @@ func TestVerifyPQFinality_PulsarM_TamperedSignatureRejected(t *testing.T) {
Commitment: make([]byte, 32),
Path: make([]byte, 16),
OpeningProof: make([]byte, 48),
RingtailBits: []byte{0x01},
CoronaBits: []byte{0x01},
BlockHeight: 100,
StateRoot: make([]byte, 32),
Timestamp: 1700000000,
@@ -123,7 +123,7 @@ func TestVerifyPQFinality_PulsarM_BitCountAlone_DoesNotPass(t *testing.T) {
Commitment: make([]byte, 32),
Path: make([]byte, 16),
OpeningProof: make([]byte, 48),
RingtailBits: []byte{0xFF}, // 8 bits set — bit-count would pass at any threshold ≤ 8
CoronaBits: []byte{0xFF}, // 8 bits set — bit-count would pass at any threshold ≤ 8
BlockHeight: 100,
StateRoot: make([]byte, 32),
Timestamp: 1700000000,
@@ -141,7 +141,7 @@ func TestVerifyPQFinality_PulsarM_BitCountAlone_DoesNotPass(t *testing.T) {
// Swap the message: mutate StateRoot so SigningDigest now yields
// M2 ≠ M1. The signature still decodes (it's a genuine Pulsar-M
// signature), the bit-count pre-filter still passes (RingtailBits
// signature), the bit-count pre-filter still passes (CoronaBits
// untouched), but the lattice verify equation MUST reject.
witness.StateRoot[0] ^= 0x01
digestM2 := witness.SigningDigest()