mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
The consensus toolkit now exposes four orthogonal paradigms:
NewChain — linear Snow-family metastable (Nova)
NewDAG — DAG Snow-family metastable (Nebula)
NewPQ — post-quantum threshold Quasar
NewBFT — classical leader-rotation BFT (Simplex/HotStuff family)
NewBFT(cfg BFTConfig) wraps a fully-configured luxbft.Epoch as a
consensus.Engine. The application owns the Epoch's wiring (Storage,
Communication, Signer, BlockBuilder, WAL); the consensus toolkit
owns the lifecycle.
Orthogonality preserved across the three axes:
- consensus paradigm — picks engine (Chain/DAG/PQ/BFT)
- ChainSecurityProfile — picks admissible primitives (strict/permissive/fips)
- FinalitySchemeID — picks the threshold kernel (Pulsar/Corona/MPTC)
A BFT engine under a strict-PQ profile with Pulsar-M-65 finality is
a valid production combination: leader-rotation ordering with
PQ-threshold-signed cert envelopes — exactly the posture a
permissioned subnet might want.
Implementation:
engine/bft/engine.go — thin lifecycle adapter (Start/Stop/
HealthCheck/IsBootstrapped/AdvanceTime/
HandleMessage)
engine/bft/engine_test.go — 6 nil-safety + fail-closed tests
consensus.go — NewBFT factory, BFT type alias,
BFTConfig re-export, MustNewBFT
go.mod requires github.com/luxfi/bft v0.1.5.
248 lines
7.2 KiB
Go
248 lines
7.2 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Package consensus provides a clean, single-import interface to the Lux consensus system.
|
|
// This is the main SDK surface for applications using Lux consensus.
|
|
//
|
|
// For VM-related types (State, Message, Fx), use github.com/luxfi/vm
|
|
package consensus
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
luxbft "github.com/luxfi/bft"
|
|
"github.com/luxfi/consensus/config"
|
|
"github.com/luxfi/consensus/engine"
|
|
bftengine "github.com/luxfi/consensus/engine/bft"
|
|
"github.com/luxfi/consensus/engine/interfaces"
|
|
"github.com/luxfi/consensus/runtime"
|
|
"github.com/luxfi/consensus/types"
|
|
)
|
|
|
|
// Type aliases for clean single-import experience
|
|
type (
|
|
// Engine types
|
|
Engine = engine.Engine
|
|
Chain = engine.Chain
|
|
Config = types.Config
|
|
|
|
// VM State type
|
|
State = interfaces.State
|
|
|
|
// Runtime type for VM wiring (chain IDs, validators, logging, etc.)
|
|
Runtime = runtime.Runtime
|
|
IDs = runtime.IDs
|
|
|
|
// Core types
|
|
Block = types.Block
|
|
Vote = types.Vote
|
|
Certificate = types.Certificate
|
|
ID = types.ID
|
|
NodeID = types.NodeID
|
|
Hash = types.Hash
|
|
Status = types.Status
|
|
Decision = types.Decision
|
|
VoteType = types.VoteType
|
|
)
|
|
|
|
// Constants re-exported for convenience
|
|
const (
|
|
// Decision outcomes
|
|
DecideUndecided = types.DecideUndecided
|
|
DecideAccept = types.DecideAccept
|
|
DecideReject = types.DecideReject
|
|
|
|
// Vote types
|
|
VotePreference = types.VotePreference
|
|
VoteCommit = types.VoteCommit
|
|
VoteCancel = types.VoteCancel
|
|
|
|
// Block status
|
|
StatusUnknown = types.StatusUnknown
|
|
StatusProcessing = types.StatusProcessing
|
|
StatusRejected = types.StatusRejected
|
|
StatusAccepted = types.StatusAccepted
|
|
|
|
// VM states
|
|
Unknown = interfaces.Unknown
|
|
Starting = interfaces.Starting
|
|
Syncing = interfaces.Syncing
|
|
Bootstrapping = interfaces.Bootstrapping
|
|
Ready = interfaces.Ready
|
|
Degraded = interfaces.Degraded
|
|
Stopping = interfaces.Stopping
|
|
Stopped = interfaces.Stopped
|
|
)
|
|
|
|
// Variables re-exported for convenience
|
|
var (
|
|
// GenesisID is the ID of the genesis block
|
|
GenesisID = types.GenesisID
|
|
|
|
// Common errors
|
|
ErrBlockNotFound = types.ErrBlockNotFound
|
|
ErrInvalidBlock = types.ErrInvalidBlock
|
|
ErrInvalidVote = types.ErrInvalidVote
|
|
ErrNoQuorum = types.ErrNoQuorum
|
|
ErrAlreadyVoted = types.ErrAlreadyVoted
|
|
ErrNotValidator = types.ErrNotValidator
|
|
ErrTimeout = types.ErrTimeout
|
|
ErrNotInitialized = types.ErrNotInitialized
|
|
ErrUnknownState = errors.New("unknown state")
|
|
)
|
|
|
|
// DefaultConfig returns the default consensus configuration
|
|
func DefaultConfig() Config {
|
|
return types.DefaultConfig()
|
|
}
|
|
|
|
// NewChain creates a new chain consensus engine
|
|
func NewChain(cfg Config) *Chain {
|
|
return engine.NewChain(cfg)
|
|
}
|
|
|
|
// NewChainEngine creates a new chain consensus engine with default config
|
|
func NewChainEngine() Engine {
|
|
return NewChain(DefaultConfig())
|
|
}
|
|
|
|
// NewDAG creates a new DAG consensus engine.
|
|
// Uses Chain with DAG-aware configuration for parallel vertex processing.
|
|
func NewDAG(cfg Config) Engine {
|
|
// Configure for DAG mode with higher parallelism
|
|
dagCfg := cfg
|
|
if dagCfg.MaxOutstanding == 0 {
|
|
dagCfg.MaxOutstanding = 10 // Enable parallel vertex polling
|
|
}
|
|
return engine.NewChain(dagCfg)
|
|
}
|
|
|
|
// NewDAGEngine creates a new DAG consensus engine with default config.
|
|
func NewDAGEngine() Engine {
|
|
return NewDAG(DefaultConfig())
|
|
}
|
|
|
|
// NewPQ creates a new post-quantum consensus engine.
|
|
// Uses Chain with Quasar protocol for BLS + Corona threshold signatures.
|
|
func NewPQ(cfg Config) Engine {
|
|
// Configure for quantum-safe mode
|
|
pqCfg := cfg
|
|
pqCfg.QuantumResistant = true
|
|
return engine.NewChain(pqCfg)
|
|
}
|
|
|
|
// NewPQEngine creates a new PQ consensus engine with default config.
|
|
func NewPQEngine() Engine {
|
|
return NewPQ(DefaultConfig())
|
|
}
|
|
|
|
// BFT is the consensus-toolkit's view of a luxfi/bft Epoch engine —
|
|
// epoch-based leader-rotation BFT (Simplex/HotStuff family). Sibling
|
|
// to NewChain / NewDAG / NewPQ; the four factories pick across four
|
|
// orthogonal consensus paradigms.
|
|
//
|
|
// Type alias here so callers can name a *BFT without reaching into
|
|
// the engine/bft subpackage.
|
|
type BFT = bftengine.Engine
|
|
|
|
// BFTConfig re-exports luxbft.EpochConfig for callers that want to
|
|
// build a BFT engine from the consensus root facade. Every field is
|
|
// owned by the application (Storage, Communication, Signer,
|
|
// BlockBuilder, WAL) — the consensus toolkit only wires the lifecycle.
|
|
type BFTConfig = luxbft.EpochConfig
|
|
|
|
// NewBFT constructs a BFT consensus engine. The application supplies a
|
|
// fully-wired BFTConfig (Storage, Communication, Signer, etc.); this
|
|
// factory takes ownership of the resulting Epoch's lifecycle and
|
|
// exposes it through the consensus.Engine surface.
|
|
//
|
|
// Returns the engine and any construction error from luxbft.NewEpoch.
|
|
// On success the engine is NOT started — call Start(ctx, requestID)
|
|
// once you've wired up message routing.
|
|
//
|
|
// Orthogonal to PQ profile / threshold-kernel selection: a BFT engine
|
|
// under a strict-PQ profile with Pulsar-M-65 finality is a valid
|
|
// production combination (leader-rotation ordering, PQ-threshold
|
|
// cert envelope).
|
|
func NewBFT(cfg BFTConfig) (*BFT, error) {
|
|
epoch, err := luxbft.NewEpoch(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return bftengine.NewEngine(epoch), nil
|
|
}
|
|
|
|
// MustNewBFT is the panic-on-error form of NewBFT. Use only when the
|
|
// EpochConfig is hard-coded / canonical and a construction failure is
|
|
// a build bug, not a runtime condition.
|
|
func MustNewBFT(cfg BFTConfig) *BFT {
|
|
e, err := NewBFT(cfg)
|
|
if err != nil {
|
|
panic("consensus.MustNewBFT: " + err.Error())
|
|
}
|
|
return e
|
|
}
|
|
|
|
// NewBlock creates a new block with default values
|
|
func NewBlock(id ID, parentID ID, height uint64, payload []byte) *Block {
|
|
return &Block{
|
|
ID: id,
|
|
ParentID: parentID,
|
|
Height: height,
|
|
Payload: payload,
|
|
}
|
|
}
|
|
|
|
// NewVote creates a new vote
|
|
func NewVote(blockID ID, voteType VoteType, voter NodeID) *Vote {
|
|
return &Vote{
|
|
BlockID: blockID,
|
|
VoteType: voteType,
|
|
Voter: voter,
|
|
}
|
|
}
|
|
|
|
// QuickStart initializes and starts a consensus engine with default config
|
|
func QuickStart(ctx context.Context) (*Chain, error) {
|
|
cfg := DefaultConfig()
|
|
chain := NewChain(cfg)
|
|
if err := chain.Start(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
return chain, nil
|
|
}
|
|
|
|
// GetConfig returns consensus parameters based on the number of nodes
|
|
func GetConfig(nodeCount int) config.Parameters {
|
|
switch {
|
|
case nodeCount == 1:
|
|
return config.SingleValidatorParams()
|
|
case nodeCount <= 5:
|
|
return config.LocalParams()
|
|
case nodeCount <= 11:
|
|
return config.TestnetParams()
|
|
case nodeCount <= 21:
|
|
return config.MainnetParams()
|
|
default:
|
|
params := config.MainnetParams()
|
|
params.K = nodeCount
|
|
params.AlphaPreference = int(float64(nodeCount) * 0.69)
|
|
params.AlphaConfidence = int(float64(nodeCount) * 0.69)
|
|
params.BetaVirtuous = int(float64(nodeCount) * 0.69)
|
|
params.BetaRogue = nodeCount
|
|
params.Beta = uint32(int(float64(nodeCount) * 0.69))
|
|
return params
|
|
}
|
|
}
|
|
|
|
// Parameter presets for convenience
|
|
var (
|
|
SingleValidatorParams = config.SingleValidatorParams
|
|
LocalParams = config.LocalParams
|
|
TestnetParams = config.TestnetParams
|
|
MainnetParams = config.MainnetParams
|
|
DefaultParams = config.DefaultParams
|
|
XChainParams = config.XChainParams
|
|
)
|