Files
consensus/consensus.go
T
zeekay ca541515d8 consensus: wire luxfi/bft as fourth engine factory
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.
2026-05-11 20:28:46 -07:00

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
)