Files
zeekayandHanzo Dev 45bff3f5b6 fix(dex): close price sources synchronously; build pkg/dpdk and pkg/orderbook on linux
`go test ./...` failed three ways on the runner. Two were build failures that
cannot happen on a mac, and one was a race that only loses under load.

pkg/dpdk — `undefined: syscall.SO_NOSIGPIPE`. DarwinOptimizations guarded itself
with `if runtime.GOOS != "darwin" { return }`, but SO_NOSIGPIPE is a COMPILE-time
constant that exists only on Darwin; a runtime check cannot save a reference the
linux build still has to resolve. Split into _darwin.go / _nodarwin.go. Verified
by cross-compiling both ways -- it failed for GOOS=linux before, both pass now.

pkg/orderbook — the cgo preamble uses uint64_t while including only <stdlib.h>.
macOS pulls stdint.h in transitively and glibc does not, so this built here and
never on the runner. Added the include.

pkg/price — TestXChainSourceStalePrice: "Expected price to be stale".

Not a flaky test; Close() was not a barrier. It closed the done channel and
returned WITHOUT waiting for the polling goroutine. A loop selecting on done
against a ticker picks a ready case AT RANDOM, so a poll could still be running
after Close() returned, and poll writes last[symbol] = time.Now(). The test
closes the source, backdates that timestamp by 10s, and asserts staleness -- an
in-flight poll overwrote it. Wide window on a loaded runner, near-zero on a
laptop, which is why it reproduces 0/30 here.

All EIGHT sources had it, so the fix is one shared `lifecycle` (embedded, so
`s.done` still resolves) whose stop() joins before returning and is safe to call
twice. Oracle had the same defect written as

    // Give time for goroutines to exit
    time.Sleep(100 * time.Millisecond)

which could not work either -- calcAverages blocks on a 1s ticker, so it ran up
to a full second after Stop() returned. Now on the same lifecycle, and its loops
select on done instead of polling a flag, so they leave promptly rather than
after one more tick. Nothing restarts a stopped source (checked: 0 tests), and
the other sources already could not.

    go build ./...                        OK
    GOOS=linux go build ./...             OK   (failed before)
    go vet price/dpdk/orderbook           OK
    go test ./pkg/price/ -race            ok, 3/3 runs
    go test -run StalePrice -count=30     ok

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-02 03:19:43 -07:00

409 lines
8.7 KiB
Go

package price
import (
"context"
"crypto/sha256"
"encoding/hex"
"sync"
"time"
)
// QChainVerifier provides quantum finality verification from Lux Q-Chain.
// Q-Chain is the quantum finality layer for cross-chain order/price verification.
// NOTE: This is NOT a price source - it verifies finality of data from other sources.
type QChainVerifier struct {
rpcURL string
wsURL string
finality map[string]*QuantumFinality
inclusions map[string]*OrderInclusion
validators map[string]*QValidator
quorum int
interval time.Duration
healthy bool
mu sync.RWMutex
lifecycle
polling bool
}
// QuantumFinality represents quantum-verified finality proof.
type QuantumFinality struct {
BlockHash string
BlockHeight uint64
StateRoot string
Timestamp time.Time
Signatures []QuantumSignature
Finalized bool
Latency time.Duration
}
// QuantumSignature is a post-quantum signature on finality.
type QuantumSignature struct {
Validator string
Algorithm string // dilithium, sphincs+, etc.
Signature []byte
PublicKey []byte
Timestamp time.Time
}
// OrderInclusion tracks order inclusion across chains.
type OrderInclusion struct {
OrderID string
Chain string // x-chain, c-chain, zoo-chain, etc.
TxHash string
BlockHeight uint64
Timestamp time.Time
Finality *QuantumFinality
Verified bool
Price float64
Symbol string
}
// QValidator represents a Q-Chain quantum validator.
type QValidator struct {
Address string
PublicKey []byte
Stake uint64
Active bool
Algorithm string
Uptime float64
LastSeen time.Time
}
// NewQChainVerifier creates a Q-Chain finality verifier.
func NewQChainVerifier(rpcURL, wsURL string) *QChainVerifier {
return &QChainVerifier{
rpcURL: rpcURL,
wsURL: wsURL,
finality: make(map[string]*QuantumFinality),
inclusions: make(map[string]*OrderInclusion),
validators: qchainValidators(),
quorum: 3,
interval: 100 * time.Millisecond,
healthy: true,
lifecycle: newLifecycle(),
}
}
// Deprecated: Use NewQChainVerifier instead.
// NewQChainSource is kept for backwards compatibility.
func NewQChainSource(rpcURL, wsURL string) *QChainVerifier {
return NewQChainVerifier(rpcURL, wsURL)
}
func qchainValidators() map[string]*QValidator {
return map[string]*QValidator{
"q-validator-1": {
Address: "Q-lux1qvalidator1...",
Stake: 2000000,
Active: true,
Algorithm: "dilithium3",
Uptime: 0.999,
LastSeen: time.Now(),
},
"q-validator-2": {
Address: "Q-lux1qvalidator2...",
Stake: 1500000,
Active: true,
Algorithm: "dilithium3",
Uptime: 0.998,
LastSeen: time.Now(),
},
"q-validator-3": {
Address: "Q-lux1qvalidator3...",
Stake: 1000000,
Active: true,
Algorithm: "sphincs-sha2-256f",
Uptime: 0.997,
LastSeen: time.Now(),
},
"q-validator-4": {
Address: "Q-lux1qvalidator4...",
Stake: 500000,
Active: true,
Algorithm: "dilithium5",
Uptime: 0.995,
LastSeen: time.Now(),
},
}
}
// Supported chains for finality verification.
func supportedChains() []string {
return []string{
"x-chain",
"a-chain",
"c-chain",
"p-chain",
"zoo-chain",
}
}
// Start begins polling Q-Chain finality.
func (v *QChainVerifier) Start() error {
v.mu.Lock()
if v.polling {
v.mu.Unlock()
return nil
}
v.polling = true
v.mu.Unlock()
v.run(v.loop)
return nil
}
func (v *QChainVerifier) loop() {
ticker := time.NewTicker(v.interval)
defer ticker.Stop()
for {
select {
case <-v.done:
return
case <-ticker.C:
v.poll()
}
}
}
func (v *QChainVerifier) poll() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
var wg sync.WaitGroup
for _, chain := range supportedChains() {
wg.Add(1)
go func(c string) {
defer wg.Done()
v.fetchFinality(ctx, c)
}(chain)
}
wg.Wait()
}
func (v *QChainVerifier) fetchFinality(ctx context.Context, chain string) {
// In production: query Q-Chain for latest finality proof
// Simulate quantum finality
fin := v.simulateFinality(chain)
v.mu.Lock()
defer v.mu.Unlock()
v.finality[chain] = fin
v.healthy = true
}
func (v *QChainVerifier) simulateFinality(chain string) *QuantumFinality {
now := time.Now()
height := uint64(now.Unix())
// Generate finality hash
hashData := []byte(chain + now.String())
hash := sha256.Sum256(hashData)
stateRoot := sha256.Sum256(hash[:])
// Simulate quantum signatures from validators
sigs := make([]QuantumSignature, 0)
for name, val := range v.validators {
if val.Active {
// Generate simulated public key (double the hash)
pubKey := append(hash[:], hash[:]...)
sigs = append(sigs, QuantumSignature{
Validator: name,
Algorithm: val.Algorithm,
Signature: hash[:],
PublicKey: pubKey[:64],
Timestamp: now,
})
}
}
return &QuantumFinality{
BlockHash: hex.EncodeToString(hash[:]),
BlockHeight: height,
StateRoot: hex.EncodeToString(stateRoot[:]),
Timestamp: now,
Signatures: sigs,
Finalized: len(sigs) >= v.quorum,
Latency: 50 * time.Millisecond, // Simulated finality latency
}
}
func (v *QChainVerifier) finalityConfidence(fin *QuantumFinality) float64 {
if !fin.Finalized {
return 0.5
}
// Confidence based on signatures and algorithms
sigCount := len(fin.Signatures)
totalValidators := len(v.validators)
if totalValidators == 0 {
return 0
}
coverage := float64(sigCount) / float64(totalValidators)
// Boost confidence for diverse algorithm usage
algorithms := make(map[string]bool)
for _, sig := range fin.Signatures {
algorithms[sig.Algorithm] = true
}
diversity := float64(len(algorithms)) / 3.0 // Assume 3 main algorithms
if diversity > 1.0 {
diversity = 1.0
}
return 0.8*coverage + 0.2*diversity
}
// Finality returns the latest finality proof for a chain.
func (v *QChainVerifier) Finality(chain string) (*QuantumFinality, error) {
v.mu.RLock()
defer v.mu.RUnlock()
fin, ok := v.finality[chain]
if !ok {
return nil, ErrNotFound
}
return fin, nil
}
// VerifyInclusion verifies an order was included with quantum finality.
func (v *QChainVerifier) VerifyInclusion(orderID, chain, txHash string) (*OrderInclusion, error) {
v.mu.Lock()
defer v.mu.Unlock()
// Check if already verified
key := orderID + ":" + chain
if inc, ok := v.inclusions[key]; ok {
return inc, nil
}
// Get chain finality
fin, ok := v.finality[chain]
if !ok {
return nil, ErrNotFound
}
// Create inclusion proof
inc := &OrderInclusion{
OrderID: orderID,
Chain: chain,
TxHash: txHash,
BlockHeight: fin.BlockHeight,
Timestamp: time.Now(),
Finality: fin,
Verified: fin.Finalized,
}
v.inclusions[key] = inc
return inc, nil
}
// VerifyOrderPrice verifies a price was finalized on Q-Chain.
func (v *QChainVerifier) VerifyOrderPrice(symbol string, price float64, chain string) bool {
v.mu.RLock()
defer v.mu.RUnlock()
fin, ok := v.finality[chain]
if !ok || !fin.Finalized {
return false
}
// Price is considered verified if finality is recent
return time.Since(fin.Timestamp) < 5*time.Second
}
// CrossChainVerify verifies finality across multiple chains.
func (v *QChainVerifier) CrossChainVerify(chains []string) (bool, map[string]*QuantumFinality) {
v.mu.RLock()
defer v.mu.RUnlock()
results := make(map[string]*QuantumFinality)
allFinalized := true
for _, chain := range chains {
fin, ok := v.finality[chain]
if !ok {
allFinalized = false
continue
}
results[chain] = fin
if !fin.Finalized {
allFinalized = false
}
}
return allFinalized, results
}
// Validators returns active Q-Chain validators.
func (v *QChainVerifier) Validators() map[string]*QValidator {
v.mu.RLock()
defer v.mu.RUnlock()
result := make(map[string]*QValidator)
for k, val := range v.validators {
result[k] = val
}
return result
}
// Healthy returns health status.
func (v *QChainVerifier) Healthy() bool {
v.mu.RLock()
defer v.mu.RUnlock()
return v.healthy
}
// Close stops the verifier.
func (v *QChainVerifier) Close() error {
v.mu.Lock()
if !v.polling {
v.mu.Unlock()
return nil // Already closed
}
v.polling = false
v.mu.Unlock()
v.stop()
return nil
}
// SetQuorum sets minimum validator count for finality.
func (v *QChainVerifier) SetQuorum(n int) {
v.mu.Lock()
v.quorum = n
v.mu.Unlock()
}
// FinalityLatency returns average finality latency.
func (v *QChainVerifier) FinalityLatency() time.Duration {
v.mu.RLock()
defer v.mu.RUnlock()
var total time.Duration
count := 0
for _, fin := range v.finality {
total += fin.Latency
count++
}
if count == 0 {
return 0
}
return total / time.Duration(count)
}
// Chains returns supported chains.
func (v *QChainVerifier) Chains() []string {
return supportedChains()
}
// Alias for backwards compatibility
type QChainSource = QChainVerifier