refactor: quasar protocol improvements and test updates

- Update quasar BLS and GPU integration
- Improve epoch and threshold management
- Remove deprecated corona module
- Update integration tests for chain engine
- Enhance dynamic and dual threshold tests
- CGO_ENABLED=1 default for GPU acceleration
This commit is contained in:
2026-01-03 07:01:00 -08:00
parent 1011cbfcfd
commit 9f512ab6c1
49 changed files with 927 additions and 1294 deletions
+48 -40
View File
@@ -1,54 +1,62 @@
# golangci-lint configuration
# golangci-lint v2 configuration
version: "2"
run:
timeout: 10m
tests: false
go: '1.21'
skip-dirs:
- vendor
- third_party
- testdata
- examples
- .git
- build
linters:
formatters:
enable:
- gofmt
linters:
default: none
enable:
- govet
- staticcheck
- ineffassign
- misspell
disable:
- unused
- gosec # Too many false positives
- revive # Conflicts with other linters
- gocritic # Too strict for now
- gofumpt # Different from gofmt
- unconvert # Too many false positives
- goimports # Not needed with gofmt
linters-settings:
govet:
check-shadowing: false # Too many false positives
gofmt:
simplify: true
staticcheck:
checks: ["all", "-SA1019"] # Ignore deprecation warnings
settings:
govet:
disable:
- shadow
staticcheck:
checks:
- "all"
- "-SA1019"
- "-QF1008" # embedded field selector (style suggestion)
- "-QF1012" # fmt.Fprintf instead of Write (style suggestion)
- "-ST1003" # ALL_CAPS naming (style)
- "-ST1005" # error string capitalization (style)
- "-ST1023" # omit type from declaration (style)
- "-QF1011" # omit type from declaration (style)
exclusions:
generated: lax
presets:
- comments
paths:
- vendor
- third_party
- testdata
- examples
- build
rules:
- path: _test\.go
linters:
- staticcheck
- ineffassign
- path: test/
linters:
- staticcheck
- ineffassign
- path: cmd/
text: "Error return value of .* is not checked"
- text: "declaration of \"err\" shadows"
linters:
- govet
issues:
exclude-rules:
- path: _test\.go
linters:
- staticcheck
- ineffassign
- path: test/
linters:
- staticcheck
- ineffassign
- path: cmd/
text: "Error return value of .* is not checked"
- text: "declaration of \"err\" shadows"
linters:
- govet
max-issues-per-linter: 50
max-same-issues: 10
max-same-issues: 10
+2 -2
View File
@@ -21,7 +21,7 @@ type Agent[T ConsensusData] struct {
nodeID string
model Model[T]
memory *SharedMemory[T]
quasar *quasar.QuasarCore
quasar *quasar.Quasar
photon *photon.UniformEmitter
// Shared hallucination state
@@ -157,7 +157,7 @@ type Model[T ConsensusData] interface {
func New[T ConsensusData](
nodeID string,
model Model[T],
quasarEngine *quasar.QuasarCore,
quasarEngine *quasar.Quasar,
photonEngine *photon.UniformEmitter,
) *Agent[T] {
return &Agent[T]{
+1 -1
View File
@@ -776,7 +776,7 @@ func TestSecurityAgent_AutomaticSecurityResponse_AutoExecuteError(t *testing.T)
}
threat := SecurityData{
ThreatLevel: "critical", // Critical triggers auto-execute
ThreatLevel: "critical", // Critical triggers auto-execute
Threats: []string{"attack"},
NodeID: "malicious-node",
Evidence: []string{"evidence"},
+1 -1
View File
@@ -147,7 +147,7 @@ func GetNodeID(ctx context.Context) ids.NodeID {
// IDs holds the IDs for consensus context
type IDs struct {
NetworkID uint32 // 1=mainnet, 2=testnet
NetworkID uint32 // 1=mainnet, 2=testnet
ChainID ids.ID
NodeID ids.NodeID
PublicKey []byte
+3 -3
View File
@@ -97,7 +97,7 @@ const (
Stopped = vm.Stopped
// Legacy aliases for VMState constants (old naming convention)
VMStateSyncing = vm.Syncing
VMBootstrapping = vm.Bootstrapping
VMNormalOp = vm.Ready
VMStateSyncing = vm.Syncing
VMBootstrapping = vm.Bootstrapping
VMNormalOp = vm.Ready
)
+7 -7
View File
@@ -1015,16 +1015,16 @@ type testBlock struct {
bytes []byte
}
func (b *testBlock) ID() ids.ID { return b.id }
func (b *testBlock) Parent() ids.ID { return b.parentID }
func (b *testBlock) ParentID() ids.ID { return b.parentID }
func (b *testBlock) Height() uint64 { return b.height }
func (b *testBlock) Timestamp() time.Time { return b.timestamp }
func (b *testBlock) Status() uint8 { return b.status }
func (b *testBlock) ID() ids.ID { return b.id }
func (b *testBlock) Parent() ids.ID { return b.parentID }
func (b *testBlock) ParentID() ids.ID { return b.parentID }
func (b *testBlock) Height() uint64 { return b.height }
func (b *testBlock) Timestamp() time.Time { return b.timestamp }
func (b *testBlock) Status() uint8 { return b.status }
func (b *testBlock) Verify(context.Context) error { return nil }
func (b *testBlock) Accept(context.Context) error { return nil }
func (b *testBlock) Reject(context.Context) error { return nil }
func (b *testBlock) Bytes() []byte { return b.bytes }
func (b *testBlock) Bytes() []byte { return b.bytes }
// mockBlockBuilder implements BlockBuilder for testing
type mockBlockBuilder struct {
+22 -6
View File
@@ -427,11 +427,23 @@ func (t *Transitive) Notify(ctx context.Context, msg Message) error {
}
// ReceiveVote queues a vote for processing.
func (t *Transitive) ReceiveVote(vote Vote) {
// Returns false if the engine is not started (vote is dropped).
func (t *Transitive) ReceiveVote(vote Vote) bool {
t.mu.RLock()
started := t.started
t.mu.RUnlock()
if !started {
// Engine not started - drop vote to prevent state corruption
return false
}
select {
case t.votes <- vote:
return true
default:
// Channel full; vote will be resent
return false
}
}
@@ -524,15 +536,19 @@ func (t *Transitive) handleVote(vote Vote) {
t.votesReceived++
// Only process votes for blocks we're tracking
pending, exists := t.pendingBlocks[vote.BlockID]
if !exists {
return
}
if err := t.consensus.ProcessVote(t.ctx, vote.BlockID, vote.Accept); err != nil {
return
}
if pending, ok := t.pendingBlocks[vote.BlockID]; ok {
pending.VoteCount++
responses := map[ids.ID]int{vote.BlockID: pending.VoteCount}
_ = t.consensus.Poll(t.ctx, responses)
}
pending.VoteCount++
responses := map[ids.ID]int{vote.BlockID: pending.VoteCount}
_ = t.consensus.Poll(t.ctx, responses)
}
func (t *Transitive) buildBlocksLocked(ctx context.Context) error {
+13 -13
View File
@@ -21,16 +21,16 @@ type mockBlock struct {
bytes []byte
}
func (b *mockBlock) ID() ids.ID { return b.id }
func (b *mockBlock) Parent() ids.ID { return b.parentID }
func (b *mockBlock) ParentID() ids.ID { return b.parentID }
func (b *mockBlock) Height() uint64 { return b.height }
func (b *mockBlock) Timestamp() time.Time { return b.timestamp }
func (b *mockBlock) Status() uint8 { return b.status }
func (b *mockBlock) ID() ids.ID { return b.id }
func (b *mockBlock) Parent() ids.ID { return b.parentID }
func (b *mockBlock) ParentID() ids.ID { return b.parentID }
func (b *mockBlock) Height() uint64 { return b.height }
func (b *mockBlock) Timestamp() time.Time { return b.timestamp }
func (b *mockBlock) Status() uint8 { return b.status }
func (b *mockBlock) Verify(context.Context) error { return nil }
func (b *mockBlock) Accept(context.Context) error { return nil }
func (b *mockBlock) Reject(context.Context) error { return nil }
func (b *mockBlock) Bytes() []byte { return b.bytes }
func (b *mockBlock) Bytes() []byte { return b.bytes }
func TestNew(t *testing.T) {
engine := New()
@@ -320,12 +320,12 @@ type trackingMockBlock struct {
rejectCalled int
}
func (b *trackingMockBlock) ID() ids.ID { return b.id }
func (b *trackingMockBlock) Parent() ids.ID { return b.parentID }
func (b *trackingMockBlock) ParentID() ids.ID { return b.parentID }
func (b *trackingMockBlock) Height() uint64 { return b.height }
func (b *trackingMockBlock) Timestamp() time.Time { return b.timestamp }
func (b *trackingMockBlock) Status() uint8 { return 0 }
func (b *trackingMockBlock) ID() ids.ID { return b.id }
func (b *trackingMockBlock) Parent() ids.ID { return b.parentID }
func (b *trackingMockBlock) ParentID() ids.ID { return b.parentID }
func (b *trackingMockBlock) Height() uint64 { return b.height }
func (b *trackingMockBlock) Timestamp() time.Time { return b.timestamp }
func (b *trackingMockBlock) Status() uint8 { return 0 }
func (b *trackingMockBlock) Verify(context.Context) error { return nil }
func (b *trackingMockBlock) Accept(context.Context) error {
b.acceptCalled++
+7 -3
View File
@@ -37,9 +37,14 @@ type NetworkConfig struct {
type Gossiper interface {
// GossipPut broadcasts a Put message with block data to validators.
// Returns the number of validators the message was sent to.
GossipPut(chainID ids.ID, netID ids.ID, blockData []byte) int
GossipPut(chainID ids.ID, networkID ids.ID, blockData []byte) int
// SendPullQuery sends a PullQuery to specific validators requesting votes.
SendPullQuery(chainID ids.ID, netID ids.ID, blockID ids.ID, validators []ids.NodeID) int
SendPullQuery(chainID ids.ID, networkID ids.ID, blockID ids.ID, validators []ids.NodeID) int
// SendChit sends a vote response (Chit) back to the node that requested our vote.
// This is called after verifying a block received via PullQuery.
// requestID is used to correlate the response with the original request.
// preferredID is the block we prefer (voted for).
SendChit(toNodeID ids.NodeID, chainID ids.ID, requestID uint32, preferredID ids.ID) error
}
// IntegratedEngine wraps Transitive with network integration and VM notification handling.
@@ -266,4 +271,3 @@ func (ie *IntegratedEngine) HandleIncomingBlock(ctx context.Context, blockData [
return blk, nil
}
+8 -6
View File
@@ -540,33 +540,35 @@ func TestRecordPollTransitivelyResetConfidenceTest(t *testing.T) {
Beta: 2, // Requires 2 rounds
}
genesisID := ids.GenerateTestID()
// Use deterministic IDs to ensure consistent preference selection
// IDs are ordered: genesis < block0 < block1 < block2 < block3
genesisID := ids.ID{0x00}
genesisHeight := uint64(0)
genesisTime := time.Now()
require.NoError(engine.Initialize(ctx, params, genesisID, genesisHeight, genesisTime))
// Build block tree
// Build block tree with deterministic IDs
block0 := &TestBlock{
IDV: ids.GenerateTestID(),
IDV: ids.ID{0x10}, // Lower than block1
HeightV: 1,
ParentV: genesisID,
TimestampV: genesisTime.Add(time.Second),
}
block1 := &TestBlock{
IDV: ids.GenerateTestID(),
IDV: ids.ID{0x20}, // Higher than block0
HeightV: 1,
ParentV: genesisID,
TimestampV: genesisTime.Add(time.Second),
}
block2 := &TestBlock{
IDV: ids.GenerateTestID(),
IDV: ids.ID{0x30}, // Lower than block3
HeightV: 2,
ParentV: block1.ID(),
TimestampV: genesisTime.Add(2 * time.Second),
}
block3 := &TestBlock{
IDV: ids.GenerateTestID(),
IDV: ids.ID{0x40}, // Higher than block2
HeightV: 2,
ParentV: block1.ID(),
TimestampV: genesisTime.Add(2 * time.Second),
+10 -10
View File
@@ -38,20 +38,20 @@ type Handler interface {
// getter implementation
type getter struct {
vtxManager state.Manager
sender sender.Sender
log log.Logger
maxTimeGetAncestors time.Duration
ancestorsMaxContainers int
vtxManager state.Manager
sender sender.Sender
log log.Logger
maxTimeGetAncestors time.Duration
ancestorsMaxContainers int
}
// Config for creating a Handler
type Config struct {
VtxManager state.Manager
Sender sender.Sender
Log log.Logger
MaxTimeGetAncestors time.Duration
AncestorsMaxContainers int
VtxManager state.Manager
Sender sender.Sender
Log log.Logger
MaxTimeGetAncestors time.Duration
AncestorsMaxContainers int
}
// New creates a new getter
+9 -9
View File
@@ -85,10 +85,10 @@ type GPUBuffer struct {
capacity int
// Transaction data (CPU-side, copied to GPU)
txHashes [][32]byte
signatures [][]byte
publicKeys [][]byte
sigTypes []SignatureType
txHashes [][32]byte
signatures [][]byte
publicKeys [][]byte
sigTypes []SignatureType
// Results (GPU-side, copied back)
validFlags []bool
@@ -217,8 +217,8 @@ type GPUMerkleTree struct {
gpuNodes uintptr
// Root cached on CPU after computation
root [32]byte
rootMu sync.RWMutex
root [32]byte
rootMu sync.RWMutex
// Pending leaves to insert
pending [][32]byte
@@ -504,9 +504,9 @@ func (p *GPUBatchPipeline) swapBuffers() {
// processBatch executes signature verification and aggregation.
func (p *GPUBatchPipeline) processBatch(buf *GPUBuffer, batchID uint64, txs []Transaction) *BatchResult {
result := &BatchResult{
BatchID: batchID,
ProcessedCount: buf.count,
Errors: make([]TransactionError, 0),
BatchID: batchID,
ProcessedCount: buf.count,
Errors: make([]TransactionError, 0),
SignatureProofs: make([]SignatureProof, 0, buf.count),
}
+1 -1
View File
@@ -503,7 +503,7 @@ func TestLuxConsensusPollFocusDecideReject(t *testing.T) {
// Now state is 1, threshold is 1, so decided=true
// Poll with low ratio to hit the reject branch
lowRatioResponses := map[ids.ID]int{
item2: 1, // Only 10% - below alpha (90%)
item2: 1, // Only 10% - below alpha (90%)
ids.GenerateTestID(): 9, // 90% for another item
}
continuePolling = lc2.Poll(lowRatioResponses)
+3
View File
@@ -86,6 +86,9 @@ func (c *CGOConsensus) Add(block Block) error {
}
c.cacheMu.Unlock()
// Update preference to latest block
c.preference.Store(blockID)
return nil
}
+15 -15
View File
@@ -449,16 +449,16 @@ func TestBlockToFinalityEvent(t *testing.T) {
validIDStr := validID.String()
testCases := []struct {
name string
block *quasar.Block
wantBLS []byte
wantPQ []byte
name string
block *quasar.Block
wantBLS []byte
wantPQ []byte
}{
{
name: "block with certificate",
block: &quasar.Block{
Hash: validIDStr,
Height: 100,
Height: 100,
Timestamp: testTime,
Cert: &quasar.BlockCert{
BLS: []byte("bls-proof-data"),
@@ -472,9 +472,9 @@ func TestBlockToFinalityEvent(t *testing.T) {
name: "block without certificate",
block: &quasar.Block{
Hash: validIDStr,
Height: 50,
Height: 50,
Timestamp: testTime,
Cert: nil,
Cert: nil,
},
wantBLS: nil,
wantPQ: nil,
@@ -483,7 +483,7 @@ func TestBlockToFinalityEvent(t *testing.T) {
name: "block with empty proofs in cert",
block: &quasar.Block{
Hash: validIDStr,
Height: 75,
Height: 75,
Timestamp: testTime,
Cert: &quasar.BlockCert{
BLS: []byte{},
@@ -497,9 +497,9 @@ func TestBlockToFinalityEvent(t *testing.T) {
name: "block with invalid hash",
block: &quasar.Block{
Hash: "invalid-hash",
Height: 25,
Height: 25,
Timestamp: testTime,
Cert: nil,
Cert: nil,
},
wantBLS: nil,
wantPQ: nil,
@@ -508,9 +508,9 @@ func TestBlockToFinalityEvent(t *testing.T) {
name: "block with empty hash",
block: &quasar.Block{
Hash: "",
Height: 10,
Height: 10,
Timestamp: testTime,
Cert: nil,
Cert: nil,
},
wantBLS: nil,
wantPQ: nil,
@@ -599,7 +599,7 @@ func TestSetFinalizedCallbackInvocation(t *testing.T) {
// Invoke the callback with a test block
testBlock := &quasar.Block{
Hash: validID.String(),
Height: 42,
Height: 42,
Timestamp: time.Now(),
Cert: &quasar.BlockCert{
BLS: []byte("test-bls"),
@@ -643,9 +643,9 @@ func TestSetFinalizedCallbackInvocationNilCert(t *testing.T) {
// Invoke the callback with a block that has no cert
testBlock := &quasar.Block{
Hash: validID.String(),
Height: 100,
Height: 100,
Timestamp: time.Now(),
Cert: nil,
Cert: nil,
}
cb(testBlock)
+1 -1
View File
@@ -18,9 +18,9 @@ import (
"time"
"github.com/luxfi/consensus/engine"
"github.com/luxfi/crypto"
"github.com/luxfi/geth/common"
"github.com/luxfi/geth/core/types"
"github.com/luxfi/crypto"
"github.com/luxfi/ids"
)
+26 -26
View File
@@ -2,7 +2,7 @@
//
// This demonstrates the complete Quasar consensus protocol showing how:
// - FPC provides dynamic thresholds
// - Wave achieves metastable convergence
// - Wave achieves metastable convergence
// - Horizon detects DAG finality
// - All together achieve <1s quantum finality
//
@@ -32,7 +32,7 @@ func main() {
demonstrateWaveConsensus()
demonstrateHorizonFinality()
demonstrateQuasarFlow()
fmt.Println("✅ Quasar protocol demonstration complete!")
fmt.Println()
}
@@ -40,26 +40,26 @@ func main() {
func demonstrateFPC() {
fmt.Println("━━━ Part 1: Fast Probabilistic Consensus (FPC) ━━━")
fmt.Println()
selector := fpc.NewSelector(0.5, 0.8, nil)
k := 20
fmt.Println(" FPC prevents stuck states with dynamic thresholds")
fmt.Printf(" Theta range: [0.5, 0.8] (50%%-80%% quorum)\n")
fmt.Printf(" Sample size: %d validators\n", k)
fmt.Println()
fmt.Println(" Threshold selection (PRF-based):")
thresholdSet := make(map[int]bool)
for round := uint64(0); round < 10; round++ {
threshold := selector.SelectThreshold(round, k)
thresholdSet[threshold] = true
theta := float64(threshold) / float64(k)
fmt.Printf(" Round %2d: α=%2d/%d (θ=%.3f) %s\n",
fmt.Printf(" Round %2d: α=%2d/%d (θ=%.3f) %s\n",
round, threshold, k, theta, bar(theta, 20))
}
fmt.Printf("\n ✓ %d unique thresholds prevent stuck states\n", len(thresholdSet))
fmt.Println()
}
@@ -67,14 +67,14 @@ func demonstrateFPC() {
func demonstrateWaveConsensus() {
fmt.Println("━━━ Part 2: Wave Consensus (Block Finalization) ━━━")
fmt.Println()
cfg := consensus.DefaultConfig()
chain := consensus.NewChain(cfg)
ctx := context.Background()
chain.Start(ctx)
defer chain.Stop()
// Create and finalize block
block := &consensus.Block{
ID: consensus.ID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
@@ -83,71 +83,71 @@ func demonstrateWaveConsensus() {
Time: time.Now(),
Payload: []byte("Quasar block with quantum finality"),
}
fmt.Printf(" Block: %x...\n", block.ID[:8])
start := time.Now()
chain.Add(ctx, block)
// Simulate votes
for i := 0; i < 20; i++ {
nodeID := consensus.NodeID{byte(i + 1)}
vote := consensus.NewVote(block.ID, consensus.VotePreference, nodeID)
chain.RecordVote(ctx, vote)
if (i+1)%5 == 0 {
fmt.Printf(" Votes: %2d/20 %s\n", i+1, bar(float64(i+1)/20.0, 30))
}
}
elapsed := time.Since(start)
status := chain.GetStatus(block.ID)
fmt.Printf("\n Status: %v\n", status)
fmt.Printf(" Time: %v\n", elapsed)
if status == consensus.StatusAccepted {
fmt.Println(" ✅ Block finalized with BFT guarantees")
}
fmt.Println()
}
func demonstrateHorizonFinality() {
fmt.Println("━━━ Part 3: Horizon DAG Finality Algorithms ━━━")
fmt.Println()
genesis := ids.Empty
b1, _ := ids.ToID([]byte("block1_left_____________________"))
b2, _ := ids.ToID([]byte("block2_right____________________"))
b3, _ := ids.ToID([]byte("block3_merge____________________"))
store := createMockDAG(genesis, b1, b2, b3)
fmt.Println(" DAG Structure: Genesis → (B1, B2) → B3")
fmt.Println()
// Test all algorithms
fmt.Println(" Horizon Algorithms Working:")
fmt.Printf(" ✓ IsReachable: %v\n", dag.IsReachable[ids.ID](store, genesis, b3))
fmt.Printf(" ✓ LCA: %s\n", dag.LCA[ids.ID](store, b1, b2))
fmt.Printf(" ✓ SafePrefix: %d finalized\n", len(dag.ComputeSafePrefix[ids.ID](store, []ids.ID{b3})))
fmt.Printf(" ✓ ChooseFrontier: %d selected\n", len(dag.ChooseFrontier[ids.ID]([]ids.ID{b1, b2, b3})))
horizons := []dag.EventHorizon[ids.ID]{
{Checkpoint: genesis, Height: 0, Validators: []string{"set0"}, Signature: []byte("sig0")},
}
newH := dag.Horizon[ids.ID](store, horizons)
fmt.Printf(" ✓ Horizon: Height %d → %d\n", 0, newH.Height)
fmt.Printf(" ✓ BeyondHorizon: %v\n", dag.BeyondHorizon[ids.ID](store, b3, newH))
fmt.Println()
}
func demonstrateQuasarFlow() {
fmt.Println("━━━ Part 4: Complete Quasar Protocol ━━━")
fmt.Println()
fmt.Println(" Quasar 2-Round Quantum Finality:")
fmt.Println()
fmt.Println(" ┌─────────────────────────────────────────┐")
+64 -63
View File
@@ -5,6 +5,7 @@ package main
import (
"context"
"fmt"
"testing"
"time"
@@ -19,24 +20,24 @@ import (
func TestFPCDynamicThresholds(t *testing.T) {
selector := fpc.NewSelector(0.5, 0.8, nil)
k := 20
// Test determinism: same round = same threshold
t1 := selector.SelectThreshold(0, k)
t2 := selector.SelectThreshold(0, k)
require.Equal(t, t1, t2, "Same round must give same threshold (determinism)")
// Test variety: different rounds = different thresholds
thresholds := make(map[int]bool)
for round := uint64(0); round < 100; round++ {
threshold := selector.SelectThreshold(round, k)
// Verify threshold is in valid range
require.GreaterOrEqual(t, threshold, 10, "Threshold should be ≥ 50%% of k")
require.LessOrEqual(t, threshold, 16, "Threshold should be ≤ 80%% of k")
thresholds[threshold] = true
}
require.Greater(t, len(thresholds), 1, "Should have variety in thresholds")
t.Logf("✓ FPC generated %d unique thresholds across 100 rounds", len(thresholds))
}
@@ -45,12 +46,12 @@ func TestFPCDynamicThresholds(t *testing.T) {
func TestBlockFinalization(t *testing.T) {
cfg := consensus.DefaultConfig()
chain := consensus.NewChain(cfg)
ctx := context.Background()
err := chain.Start(ctx)
require.NoError(t, err)
defer chain.Stop()
// Create block
block := &consensus.Block{
ID: consensus.ID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
@@ -59,27 +60,27 @@ func TestBlockFinalization(t *testing.T) {
Time: time.Now(),
Payload: []byte("Test block finalization"),
}
// Add block
err = chain.Add(ctx, block)
require.NoError(t, err, "Block should be added")
// Simulate votes
validators := make([]consensus.NodeID, 20)
for i := range validators {
validators[i] = consensus.NodeID{byte(i + 1)}
}
for _, validator := range validators {
vote := consensus.NewVote(block.ID, consensus.VotePreference, validator)
err = chain.RecordVote(ctx, vote)
require.NoError(t, err)
}
// Verify finality
status := chain.GetStatus(block.ID)
require.Equal(t, consensus.StatusAccepted, status, "Block should achieve finality")
t.Log("✓ Block achieved finality with full validator support")
}
@@ -89,18 +90,18 @@ func TestHorizonReachability(t *testing.T) {
b1, _ := ids.ToID([]byte("block_1_________________________"))
b2, _ := ids.ToID([]byte("block_2_________________________"))
b3, _ := ids.ToID([]byte("block_3_________________________"))
store := createMockDAG(genesis, b1, b2, b3)
// Test forward reachability
require.True(t, dag.IsReachable[ids.ID](store, genesis, b1), "Genesis should reach B1")
require.True(t, dag.IsReachable[ids.ID](store, genesis, b3), "Genesis should reach B3")
require.True(t, dag.IsReachable[ids.ID](store, b1, b3), "B1 should reach B3")
// Test backward non-reachability (DAG is directed)
require.False(t, dag.IsReachable[ids.ID](store, b3, genesis), "B3 cannot reach Genesis")
require.False(t, dag.IsReachable[ids.ID](store, b1, genesis), "B1 cannot reach Genesis")
t.Log("✓ Reachability algorithm works correctly")
}
@@ -110,13 +111,13 @@ func TestLCA(t *testing.T) {
b1, _ := ids.ToID([]byte("block_1_________________________"))
b2, _ := ids.ToID([]byte("block_2_________________________"))
b3, _ := ids.ToID([]byte("block_3_________________________"))
store := createMockDAG(genesis, b1, b2, b3)
// LCA of parallel blocks should be their common parent
lca := dag.LCA[ids.ID](store, b1, b2)
require.Equal(t, genesis, lca, "LCA of B1 and B2 should be Genesis")
t.Log("✓ LCA algorithm works correctly")
}
@@ -126,13 +127,13 @@ func TestSafePrefix(t *testing.T) {
b1, _ := ids.ToID([]byte("block_1_________________________"))
b2, _ := ids.ToID([]byte("block_2_________________________"))
b3, _ := ids.ToID([]byte("block_3_________________________"))
store := createMockDAG(genesis, b1, b2, b3)
// Safe prefix with B3 as frontier should include ancestors
frontier := []ids.ID{b3}
safe := dag.ComputeSafePrefix[ids.ID](store, frontier)
require.NotNil(t, safe, "Should return safe prefix")
t.Logf("✓ Safe prefix computed: %d vertices finalized", len(safe))
}
@@ -144,13 +145,13 @@ func TestChooseFrontier(t *testing.T) {
for i := range vertices {
vertices[i], _ = ids.ToID([]byte(fmt.Sprintf("vertex_%d", i)))
}
// Choose frontier with Byzantine tolerance
chosen := dag.ChooseFrontier[ids.ID](vertices)
require.NotEmpty(t, chosen, "Should choose some vertices")
require.LessOrEqual(t, len(chosen), len(vertices), "Can't choose more than available")
// For 10 vertices, f=(10-1)/3=3, so 2f+1=7
// Should choose min(7, 10) = 7 or all if < 7
t.Logf("✓ Chose %d vertices with Byzantine tolerance", len(chosen))
@@ -162,9 +163,9 @@ func TestEventHorizon(t *testing.T) {
b1, _ := ids.ToID([]byte("block_1_________________________"))
b2, _ := ids.ToID([]byte("block_2_________________________"))
b3, _ := ids.ToID([]byte("block_3_________________________"))
store := createMockDAG(genesis, b1, b2, b3)
// Create initial checkpoint
checkpoints := []dag.EventHorizon[ids.ID]{
{
@@ -174,13 +175,13 @@ func TestEventHorizon(t *testing.T) {
Signature: []byte("corona+bls_sig_0"),
},
}
// Compute new horizon
newHorizon := dag.Horizon[ids.ID](store, checkpoints)
require.NotEqual(t, ids.ID{}, newHorizon.Checkpoint, "Should have valid checkpoint")
require.GreaterOrEqual(t, newHorizon.Height, checkpoints[0].Height, "Horizon should not regress")
t.Logf("✓ Event horizon advanced from height %d to %d", checkpoints[0].Height, newHorizon.Height)
}
@@ -190,20 +191,20 @@ func TestBeyondHorizon(t *testing.T) {
b1, _ := ids.ToID([]byte("block_1_________________________"))
b2, _ := ids.ToID([]byte("block_2_________________________"))
b3, _ := ids.ToID([]byte("block_3_________________________"))
store := createMockDAG(genesis, b1, b2, b3)
horizon := dag.EventHorizon[ids.ID]{
Checkpoint: genesis,
Height: 0,
Validators: []string{"set"},
Signature: []byte("sig"),
}
// Blocks reachable from genesis should be beyond horizon
beyond := dag.BeyondHorizon[ids.ID](store, b3, horizon)
require.True(t, beyond, "B3 should be beyond horizon (reachable from checkpoint)")
t.Log("✓ BeyondHorizon correctly identifies finalized vertices")
}
@@ -212,12 +213,12 @@ func TestQuasarIntegration(t *testing.T) {
// Create chain
cfg := consensus.DefaultConfig()
chain := consensus.NewChain(cfg)
ctx := context.Background()
err := chain.Start(ctx)
require.NoError(t, err)
defer chain.Stop()
// Add multiple blocks
blocks := make([]*consensus.Block, 5)
for i := range blocks {
@@ -228,24 +229,24 @@ func TestQuasarIntegration(t *testing.T) {
Time: time.Now(),
Payload: []byte(fmt.Sprintf("Block %d", i+1)),
}
err = chain.Add(ctx, blocks[i])
require.NoError(t, err)
}
// Vote on all blocks
validators := make([]consensus.NodeID, 20)
for i := range validators {
validators[i] = consensus.NodeID{byte(i + 1)}
}
for _, block := range blocks {
for _, validator := range validators {
vote := consensus.NewVote(block.ID, consensus.VotePreference, validator)
chain.RecordVote(ctx, vote)
}
}
// Verify all blocks finalized
finalizedCount := 0
for _, block := range blocks {
@@ -253,7 +254,7 @@ func TestQuasarIntegration(t *testing.T) {
finalizedCount++
}
}
require.Greater(t, finalizedCount, 0, "At least some blocks should finalize")
t.Logf("✓ %d/%d blocks achieved finality", finalizedCount, len(blocks))
}
@@ -261,34 +262,34 @@ func TestQuasarIntegration(t *testing.T) {
// TestCertificateThresholds tests Byzantine fault tolerance math
func TestCertificateThresholds(t *testing.T) {
testCases := []struct {
n int
f int
certThreshold int
description string
n int
f int
certThreshold int
description string
}{
{20, 6, 13, "Production network (n=20, f=6)"},
{100, 33, 67, "Large network (n=100, f=33)"},
{7, 2, 5, "Small network (n=7, f=2)"},
{4, 1, 3, "Minimal BFT (n=4, f=1)"},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
params := dag.Params{N: tc.n, F: tc.f}
// Verify Byzantine tolerance: n > 3f
require.Greater(t, params.N, 3*params.F, "Must have n > 3f for BFT")
// Verify certificate threshold: 2f+1
certThreshold := 2*params.F + 1
require.Equal(t, tc.certThreshold, certThreshold)
// Verify safety: can't have both cert and skip
// (need 2f+1 for cert AND 2f+1 for skip = 4f+2 > n when n=3f+1)
require.Greater(t, 2*certThreshold, params.N,
require.Greater(t, 2*certThreshold, params.N,
"Certificate and skip thresholds ensure mutual exclusivity")
t.Logf("✓ n=%d, f=%d: requires %d/%d validators (%.1f%%)",
t.Logf("✓ n=%d, f=%d: requires %d/%d validators (%.1f%%)",
tc.n, tc.f, certThreshold, tc.n, 100.0*float64(certThreshold)/float64(tc.n))
})
}
@@ -298,11 +299,11 @@ func TestCertificateThresholds(t *testing.T) {
func BenchmarkQuasarFullProtocol(b *testing.B) {
cfg := consensus.DefaultConfig()
chain := consensus.NewChain(cfg)
ctx := context.Background()
chain.Start(ctx)
defer chain.Stop()
b.ResetTimer()
for i := 0; i < b.N; i++ {
block := &consensus.Block{
@@ -311,9 +312,9 @@ func BenchmarkQuasarFullProtocol(b *testing.B) {
Height: uint64(i + 1),
Payload: []byte("benchmark"),
}
chain.Add(ctx, block)
// Simulate votes
for j := 0; j < 20; j++ {
vote := consensus.NewVote(block.ID, consensus.VotePreference, consensus.NodeID{byte(j)})
@@ -326,7 +327,7 @@ func BenchmarkQuasarFullProtocol(b *testing.B) {
func BenchmarkFPCThresholdSelection(b *testing.B) {
selector := fpc.NewSelector(0.5, 0.8, nil)
k := 20
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = selector.SelectThreshold(uint64(i), k)
@@ -339,35 +340,35 @@ func BenchmarkHorizonAlgorithms(b *testing.B) {
b1, _ := ids.ToID([]byte("block_1_________________________"))
b2, _ := ids.ToID([]byte("block_2_________________________"))
b3, _ := ids.ToID([]byte("block_3_________________________"))
store := createMockDAG(genesis, b1, b2, b3)
b.Run("IsReachable", func(b *testing.B) {
for i := 0; i < b.N; i++ {
dag.IsReachable[ids.ID](store, genesis, b3)
}
})
b.Run("LCA", func(b *testing.B) {
for i := 0; i < b.N; i++ {
dag.LCA[ids.ID](store, b1, b2)
}
})
b.Run("ComputeSafePrefix", func(b *testing.B) {
frontier := []ids.ID{b3}
for i := 0; i < b.N; i++ {
dag.ComputeSafePrefix[ids.ID](store, frontier)
}
})
b.Run("ChooseFrontier", func(b *testing.B) {
vertices := []ids.ID{b1, b2, b3}
for i := 0; i < b.N; i++ {
dag.ChooseFrontier[ids.ID](vertices)
}
})
b.Run("Horizon", func(b *testing.B) {
checkpoints := []dag.EventHorizon[ids.ID]{
{Checkpoint: genesis, Height: 0},
+2 -2
View File
@@ -15,7 +15,7 @@ require (
github.com/luxfi/math v1.2.0
github.com/luxfi/p2p v1.4.6
github.com/luxfi/corona v0.2.0
github.com/luxfi/vm v1.0.1
github.com/luxfi/vm v1.0.2
github.com/luxfi/warp v1.18.2
github.com/prometheus/client_golang v1.23.2
github.com/prometheus/client_model v0.6.2
@@ -86,7 +86,7 @@ require (
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
+4 -4
View File
@@ -152,8 +152,8 @@ github.com/luxfi/sampler v1.0.0 h1:k8Sf6otW83w4pQp0jXLA+g3J/joB7w7SqXQsWmNTOV0=
github.com/luxfi/sampler v1.0.0/go.mod h1:f96/ozlj9vFfZj+akLtrHn4VpulQahwB+MQQhpeIekk=
github.com/luxfi/utils v1.1.0 h1:ti7HvjNwJd4ILDMERJtOAWE9mF8l+zqDVkgWnF7Agic=
github.com/luxfi/utils v1.1.0/go.mod h1:ABqhBdGNig0CaDcnNYldv1byS0BTNi5IKPbJSPF1p98=
github.com/luxfi/vm v1.0.1 h1:eZqrp6mEFPkhiv5kf5ZXmYAbXXjpS9axpUQG3cd3yts=
github.com/luxfi/vm v1.0.1/go.mod h1:PJinuF4McLaHN57iKf8p7h89wIQhQT//LD/fac+/Dk8=
github.com/luxfi/vm v1.0.2 h1:JnMm6QTh1nwWKXFy4Qf9Ej38KyXzFeprcy3Rp8/516s=
github.com/luxfi/vm v1.0.2/go.mod h1:cRmy9WL9keIkl5XgGcP1w/RbwiMSYucjGdQ3LrSF0aQ=
github.com/luxfi/warp v1.18.2 h1:TWmXjKXI7nxaDOnXIrw8BQTI/nCEniA17bs06bwNB4Q=
github.com/luxfi/warp v1.18.2/go.mod h1:qu3TZv98repNhIDf04I6pzXePSgHjzP+JoSfWmF4PBA=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
@@ -260,8 +260,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+2 -1
View File
@@ -1,8 +1,9 @@
package flare
import (
"github.com/luxfi/consensus/core/dag"
"testing"
"github.com/luxfi/consensus/core/dag"
)
type testVertex struct {
+34 -21
View File
@@ -1,3 +1,15 @@
// Package quasar - BLS DAG Event Horizon Implementation
//
// This file implements DAG-based event horizon consensus for vertex ordering.
// It uses SHA256 commitments for local attestations within the DAG.
//
// IMPORTANT: This is NOT the threshold signature implementation.
// For real cryptographic threshold signatures (BLS + Corona), see:
// - quasar.go: Signer struct with github.com/luxfi/crypto/bls integration
// - epoch.go: Corona threshold signing via github.com/luxfi/corona/threshold
//
// The BLS struct here handles DAG vertex ordering and event horizon
// establishment, which operates independently of block finality signatures.
package quasar
import (
@@ -95,14 +107,16 @@ func (q *BLS) SetFinalizedCallback(cb func(*Block)) {
q.finalizedCb = cb
}
// generateBLSAggregate generates a BLS aggregate signature
// generateBLSAggregate generates a commitment for DAG event horizon.
// NOTE: This uses SHA256 as a placeholder for local vertex ordering.
// For threshold block finality with real BLS signatures, use the Signer
// in quasar.go which integrates with github.com/luxfi/crypto/bls.
func (q *BLS) generateBLSAggregate(blockID ids.ID, votes map[string]int) []byte {
if len(q.blsKey) == 0 {
// Return empty if no key
return []byte{}
}
// Create deterministic signature based on blockID and votes
// Create deterministic commitment based on blockID and votes
h := sha256.New()
h.Write(blockID[:])
@@ -118,21 +132,22 @@ func (q *BLS) generateBLSAggregate(blockID ids.ID, votes map[string]int) []byte
h.Write(countBytes)
}
// Mix in BLS key
// Mix in key for local binding
h.Write(q.blsKey)
// Production: Use real BLS aggregation from github.com/luxfi/crypto/bls
return h.Sum(nil)
}
// generatePQCertificate generates a post-quantum certificate
// generatePQCertificate generates a post-quantum commitment for DAG event horizon.
// NOTE: This uses SHA256 as a placeholder for local vertex ordering.
// For real PQ threshold signatures, use the Signer in quasar.go which
// integrates with github.com/luxfi/corona/threshold.
func (q *BLS) generatePQCertificate(blockID ids.ID, votes map[string]int) []byte {
if len(q.pqKey) == 0 {
// Return empty if no key
return []byte{}
}
// Create message to sign
// Create message to commit
h := sha256.New()
h.Write(blockID[:])
@@ -150,12 +165,11 @@ func (q *BLS) generatePQCertificate(blockID ids.ID, votes map[string]int) []byte
message := h.Sum(nil)
// Create certificate
// Create local commitment
cert := sha256.New()
cert.Write(message)
cert.Write(q.pqKey)
// Production: Use ML-DSA from github.com/luxfi/crypto/mldsa or SLH-DSA from /slhdsa
return cert.Sum(nil)
}
@@ -249,15 +263,15 @@ func (q *BLS) GetLatestHorizon() *dag.EventHorizon[VertexID] {
return &q.horizons[len(q.horizons)-1]
}
// createHorizonSignature creates a Corona + BLS fusion signature for the event horizon.
// The signature combines:
// 1. BLS aggregate signature (32 bytes) - for efficiency
// 2. Corona post-quantum hash (32 bytes) - for security binding
// createHorizonSignature creates a local attestation for the event horizon checkpoint.
// This is a SHA256-based commitment used for DAG vertex ordering.
//
// Note: Full threshold signing (multi-party Corona) is handled by Quasar.hybridConsensus.
// This function creates a local attestation for the horizon checkpoint.
// NOTE: For production threshold signatures with real BLS + Corona,
// use the Signer in quasar.go which integrates:
// - github.com/luxfi/crypto/bls for BLS threshold signatures
// - github.com/luxfi/corona/threshold for post-quantum signatures
func (q *BLS) createHorizonSignature(checkpoint VertexID, validators []string) []byte {
// Create message to sign: checkpoint + sorted validators
// Create message: checkpoint + validators
h := sha256.New()
h.Write(checkpoint[:])
for _, v := range validators {
@@ -265,19 +279,18 @@ func (q *BLS) createHorizonSignature(checkpoint VertexID, validators []string) [
}
message := h.Sum(nil)
// BLS component: sign with BLS key
// BLS component commitment
blsSig := sha256.New()
blsSig.Write(message)
blsSig.Write(q.blsKey)
blsPart := blsSig.Sum(nil)
// PQ component: sign with post-quantum key
// PQ component commitment
pqSig := sha256.New()
pqSig.Write(message)
pqSig.Write(q.pqKey)
pqPart := pqSig.Sum(nil)
// Fusion: concatenate both signatures (64 bytes total)
// Production: Use github.com/luxfi/crypto/bls and /mldsa for real signatures
// Combined attestation (64 bytes)
return append(blsPart, pqPart...)
}
+138 -266
View File
@@ -536,9 +536,9 @@ func TestEngine_ComputeHash(t *testing.T) {
}
func TestHybridConsensus_AddRemoveValidator(t *testing.T) {
hc, err := newHybridConsensus(1)
hc, err := newCertifier(1)
if err != nil {
t.Fatalf("newHybridConsensus failed: %v", err)
t.Fatalf("newCertifier failed: %v", err)
}
hc.AddValidator("v1", 100)
@@ -560,9 +560,9 @@ func TestHybridConsensus_AddRemoveValidator(t *testing.T) {
}
func TestHybridConsensus_GenerateCert(t *testing.T) {
hc, err := newHybridConsensus(1)
hc, err := newCertifier(1)
if err != nil {
t.Fatalf("newHybridConsensus failed: %v", err)
t.Fatalf("newCertifier failed: %v", err)
}
block := &Block{
@@ -595,22 +595,22 @@ func TestHybridConsensus_GenerateCert(t *testing.T) {
// Hybrid Tests (hybrid.go)
// =============================================================================
func TestHybrid_NewHybrid_InvalidThreshold(t *testing.T) {
_, err := NewHybrid(0)
func TestSigner_NewSigner_InvalidThreshold(t *testing.T) {
_, err := NewSigner(0)
if err == nil {
t.Error("expected error for threshold 0")
}
_, err = NewHybrid(-1)
_, err = NewSigner(-1)
if err == nil {
t.Error("expected error for negative threshold")
}
}
func TestHybrid_AddValidator(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_AddValidator(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
err = h.AddValidator("v1", 100)
@@ -627,10 +627,10 @@ func TestHybrid_AddValidator(t *testing.T) {
}
}
func TestHybrid_SignMessage_ValidatorNotFound(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_SignMessage_ValidatorNotFound(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_, err = h.SignMessage("nonexistent", []byte("test"))
@@ -639,67 +639,67 @@ func TestHybrid_SignMessage_ValidatorNotFound(t *testing.T) {
}
}
func TestHybrid_ReleaseHybridSignature(t *testing.T) {
func TestSigner_ReleaseQuasarSig(t *testing.T) {
// Test with nil - should not panic
ReleaseHybridSignature(nil)
ReleaseQuasarSig(nil)
// Test with valid signature
h, _ := NewHybrid(1)
h, _ := NewSigner(1)
_ = h.AddValidator("v1", 100)
sig, _ := h.SignMessage("v1", []byte("test"))
ReleaseHybridSignature(sig)
ReleaseQuasarSig(sig)
// No assertion needed - just checking it doesn't panic
}
func TestHybrid_VerifyHybridSignature_ValidatorNotFound(t *testing.T) {
h, _ := NewHybrid(1)
func TestSigner_VerifyQuasarSig_ValidatorNotFound(t *testing.T) {
h, _ := NewSigner(1)
_ = h.AddValidator("v1", 100)
sig := &HybridSignature{
sig := &QuasarSig{
ValidatorID: "nonexistent",
BLS: []byte{1, 2, 3},
Corona: []byte{4, 5, 6},
}
result := h.VerifyHybridSignature([]byte("test"), sig)
result := h.VerifyQuasarSig([]byte("test"), sig)
if result {
t.Error("expected false for nonexistent validator")
}
}
func TestHybrid_VerifyHybridSignature_InvalidBLS(t *testing.T) {
h, _ := NewHybrid(1)
func TestSigner_VerifyQuasarSig_InvalidBLS(t *testing.T) {
h, _ := NewSigner(1)
_ = h.AddValidator("v1", 100)
sig := &HybridSignature{
sig := &QuasarSig{
ValidatorID: "v1",
BLS: []byte{1, 2, 3}, // Invalid BLS bytes
Corona: []byte{4, 5, 6},
}
result := h.VerifyHybridSignature([]byte("test"), sig)
result := h.VerifyQuasarSig([]byte("test"), sig)
if result {
t.Error("expected false for invalid BLS signature")
}
}
func TestHybrid_AggregateSignatures_InsufficientSignatures(t *testing.T) {
h, _ := NewHybrid(3) // Require 3 validators
func TestSigner_AggregateSignatures_InsufficientSignatures(t *testing.T) {
h, _ := NewSigner(3) // Require 3 validators
_ = h.AddValidator("v1", 100)
sig, _ := h.SignMessage("v1", []byte("test"))
// Only 1 signature, but threshold is 3
_, err := h.AggregateSignatures([]byte("test"), []*HybridSignature{sig})
_, err := h.AggregateSignatures([]byte("test"), []*QuasarSig{sig})
if err == nil {
t.Error("expected error for insufficient signatures")
}
}
func TestHybrid_AggregateSignatures_Success(t *testing.T) {
h, _ := NewHybrid(2)
func TestSigner_AggregateSignatures_Success(t *testing.T) {
h, _ := NewSigner(2)
_ = h.AddValidator("v1", 100)
_ = h.AddValidator("v2", 100)
@@ -708,7 +708,7 @@ func TestHybrid_AggregateSignatures_Success(t *testing.T) {
sig1, _ := h.SignMessage("v1", msg)
sig2, _ := h.SignMessage("v2", msg)
aggSig, err := h.AggregateSignatures(msg, []*HybridSignature{sig1, sig2})
aggSig, err := h.AggregateSignatures(msg, []*QuasarSig{sig1, sig2})
if err != nil {
t.Fatalf("AggregateSignatures failed: %v", err)
}
@@ -726,8 +726,8 @@ func TestHybrid_AggregateSignatures_Success(t *testing.T) {
}
}
func TestHybrid_VerifyAggregatedSignature(t *testing.T) {
h, _ := NewHybrid(2)
func TestSigner_VerifyAggregatedSignature(t *testing.T) {
h, _ := NewSigner(2)
_ = h.AddValidator("v1", 100)
_ = h.AddValidator("v2", 100)
@@ -736,7 +736,7 @@ func TestHybrid_VerifyAggregatedSignature(t *testing.T) {
sig1, _ := h.SignMessage("v1", msg)
sig2, _ := h.SignMessage("v2", msg)
aggSig, _ := h.AggregateSignatures(msg, []*HybridSignature{sig1, sig2})
aggSig, _ := h.AggregateSignatures(msg, []*QuasarSig{sig1, sig2})
result := h.VerifyAggregatedSignature(msg, aggSig)
if !result {
@@ -744,8 +744,8 @@ func TestHybrid_VerifyAggregatedSignature(t *testing.T) {
}
}
func TestHybrid_VerifyAggregatedSignature_InsufficientSigners(t *testing.T) {
h, _ := NewHybrid(3) // Require 3
func TestSigner_VerifyAggregatedSignature_InsufficientSigners(t *testing.T) {
h, _ := NewSigner(3) // Require 3
_ = h.AddValidator("v1", 100)
_ = h.AddValidator("v2", 100)
@@ -763,8 +763,8 @@ func TestHybrid_VerifyAggregatedSignature_InsufficientSigners(t *testing.T) {
}
}
func TestHybrid_VerifyAggregatedSignature_InvalidBLS(t *testing.T) {
h, _ := NewHybrid(1)
func TestSigner_VerifyAggregatedSignature_InvalidBLS(t *testing.T) {
h, _ := NewSigner(1)
_ = h.AddValidator("v1", 100)
aggSig := &AggregatedSignature{
@@ -779,8 +779,8 @@ func TestHybrid_VerifyAggregatedSignature_InvalidBLS(t *testing.T) {
}
}
func TestHybrid_VerifyAggregatedSignature_InactiveValidator(t *testing.T) {
h, _ := NewHybrid(1)
func TestSigner_VerifyAggregatedSignature_InactiveValidator(t *testing.T) {
h, _ := NewSigner(1)
_ = h.AddValidator("v1", 100)
// Make validator inactive
@@ -801,8 +801,8 @@ func TestHybrid_VerifyAggregatedSignature_InactiveValidator(t *testing.T) {
}
}
func TestHybrid_GetActiveValidatorCount(t *testing.T) {
h, _ := NewHybrid(1)
func TestSigner_GetActiveValidatorCount(t *testing.T) {
h, _ := NewSigner(1)
if h.GetActiveValidatorCount() != 0 {
t.Error("expected 0 validators initially")
@@ -826,137 +826,13 @@ func TestHybrid_GetActiveValidatorCount(t *testing.T) {
}
// =============================================================================
// Corona Tests (corona.go)
// Corona Tests
// =============================================================================
func TestCorona_Initialize(t *testing.T) {
r := NewCorona()
err := r.Initialize(SecurityLow)
if err != nil {
t.Fatalf("Initialize SecurityLow failed: %v", err)
}
err = r.Initialize(SecurityMedium)
if err != nil {
t.Fatalf("Initialize SecurityMedium failed: %v", err)
}
err = r.Initialize(SecurityHigh)
if err != nil {
t.Fatalf("Initialize SecurityHigh failed: %v", err)
}
}
func TestCorona_KeyGen(t *testing.T) {
seed := []byte("test-seed-32-bytes-long-enough!!")
sk, pk, err := KeyGen(seed)
if err != nil {
t.Fatalf("KeyGen failed: %v", err)
}
if len(sk) == 0 || len(pk) == 0 {
t.Error("expected non-empty keys")
}
}
func TestCorona_Precompute(t *testing.T) {
sk := make([]byte, 32)
precomp, err := Precompute(sk)
if err != nil {
t.Fatalf("Precompute failed: %v", err)
}
if len(precomp) == 0 {
t.Error("expected non-empty precomp")
}
}
func TestCorona_QuickSign(t *testing.T) {
precomp := make([]byte, 32)
for i := range precomp {
precomp[i] = byte(i)
}
msg := []byte("test message")
share, err := QuickSign(precomp, msg)
if err != nil {
t.Fatalf("QuickSign failed: %v", err)
}
if len(share) == 0 {
t.Error("expected non-empty share")
}
}
func TestCorona_VerifyShare(t *testing.T) {
pk := []byte("public-key")
msg := []byte("test message")
share := []byte("signature-share")
valid := VerifyShare(pk, msg, share)
if !valid {
t.Error("VerifyShare should return true (stub implementation)")
}
}
func TestCorona_Aggregate(t *testing.T) {
shares := []Share{
[]byte("share1"),
[]byte("share2"),
[]byte("share3"),
}
cert, err := Aggregate(shares)
if err != nil {
t.Fatalf("Aggregate failed: %v", err)
}
if len(cert) == 0 {
t.Error("expected non-empty cert")
}
}
func TestCorona_Aggregate_Empty(t *testing.T) {
_, err := Aggregate([]Share{})
if err == nil {
t.Error("expected error for empty shares")
}
}
func TestCorona_Verify(t *testing.T) {
pk := []byte("public-key")
msg := []byte("test message")
cert := []byte("certificate")
valid := Verify(pk, msg, cert)
if !valid {
t.Error("Verify should return true (stub implementation)")
}
}
func TestCorona_SecurityLevels(t *testing.T) {
tests := []struct {
level SecurityLevel
name string
}{
{SecurityLow, "Low"},
{SecurityMedium, "Medium"},
{SecurityHigh, "High"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := NewCorona()
if err := r.Initialize(tt.level); err != nil {
t.Errorf("Initialize %s failed: %v", tt.name, err)
}
})
}
}
//
// NOTE: Corona post-quantum crypto is tested in the real corona package
// at github.com/luxfi/corona/threshold. The quasar package uses the real
// implementation via the Signer type in quasar.go. Tests for threshold signing
// are in quasar_test.go and epoch_test.go.
// =============================================================================
// Types Tests (types.go)
@@ -1277,11 +1153,11 @@ func TestVerkleWitness_CheckPQFinality(t *testing.T) {
w := NewVerkleWitness(3)
tests := []struct {
name string
bits []byte
want bool
name string
bits []byte
want bool
}{
{"sufficient bits", []byte{0x07}, true}, // 3 bits set
{"sufficient bits", []byte{0x07}, true}, // 3 bits set
{"insufficient bits", []byte{0x03}, false}, // 2 bits set
{"empty", []byte{}, false},
}
@@ -1593,7 +1469,7 @@ func TestQuasar_ProcessBlockWithContext_Cancelled(t *testing.T) {
t.Fatalf("NewQuasar failed: %v", err)
}
_ = q.hybridConsensus.AddValidator("v1", 100)
_, _ = q.AddValidator("v1", 100)
block := &Block{
ChainID: [32]byte{1},
@@ -1622,7 +1498,7 @@ func TestQuasar_SubmitBlock_AutoRegister(t *testing.T) {
t.Fatalf("NewQuasar failed: %v", err)
}
_ = q.hybridConsensus.AddValidator("v1", 100)
_, _ = q.AddValidator("v1", 100)
ctx := context.Background()
_ = q.Start(ctx)
@@ -1758,28 +1634,24 @@ func TestHorizon_ComputeBlockHash(t *testing.T) {
func TestTypeAliases(t *testing.T) {
// Test that type aliases work correctly
var _ *Core = (*Quasar)(nil)
var _ *QuasarCore = (*Quasar)(nil)
var _ *PChain = (*BLS)(nil)
var _ *QuasarHybridConsensus = (*Hybrid)(nil)
var _ *QBlock = (*Block)(nil)
var _ *ChainBlock = (*Block)(nil)
// NewPChain should be the same as NewBLS
// NewBLS creates a BLS instance
cfg := config.DefaultParams()
store := newMockStore()
p := NewPChain(cfg, store)
p := NewBLS(cfg, store)
if p == nil {
t.Error("NewPChain returned nil")
t.Error("NewBLS returned nil")
}
// NewQuasarHybridConsensus should be the same as NewHybrid
h, err := NewQuasarHybridConsensus(1)
// NewSigner creates a signer instance
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewQuasarHybridConsensus failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
if h == nil {
t.Error("NewQuasarHybridConsensus returned nil")
t.Error("NewSigner returned nil")
}
}
@@ -1787,17 +1659,17 @@ func TestTypeAliases(t *testing.T) {
// Edge Cases and Error Paths
// =============================================================================
func TestHybrid_AggregateSignatures_InvalidBLS(t *testing.T) {
h, _ := NewHybrid(1)
func TestSigner_AggregateSignatures_InvalidBLS(t *testing.T) {
h, _ := NewSigner(1)
_ = h.AddValidator("v1", 100)
sig := &HybridSignature{
sig := &QuasarSig{
ValidatorID: "v1",
BLS: []byte{1, 2, 3}, // Invalid BLS bytes
Corona: []byte{4, 5, 6},
}
_, err := h.AggregateSignatures([]byte("test"), []*HybridSignature{sig})
_, err := h.AggregateSignatures([]byte("test"), []*QuasarSig{sig})
if err == nil {
t.Error("expected error for invalid BLS signature")
}
@@ -1939,7 +1811,7 @@ func TestQuasar_ProcessBlockWithContext_ContextCancelledAfterLock(t *testing.T)
t.Fatalf("NewQuasar failed: %v", err)
}
_ = q.hybridConsensus.AddValidator("v1", 100)
_, _ = q.AddValidator("v1", 100)
block := &Block{
ChainID: [32]byte{1},
@@ -1967,7 +1839,7 @@ func TestQuasar_VerifyQuantumFinalityWithContext_AllPaths(t *testing.T) {
t.Fatalf("NewQuasar failed: %v", err)
}
_ = q.hybridConsensus.AddValidator("v1", 100)
_, _ = q.AddValidator("v1", 100)
// Process a block first
block := &Block{
@@ -2145,10 +2017,10 @@ func TestEngine_FinalizedChannel_BufferFull(t *testing.T) {
// Just ensure no panic occurred
}
func TestHybrid_SignMessageWithContext_ValidatorNotFound(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_SignMessageWithContext_ValidatorNotFound(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
// Add validator but then remove it manually
@@ -2166,10 +2038,10 @@ func TestHybrid_SignMessageWithContext_ValidatorNotFound(t *testing.T) {
}
}
func TestHybrid_VerifyHybridSignatureWithContext_ContextCancelledMidVerify(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyQuasarSigWithContext_ContextCancelledMidVerify(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2184,16 +2056,16 @@ func TestHybrid_VerifyHybridSignatureWithContext_ContextCancelledMidVerify(t *te
ctx, cancel := context.WithCancel(context.Background())
cancel()
result := h.VerifyHybridSignatureWithContext(ctx, msg, sig)
result := h.VerifyQuasarSigWithContext(ctx, msg, sig)
if result {
t.Error("expected false for cancelled context")
}
}
func TestHybrid_AggregateSignaturesWithContext_ContextCancelledMid(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_AggregateSignaturesWithContext_ContextCancelledMid(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2207,23 +2079,23 @@ func TestHybrid_AggregateSignaturesWithContext_ContextCancelledMid(t *testing.T)
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, err = h.AggregateSignaturesWithContext(ctx, msg, []*HybridSignature{sig1, sig2})
_, err = h.AggregateSignaturesWithContext(ctx, msg, []*QuasarSig{sig1, sig2})
if err == nil {
t.Error("expected error for cancelled context")
}
}
func TestHybrid_VerifyAggregatedSignatureWithContext_AllErrorPaths(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyAggregatedSignatureWithContext_AllErrorPaths(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
msg := []byte("test message")
sig, _ := h.SignMessage("v1", msg)
aggSig, _ := h.AggregateSignatures(msg, []*HybridSignature{sig})
aggSig, _ := h.AggregateSignatures(msg, []*QuasarSig{sig})
// Test with context cancelled before RLock
ctx, cancel := context.WithCancel(context.Background())
@@ -2353,7 +2225,7 @@ func TestQuasar_VerifyQuantumFinalityWithContext_InvalidSignature(t *testing.T)
t.Fatalf("NewQuasar failed: %v", err)
}
_ = q.hybridConsensus.AddValidator("validator1", 100)
_, _ = q.AddValidator("validator1", 100)
// Process a block first
block := &Block{
@@ -2410,10 +2282,10 @@ func TestQuasar_QuantumFinalizer_TickerCase(t *testing.T) {
}
}
func TestHybrid_SignMessageWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_SignMessageWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2431,10 +2303,10 @@ func TestHybrid_SignMessageWithContext_ContextCancelledAfterLock(t *testing.T) {
}
}
func TestHybrid_VerifyHybridSignatureWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyQuasarSigWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2446,23 +2318,23 @@ func TestHybrid_VerifyHybridSignatureWithContext_ContextCancelledAfterLock(t *te
ctx, cancel := context.WithCancel(context.Background())
cancel()
result := h.VerifyHybridSignatureWithContext(ctx, msg, sig)
result := h.VerifyQuasarSigWithContext(ctx, msg, sig)
if result {
t.Error("expected false for cancelled context")
}
}
func TestHybrid_VerifyAggregatedSignatureWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyAggregatedSignatureWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
msg := []byte("test message")
sig, _ := h.SignMessage("v1", msg)
aggSig, _ := h.AggregateSignatures(msg, []*HybridSignature{sig})
aggSig, _ := h.AggregateSignatures(msg, []*QuasarSig{sig})
// Pre-cancel context
ctx, cancel := context.WithCancel(context.Background())
@@ -2474,10 +2346,10 @@ func TestHybrid_VerifyAggregatedSignatureWithContext_ContextCancelledAfterLock(t
}
}
func TestHybrid_AggregateSignaturesWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_AggregateSignaturesWithContext_ContextCancelledAfterLock(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2489,16 +2361,16 @@ func TestHybrid_AggregateSignaturesWithContext_ContextCancelledAfterLock(t *test
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, err = h.AggregateSignaturesWithContext(ctx, msg, []*HybridSignature{sig})
_, err = h.AggregateSignaturesWithContext(ctx, msg, []*QuasarSig{sig})
if err == nil {
t.Error("expected error for cancelled context")
}
}
func TestHybrid_VerifyAggregatedSignature_PublicKeyAggregationError(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyAggregatedSignature_PublicKeyAggregationError(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2520,17 +2392,17 @@ func TestHybrid_VerifyAggregatedSignature_PublicKeyAggregationError(t *testing.T
}
}
func TestHybrid_VerifyAggregatedSignature_BLSVerifyFail(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyAggregatedSignature_BLSVerifyFail(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
msg := []byte("test message")
sig, _ := h.SignMessage("v1", msg)
aggSig, _ := h.AggregateSignatures(msg, []*HybridSignature{sig})
aggSig, _ := h.AggregateSignatures(msg, []*QuasarSig{sig})
// Verify with different message - BLS verification should fail
wrongMsg := []byte("wrong message")
@@ -2540,10 +2412,10 @@ func TestHybrid_VerifyAggregatedSignature_BLSVerifyFail(t *testing.T) {
}
}
func TestHybrid_VerifyAggregatedSignature_BLSSignatureTamperedFail(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyAggregatedSignature_BLSSignatureTamperedFail(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2552,7 +2424,7 @@ func TestHybrid_VerifyAggregatedSignature_BLSSignatureTamperedFail(t *testing.T)
msg := []byte("test message")
sig1, _ := h.SignMessage("v1", msg)
sig2, _ := h.SignMessage("v2", msg)
aggSig, _ := h.AggregateSignatures(msg, []*HybridSignature{sig1, sig2})
aggSig, _ := h.AggregateSignatures(msg, []*QuasarSig{sig1, sig2})
// Corrupt the BLS signature
if len(aggSig.BLSAggregated) > 0 {
@@ -2670,9 +2542,9 @@ func TestQuasar_VerifyQuantumFinalityWithContext_LoopContextCheck(t *testing.T)
t.Fatalf("NewQuasar failed: %v", err)
}
_ = q.hybridConsensus.AddValidator("validator1", 100)
_ = q.hybridConsensus.AddValidator("validator2", 100)
_ = q.hybridConsensus.AddValidator("validator3", 100)
_, _ = q.AddValidator("validator1", 100)
_, _ = q.AddValidator("validator2", 100)
_, _ = q.AddValidator("validator3", 100)
// Process a block first
block := &Block{
@@ -2692,7 +2564,7 @@ func TestQuasar_VerifyQuantumFinalityWithContext_LoopContextCheck(t *testing.T)
if qBlock != nil {
// Add signatures for all validators
for _, vid := range []string{"validator1", "validator2", "validator3"} {
sig, _ := q.hybridConsensus.SignMessage(vid, []byte(blockHash))
sig, _ := q.SignMessage(vid, []byte(blockHash))
if sig != nil {
qBlock.ValidatorSigs[vid] = sig
}
@@ -2707,10 +2579,10 @@ func TestQuasar_VerifyQuantumFinalityWithContext_LoopContextCheck(t *testing.T)
}
}
func TestHybrid_VerifyAggregatedSignature_ContextCancelledInLoop(t *testing.T) {
h, err := NewHybrid(1)
func TestSigner_VerifyAggregatedSignature_ContextCancelledInLoop(t *testing.T) {
h, err := NewSigner(1)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
// Add multiple validators
@@ -2722,7 +2594,7 @@ func TestHybrid_VerifyAggregatedSignature_ContextCancelledInLoop(t *testing.T) {
sig1, _ := h.SignMessage("v1", msg)
sig2, _ := h.SignMessage("v2", msg)
sig3, _ := h.SignMessage("v3", msg)
aggSig, _ := h.AggregateSignatures(msg, []*HybridSignature{sig1, sig2, sig3})
aggSig, _ := h.AggregateSignatures(msg, []*QuasarSig{sig1, sig2, sig3})
// Verify with valid context should pass
result := h.VerifyAggregatedSignature(msg, aggSig)
@@ -2829,10 +2701,10 @@ func TestQuasar_SubmitBlock_BufferFullDropOldest(t *testing.T) {
// Should not error - drops oldest when full
}
func TestHybrid_AggregateSignatures_ContextCancelledDuringLoop(t *testing.T) {
h, err := NewHybrid(2)
func TestSigner_AggregateSignatures_ContextCancelledDuringLoop(t *testing.T) {
h, err := NewSigner(2)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
_ = h.AddValidator("v1", 100)
@@ -2844,7 +2716,7 @@ func TestHybrid_AggregateSignatures_ContextCancelledDuringLoop(t *testing.T) {
// Valid context should work
ctx := context.Background()
aggSig, err := h.AggregateSignaturesWithContext(ctx, msg, []*HybridSignature{sig1, sig2})
aggSig, err := h.AggregateSignaturesWithContext(ctx, msg, []*QuasarSig{sig1, sig2})
if err != nil {
t.Errorf("AggregateSignatures failed: %v", err)
}
@@ -2857,7 +2729,7 @@ func TestHybrid_AggregateSignatures_ContextCancelledDuringLoop(t *testing.T) {
// Threshold Mode Tests (hybrid.go threshold integration)
// =============================================================================
func TestHybrid_ThresholdMode_GenerateKeys(t *testing.T) {
func TestSigner_ThresholdMode_GenerateKeys(t *testing.T) {
// Generate threshold key shares using the helper function
// t=1 means need at least 2 shares to sign
shares, groupKey, err := GenerateThresholdKeys(threshold.SchemeBLS, 1, 3)
@@ -2881,7 +2753,7 @@ func TestHybrid_ThresholdMode_GenerateKeys(t *testing.T) {
}
}
func TestHybrid_ThresholdMode_NewHybridWithThreshold(t *testing.T) {
func TestSigner_ThresholdMode_NewSignerWithThreshold(t *testing.T) {
// Generate threshold key shares
shares, groupKey, err := GenerateThresholdKeys(threshold.SchemeBLS, 1, 3)
if err != nil {
@@ -2903,9 +2775,9 @@ func TestHybrid_ThresholdMode_NewHybridWithThreshold(t *testing.T) {
GroupKey: groupKey,
}
h, err := NewHybridWithThresholdConfig(config)
h, err := NewSignerWithThresholdConfig(config)
if err != nil {
t.Fatalf("NewHybridWithThreshold failed: %v", err)
t.Fatalf("NewSignerWithThreshold failed: %v", err)
}
// Verify threshold mode is enabled
@@ -2924,7 +2796,7 @@ func TestHybrid_ThresholdMode_NewHybridWithThreshold(t *testing.T) {
}
}
func TestHybrid_ThresholdMode_SignAndVerify(t *testing.T) {
func TestSigner_ThresholdMode_SignAndVerify(t *testing.T) {
// Generate threshold key shares (t=1 means need 2+ shares)
shares, groupKey, err := GenerateThresholdKeys(threshold.SchemeBLS, 1, 3)
if err != nil {
@@ -2946,9 +2818,9 @@ func TestHybrid_ThresholdMode_SignAndVerify(t *testing.T) {
GroupKey: groupKey,
}
h, err := NewHybridWithThresholdConfig(config)
h, err := NewSignerWithThresholdConfig(config)
if err != nil {
t.Fatalf("NewHybridWithThreshold failed: %v", err)
t.Fatalf("NewSignerWithThreshold failed: %v", err)
}
// Sign message with threshold signing
@@ -2990,13 +2862,13 @@ func TestHybrid_ThresholdMode_SignAndVerify(t *testing.T) {
//
// For now, we verify the infrastructure is correctly wired up:
// - Key generation works
// - Signing produces valid shares
// - Signing produces valid shares
// - Aggregation produces a signature
// - The threshold scheme is correctly registered and usable
t.Log("Note: Full threshold signature verification pending BLS scalar field implementation")
}
func TestHybrid_ThresholdMode_InsufficientShares(t *testing.T) {
func TestSigner_ThresholdMode_InsufficientShares(t *testing.T) {
// Generate threshold key shares (t=1 means need 2+ shares)
shares, groupKey, err := GenerateThresholdKeys(threshold.SchemeBLS, 1, 3)
if err != nil {
@@ -3018,9 +2890,9 @@ func TestHybrid_ThresholdMode_InsufficientShares(t *testing.T) {
GroupKey: groupKey,
}
h, err := NewHybridWithThresholdConfig(config)
h, err := NewSignerWithThresholdConfig(config)
if err != nil {
t.Fatalf("NewHybridWithThreshold failed: %v", err)
t.Fatalf("NewSignerWithThreshold failed: %v", err)
}
// Sign message with threshold signing
@@ -3040,11 +2912,11 @@ func TestHybrid_ThresholdMode_InsufficientShares(t *testing.T) {
}
}
func TestHybrid_ThresholdMode_NotEnabled(t *testing.T) {
func TestSigner_ThresholdMode_NotEnabled(t *testing.T) {
// Create regular hybrid engine (non-threshold mode)
h, err := NewHybrid(2)
h, err := NewSigner(2)
if err != nil {
t.Fatalf("NewHybrid failed: %v", err)
t.Fatalf("NewSigner failed: %v", err)
}
// Threshold mode should be disabled
@@ -3069,7 +2941,7 @@ func TestHybrid_ThresholdMode_NotEnabled(t *testing.T) {
}
}
func TestHybrid_ThresholdMode_AddValidatorThreshold(t *testing.T) {
func TestSigner_ThresholdMode_AddValidatorThreshold(t *testing.T) {
// Generate threshold key shares
shares, groupKey, err := GenerateThresholdKeys(threshold.SchemeBLS, 1, 3)
if err != nil {
@@ -3089,9 +2961,9 @@ func TestHybrid_ThresholdMode_AddValidatorThreshold(t *testing.T) {
GroupKey: groupKey,
}
h, err := NewHybridWithThresholdConfig(config)
h, err := NewSignerWithThresholdConfig(config)
if err != nil {
t.Fatalf("NewHybridWithThresholdConfig failed: %v", err)
t.Fatalf("NewSignerWithThresholdConfig failed: %v", err)
}
// Add third validator dynamically
+87 -22
View File
@@ -29,7 +29,7 @@ type Quasar struct {
cChainBlocks chan *ChainBlock
// Quantum consensus engine - the event horizon
hybridConsensus *Hybrid
signer *signer
// Epoch-based Corona key management
// Keys rotate when validator set changes (max 1x per hour)
@@ -62,14 +62,14 @@ type QuantumBlock struct {
BLSSignature []byte
CoronaProof []byte // ML-DSA signature
Timestamp time.Time
ValidatorSigs map[string]*HybridSignature
ValidatorSigs map[string]*QuasarSig
}
// NewQuasar creates the supermassive black hole at the center of the blockchain galaxy
func NewQuasar(threshold int) (*Quasar, error) {
hybrid, err := NewHybrid(threshold)
s, err := newSigner(threshold)
if err != nil {
return nil, fmt.Errorf("failed to create hybrid consensus: %w", err)
return nil, fmt.Errorf("failed to create signer: %w", err)
}
core := &Quasar{
@@ -77,7 +77,7 @@ func NewQuasar(threshold int) (*Quasar, error) {
xChainBlocks: make(chan *ChainBlock, 100),
cChainBlocks: make(chan *ChainBlock, 100),
chainBuffers: make(map[string]chan *ChainBlock),
hybridConsensus: hybrid,
signer: s,
epochManager: NewEpochManager(threshold, 3), // Keep 3 epochs in history
finalizedBlocks: make(map[string]*QuantumBlock),
quantumHeight: 0,
@@ -209,11 +209,11 @@ func (q *Quasar) processBlockWithContext(ctx context.Context, block *ChainBlock)
quantumHash := q.computeQuantumHash(block)
// Collect validator signatures (BLS + Corona parallel)
signatures := make(map[string]*HybridSignature)
signatures := make(map[string]*QuasarSig)
// In production, this would collect from actual validators
// For now, simulate with local validator
sig, err := q.hybridConsensus.SignMessageWithContext(ctx, "validator1", []byte(quantumHash))
sig, err := q.signer.SignMessageWithContext(ctx, "validator1", []byte(quantumHash))
if err == nil {
signatures["validator1"] = sig
}
@@ -339,7 +339,7 @@ func (q *Quasar) VerifyQuantumFinalityWithContext(ctx context.Context, blockHash
if ctx.Err() != nil {
return false
}
if !q.hybridConsensus.VerifyHybridSignatureWithContext(ctx, []byte(blockHash), sig) {
if !q.signer.VerifyQuasarSigWithContext(ctx, []byte(blockHash), sig) {
fmt.Printf("[QUANTUM] Invalid signature from validator %s\n", validatorID)
return false
}
@@ -467,9 +467,9 @@ func (q *Quasar) InitializeValidators(validatorIDs []string) error {
return fmt.Errorf("need at least 2 validators")
}
// Add validators to hybrid consensus (BLS)
// Add validators to signer (BLS)
for _, id := range validatorIDs {
if err := q.hybridConsensus.AddValidator(id, 1); err != nil {
if err := q.signer.AddValidator(id, 1); err != nil {
return fmt.Errorf("failed to add validator %s to BLS: %w", id, err)
}
}
@@ -494,7 +494,7 @@ func (q *Quasar) UpdateValidatorSet(validatorIDs []string) (rotated bool, err er
// Update BLS validators
// First, track current validators
currentBLS := make(map[string]bool)
for id, v := range q.hybridConsensus.validators {
for id, v := range q.signer.validators {
if v.Active {
currentBLS[id] = true
}
@@ -505,7 +505,7 @@ func (q *Quasar) UpdateValidatorSet(validatorIDs []string) (rotated bool, err er
for _, id := range validatorIDs {
newIDs[id] = true
if !currentBLS[id] {
if err := q.hybridConsensus.AddValidator(id, 1); err != nil {
if err := q.signer.AddValidator(id, 1); err != nil {
return false, fmt.Errorf("failed to add validator %s: %w", id, err)
}
}
@@ -514,7 +514,7 @@ func (q *Quasar) UpdateValidatorSet(validatorIDs []string) (rotated bool, err er
// Deactivate removed validators
for id := range currentBLS {
if !newIDs[id] {
if v, exists := q.hybridConsensus.validators[id]; exists {
if v, exists := q.signer.validators[id]; exists {
v.Active = false
}
}
@@ -541,7 +541,7 @@ func (q *Quasar) AddValidator(validatorID string, weight uint64) (rotated bool,
defer q.mu.Unlock()
// Add to BLS
if err := q.hybridConsensus.AddValidator(validatorID, weight); err != nil {
if err := q.signer.AddValidator(validatorID, weight); err != nil {
return false, err
}
@@ -557,11 +557,12 @@ func (q *Quasar) AddValidator(validatorID string, weight uint64) (rotated bool,
rotated = true
fmt.Printf("[QUASAR] Added validator %s, rotated to epoch %d\n",
validatorID, q.epochManager.GetCurrentEpoch())
} else if errors.Is(err, ErrEpochRateLimited) || errors.Is(err, ErrNoValidatorChange) {
// Rate limited or no change - validator added to BLS but RT keys not rotated yet
} else if errors.Is(err, ErrEpochRateLimited) || errors.Is(err, ErrNoValidatorChange) || errors.Is(err, ErrInvalidValidatorSet) {
// Rate limited, no change, or insufficient validators (e.g., first validator added)
// Validator added to BLS but RT keys not rotated yet
rotated = false
err = nil
fmt.Printf("[QUASAR] Added validator %s to BLS (RT rotation rate-limited)\n", validatorID)
fmt.Printf("[QUASAR] Added validator %s to BLS (RT rotation pending)\n", validatorID)
}
return rotated, err
@@ -573,7 +574,7 @@ func (q *Quasar) RemoveValidator(validatorID string) (rotated bool, err error) {
defer q.mu.Unlock()
// Deactivate in BLS
if v, exists := q.hybridConsensus.validators[validatorID]; exists {
if v, exists := q.signer.validators[validatorID]; exists {
v.Active = false
}
@@ -586,10 +587,10 @@ func (q *Quasar) RemoveValidator(validatorID string) (rotated bool, err error) {
rotated = true
fmt.Printf("[QUASAR] Removed validator %s, rotated to epoch %d\n",
validatorID, q.epochManager.GetCurrentEpoch())
} else if errors.Is(err, ErrEpochRateLimited) || errors.Is(err, ErrNoValidatorChange) {
} else if errors.Is(err, ErrEpochRateLimited) || errors.Is(err, ErrNoValidatorChange) || errors.Is(err, ErrInvalidValidatorSet) {
rotated = false
err = nil
fmt.Printf("[QUASAR] Removed validator %s from BLS (RT rotation rate-limited)\n", validatorID)
fmt.Printf("[QUASAR] Removed validator %s from BLS (RT rotation pending)\n", validatorID)
}
return rotated, err
@@ -638,11 +639,75 @@ func (q *Quasar) GetEpochManager() *EpochManager {
return q.epochManager
}
// SignMessage signs a message with the specified validator's key.
func (q *Quasar) SignMessage(validatorID string, message []byte) (*QuasarSig, error) {
return q.signer.SignMessage(validatorID, message)
}
// AggregateSignatures aggregates multiple signatures into one.
func (q *Quasar) AggregateSignatures(message []byte, signatures []*QuasarSig) (*AggregatedSignature, error) {
return q.signer.AggregateSignatures(message, signatures)
}
// VerifyAggregatedSignature verifies an aggregated signature.
func (q *Quasar) VerifyAggregatedSignature(message []byte, sig *AggregatedSignature) bool {
return q.signer.VerifyAggregatedSignature(message, sig)
}
// SignMessageWithContext signs a message with context cancellation support.
func (q *Quasar) SignMessageWithContext(ctx context.Context, validatorID string, message []byte) (*QuasarSig, error) {
return q.signer.SignMessageWithContext(ctx, validatorID, message)
}
// AggregateSignaturesWithContext aggregates multiple signatures with context support.
func (q *Quasar) AggregateSignaturesWithContext(ctx context.Context, message []byte, signatures []*QuasarSig) (*AggregatedSignature, error) {
return q.signer.AggregateSignaturesWithContext(ctx, message, signatures)
}
// VerifyAggregatedSignatureWithContext verifies an aggregated signature with context support.
func (q *Quasar) VerifyAggregatedSignatureWithContext(ctx context.Context, message []byte, sig *AggregatedSignature) bool {
return q.signer.VerifyAggregatedSignatureWithContext(ctx, message, sig)
}
// IsThresholdMode returns true if the signer is in threshold mode.
func (q *Quasar) IsThresholdMode() bool {
return q.signer.IsThresholdMode()
}
// IsDualThresholdMode returns true if the signer is in dual threshold mode (BLS + Corona).
func (q *Quasar) IsDualThresholdMode() bool {
return q.signer.IsDualThresholdMode()
}
// GetActiveValidatorCount returns the number of active validators.
func (q *Quasar) GetActiveValidatorCount() int {
return q.signer.GetActiveValidatorCount()
}
// GetThreshold returns the consensus threshold.
func (q *Quasar) GetThreshold() int {
return q.signer.GetThreshold()
}
// VerifyQuasarSig verifies a QuasarSig signature.
func (q *Quasar) VerifyQuasarSig(message []byte, sig *QuasarSig) bool {
return q.signer.VerifyQuasarSig(message, sig)
}
// CoronaRound1 executes Round 1 of the Corona threshold signing protocol.
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 &CoronaRound1Data{PartyID: data.PartyID}, nil
}
// Internal helpers
func (q *Quasar) getActiveValidatorIDsLocked() []string {
ids := make([]string, 0, len(q.hybridConsensus.validators))
for id, v := range q.hybridConsensus.validators {
ids := make([]string, 0, len(q.signer.validators))
for id, v := range q.signer.validators {
if v.Active {
ids = append(ids, id)
}
+32 -31
View File
@@ -7,16 +7,17 @@ import (
)
func TestQuasar(t *testing.T) {
// Create quantum aggregator with threshold of 1 validator
qa, err := NewQuasar(1)
// Create quantum aggregator with threshold of 2 validators
// Need 3 validators for threshold 2 (t < n)
qa, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create quantum aggregator: %v", err)
}
// Add a test validator
err = qa.hybridConsensus.AddValidator("validator1", 100)
// Initialize validators (need more than threshold)
err = qa.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Start the aggregator
@@ -30,7 +31,7 @@ func TestQuasar(t *testing.T) {
pBlock := &ChainBlock{
ChainID: [32]byte{1},
ChainName: "P-Chain",
ID: [32]byte{0x01, 0x02, 0x03},
ID: [32]byte{0x01, 0x02, 0x03},
Height: 100,
Timestamp: time.Now(),
Data: []byte("P-Chain block data"),
@@ -40,7 +41,7 @@ func TestQuasar(t *testing.T) {
xBlock := &ChainBlock{
ChainID: [32]byte{2},
ChainName: "X-Chain",
ID: [32]byte{0x04, 0x05, 0x06},
ID: [32]byte{0x04, 0x05, 0x06},
Height: 200,
Timestamp: time.Now(),
Data: []byte("X-Chain block data"),
@@ -50,7 +51,7 @@ func TestQuasar(t *testing.T) {
cBlock := &ChainBlock{
ChainID: [32]byte{3},
ChainName: "C-Chain",
ID: [32]byte{0x07, 0x08, 0x09},
ID: [32]byte{0x07, 0x08, 0x09},
Height: 300,
Timestamp: time.Now(),
Data: []byte("C-Chain block data"),
@@ -84,22 +85,22 @@ func TestQuasar(t *testing.T) {
func TestQuantumFinalityWithCorona(t *testing.T) {
// Test that Corona and BLS signatures work in parallel
qa, err := NewQuasar(1)
qa, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create quantum aggregator: %v", err)
}
// Add validator with both BLS and Corona keys
err = qa.hybridConsensus.AddValidator("validator1", 100)
err = qa.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Create a test message
message := []byte("Test quantum finality message")
// Sign with hybrid (BLS + Corona)
sig, err := qa.hybridConsensus.SignMessage("validator1", message)
sig, err := qa.SignMessage("validator1", message)
if err != nil {
t.Fatalf("Failed to sign message: %v", err)
}
@@ -114,7 +115,7 @@ func TestQuantumFinalityWithCorona(t *testing.T) {
}
// Verify hybrid signature
if !qa.hybridConsensus.VerifyHybridSignature(message, sig) {
if !qa.VerifyQuasarSig(message, sig) {
t.Error("Failed to verify hybrid signature")
}
@@ -122,15 +123,15 @@ func TestQuantumFinalityWithCorona(t *testing.T) {
}
func TestQuantumEpochFinalization(t *testing.T) {
qa, err := NewQuasar(1)
qa, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create quantum aggregator: %v", err)
}
// Add validator
err = qa.hybridConsensus.AddValidator("validator1", 100)
err = qa.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Submit multiple blocks
@@ -138,7 +139,7 @@ func TestQuantumEpochFinalization(t *testing.T) {
block := &ChainBlock{
ChainID: [32]byte{byte(i)},
ChainName: "P-Chain",
ID: [32]byte{byte(i * 10)},
ID: [32]byte{byte(i * 10)},
Height: uint64(100 + i),
Timestamp: time.Now(),
Data: []byte("Block data"),
@@ -160,7 +161,7 @@ func TestQuantumEpochFinalization(t *testing.T) {
func TestContextCancellation(t *testing.T) {
t.Run("SignMessageWithContext_cancelled", func(t *testing.T) {
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
t.Fatalf("Failed to create hybrid: %v", err)
}
@@ -184,8 +185,8 @@ func TestContextCancellation(t *testing.T) {
}
})
t.Run("VerifyHybridSignatureWithContext_cancelled", func(t *testing.T) {
hybrid, err := NewHybrid(1)
t.Run("VerifyQuasarSigWithContext_cancelled", func(t *testing.T) {
hybrid, err := NewSigner(1)
if err != nil {
t.Fatalf("Failed to create hybrid: %v", err)
}
@@ -206,14 +207,14 @@ func TestContextCancellation(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
result := hybrid.VerifyHybridSignatureWithContext(ctx, msg, sig)
result := hybrid.VerifyQuasarSigWithContext(ctx, msg, sig)
if result {
t.Error("Expected false from cancelled context verification")
}
})
t.Run("AggregateSignaturesWithContext_cancelled", func(t *testing.T) {
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
t.Fatalf("Failed to create hybrid: %v", err)
}
@@ -234,7 +235,7 @@ func TestContextCancellation(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, err = hybrid.AggregateSignaturesWithContext(ctx, msg, []*HybridSignature{sig})
_, err = hybrid.AggregateSignaturesWithContext(ctx, msg, []*QuasarSig{sig})
if err == nil {
t.Error("Expected error from cancelled context, got nil")
}
@@ -244,14 +245,14 @@ func TestContextCancellation(t *testing.T) {
})
t.Run("VerifyQuantumFinalityWithContext_cancelled", func(t *testing.T) {
qa, err := NewQuasar(1)
qa, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create quasar: %v", err)
}
err = qa.hybridConsensus.AddValidator("validator1", 100)
err = qa.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Process a block to create finality
@@ -278,7 +279,7 @@ func TestContextCancellation(t *testing.T) {
})
t.Run("WithContext_valid_context_works", func(t *testing.T) {
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
t.Fatalf("Failed to create hybrid: %v", err)
}
@@ -301,12 +302,12 @@ func TestContextCancellation(t *testing.T) {
}
// Verify should succeed
if !hybrid.VerifyHybridSignatureWithContext(ctx, msg, sig) {
t.Error("VerifyHybridSignatureWithContext returned false for valid signature")
if !hybrid.VerifyQuasarSigWithContext(ctx, msg, sig) {
t.Error("VerifyQuasarSigWithContext returned false for valid signature")
}
// Aggregate should succeed
aggSig, err := hybrid.AggregateSignaturesWithContext(ctx, msg, []*HybridSignature{sig})
aggSig, err := hybrid.AggregateSignaturesWithContext(ctx, msg, []*QuasarSig{sig})
if err != nil {
t.Fatalf("AggregateSignaturesWithContext failed: %v", err)
}
@@ -316,4 +317,4 @@ func TestContextCancellation(t *testing.T) {
t.Error("VerifyAggregatedSignatureWithContext returned false for valid signature")
}
})
}
}
-220
View File
@@ -1,220 +0,0 @@
// Copyright (C) 2020-2025, Lux Industries Inc All rights reserved.
// See the file LICENSE for licensing terms.
// Package corona provides post-quantum cryptographic primitives for the Lux consensus.
// This is a stub implementation that forwards to the actual implementation in github.com/luxfi/crypto/corona.
package quasar
import (
"crypto/rand"
"errors"
)
// Type aliases for cleaner API
type (
Precomp = []byte
Share = []byte
Cert = []byte
SecretKey = []byte
PublicKey = []byte
Signature = []byte // Alias for Share or Cert depending on context
)
// SecurityLevel represents the post-quantum security level
type SecurityLevel int
const (
SecurityLow SecurityLevel = 0
SecurityMedium SecurityLevel = 1
SecurityHigh SecurityLevel = 2
)
// CoronaEngine represents the post-quantum consensus engine
type CoronaEngine interface {
// Initialize the engine with security parameters
Initialize(level SecurityLevel) error
// Sign a message with the secret key
Sign(msg []byte, sk SecretKey) (Signature, error)
// Verify a signature
Verify(msg []byte, sig Signature, pk PublicKey) bool
// Generate a new key pair
GenerateKeyPair() (SecretKey, PublicKey, error)
// KEM operations for post-quantum key exchange
Encapsulate(pk PublicKey) ([]byte, []byte, error)
Decapsulate(ct []byte, sk SecretKey) ([]byte, error)
// Shared secret operations
CombineSharedSecrets(ss1, ss2 []byte) []byte
DeriveKey(secret []byte, length int) []byte
}
// Error variables
var (
ErrInvalidCertificate = errors.New("invalid certificate")
ErrMissingCertificate = errors.New("missing certificate")
ErrCertificateMismatch = errors.New("certificate mismatch")
)
// stubEngine is a stub implementation of CoronaEngine for testing
type stubEngine struct {
level SecurityLevel
}
// NewCorona creates a new corona engine
func NewCorona() CoronaEngine {
return &stubEngine{}
}
// Initialize sets the security level
func (e *stubEngine) Initialize(level SecurityLevel) error {
e.level = level
return nil
}
// Sign signs a message (stub implementation)
func (e *stubEngine) Sign(_ []byte, sk SecretKey) (Signature, error) {
// Stub implementation - return non-zero signature
sig := make([]byte, 32)
// Put some non-zero bytes to make it a "valid" signature
for i := range sig {
sig[i] = byte(i + 1)
}
return sig, nil
}
// Verify verifies a signature (stub implementation)
func (e *stubEngine) Verify(msg []byte, sig Signature, pk PublicKey) bool {
// Stub implementation - check if signature is non-zero
// A real implementation would verify the cryptographic signature
for _, b := range sig {
if b != 0 {
return true // Non-zero signature considered valid for stub
}
}
return false // All-zero signature is invalid
}
// GenerateKeyPair generates a new key pair (stub implementation)
func (e *stubEngine) GenerateKeyPair() (SecretKey, PublicKey, error) {
// Stub implementation
sk := make([]byte, 32)
pk := make([]byte, 32)
return sk, pk, nil
}
// Encapsulate generates a ciphertext and shared secret (stub implementation)
func (e *stubEngine) Encapsulate(pk PublicKey) ([]byte, []byte, error) {
ct := make([]byte, 64)
ss := make([]byte, 32)
if _, err := rand.Read(ct); err != nil {
return nil, nil, err
}
if _, err := rand.Read(ss); err != nil {
return nil, nil, err
}
return ct, ss, nil
}
// Decapsulate recovers shared secret from ciphertext (stub implementation)
func (e *stubEngine) Decapsulate(ct []byte, sk SecretKey) ([]byte, error) {
ss := make([]byte, 32)
if _, err := rand.Read(ss); err != nil {
return nil, err
}
return ss, nil
}
// CombineSharedSecrets combines two shared secrets (stub implementation)
func (e *stubEngine) CombineSharedSecrets(ss1, ss2 []byte) []byte {
combined := make([]byte, 32)
for i := 0; i < 32 && i < len(ss1) && i < len(ss2); i++ {
combined[i] = ss1[i] ^ ss2[i]
}
return combined
}
// DeriveKey derives a key from shared secret (stub implementation)
func (e *stubEngine) DeriveKey(secret []byte, length int) []byte {
key := make([]byte, length)
copy(key, secret)
return key
}
// KeyGen generates a key pair from seed
func KeyGen(seed []byte) ([]byte, []byte, error) {
// Stub implementation
sk := make([]byte, 32)
pk := make([]byte, 32)
copy(sk, seed)
copy(pk, seed)
return sk, pk, nil
}
// Precompute generates a precomputed share
func Precompute(sk []byte) (Precomp, error) {
// Stub implementation
precomp := make([]byte, 32)
if _, err := rand.Read(precomp); err != nil {
return nil, err
}
return precomp, nil
}
// QuickSign signs using a precomputed share
func QuickSign(precomp Precomp, msg []byte) (Share, error) {
// Stub implementation
share := make([]byte, 32)
copy(share, precomp)
// XOR with message hash for demo
for i := 0; i < len(share) && i < len(msg); i++ {
share[i] ^= msg[i]
}
return share, nil
}
// VerifyShare verifies a share signature
func VerifyShare(pk []byte, msg []byte, share []byte) bool {
// Stub implementation - always return true
return true
}
// Aggregate aggregates shares into a certificate
func Aggregate(shares []Share) (Cert, error) {
// Stub implementation
if len(shares) == 0 {
return nil, errors.New("no shares to aggregate")
}
cert := make([]byte, 32)
// XOR all shares together for demo
for _, share := range shares {
for i := 0; i < len(cert) && i < len(share); i++ {
cert[i] ^= share[i]
}
}
return cert, nil
}
// Verify verifies a certificate
func Verify(pk []byte, msg []byte, cert []byte) bool {
// Stub implementation - always return true
return true
}
// NewCertificate creates a new empty certificate
// func NewCertificate(round, height uint64, blockHash [32]byte) *Certificate {
// return rt.NewCertificate(round, height, blockHash)
// }
// NewCertificateManager creates a new certificate manager
// func NewCertificateManager(nodeID ids.NodeID, blsKey, rtKey interface{}, validators ValidatorSet) *CertificateManager {
// return rt.NewCertificateManager(nodeID, blsKey, rtKey, validators)
// }
// VerifyAggregate verifies an aggregate signature
// func VerifyAggregate(pubKeys [][]byte, msg []byte, aggregateData []byte, threshold int) error {
// return rt.VerifyAggregate(pubKeys, msg, aggregateData, threshold)
// }
+5 -5
View File
@@ -40,7 +40,7 @@ func TestBLSThresholdSigningFlow(t *testing.T) {
GroupKey: groupKey,
}
h, err := NewHybridWithThresholdConfig(config)
h, err := NewSignerWithThresholdConfig(config)
require.NoError(t, err, "Failed to create hybrid engine")
// Verify threshold mode is enabled
@@ -93,7 +93,7 @@ func TestBLSThresholdInsufficientShares(t *testing.T) {
keyShares["v1"] = shares[1]
keyShares["v2"] = shares[2]
h, err := NewHybridWithThresholdConfig(ThresholdConfig{
h, err := NewSignerWithThresholdConfig(ThresholdConfig{
SchemeID: threshold.SchemeBLS,
Threshold: 2,
TotalParties: 3,
@@ -124,7 +124,7 @@ func TestBLSThresholdWrongMessage(t *testing.T) {
keyShares["v1"] = shares[1]
keyShares["v2"] = shares[2]
h, err := NewHybridWithThresholdConfig(ThresholdConfig{
h, err := NewSignerWithThresholdConfig(ThresholdConfig{
SchemeID: threshold.SchemeBLS,
Threshold: 2,
TotalParties: 3,
@@ -174,7 +174,7 @@ func TestDualSigningFlow(t *testing.T) {
require.NoError(t, err, "Failed to generate dual keys")
// Create hybrid engine with dual threshold signing
h, err := NewHybridWithDualThreshold(*config)
h, err := NewSignerWithDualThreshold(*config)
require.NoError(t, err, "Failed to create hybrid engine")
require.True(t, h.IsDualThresholdMode(), "Should be in dual threshold mode")
@@ -189,7 +189,7 @@ func TestDualSigningFlow(t *testing.T) {
// === ROUND 1: All validators compute BLS share + Corona D+MACs in parallel ===
t.Log("=== Round 1: BLS signing + Corona D matrices ===")
blsSigs := make([]*HybridSignature, 3)
blsSigs := make([]*QuasarSig, 3)
allRound1 := make(map[int]*coronaThreshold.Round1Data)
for i, vid := range validatorIDs {
+15 -15
View File
@@ -8,15 +8,15 @@ import (
func TestDynamicChainRegistration(t *testing.T) {
// Create Quasar core
q, err := NewQuasar(1)
q, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create Quasar core: %v", err)
}
// Add validator
err = q.hybridConsensus.AddValidator("validator1", 100)
err = q.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Start the Quasar
@@ -49,15 +49,15 @@ func TestDynamicChainRegistration(t *testing.T) {
func TestAutoRegisterNewSubnet(t *testing.T) {
// Create Quasar core
q, err := NewQuasar(1)
q, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create Quasar core: %v", err)
}
// Add validator
err = q.hybridConsensus.AddValidator("validator1", 100)
err = q.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Start the Quasar
@@ -71,7 +71,7 @@ func TestAutoRegisterNewSubnet(t *testing.T) {
bridgeBlock := &ChainBlock{
ChainID: [32]byte{0xFF},
ChainName: "Bridge-Net",
ID: [32]byte{0xAA, 0xBB, 0xCC},
ID: [32]byte{0xAA, 0xBB, 0xCC},
Height: 1,
Timestamp: time.Now(),
Data: []byte("Bridge transaction data"),
@@ -104,15 +104,15 @@ func TestAutoRegisterNewSubnet(t *testing.T) {
func TestMultipleExternalChains(t *testing.T) {
// Create Quasar core
q, err := NewQuasar(1)
q, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create Quasar core: %v", err)
}
// Add validator
err = q.hybridConsensus.AddValidator("validator1", 100)
err = q.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Start the Quasar
@@ -135,7 +135,7 @@ func TestMultipleExternalChains(t *testing.T) {
block := &ChainBlock{
ChainID: [32]byte{byte(i + 10)},
ChainName: chainName,
ID: [32]byte{byte(i * 100)},
ID: [32]byte{byte(i * 100)},
Height: uint64(i + 1),
Timestamp: time.Now(),
Data: []byte(chainName + " block data"),
@@ -166,15 +166,15 @@ func TestMultipleExternalChains(t *testing.T) {
func TestQuantumSecurityForAllChains(t *testing.T) {
// Create Quasar core
q, err := NewQuasar(1)
q, err := NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create Quasar core: %v", err)
}
// Add validator
err = q.hybridConsensus.AddValidator("validator1", 100)
err = q.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Start the Quasar
@@ -188,7 +188,7 @@ func TestQuantumSecurityForAllChains(t *testing.T) {
bridgeBlock := &ChainBlock{
ChainID: [32]byte{0xFF},
ChainName: "Bridge-Net",
ID: [32]byte{0xDD, 0xEE, 0xFF},
ID: [32]byte{0xDD, 0xEE, 0xFF},
Height: 1,
Timestamp: time.Now(),
Data: []byte("Bridge cross-chain transaction"),
+20 -17
View File
@@ -29,7 +29,7 @@ type quasarEngine struct {
startTime time.Time
// Consensus engine
hybrid *HybridConsensus
certifier *Certifier
// Metrics
processed uint64
@@ -42,9 +42,9 @@ func NewEngine(cfg Config) (Engine, error) {
threshold = 1
}
hybrid, err := newHybridConsensus(threshold)
certifier, err := newCertifier(threshold)
if err != nil {
return nil, fmt.Errorf("failed to create hybrid consensus: %w", err)
return nil, fmt.Errorf("failed to create certifier: %w", err)
}
bufSize := 1000
@@ -53,7 +53,7 @@ func NewEngine(cfg Config) (Engine, error) {
incoming: make(chan *Block, bufSize),
finalized: make(chan *Block, bufSize),
finalizedBlocks: make(map[string]*Block),
hybrid: hybrid,
certifier: certifier,
}, nil
}
@@ -119,7 +119,7 @@ func (q *quasarEngine) Stats() Stats {
ProcessedBlocks: q.processed,
FinalizedBlocks: uint64(len(q.finalizedBlocks)),
PendingBlocks: len(q.incoming),
Validators: q.hybrid.validatorCount(),
Validators: q.certifier.validatorCount(),
Uptime: time.Since(q.startTime),
}
}
@@ -144,7 +144,7 @@ func (q *quasarEngine) processBlock(block *Block) {
q.processed++
// Generate quantum certificate
cert := q.hybrid.generateCert(block)
cert := q.certifier.generateCert(block)
if cert == nil {
return // Did not achieve consensus
}
@@ -174,34 +174,37 @@ func computeHash(block *Block) string {
return hex.EncodeToString(h.Sum(nil))
}
// HybridConsensus handles BLS + PQ certificate generation.
type HybridConsensus struct {
// Certifier handles lightweight certificate generation for the engine.
// NOTE: This uses SHA256 commitments for internal block tracking.
// For real threshold BLS + Corona signatures, see the Signer in quasar.go.
type Certifier struct {
mu sync.RWMutex
threshold int
validators map[string]int // validator -> weight
}
func newHybridConsensus(threshold int) (*HybridConsensus, error) {
return &HybridConsensus{
func newCertifier(threshold int) (*Certifier, error) {
return &Certifier{
threshold: threshold,
validators: make(map[string]int),
}, nil
}
func (h *HybridConsensus) validatorCount() int {
func (h *Certifier) validatorCount() int {
h.mu.RLock()
defer h.mu.RUnlock()
return len(h.validators)
}
func (h *HybridConsensus) generateCert(block *Block) *BlockCert {
// generateCert creates a lightweight certificate for internal block tracking.
// NOTE: This uses SHA256 for internal engine use only. For real threshold
// signatures with BLS + Corona, use the Signer via ProcessBlock in Quasar.
func (h *Certifier) generateCert(block *Block) *BlockCert {
h.mu.RLock()
defer h.mu.RUnlock()
// Generate BLS aggregate
// Create deterministic commitments for block tracking
blsData := sha256.Sum256(block.ID[:])
// Generate PQ certificate
pqData := sha256.Sum256(append(block.ID[:], block.ChainID[:]...))
return &BlockCert{
@@ -214,14 +217,14 @@ func (h *HybridConsensus) generateCert(block *Block) *BlockCert {
}
// AddValidator adds a validator to the consensus.
func (h *HybridConsensus) AddValidator(id string, weight int) {
func (h *Certifier) AddValidator(id string, weight int) {
h.mu.Lock()
defer h.mu.Unlock()
h.validators[id] = weight
}
// RemoveValidator removes a validator from the consensus.
func (h *HybridConsensus) RemoveValidator(id string) {
func (h *Certifier) RemoveValidator(id string) {
h.mu.Lock()
defer h.mu.Unlock()
delete(h.validators, id)
+3 -96
View File
@@ -377,102 +377,9 @@ func BenchmarkCertVerify(b *testing.B) {
}
}
// Additional tests for Corona post-quantum functions
func TestCorona(t *testing.T) {
t.Run("NewCorona", func(t *testing.T) {
r := NewCorona()
if r == nil {
t.Fatal("NewCorona returned nil")
}
})
t.Run("GenerateKeyPair", func(t *testing.T) {
rt := NewCorona()
pub, priv, err := rt.GenerateKeyPair()
if err != nil {
t.Fatalf("GenerateKeyPair failed: %v", err)
}
if len(pub) == 0 || len(priv) == 0 {
t.Error("Generated empty keys")
}
})
t.Run("Encapsulate", func(t *testing.T) {
rt := NewCorona()
pub, _, _ := rt.GenerateKeyPair()
ct, ss, err := rt.Encapsulate(pub)
if err != nil {
t.Fatalf("Encapsulate failed: %v", err)
}
if len(ct) == 0 || len(ss) == 0 {
t.Error("Empty ciphertext or shared secret")
}
})
t.Run("Decapsulate", func(t *testing.T) {
rt := NewCorona()
pub, priv, _ := rt.GenerateKeyPair()
ct, ss1, _ := rt.Encapsulate(pub)
ss2, err := rt.Decapsulate(ct, priv)
if err != nil {
t.Fatalf("Decapsulate failed: %v", err)
}
// Note: In stub implementation, secrets won't match since we use random
_ = ss1
_ = ss2
})
t.Run("Sign", func(t *testing.T) {
rt := NewCorona()
_, priv, _ := rt.GenerateKeyPair()
msg := []byte("test message")
sig, err := rt.Sign(msg, priv)
if err != nil {
t.Fatalf("Sign failed: %v", err)
}
if len(sig) == 0 {
t.Error("Empty signature")
}
})
t.Run("Verify", func(t *testing.T) {
rt := NewCorona()
pub, priv, _ := rt.GenerateKeyPair()
msg := []byte("test message")
sig, _ := rt.Sign(msg, priv)
valid := rt.Verify(msg, sig, pub)
if !valid {
t.Error("Valid signature failed verification")
}
// Test invalid signature
badSig := make([]byte, len(sig))
invalid := rt.Verify(msg, badSig, pub)
if invalid {
t.Error("Invalid signature passed verification")
}
})
t.Run("CombineSharedSecrets", func(t *testing.T) {
rt := NewCorona()
ss1 := []byte("secret1")
ss2 := []byte("secret2")
combined := rt.CombineSharedSecrets(ss1, ss2)
if len(combined) == 0 {
t.Error("Empty combined secret")
}
})
t.Run("DeriveKey", func(t *testing.T) {
rt := NewCorona()
secret := []byte("shared secret")
key := rt.DeriveKey(secret, 32)
if len(key) != 32 {
t.Errorf("DeriveKey returned wrong length: got %d, want 32", len(key))
}
})
}
// NOTE: Corona post-quantum crypto tests are in the real corona package
// at github.com/luxfi/corona/threshold. The quasar package uses the real
// implementation via the Signer type in quasar.go.
func TestBundle(t *testing.T) {
b := Bundle{
+20 -20
View File
@@ -38,9 +38,9 @@ const (
)
var (
ErrEpochRateLimited = errors.New("epoch keygen rate limited: must wait at least 10 minutes between rotations")
ErrNoValidatorChange = errors.New("validator set unchanged, no keygen needed")
ErrEpochNotFound = errors.New("epoch not found")
ErrEpochRateLimited = errors.New("epoch keygen rate limited: must wait at least 10 minutes between rotations")
ErrNoValidatorChange = errors.New("validator set unchanged, no keygen needed")
ErrEpochNotFound = errors.New("epoch not found")
ErrInvalidValidatorSet = errors.New("invalid validator set configuration")
)
@@ -52,14 +52,14 @@ type EpochManager struct {
mu sync.RWMutex
// Current epoch state
currentEpoch uint64
currentKeys *EpochKeys
lastKeygenTime time.Time
currentEpoch uint64
currentKeys *EpochKeys
lastKeygenTime time.Time
// Historical epochs for signature verification
// We need to verify signatures from recent epochs during transitions
epochHistory map[uint64]*EpochKeys
historyLimit int // How many old epochs to keep
epochHistory map[uint64]*EpochKeys
historyLimit int // How many old epochs to keep
// Validator set tracking
currentValidators []string
@@ -68,15 +68,15 @@ type EpochManager struct {
// EpochKeys holds the Corona keys for a specific epoch.
type EpochKeys struct {
Epoch uint64
CreatedAt time.Time
ExpiresAt time.Time
ValidatorSet []string
Threshold int
TotalParties int
GroupKey *coronaThreshold.GroupKey
Shares map[string]*coronaThreshold.KeyShare
Signers map[string]*coronaThreshold.Signer
Epoch uint64
CreatedAt time.Time
ExpiresAt time.Time
ValidatorSet []string
Threshold int
TotalParties int
GroupKey *coronaThreshold.GroupKey
Shares map[string]*coronaThreshold.KeyShare
Signers map[string]*coronaThreshold.Signer
}
// NewEpochManager creates a new epoch manager.
@@ -86,9 +86,9 @@ func NewEpochManager(threshold int, historyLimit int) *EpochManager {
}
return &EpochManager{
epochHistory: make(map[uint64]*EpochKeys),
historyLimit: historyLimit,
threshold: threshold,
epochHistory: make(map[uint64]*EpochKeys),
historyLimit: historyLimit,
threshold: threshold,
}
}
+9 -11
View File
@@ -400,7 +400,7 @@ func TestQuasar_InitializeValidators(t *testing.T) {
require.NoError(t, err)
// Verify BLS validators were added
require.Equal(t, 3, q.hybridConsensus.GetActiveValidatorCount())
require.Equal(t, 3, q.GetActiveValidatorCount())
// Verify Corona epoch was initialized
require.Equal(t, uint64(0), q.GetCurrentEpoch())
@@ -432,7 +432,7 @@ func TestQuasar_AddValidator_WithRotation(t *testing.T) {
require.True(t, rotated, "Should have rotated RT keys")
require.Equal(t, uint64(1), q.GetCurrentEpoch())
require.Equal(t, 4, q.hybridConsensus.GetActiveValidatorCount())
require.Equal(t, 4, q.GetActiveValidatorCount())
t.Log("Added v3 and rotated to epoch 1")
}
@@ -451,7 +451,7 @@ func TestQuasar_AddValidator_RateLimited(t *testing.T) {
require.False(t, rotated, "Should NOT have rotated RT keys (rate limited)")
// BLS validator is still added
require.Equal(t, 4, q.hybridConsensus.GetActiveValidatorCount())
require.Equal(t, 4, q.GetActiveValidatorCount())
// But epoch stays at 0
require.Equal(t, uint64(0), q.GetCurrentEpoch())
@@ -477,7 +477,7 @@ func TestQuasar_RemoveValidator_WithRotation(t *testing.T) {
require.True(t, rotated, "Should have rotated RT keys")
require.Equal(t, uint64(1), q.GetCurrentEpoch())
require.Equal(t, 3, q.hybridConsensus.GetActiveValidatorCount())
require.Equal(t, 3, q.GetActiveValidatorCount())
t.Log("Removed v3 and rotated to epoch 1")
}
@@ -502,12 +502,10 @@ func TestQuasar_UpdateValidatorSet(t *testing.T) {
require.True(t, rotated)
require.Equal(t, uint64(1), q.GetCurrentEpoch())
require.Equal(t, 4, q.hybridConsensus.GetActiveValidatorCount())
require.Equal(t, 4, q.GetActiveValidatorCount())
// v2 should be deactivated
v2, exists := q.hybridConsensus.validators["v2"]
require.True(t, exists)
require.False(t, v2.Active, "v2 should be deactivated")
// v2 should be deactivated (proven by active count being 4 for v0,v1,v3,v4)
// If v2 were still active, count would be 5
t.Log("Updated validator set: v2->inactive, added v3, v4")
}
@@ -521,7 +519,7 @@ func TestQuasar_ValidatorSetSync_BLSAndCorona(t *testing.T) {
require.NoError(t, err)
// Verify both BLS and Corona have same validator count
blsCount := q.hybridConsensus.GetActiveValidatorCount()
blsCount := q.GetActiveValidatorCount()
epochKeys := q.epochManager.GetCurrentKeys()
rtCount := len(epochKeys.ValidatorSet)
@@ -529,7 +527,7 @@ func TestQuasar_ValidatorSetSync_BLSAndCorona(t *testing.T) {
require.Equal(t, 3, blsCount)
// Verify threshold is synchronized
require.Equal(t, q.hybridConsensus.GetThreshold(), epochKeys.Threshold)
require.Equal(t, q.GetThreshold(), epochKeys.Threshold)
t.Logf("BLS validators=%d, RT validators=%d, threshold=%d",
blsCount, rtCount, epochKeys.Threshold)
+16 -10
View File
@@ -59,8 +59,8 @@ func (o *GPUOrchestrator) BLSSign(sk, msg []byte) ([]byte, error) { return nil,
func (o *GPUOrchestrator) BLSVerify(sig, pk, msg []byte) bool { return false }
// ML-DSA Operations - all return errors without CGO
func (o *GPUOrchestrator) MLDSASign(sk, msg []byte) ([]byte, error) { return nil, ErrCGODisabled }
func (o *GPUOrchestrator) MLDSAVerify(sig, msg, pk []byte) bool { return false }
func (o *GPUOrchestrator) MLDSASign(sk, msg []byte) ([]byte, error) { return nil, ErrCGODisabled }
func (o *GPUOrchestrator) MLDSAVerify(sig, msg, pk []byte) bool { return false }
func (o *GPUOrchestrator) MLDSABatchVerify(sigs, msgs [][]byte, pks [][]byte) ([]bool, error) {
return nil, ErrCGODisabled
}
@@ -71,8 +71,10 @@ type GPUThresholdContext struct{}
func (o *GPUOrchestrator) NewThresholdContext(t, n uint32) (*GPUThresholdContext, error) {
return nil, ErrCGODisabled
}
func (tc *GPUThresholdContext) Close() {}
func (tc *GPUThresholdContext) Keygen(seed []byte) ([][]byte, []byte, error) { return nil, nil, ErrCGODisabled }
func (tc *GPUThresholdContext) Close() {}
func (tc *GPUThresholdContext) Keygen(seed []byte) ([][]byte, []byte, error) {
return nil, nil, ErrCGODisabled
}
func (tc *GPUThresholdContext) PartialSign(shareIndex uint32, share, msg []byte) ([]byte, error) {
return nil, ErrCGODisabled
}
@@ -82,12 +84,16 @@ func (tc *GPUThresholdContext) Combine(partialSigs [][]byte, indices []uint32) (
func (tc *GPUThresholdContext) Verify(sig, pk, msg []byte) bool { return false }
// Hash Operations - stubs
func (o *GPUOrchestrator) BatchSHA3_256(inputs [][]byte) ([][]byte, error) { return nil, ErrCGODisabled }
func (o *GPUOrchestrator) BatchSHA3_512(inputs [][]byte) ([][]byte, error) { return nil, ErrCGODisabled }
func (o *GPUOrchestrator) BatchBLAKE3(inputs [][]byte) ([][]byte, error) { return nil, ErrCGODisabled }
func (o *GPUOrchestrator) SHA3_256(data []byte) []byte { return nil }
func (o *GPUOrchestrator) SHA3_512(data []byte) []byte { return nil }
func (o *GPUOrchestrator) BLAKE3(data []byte) []byte { return nil }
func (o *GPUOrchestrator) BatchSHA3_256(inputs [][]byte) ([][]byte, error) {
return nil, ErrCGODisabled
}
func (o *GPUOrchestrator) BatchSHA3_512(inputs [][]byte) ([][]byte, error) {
return nil, ErrCGODisabled
}
func (o *GPUOrchestrator) BatchBLAKE3(inputs [][]byte) ([][]byte, error) { return nil, ErrCGODisabled }
func (o *GPUOrchestrator) SHA3_256(data []byte) []byte { return nil }
func (o *GPUOrchestrator) SHA3_512(data []byte) []byte { return nil }
func (o *GPUOrchestrator) BLAKE3(data []byte) []byte { return nil }
// Block Verification - stub
func (o *GPUOrchestrator) VerifyBlock(blsSigs, blsPKs [][]byte, thresholdSig, thresholdPK, blockHash []byte) bool {
+4 -4
View File
@@ -355,10 +355,10 @@ func (o *GPUOrchestrator) VerifyBlock(blsSigs, blsPKs [][]byte, thresholdSig, th
// GPUStats contains GPU acceleration statistics
type GPUStats struct {
Enabled bool
Backend string
BatchSize int
MaxWorkers int
Enabled bool
Backend string
BatchSize int
MaxWorkers int
}
// Stats returns current GPU orchestrator statistics
+10 -10
View File
@@ -40,8 +40,8 @@ const (
)
var (
ErrInsufficientGroups = errors.New("insufficient groups signed")
ErrGroupSignatureFailed = errors.New("group signature failed")
ErrInsufficientGroups = errors.New("insufficient groups signed")
ErrGroupSignatureFailed = errors.New("group signature failed")
ErrInvalidGroupAssignment = errors.New("invalid group assignment")
)
@@ -60,7 +60,7 @@ type GroupedEpochManager struct {
groupQuorum int // Number of groups required (out of total)
// Current epoch group state
groups []*ValidatorGroup
groups []*ValidatorGroup
groupByValidator map[string]int // validator -> group index
// Epoch randomness for group assignment (VRF-based)
@@ -69,12 +69,12 @@ type GroupedEpochManager struct {
// ValidatorGroup holds the Corona keys for a single group of validators.
type ValidatorGroup struct {
Index int
Validators []string
Threshold int
GroupKey *coronaThreshold.GroupKey
Shares map[string]*coronaThreshold.KeyShare
Signers map[string]*coronaThreshold.Signer
Index int
Validators []string
Threshold int
GroupKey *coronaThreshold.GroupKey
Shares map[string]*coronaThreshold.KeyShare
Signers map[string]*coronaThreshold.Signer
}
// GroupedSignature holds signatures from multiple groups.
@@ -472,7 +472,7 @@ type EpochCheckpoint struct {
Timestamp int64 // Unix timestamp
// Quantum-safe signature (Corona grouped threshold)
Signature *GroupedSignature
Signature *GroupedSignature
}
// CheckpointHash returns the hash of this checkpoint (for chaining).
+16 -16
View File
@@ -10,7 +10,7 @@ import (
// BenchmarkSignMessage benchmarks signature creation with pooled buffers
func BenchmarkSignMessage(b *testing.B) {
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
b.Fatal(err)
}
@@ -28,13 +28,13 @@ func BenchmarkSignMessage(b *testing.B) {
if err != nil {
b.Fatal(err)
}
ReleaseHybridSignature(sig)
ReleaseQuasarSig(sig)
}
}
// BenchmarkSignMessageParallel benchmarks parallel signature creation
func BenchmarkSignMessageParallel(b *testing.B) {
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
b.Fatal(err)
}
@@ -53,14 +53,14 @@ func BenchmarkSignMessageParallel(b *testing.B) {
if err != nil {
b.Fatal(err)
}
ReleaseHybridSignature(sig)
ReleaseQuasarSig(sig)
}
})
}
// BenchmarkAggregateSignatures benchmarks signature aggregation with pooled slices
func BenchmarkAggregateSignatures(b *testing.B) {
hybrid, err := NewHybrid(3)
hybrid, err := NewSigner(3)
if err != nil {
b.Fatal(err)
}
@@ -75,19 +75,19 @@ func BenchmarkAggregateSignatures(b *testing.B) {
msg := []byte("benchmark message for aggregation")
// Pre-create signatures
sigs := make([]*HybridSignature, 5)
sigs := make([]*QuasarSig, 5)
for i := 0; i < 5; i++ {
sig, err := hybrid.SignMessage(string(rune('A'+i)), msg)
if err != nil {
b.Fatal(err)
}
// Copy to avoid pool reuse during benchmark
sigs[i] = &HybridSignature{
sigs[i] = &QuasarSig{
BLS: append([]byte(nil), sig.BLS...),
Corona: append([]byte(nil), sig.Corona...),
ValidatorID: sig.ValidatorID,
}
ReleaseHybridSignature(sig)
ReleaseQuasarSig(sig)
}
b.ResetTimer()
@@ -103,7 +103,7 @@ func BenchmarkAggregateSignatures(b *testing.B) {
// BenchmarkVerifyAggregatedSignature benchmarks aggregated signature verification with pooled slices
func BenchmarkVerifyAggregatedSignature(b *testing.B) {
hybrid, err := NewHybrid(3)
hybrid, err := NewSigner(3)
if err != nil {
b.Fatal(err)
}
@@ -118,18 +118,18 @@ func BenchmarkVerifyAggregatedSignature(b *testing.B) {
msg := []byte("benchmark message for verification")
// Pre-create signatures
sigs := make([]*HybridSignature, 5)
sigs := make([]*QuasarSig, 5)
for i := 0; i < 5; i++ {
sig, err := hybrid.SignMessage(string(rune('A'+i)), msg)
if err != nil {
b.Fatal(err)
}
sigs[i] = &HybridSignature{
sigs[i] = &QuasarSig{
BLS: append([]byte(nil), sig.BLS...),
Corona: append([]byte(nil), sig.Corona...),
ValidatorID: sig.ValidatorID,
}
ReleaseHybridSignature(sig)
ReleaseQuasarSig(sig)
}
aggSig, err := hybrid.AggregateSignatures(msg, sigs)
@@ -149,7 +149,7 @@ func BenchmarkVerifyAggregatedSignature(b *testing.B) {
// BenchmarkVerifyAggregatedSignatureParallel benchmarks parallel verification
func BenchmarkVerifyAggregatedSignatureParallel(b *testing.B) {
hybrid, err := NewHybrid(3)
hybrid, err := NewSigner(3)
if err != nil {
b.Fatal(err)
}
@@ -165,18 +165,18 @@ func BenchmarkVerifyAggregatedSignatureParallel(b *testing.B) {
ctx := context.Background()
// Pre-create signatures
sigs := make([]*HybridSignature, 5)
sigs := make([]*QuasarSig, 5)
for i := 0; i < 5; i++ {
sig, err := hybrid.SignMessage(string(rune('A'+i)), msg)
if err != nil {
b.Fatal(err)
}
sigs[i] = &HybridSignature{
sigs[i] = &QuasarSig{
BLS: append([]byte(nil), sig.BLS...),
Corona: append([]byte(nil), sig.Corona...),
ValidatorID: sig.ValidatorID,
}
ReleaseHybridSignature(sig)
ReleaseQuasarSig(sig)
}
aggSig, err := hybrid.AggregateSignatures(msg, sigs)
+3 -3
View File
@@ -370,9 +370,9 @@ func TestBundleSigner_ChainLinkage(t *testing.T) {
}
// Verify chain linkage
require.Equal(t, [32]byte{}, bundles[0].PreviousHash) // Genesis has no previous
require.Equal(t, bundles[0].Hash(), bundles[1].PreviousHash) // Bundle 1 links to 0
require.Equal(t, bundles[1].Hash(), bundles[2].PreviousHash) // Bundle 2 links to 1
require.Equal(t, [32]byte{}, bundles[0].PreviousHash) // Genesis has no previous
require.Equal(t, bundles[0].Hash(), bundles[1].PreviousHash) // Bundle 1 links to 0
require.Equal(t, bundles[1].Hash(), bundles[2].PreviousHash) // Bundle 2 links to 1
// Verify sequences
require.Equal(t, uint64(0), bundles[0].Sequence)
+145 -145
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2025, Lux Industries Inc All rights reserved.
// Quasar Hybrid Consensus: BLS + Corona for Full Post-Quantum Security
// Quasar: accretion-powered finality with BLS + Corona signatures
package quasar
@@ -18,9 +18,9 @@ import (
// Buffer pools for hot paths - reduces GC pressure during signing/verification
var (
hybridSigPool = sync.Pool{
sigPool = sync.Pool{
New: func() any {
return &HybridSignature{
return &QuasarSig{
BLS: make([]byte, 0, 96),
Corona: make([]byte, 0, 4096),
}
@@ -42,11 +42,11 @@ var (
}
)
// Hybrid implements parallel BLS+Corona threshold signing for PQ-safe consensus.
// Signer implements parallel BLS+Corona threshold signing for PQ-safe consensus.
// BLS provides fast classical threshold signatures.
// Corona provides post-quantum threshold signatures based on Ring-LWE.
// Both run in parallel to provide quantum-safe finality.
type Hybrid struct {
type signer struct {
mu sync.RWMutex
// Classical BLS threshold signing (via crypto/threshold)
@@ -79,8 +79,8 @@ type Validator struct {
Active bool
}
// HybridConfig configures the dual threshold signing system.
type HybridConfig struct {
// SignerConfig configures the dual threshold signing system.
type SignerConfig struct {
Threshold int
TotalParties int
@@ -101,13 +101,13 @@ type CoronaRound1State struct {
Round1Data map[int]*coronaThreshold.Round1Data
}
// NewHybrid creates a new hybrid consensus engine with basic BLS support.
func NewHybrid(thresholdVal int) (*Hybrid, error) {
// NewSigner creates a new signer engine with basic BLS support.
func newSigner(thresholdVal int) (*signer, error) {
if thresholdVal < 1 {
return nil, errors.New("threshold must be at least 1")
}
return &Hybrid{
return &signer{
blsKeys: make(map[string]*bls.SecretKey),
blsPubKeys: make(map[string]*bls.PublicKey),
blsSigners: make(map[string]threshold.Signer),
@@ -118,13 +118,13 @@ func NewHybrid(thresholdVal int) (*Hybrid, error) {
}, nil
}
// NewHybridWithDualThreshold creates a hybrid engine with full dual threshold signing.
func NewHybridWithDualThreshold(config HybridConfig) (*Hybrid, error) {
// NewSignerWithDualThreshold creates a signer with full dual threshold signing.
func newSignerWithDualThreshold(config SignerConfig) (*signer, error) {
if config.Threshold < 1 {
return nil, errors.New("threshold must be at least 1")
}
h := &Hybrid{
h := &signer{
blsKeys: make(map[string]*bls.SecretKey),
blsPubKeys: make(map[string]*bls.PublicKey),
blsSigners: make(map[string]threshold.Signer),
@@ -173,7 +173,7 @@ func NewHybridWithDualThreshold(config HybridConfig) (*Hybrid, error) {
// GenerateDualKeys generates both BLS and Corona threshold keys for an epoch.
// Call this when the validator set changes.
func GenerateDualKeys(t, n int) (*HybridConfig, error) {
func GenerateDualKeys(t, n int) (*SignerConfig, error) {
ctx := context.Background()
// Generate BLS threshold keys
@@ -211,7 +211,7 @@ func GenerateDualKeys(t, n int) (*HybridConfig, error) {
coronaShareMap[id] = coronaShares[i]
}
return &HybridConfig{
return &SignerConfig{
Threshold: t,
TotalParties: n,
BLSKeyShares: blsShareMap,
@@ -227,18 +227,18 @@ func GenerateDualKeys(t, n int) (*HybridConfig, error) {
// CoronaRound1 performs Round 1 of Corona signing for a validator.
// Returns Round1Data to broadcast to other validators.
func (h *Hybrid) CoronaRound1(validatorID string, sessionID int, prfKey []byte) (*coronaThreshold.Round1Data, error) {
h.mu.RLock()
signer, exists := h.coronaSigners[validatorID]
h.mu.RUnlock()
func (s *signer) CoronaRound1(validatorID string, sessionID int, prfKey []byte) (*coronaThreshold.Round1Data, error) {
s.mu.RLock()
signer, exists := s.coronaSigners[validatorID]
s.mu.RUnlock()
if !exists {
return nil, fmt.Errorf("validator %s not found in Corona signers", validatorID)
}
// Get all signer indices
signerIDs := make([]int, 0, len(h.coronaSigners))
for _, s := range h.coronaShares {
signerIDs := make([]int, 0, len(s.coronaSigners))
for _, s := range s.coronaShares {
signerIDs = append(signerIDs, s.Index)
}
@@ -248,17 +248,17 @@ func (h *Hybrid) CoronaRound1(validatorID string, sessionID int, prfKey []byte)
// CoronaRound2 performs Round 2 of Corona signing for a validator.
// Requires collected Round 1 data from all signers.
// Returns Round2Data to broadcast.
func (h *Hybrid) CoronaRound2(validatorID string, sessionID int, message string, prfKey []byte, round1Data map[int]*coronaThreshold.Round1Data) (*coronaThreshold.Round2Data, error) {
h.mu.RLock()
signer, exists := h.coronaSigners[validatorID]
h.mu.RUnlock()
func (s *signer) CoronaRound2(validatorID string, sessionID int, message string, prfKey []byte, round1Data map[int]*coronaThreshold.Round1Data) (*coronaThreshold.Round2Data, error) {
s.mu.RLock()
signer, exists := s.coronaSigners[validatorID]
s.mu.RUnlock()
if !exists {
return nil, fmt.Errorf("validator %s not found in Corona signers", validatorID)
}
signerIDs := make([]int, 0, len(h.coronaSigners))
for _, s := range h.coronaShares {
signerIDs := make([]int, 0, len(s.coronaSigners))
for _, s := range s.coronaShares {
signerIDs = append(signerIDs, s.Index)
}
@@ -267,10 +267,10 @@ func (h *Hybrid) CoronaRound2(validatorID string, sessionID int, message string,
// CoronaFinalize aggregates Round 2 data into the final signature.
// Any validator can call this.
func (h *Hybrid) CoronaFinalize(validatorID string, round2Data map[int]*coronaThreshold.Round2Data) (*coronaThreshold.Signature, error) {
h.mu.RLock()
signer, exists := h.coronaSigners[validatorID]
h.mu.RUnlock()
func (s *signer) CoronaFinalize(validatorID string, round2Data map[int]*coronaThreshold.Round2Data) (*coronaThreshold.Signature, error) {
s.mu.RLock()
signer, exists := s.coronaSigners[validatorID]
s.mu.RUnlock()
if !exists {
return nil, fmt.Errorf("validator %s not found in Corona signers", validatorID)
@@ -280,11 +280,11 @@ func (h *Hybrid) CoronaFinalize(validatorID string, round2Data map[int]*coronaTh
}
// VerifyCoronaSignature verifies a Corona threshold signature.
func (h *Hybrid) VerifyCoronaSignature(message string, sig *coronaThreshold.Signature) bool {
if h.coronaGroupKey == nil || sig == nil {
func (s *signer) VerifyCoronaSignature(message string, sig *coronaThreshold.Signature) bool {
if s.coronaGroupKey == nil || sig == nil {
return false
}
return coronaThreshold.Verify(h.coronaGroupKey, message, sig)
return coronaThreshold.Verify(s.coronaGroupKey, message, sig)
}
// ============================================================================
@@ -294,11 +294,11 @@ func (h *Hybrid) VerifyCoronaSignature(message string, sig *coronaThreshold.Sign
// DualSignRound1 performs Round 1 of both BLS and Corona in parallel.
// BLS: Computes signature share (single round)
// Corona: Computes D matrix + MACs (Round 1 of 2)
func (h *Hybrid) DualSignRound1(ctx context.Context, validatorID string, message []byte, sessionID int, prfKey []byte) (*HybridSignature, *coronaThreshold.Round1Data, error) {
h.mu.RLock()
blsSigner, hasBLS := h.blsSigners[validatorID]
_, hasCorona := h.coronaSigners[validatorID]
h.mu.RUnlock()
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]
_, hasCorona := s.coronaSigners[validatorID]
s.mu.RUnlock()
if !hasBLS || !hasCorona {
return nil, nil, errors.New("validator not configured for dual signing")
@@ -310,8 +310,8 @@ func (h *Hybrid) DualSignRound1(ctx context.Context, validatorID string, message
var round1Data *coronaThreshold.Round1Data
// Get BLS signer indices
blsIndices := make([]int, 0, len(h.blsSigners))
for _, s := range h.blsSigners {
blsIndices := make([]int, 0, len(s.blsSigners))
for _, s := range s.blsSigners {
blsIndices = append(blsIndices, s.Index())
}
@@ -326,7 +326,7 @@ func (h *Hybrid) DualSignRound1(ctx context.Context, validatorID string, message
// Corona Round 1
go func() {
defer wg.Done()
round1Data, _ = h.CoronaRound1(validatorID, sessionID, prfKey)
round1Data, _ = s.CoronaRound1(validatorID, sessionID, prfKey)
}()
wg.Wait()
@@ -335,7 +335,7 @@ func (h *Hybrid) DualSignRound1(ctx context.Context, validatorID string, message
return nil, nil, fmt.Errorf("BLS signing failed: %w", blsErr)
}
sig := &HybridSignature{
sig := &QuasarSig{
BLS: blsShare.Bytes(),
ValidatorID: validatorID,
IsThreshold: true,
@@ -346,8 +346,8 @@ func (h *Hybrid) DualSignRound1(ctx context.Context, validatorID string, message
}
// DualSignRound2 performs Round 2 of Corona (BLS is already done in Round1).
func (h *Hybrid) DualSignRound2(validatorID string, sessionID int, message string, prfKey []byte, round1Data map[int]*coronaThreshold.Round1Data) (*coronaThreshold.Round2Data, error) {
return h.CoronaRound2(validatorID, sessionID, message, prfKey, round1Data)
func (s *signer) DualSignRound2(validatorID string, sessionID int, message string, prfKey []byte, round1Data map[int]*coronaThreshold.Round1Data) (*coronaThreshold.Round2Data, error) {
return s.CoronaRound2(validatorID, sessionID, message, prfKey, round1Data)
}
// ============================================================================
@@ -355,9 +355,9 @@ func (h *Hybrid) DualSignRound2(validatorID string, sessionID int, message strin
// ============================================================================
// AddValidator adds a validator with legacy BLS key generation.
func (h *Hybrid) AddValidator(id string, weight uint64) error {
h.mu.Lock()
defer h.mu.Unlock()
func (s *signer) AddValidator(id string, weight uint64) error {
s.mu.Lock()
defer s.mu.Unlock()
blsSK, err := bls.NewSecretKey()
if err != nil {
@@ -365,10 +365,10 @@ func (h *Hybrid) AddValidator(id string, weight uint64) error {
}
blsPK := blsSK.PublicKey()
h.blsKeys[id] = blsSK
h.blsPubKeys[id] = blsPK
s.blsKeys[id] = blsSK
s.blsPubKeys[id] = blsPK
h.validators[id] = &Validator{
s.validators[id] = &Validator{
ID: id,
BLSPubKey: blsPK,
Weight: weight,
@@ -379,29 +379,29 @@ func (h *Hybrid) AddValidator(id string, weight uint64) error {
}
// SignMessage signs a message with BLS (legacy mode or threshold).
func (h *Hybrid) SignMessage(validatorID string, message []byte) (*HybridSignature, error) {
return h.SignMessageWithContext(context.Background(), validatorID, message)
func (s *signer) SignMessage(validatorID string, message []byte) (*QuasarSig, error) {
return s.SignMessageWithContext(context.Background(), validatorID, message)
}
// SignMessageWithContext signs a message.
func (h *Hybrid) SignMessageWithContext(ctx context.Context, validatorID string, message []byte) (*HybridSignature, error) {
func (s *signer) SignMessageWithContext(ctx context.Context, validatorID string, message []byte) (*QuasarSig, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
h.mu.RLock()
defer h.mu.RUnlock()
s.mu.RLock()
defer s.mu.RUnlock()
sig := hybridSigPool.Get().(*HybridSignature)
sig := sigPool.Get().(*QuasarSig)
sig.BLS = sig.BLS[:0]
sig.Corona = sig.Corona[:0]
sig.ValidatorID = validatorID
// Check for threshold signer
blsSigner, hasBLSSigner := h.blsSigners[validatorID]
blsSigner, hasBLSSigner := s.blsSigners[validatorID]
if hasBLSSigner {
blsIndices := make([]int, 0, len(h.blsSigners))
for _, s := range h.blsSigners {
blsIndices := make([]int, 0, len(s.blsSigners))
for _, s := range s.blsSigners {
blsIndices = append(blsIndices, s.Index())
}
@@ -417,7 +417,7 @@ func (h *Hybrid) SignMessageWithContext(ctx context.Context, validatorID string,
}
// Fall back to legacy BLS
blsSK, exists := h.blsKeys[validatorID]
blsSK, exists := s.blsKeys[validatorID]
if !exists {
return nil, errors.New("validator not found")
}
@@ -433,36 +433,36 @@ func (h *Hybrid) SignMessageWithContext(ctx context.Context, validatorID string,
return sig, nil
}
// ReleaseHybridSignature returns a HybridSignature to the pool.
func ReleaseHybridSignature(sig *HybridSignature) {
// ReleaseQuasarSig returns a QuasarSig to the pool.
func ReleaseQuasarSig(sig *QuasarSig) {
if sig == nil {
return
}
sig.ValidatorID = ""
sig.IsThreshold = false
sig.SignerIndex = 0
hybridSigPool.Put(sig)
sigPool.Put(sig)
}
// VerifyHybridSignature verifies a signature.
func (h *Hybrid) VerifyHybridSignature(message []byte, sig *HybridSignature) bool {
return h.VerifyHybridSignatureWithContext(context.Background(), message, sig)
// VerifyQuasarSig verifies a signature.
func (s *signer) VerifyQuasarSig(message []byte, sig *QuasarSig) bool {
return s.VerifyQuasarSigWithContext(context.Background(), message, sig)
}
// VerifyHybridSignatureWithContext verifies a signature.
func (h *Hybrid) VerifyHybridSignatureWithContext(ctx context.Context, message []byte, sig *HybridSignature) bool {
// VerifyQuasarSigWithContext verifies a signature.
func (s *signer) VerifyQuasarSigWithContext(ctx context.Context, message []byte, sig *QuasarSig) bool {
if ctx.Err() != nil {
return false
}
h.mu.RLock()
defer h.mu.RUnlock()
s.mu.RLock()
defer s.mu.RUnlock()
if sig.IsThreshold {
return true // Shares verified during aggregation
}
validator, exists := h.validators[sig.ValidatorID]
validator, exists := s.validators[sig.ValidatorID]
if !exists {
return false
}
@@ -476,38 +476,38 @@ func (h *Hybrid) VerifyHybridSignatureWithContext(ctx context.Context, message [
}
// AggregateSignatures aggregates BLS threshold signature shares.
func (h *Hybrid) AggregateSignatures(message []byte, signatures []*HybridSignature) (*AggregatedSignature, error) {
return h.AggregateSignaturesWithContext(context.Background(), message, signatures)
func (s *signer) AggregateSignatures(message []byte, signatures []*QuasarSig) (*AggregatedSignature, error) {
return s.AggregateSignaturesWithContext(context.Background(), message, signatures)
}
// AggregateSignaturesWithContext aggregates signatures.
func (h *Hybrid) AggregateSignaturesWithContext(ctx context.Context, message []byte, signatures []*HybridSignature) (*AggregatedSignature, error) {
func (s *signer) AggregateSignaturesWithContext(ctx context.Context, message []byte, signatures []*QuasarSig) (*AggregatedSignature, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
h.mu.Lock()
defer h.mu.Unlock()
s.mu.Lock()
defer s.mu.Unlock()
if len(signatures) < h.threshold {
return nil, fmt.Errorf("insufficient signatures: %d < %d", len(signatures), h.threshold)
if len(signatures) < s.threshold {
return nil, fmt.Errorf("insufficient signatures: %d < %d", len(signatures), s.threshold)
}
// Check for threshold mode
if len(signatures) > 0 && signatures[0].IsThreshold && h.blsAggregator != nil {
if len(signatures) > 0 && signatures[0].IsThreshold && s.blsAggregator != nil {
blsShares := make([]threshold.SignatureShare, 0, len(signatures))
for _, sig := range signatures {
if len(sig.BLS) > 0 {
share, err := h.blsScheme.ParseSignatureShare(sig.BLS)
share, err := s.blsScheme.ParseSignatureShare(sig.BLS)
if err == nil {
blsShares = append(blsShares, share)
}
}
}
if len(blsShares) >= h.threshold {
blsAggSig, err := h.blsAggregator.Aggregate(ctx, message, blsShares, nil)
if len(blsShares) >= s.threshold {
blsAggSig, err := s.blsAggregator.Aggregate(ctx, message, blsShares, nil)
if err != nil {
return nil, fmt.Errorf("BLS aggregation failed: %w", err)
}
@@ -552,26 +552,26 @@ func (h *Hybrid) AggregateSignaturesWithContext(ctx context.Context, message []b
}
// VerifyAggregatedSignature verifies an aggregated signature.
func (h *Hybrid) VerifyAggregatedSignature(message []byte, aggSig *AggregatedSignature) bool {
return h.VerifyAggregatedSignatureWithContext(context.Background(), message, aggSig)
func (s *signer) VerifyAggregatedSignature(message []byte, aggSig *AggregatedSignature) bool {
return s.VerifyAggregatedSignatureWithContext(context.Background(), message, aggSig)
}
// VerifyAggregatedSignatureWithContext verifies an aggregated signature.
func (h *Hybrid) VerifyAggregatedSignatureWithContext(ctx context.Context, message []byte, aggSig *AggregatedSignature) bool {
func (s *signer) VerifyAggregatedSignatureWithContext(ctx context.Context, message []byte, aggSig *AggregatedSignature) bool {
if ctx.Err() != nil {
return false
}
h.mu.RLock()
defer h.mu.RUnlock()
s.mu.RLock()
defer s.mu.RUnlock()
if aggSig.SignerCount < h.threshold {
if aggSig.SignerCount < s.threshold {
return false
}
if aggSig.IsThreshold {
if h.blsVerifier != nil && len(aggSig.BLSAggregated) > 0 {
return h.blsVerifier.VerifyBytes(message, aggSig.BLSAggregated)
if s.blsVerifier != nil && len(aggSig.BLSAggregated) > 0 {
return s.blsVerifier.VerifyBytes(message, aggSig.BLSAggregated)
}
return false
}
@@ -590,7 +590,7 @@ func (h *Hybrid) VerifyAggregatedSignatureWithContext(ctx context.Context, messa
}()
for _, validatorID := range aggSig.ValidatorIDs {
validator, exists := h.validators[validatorID]
validator, exists := s.validators[validatorID]
if !exists || !validator.Active {
return false
}
@@ -605,8 +605,8 @@ func (h *Hybrid) VerifyAggregatedSignatureWithContext(ctx context.Context, messa
return bls.Verify(aggPubKey, blsSig, message)
}
// HybridSignature contains BLS and optionally Corona signature data.
type HybridSignature struct {
// QuasarSig contains BLS and optionally Corona signature data.
type QuasarSig struct {
BLS []byte
Corona []byte
ValidatorID string
@@ -624,12 +624,12 @@ type AggregatedSignature struct {
}
// GetActiveValidatorCount returns the number of active validators.
func (h *Hybrid) GetActiveValidatorCount() int {
h.mu.RLock()
defer h.mu.RUnlock()
func (s *signer) GetActiveValidatorCount() int {
s.mu.RLock()
defer s.mu.RUnlock()
count := 0
for _, v := range h.validators {
for _, v := range s.validators {
if v.Active {
count++
}
@@ -638,18 +638,18 @@ func (h *Hybrid) GetActiveValidatorCount() int {
}
// GetThreshold returns the consensus threshold.
func (h *Hybrid) GetThreshold() int {
return h.threshold
func (s *signer) GetThreshold() int {
return s.threshold
}
// IsThresholdMode returns true if BLS threshold signing is enabled.
func (h *Hybrid) IsThresholdMode() bool {
return h.blsScheme != nil
func (s *signer) IsThresholdMode() bool {
return s.blsScheme != nil
}
// IsDualThresholdMode returns true if both BLS and Corona are enabled.
func (h *Hybrid) IsDualThresholdMode() bool {
return h.blsScheme != nil && h.coronaGroupKey != nil
func (s *signer) IsDualThresholdMode() bool {
return s.blsScheme != nil && s.coronaGroupKey != nil
}
// ============================================================================
@@ -665,8 +665,8 @@ type ThresholdConfig struct {
GroupKey threshold.PublicKey
}
// NewHybridWithThresholdConfig creates a hybrid engine from ThresholdConfig.
func NewHybridWithThresholdConfig(config ThresholdConfig) (*Hybrid, error) {
// newSignerWithThresholdConfig creates a signer from ThresholdConfig.
func newSignerWithThresholdConfig(config ThresholdConfig) (*signer, error) {
if config.Threshold < 1 {
return nil, errors.New("threshold must be at least 1")
}
@@ -676,7 +676,7 @@ func NewHybridWithThresholdConfig(config ThresholdConfig) (*Hybrid, error) {
return nil, fmt.Errorf("failed to get threshold scheme: %w", err)
}
h := &Hybrid{
h := &signer{
blsKeys: make(map[string]*bls.SecretKey),
blsPubKeys: make(map[string]*bls.PublicKey),
blsSigners: make(map[string]threshold.Signer),
@@ -710,9 +710,9 @@ func NewHybridWithThresholdConfig(config ThresholdConfig) (*Hybrid, error) {
return h, nil
}
// NewHybridWithThreshold is an alias for NewHybridWithDualThreshold.
func NewHybridWithThreshold(config HybridConfig) (*Hybrid, error) {
return NewHybridWithDualThreshold(config)
// newSignerWithThreshold is an alias for newSignerWithDualThreshold.
func newSignerWithThreshold(config SignerConfig) (*signer, error) {
return newSignerWithDualThreshold(config)
}
// GenerateThresholdKeys generates threshold keys for a single scheme.
@@ -734,32 +734,32 @@ func GenerateThresholdKeys(schemeID threshold.SchemeID, t, n int) ([]threshold.K
}
// GenerateDualThresholdKeys generates both BLS and Corona keys (backward compat).
func GenerateDualThresholdKeys(t, n int) (*HybridConfig, error) {
func GenerateDualThresholdKeys(t, n int) (*SignerConfig, error) {
return GenerateDualKeys(t, n)
}
// ThresholdScheme returns the BLS threshold scheme.
func (h *Hybrid) ThresholdScheme() threshold.Scheme {
return h.blsScheme
func (s *signer) ThresholdScheme() threshold.Scheme {
return s.blsScheme
}
// ThresholdGroupKey returns the BLS group public key.
func (h *Hybrid) ThresholdGroupKey() threshold.PublicKey {
return h.blsGroupKey
func (s *signer) ThresholdGroupKey() threshold.PublicKey {
return s.blsGroupKey
}
// SignMessageThreshold signs using BLS threshold.
func (h *Hybrid) SignMessageThreshold(ctx context.Context, validatorID string, message []byte) (threshold.SignatureShare, error) {
h.mu.RLock()
defer h.mu.RUnlock()
func (s *signer) SignMessageThreshold(ctx context.Context, validatorID string, message []byte) (threshold.SignatureShare, error) {
s.mu.RLock()
defer s.mu.RUnlock()
signer, exists := h.blsSigners[validatorID]
signer, exists := s.blsSigners[validatorID]
if !exists {
return nil, fmt.Errorf("validator %s not found in BLS signers", validatorID)
}
signerIndices := make([]int, 0, len(h.blsSigners))
for _, s := range h.blsSigners {
signerIndices := make([]int, 0, len(s.blsSigners))
for _, s := range s.blsSigners {
signerIndices = append(signerIndices, s.Index())
}
@@ -767,62 +767,62 @@ func (h *Hybrid) SignMessageThreshold(ctx context.Context, validatorID string, m
}
// AggregateThresholdSignatures aggregates BLS threshold shares.
func (h *Hybrid) AggregateThresholdSignatures(ctx context.Context, message []byte, shares []threshold.SignatureShare) (threshold.Signature, error) {
if h.blsAggregator == nil {
func (s *signer) AggregateThresholdSignatures(ctx context.Context, message []byte, shares []threshold.SignatureShare) (threshold.Signature, error) {
if s.blsAggregator == nil {
return nil, errors.New("BLS aggregator not initialized")
}
if len(shares) <= h.threshold {
return nil, fmt.Errorf("insufficient shares: need at least %d, got %d", h.threshold+1, len(shares))
if len(shares) <= s.threshold {
return nil, fmt.Errorf("insufficient shares: need at least %d, got %d", s.threshold+1, len(shares))
}
h.mu.Lock()
defer h.mu.Unlock()
s.mu.Lock()
defer s.mu.Unlock()
return h.blsAggregator.Aggregate(ctx, message, shares, nil)
return s.blsAggregator.Aggregate(ctx, message, shares, nil)
}
// VerifyThresholdSignature verifies a BLS threshold signature.
func (h *Hybrid) VerifyThresholdSignature(message []byte, sig threshold.Signature) bool {
if h.blsVerifier == nil {
func (s *signer) VerifyThresholdSignature(message []byte, sig threshold.Signature) bool {
if s.blsVerifier == nil {
return false
}
h.mu.RLock()
defer h.mu.RUnlock()
s.mu.RLock()
defer s.mu.RUnlock()
return h.blsVerifier.Verify(message, sig)
return s.blsVerifier.Verify(message, sig)
}
// VerifyThresholdSignatureBytes verifies serialized BLS threshold signature.
func (h *Hybrid) VerifyThresholdSignatureBytes(message, sig []byte) bool {
if h.blsVerifier == nil {
func (s *signer) VerifyThresholdSignatureBytes(message, sig []byte) bool {
if s.blsVerifier == nil {
return false
}
h.mu.RLock()
defer h.mu.RUnlock()
s.mu.RLock()
defer s.mu.RUnlock()
return h.blsVerifier.VerifyBytes(message, sig)
return s.blsVerifier.VerifyBytes(message, sig)
}
// AddValidatorThreshold adds a validator with BLS threshold key share.
func (h *Hybrid) AddValidatorThreshold(id string, keyShare threshold.KeyShare, weight uint64) error {
if h.blsScheme == nil {
func (s *signer) AddValidatorThreshold(id string, keyShare threshold.KeyShare, weight uint64) error {
if s.blsScheme == nil {
return errors.New("BLS threshold scheme not initialized")
}
h.mu.Lock()
defer h.mu.Unlock()
s.mu.Lock()
defer s.mu.Unlock()
signer, err := h.blsScheme.NewSigner(keyShare)
signer, err := s.blsScheme.NewSigner(keyShare)
if err != nil {
return fmt.Errorf("failed to create signer: %w", err)
}
h.blsSigners[id] = signer
s.blsSigners[id] = signer
h.validators[id] = &Validator{
s.validators[id] = &Validator{
ID: id,
Weight: weight,
Active: true,
+26 -106
View File
@@ -96,8 +96,8 @@ func BenchmarkBLSSigningVariableMessageSize(b *testing.B) {
// Hybrid Signature Benchmarks (BLS + ML-DSA/Corona)
// =============================================================================
func BenchmarkHybridSignatureCreation(b *testing.B) {
hybrid, err := NewHybrid(1)
func BenchmarkQuasarSigCreation(b *testing.B) {
hybrid, err := NewSigner(1)
if err != nil {
b.Fatal(err)
}
@@ -118,8 +118,8 @@ func BenchmarkHybridSignatureCreation(b *testing.B) {
}
}
func BenchmarkHybridSignatureVerification(b *testing.B) {
hybrid, err := NewHybrid(1)
func BenchmarkQuasarSigVerification(b *testing.B) {
hybrid, err := NewSigner(1)
if err != nil {
b.Fatal(err)
}
@@ -137,15 +137,15 @@ func BenchmarkHybridSignatureVerification(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if !hybrid.VerifyHybridSignature(message, sig) {
if !hybrid.VerifyQuasarSig(message, sig) {
b.Fatal("verification failed")
}
}
}
func BenchmarkHybridSignatureVariableMessageSize(b *testing.B) {
func BenchmarkQuasarSigVariableMessageSize(b *testing.B) {
sizes := []int{32, 64, 128, 256, 512, 1024}
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
b.Fatal(err)
}
@@ -179,7 +179,7 @@ func BenchmarkHybridSignatureVariableMessageSize(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if !hybrid.VerifyHybridSignature(message, sig) {
if !hybrid.VerifyQuasarSig(message, sig) {
b.Fatal("verification failed")
}
}
@@ -268,12 +268,12 @@ func BenchmarkBLSAggregatedVerification(b *testing.B) {
}
}
func BenchmarkHybridAggregation(b *testing.B) {
func BenchmarkSignerAggregation(b *testing.B) {
counts := []int{4, 8, 16, 32}
for _, count := range counts {
b.Run(fmt.Sprintf("%d_validators", count), func(b *testing.B) {
hybrid, err := NewHybrid(count)
hybrid, err := NewSigner(count)
if err != nil {
b.Fatal(err)
}
@@ -282,7 +282,7 @@ func BenchmarkHybridAggregation(b *testing.B) {
rand.Read(message)
// Add validators and collect signatures
sigs := make([]*HybridSignature, count)
sigs := make([]*QuasarSig, count)
for i := 0; i < count; i++ {
id := fmt.Sprintf("validator-%d", i)
if err := hybrid.AddValidator(id, 100); err != nil {
@@ -307,12 +307,12 @@ func BenchmarkHybridAggregation(b *testing.B) {
}
}
func BenchmarkHybridAggregatedVerification(b *testing.B) {
func BenchmarkSignerAggregatedVerification(b *testing.B) {
counts := []int{4, 8, 16, 32}
for _, count := range counts {
b.Run(fmt.Sprintf("%d_validators", count), func(b *testing.B) {
hybrid, err := NewHybrid(count)
hybrid, err := NewSigner(count)
if err != nil {
b.Fatal(err)
}
@@ -321,7 +321,7 @@ func BenchmarkHybridAggregatedVerification(b *testing.B) {
rand.Read(message)
// Add validators and collect signatures
sigs := make([]*HybridSignature, count)
sigs := make([]*QuasarSig, count)
for i := 0; i < count; i++ {
id := fmt.Sprintf("validator-%d", i)
if err := hybrid.AddValidator(id, 100); err != nil {
@@ -369,7 +369,7 @@ func BenchmarkThresholdRound(b *testing.B) {
for _, tc := range thresholds {
b.Run(fmt.Sprintf("n%d_t%d", tc.n, tc.t), func(b *testing.B) {
hybrid, err := NewHybrid(tc.t)
hybrid, err := NewSigner(tc.t)
if err != nil {
b.Fatal(err)
}
@@ -391,7 +391,7 @@ func BenchmarkThresholdRound(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Collect threshold signatures (simulate a round)
sigs := make([]*HybridSignature, tc.t)
sigs := make([]*QuasarSig, tc.t)
for j := 0; j < tc.t; j++ {
sig, err := hybrid.SignMessage(ids[j], message)
if err != nil {
@@ -421,7 +421,7 @@ func BenchmarkThresholdSigningOnly(b *testing.B) {
for _, t := range thresholds {
b.Run(fmt.Sprintf("%d_signers", t), func(b *testing.B) {
hybrid, err := NewHybrid(t)
hybrid, err := NewSigner(t)
if err != nil {
b.Fatal(err)
}
@@ -533,93 +533,9 @@ func BenchmarkMLDSAVerification(b *testing.B) {
// Corona (Stub) Benchmarks
// =============================================================================
func BenchmarkCoronaKeyGen(b *testing.B) {
seed := make([]byte, 32)
rand.Read(seed)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, err := KeyGen(seed)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCoronaPrecompute(b *testing.B) {
sk := make([]byte, 32)
rand.Read(sk)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := Precompute(sk)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCoronaQuickSign(b *testing.B) {
sk := make([]byte, 32)
rand.Read(sk)
precomp, err := Precompute(sk)
if err != nil {
b.Fatal(err)
}
message := make([]byte, 32)
rand.Read(message)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := QuickSign(precomp, message)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCoronaAggregate(b *testing.B) {
counts := []int{4, 8, 16, 32, 64}
for _, count := range counts {
b.Run(fmt.Sprintf("%d_shares", count), func(b *testing.B) {
shares := make([]Share, count)
for i := 0; i < count; i++ {
shares[i] = make([]byte, 32)
rand.Read(shares[i])
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := Aggregate(shares)
if err != nil {
b.Fatal(err)
}
}
})
}
}
func BenchmarkCoronaVerify(b *testing.B) {
pk := make([]byte, 32)
rand.Read(pk)
message := make([]byte, 32)
rand.Read(message)
cert := make([]byte, 32)
rand.Read(cert)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if !Verify(pk, message, cert) {
b.Fatal("verification failed")
}
}
}
// NOTE: Corona benchmarks are in the real corona package at
// github.com/luxfi/corona/threshold. The quasar package uses the real
// implementation via the Signer type in quasar.go.
// =============================================================================
// End-to-End Quasar Benchmarks
@@ -630,7 +546,11 @@ func BenchmarkQuasarBlockProcessing(b *testing.B) {
if err != nil {
b.Fatal(err)
}
if err := qa.hybridConsensus.AddValidator("validator1", 100); err != nil {
// Need at least 2 validators for epoch manager
if _, err := qa.AddValidator("validator1", 100); err != nil {
b.Fatal(err)
}
if _, err := qa.AddValidator("validator2", 100); err != nil {
b.Fatal(err)
}
@@ -680,7 +600,7 @@ func BenchmarkQuasarValidatorAddition(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
b.StopTimer()
hybrid, err := NewHybrid(1)
hybrid, err := NewSigner(1)
if err != nil {
b.Fatal(err)
}
+10 -10
View File
@@ -57,13 +57,13 @@ func (u *unarySnowball) RecordPoll(voteCount, threshold int) bool {
// binaryTreeSnowball tracks binary choice at tree branch point
type binaryTreeSnowball struct {
preference int
prefStrength [2]int
confidence int
finalized bool
alphaPreference int
alphaConfidence int
beta int
preference int
prefStrength [2]int
confidence int
finalized bool
alphaPreference int
alphaConfidence int
beta int
}
func newBinaryTreeSnowball(alphaPreference, alphaConfidence, beta int) *binaryTreeSnowball {
@@ -114,7 +114,7 @@ type consensusTree struct {
preference [32]byte
finalized bool
// Track choice to branch mapping for binary snowball
choices [2][32]byte // choices[0] = first choice, choices[1] = second choice
choices [2][32]byte // choices[0] = first choice, choices[1] = second choice
numChoices int
}
@@ -643,7 +643,7 @@ func TestQuasarThroughput(t *testing.T) {
func TestHybridConsensusBasic(t *testing.T) {
require := require.New(t)
hybrid, err := newHybridConsensus(2)
hybrid, err := newCertifier(2)
require.NoError(err)
// Add validators
@@ -676,7 +676,7 @@ func TestHybridConsensusBasic(t *testing.T) {
func TestHybridConsensusValidatorChurn(t *testing.T) {
require := require.New(t)
hybrid, err := newHybridConsensus(2)
hybrid, err := newCertifier(2)
require.NoError(err)
hybrid.AddValidator("v1", 100)
+50 -18
View File
@@ -69,26 +69,58 @@ type Stats struct {
Uptime time.Duration // Time since start
}
// Core is an alias for the aggregator implementation.
// Use NewCore() to create a new instance.
type Core = Quasar
// BLSSignature contains a classical BLS threshold signature.
// Fast path for consensus - used in parallel with CoronaSignature.
type BLSSignature struct {
Signature []byte // BLS signature bytes
ValidatorID string // Signing validator
IsThreshold bool // True if threshold signature
SignerIndex int // Signer index in committee
}
// QuasarCore is a deprecated alias for backward compatibility.
// Deprecated: Use Quasar or Core instead.
type QuasarCore = Quasar
// CoronaSignature contains a post-quantum Corona threshold signature.
// Quantum-safe path - used in parallel with BLSSignature.
type CoronaSignature struct {
Signature []byte // Corona (Ring-LWE) signature bytes
ValidatorID string // Signing validator
IsThreshold bool // True if threshold signature
SignerIndex int // Signer index in committee
Round int // Corona protocol round (1 or 2)
}
// PChain is a deprecated alias for backward compatibility.
// Deprecated: Use BLS instead.
type PChain = BLS
// QuasarSignature bundles BLS + Corona for complete quantum finality.
// Both signatures are collected in parallel.
type QuasarSignature struct {
BLS *BLSSignature // Classical fast path
Corona *CoronaSignature // Quantum-safe path
}
// NewPChain is a deprecated alias for backward compatibility.
// Deprecated: Use NewBLS instead.
var NewPChain = NewBLS
// CoronaRound1Data contains the output of Corona Round 1.
type CoronaRound1Data struct {
PartyID int
}
// QuasarHybridConsensus is a deprecated alias for backward compatibility.
// Deprecated: Use Hybrid instead.
type QuasarHybridConsensus = Hybrid
// Signer is the exported interface for the quantum signing engine.
// It provides parallel BLS+Corona threshold signing for PQ-safe consensus.
type Signer = signer
// NewQuasarHybridConsensus is a deprecated alias for backward compatibility.
// Deprecated: Use NewHybrid instead.
var NewQuasarHybridConsensus = NewHybrid
// NewSigner creates a new quantum signer with the given threshold.
func NewSigner(threshold int) (*Signer, error) {
return newSigner(threshold)
}
// NewSignerWithConfig creates a new quantum signer with full configuration.
func NewSignerWithConfig(config SignerConfig) (*Signer, error) {
return newSignerWithDualThreshold(config)
}
// NewSignerWithDualThreshold creates a new quantum signer with dual threshold configuration.
// This is an alias for NewSignerWithConfig for backward compatibility.
func NewSignerWithDualThreshold(config SignerConfig) (*Signer, error) {
return NewSignerWithConfig(config)
}
// NewSignerWithThresholdConfig creates a signer from ThresholdConfig.
func NewSignerWithThresholdConfig(config ThresholdConfig) (*Signer, error) {
return newSignerWithThresholdConfig(config)
}
+10 -2
View File
@@ -267,9 +267,17 @@ func (v *VerkleWitness) cacheWitness(witness *WitnessProof) {
}
}
// verifyBLSAggregate verifies BLS aggregate signature for fallback verification.
// NOTE: This is a placeholder for the VerkleWitness slow path. Since the witness
// assumes PQ finality (via checkPQFinality), this path is rarely exercised.
// For real BLS verification, see the Signer.VerifyQuasarSig in quasar.go which
// uses github.com/luxfi/crypto/bls for actual signature verification.
func (v *VerkleWitness) verifyBLSAggregate(aggSig []byte, validatorSet []byte) error {
// Placeholder for BLS aggregate verification
// In production, this would verify against the validator set
// With PQ finality assumption, this path is rarely used.
// Real verification happens in Signer.VerifyQuasarSig.
if len(aggSig) == 0 {
return errors.New("empty aggregate signature")
}
return nil
}
+8 -8
View File
@@ -32,12 +32,12 @@ const (
// - confidence -> consecutive rounds at threshold
// - finalized -> decided
type binarySnowball struct {
alphaPreference int // minimum votes to update preference
alphaConfidence int // minimum votes to increment confidence
beta int // consecutive rounds needed for finalization
preference int // current preference (0 or 1)
alphaPreference int // minimum votes to update preference
alphaConfidence int // minimum votes to increment confidence
beta int // consecutive rounds needed for finalization
preference int // current preference (0 or 1)
prefStrength [2]int // accumulated votes per choice
confidence int // consecutive successful polls
confidence int // consecutive successful polls
finalized bool
}
@@ -429,9 +429,9 @@ func TestWaveSnowballDecisionPersistence(t *testing.T) {
// TestWaveParameterValidation tests configuration constraints
func TestWaveParameterValidation(t *testing.T) {
tests := []struct {
name string
cfg Config
valid bool
name string
cfg Config
valid bool
}{
{
name: "valid minimal",
+1 -1
View File
@@ -62,7 +62,7 @@ const (
type HonestNode struct {
id string
agent *ai.Agent[ai.BlockData]
quasar *quasar.QuasarCore
quasar *quasar.Quasar
photon *photon.UniformEmitter
votes map[ids.ID]float64
preference ids.ID
+6 -11
View File
@@ -11,20 +11,15 @@ import (
func TestAIConsensusIntegration(t *testing.T) {
t.Run("AI Agent with Quasar Consensus", func(t *testing.T) {
// Create Quasar hybrid consensus
consensus, err := quasar.NewQuasarHybridConsensus(2)
consensus, err := quasar.NewQuasar(2)
if err != nil {
t.Fatalf("Failed to create consensus: %v", err)
}
// Add validators
err = consensus.AddValidator("validator1", 100)
// Initialize validators (requires threshold < validator count)
err = consensus.InitializeValidators([]string{"validator1", "validator2", "validator3"})
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
}
err = consensus.AddValidator("validator2", 100)
if err != nil {
t.Fatalf("Failed to add validator: %v", err)
t.Fatalf("Failed to initialize validators: %v", err)
}
// Create a simple model that implements BasicModel
@@ -96,7 +91,7 @@ func TestAIConsensusIntegration(t *testing.T) {
}
// Verify signature
if !consensus.VerifyHybridSignature(message, sig) {
if !consensus.VerifyQuasarSig(message, sig) {
t.Fatal("Signature verification failed")
}
@@ -106,7 +101,7 @@ func TestAIConsensusIntegration(t *testing.T) {
t.Fatalf("Failed to sign with validator2: %v", err)
}
sigs := []*quasar.HybridSignature{sig, sig2}
sigs := []*quasar.QuasarSig{sig, sig2}
aggSig, err := consensus.AggregateSignatures(message, sigs)
if err != nil {
t.Fatalf("Failed to aggregate signatures: %v", err)
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"testing"
"github.com/luxfi/consensus/core/choices"
"github.com/luxfi/consensus/test/helpers"
consensustest "github.com/luxfi/consensus/test/helpers"
"github.com/luxfi/consensus/types/bag"
"github.com/luxfi/consensus/utils/set"
"github.com/luxfi/ids"
+5 -7
View File
@@ -706,16 +706,14 @@ func TestAIConsensusRandomized(t *testing.T) {
// ==================== Hybrid Consensus Tests ====================
func TestHybridConsensusRandomized(t *testing.T) {
quasarConsensus, err := quasar.NewQuasarHybridConsensus(3)
quasarConsensus, err := quasar.NewQuasar(3)
if err != nil {
t.Fatalf("Failed to create Quasar consensus: %v", err)
}
validators := []string{"val1", "val2", "val3"}
for _, v := range validators {
if err := quasarConsensus.AddValidator(v, 100); err != nil {
t.Fatalf("Failed to add validator %s: %v", v, err)
}
validators := []string{"val1", "val2", "val3", "val4"}
if err := quasarConsensus.InitializeValidators(validators); err != nil {
t.Fatalf("Failed to initialize validators: %v", err)
}
rng := NewMersenneTwister(123)
@@ -733,7 +731,7 @@ func TestHybridConsensusRandomized(t *testing.T) {
continue
}
if quasarConsensus.VerifyHybridSignature(message, sig) {
if quasarConsensus.VerifyQuasarSig(message, sig) {
successfulSigs++
} else {
t.Errorf("Signature verification failed for message %d", i)
+2 -2
View File
@@ -734,6 +734,6 @@ func (l *testListener) OnValidatorLightChanged(netID ids.ID, nodeID ids.NodeID,
type testSetListener struct{}
func (l *testSetListener) OnValidatorAdded(nodeID ids.NodeID, light uint64) {}
func (l *testSetListener) OnValidatorRemoved(nodeID ids.NodeID, light uint64) {}
func (l *testSetListener) OnValidatorAdded(nodeID ids.NodeID, light uint64) {}
func (l *testSetListener) OnValidatorRemoved(nodeID ids.NodeID, light uint64) {}
func (l *testSetListener) OnValidatorLightChanged(nodeID ids.NodeID, oldLight, newLight uint64) {}
+2 -2
View File
@@ -7,9 +7,9 @@ import (
"math"
"testing"
"github.com/luxfi/crypto/bls"
"github.com/luxfi/ids"
mathset "github.com/luxfi/math/set"
"github.com/luxfi/crypto/bls"
"github.com/stretchr/testify/require"
)
@@ -72,7 +72,7 @@ func TestFlattenValidatorSetNoPubKey(t *testing.T) {
result, err := FlattenValidatorSet(vdrSet)
require.NoError(err)
require.Empty(result.Validators) // No validators with public keys
require.Empty(result.Validators) // No validators with public keys
require.Equal(uint64(100), result.TotalWeight) // But weight still counted
}