Help us shape the future of Go! Take the 2026 Go Developer Survey

quasar

package
v1.36.185 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: BSD-3-Clause Imports: 5 Imported by: 0

Documentation

Overview

Package quasar is the node-side integration of the luxfi/consensus Quasar post-quantum finality-certificate layer.

luxd finalizes blocks on the classical sampling path (fast, every block). On top, at CHECKPOINTS (epoch boundaries — NOT every block), a sampled committee produces a QuasarCert over the finalized digest and validators VERIFY it. This package wires the VERIFY half: it consumes github.com/luxfi/consensus/protocol/quasar.VerifyConsensusCert as an OPTIONAL, FORWARD-DATED, DORMANT-BY-DEFAULT check in the block-accept path.

Safety contract

The forward-dated dormant activation is the whole reason this package has the shape it does:

  • Pre-activation (the default): VerifyAccepted is a pure no-op. Classical Snow finality is UNCHANGED. A nil *Gate, a zero Gate, or an unset activation height all mean "dormant" — zero behavior change.
  • Post-activation (owner sets Activation.Height to a real, forward-dated height): at every checkpoint height the gate REQUIRES a valid QuasarCert bound to the just-finalized block and FAILS CLOSED — a missing or invalid cert returns an error from Accept(), halting the chain rather than finalizing a checkpoint without post-quantum evidence.

Activation is therefore a deliberate switch the owner flips only AFTER the cert PRODUCER (the per-validator committee signer) is live and certs flow at the checkpoint cadence — otherwise every checkpoint would halt. See producer.go.

Default posture

HYBRID_PQ = Beam(BLS) ∧ Pulsar (standard FIPS-204 threshold ML-DSA), at checkpoint cadence. Per the measured policy-tier benchmarks, Pulsar verify (~140µs) is cheaper than BLS itself and the cert is compact (~27KB) — the right default production finality posture. STRICT_DUAL_PQ (∧ Corona) and the POLARIS tiers (∧ Magnetar) are configurable for stricter mainnet finality.

Index

Constants

View Source
const DefaultCheckpointInterval uint64 = 256

DefaultCheckpointInterval is the default checkpoint cadence in blocks. PQ certs ride epoch-boundary checkpoints, never every block (Magnetar sign is checkpoint-only; even the cheap Pulsar sign is checkpoint cadence). The owner overrides this to match the producer's cadence at activation time.

DefaultMode is the default Quasar posture: HYBRID_PQ (Beam ∧ Pulsar).

Variables

View Source
var (
	// ErrFinalityCertMissing — a checkpoint was finalized post-activation but no
	// QuasarCert is available for it (the producer has not delivered one).
	ErrFinalityCertMissing = errors.New("quasar: finality cert missing for checkpoint")

	// ErrFinalityCertMismatch — a cert exists but does not bind the finalized
	// block (chain/height/block/state mismatch). Anti-replay.
	ErrFinalityCertMismatch = errors.New("quasar: finality cert does not bind the finalized block")

	// ErrFinalityCertInvalid — the cert is bound correctly but failed consensus
	// verification (policy, validator-set root, or a leg signature).
	ErrFinalityCertInvalid = errors.New("quasar: finality cert failed verification")

	// ErrValidatorSetUnavailable — no committed validator set for the cert's
	// epoch (the verifier cannot resolve the per-leg verification keys).
	ErrValidatorSetUnavailable = errors.New("quasar: validator set unavailable for epoch")

	// ErrPolicyUnavailable — the gate has no configured policy.
	ErrPolicyUnavailable = errors.New("quasar: policy unavailable")

	// ErrPolicyMismatch — the cert's PolicyID is not the configured policy. A
	// cert cannot select its own (weaker) posture.
	ErrPolicyMismatch = errors.New("quasar: cert policy id does not match configured policy")

	// ErrGateMisconfigured — the gate is activated at a checkpoint but has no
	// cert store or validator provider. Fail closed rather than panic.
	ErrGateMisconfigured = errors.New("quasar: gate activated but missing store or validator provider")
)

Typed, fail-closed errors. Every one is returned (never swallowed) and, when surfaced from the accept hook post-activation, halts finalization rather than accepting a checkpoint without valid post-quantum evidence.

Functions

This section is empty.

Types

type ActivationConfig added in v1.31.0

type ActivationConfig struct {
	// Height is the block height at and above which PQ-finality verification is
	// enforced at checkpoints. 0 == dormant (never).
	Height uint64
}

ActivationConfig is the forward-dated activation switch.

The zero value is DORMANT: Height == 0 means "never activate" and the gate is a no-op for every block. This mirrors the genesis upgrade discipline (a far-future / unset activation point cannot affect live finality).

Activation is by HEIGHT ONLY, deliberately. A block height is agreed by consensus, so every honest validator enforces PQ finality at exactly the SAME checkpoints — there is no node-local decision. (A wall-clock gate would split finalization across validators with skewed clocks: some halting on a missing cert while others finalize without one. Timestamp-based forward-dating is expressed by choosing the activation HEIGHT at the target time.)

type CertStore added in v1.31.0

type CertStore interface {
	Lookup(chainID uint32, height uint64, blockID [32]byte) (*qcert.ConsensusCert, bool)
}

CertStore resolves the QuasarCert that certifies a finalized block. In production it is filled by the cert gossip/ingest path (the producer follow-on, producer.go); the verify gate only READS from it. Keyed by the finalized position (chainID, height, blockID) so a cert can never be returned for the wrong block.

type Checkpoint added in v1.31.0

type Checkpoint struct {
	Epoch     uint64
	Height    uint64
	Round     uint32
	BlockID   [32]byte
	StateRoot [32]byte
}

Checkpoint is the finalized-block position the accept hook hands the gate. It is the binding the cert must match (anti-replay): a valid cert for a DIFFERENT block must never satisfy THIS checkpoint. The chain id is gate-level config, not a per-block field.

type Config added in v1.22.79

type Config struct {
	// ChainID is THIS chain's numeric identifier (the sovereign/EVM chain id),
	// bound into every cert and checked against it. A per-chain constant sourced
	// from chain config at gate construction — NOT pulled from a block, because
	// the proposervm layer carries the 32-byte validator-set id, not the numeric
	// chain id. Inert while dormant.
	ChainID uint32

	// Activation is the forward-dated dormant switch. Zero => dormant.
	Activation ActivationConfig

	// Mode is the Quasar evidence posture. Zero => DefaultMode (HYBRID_PQ).
	Mode qcert.QuasarEvidenceMode

	// MLDSAParam selects the ML-DSA parameter set for the Pulsar leg. 0 =>
	// ML-DSA-65 (the consensus default).
	MLDSAParam uint8

	// Threshold is the BFT quorum floor (minimum aggregate signer weight) every
	// leg's evidence must establish.
	Threshold uint64

	// CheckpointInterval is the checkpoint cadence in blocks. 0 =>
	// DefaultCheckpointInterval.
	CheckpointInterval uint64
}

Config is the node-surfaced PQ-finality configuration. Its zero value is dormant + HYBRID_PQ + default cadence.

type Gate added in v1.31.0

type Gate struct {
	// contains filtered or unexported fields
}

Gate enforces (or, dormant, ignores) PQ-finality at checkpoints. It is the one node-side connection between the classical accept path and the consensus Quasar verifier.

func NewGate added in v1.31.0

func NewGate(cfg Config, store CertStore, validators ValidatorSetProvider) *Gate

NewGate constructs a Gate. A Gate is meaningful even with a dormant Config: VerifyAccepted is a no-op until Activation.Height is set. store and validators are only consulted post-activation at checkpoints.

func (*Gate) Activated added in v1.31.0

func (g *Gate) Activated(height uint64) bool

Activated reports whether enforcement is live for a block at the given height and the current wall clock. Used by the producer-request site to decide whether a cert is needed at a checkpoint.

func (*Gate) IsCheckpoint added in v1.31.0

func (g *Gate) IsCheckpoint(height uint64) bool

IsCheckpoint reports whether the given height is a checkpoint under the gate's configured cadence. Exported so the producer-request site shares ONE cadence definition with the verify path (no second source of truth).

func (*Gate) MaybeProduce added in v1.31.0

func (g *Gate) MaybeProduce(ctx context.Context, producer Producer, cp Checkpoint) (*qcert.ConsensusCert, error)

MaybeProduce is the checkpoint producer-request site. It is nil-safe and activation-aware so the accept hook can call it unconditionally: a nil gate, dormant activation, a non-checkpoint height, or a nil producer all short- circuit to (nil, nil) — the verify-only default. When a producer IS wired and the checkpoint is live, it requests the cert; the caller gossips/stores it.

This keeps producer cadence and verify cadence on ONE definition (g.IsCheckpoint), so producer and verifier can never disagree on which heights carry certs.

func (*Gate) VerifyAccepted added in v1.31.0

func (g *Gate) VerifyAccepted(cp Checkpoint) error

VerifyAccepted is the accept-path hook and the SAFETY BOUNDARY.

  • g == nil OR dormant activation => returns nil immediately. This is the default and guarantees classical Snow finality is unchanged.
  • height below activation, or activation time not yet reached => nil.
  • not a checkpoint height => nil (certs ride checkpoints only).
  • checkpoint, activated => REQUIRE a valid cert bound to this block; FAIL CLOSED. A missing, mis-bound, or invalid cert is an error (the caller returns it from Accept, halting rather than finalizing without PQ evidence).

It is intentionally nil-safe so the proposervm hook can call vm.quasarGate.VerifyAccepted(...) unconditionally with a nil gate.

type MemCertStore added in v1.31.0

type MemCertStore struct {
	// contains filtered or unexported fields
}

MemCertStore is an in-memory CertStore keyed by (chainID, height, blockID). It is the ingest sink the cert-gossip handler writes into (Put) and the gate reads from (Lookup). Safe for concurrent use.

func NewMemCertStore added in v1.31.0

func NewMemCertStore() *MemCertStore

NewMemCertStore returns an empty in-memory cert store.

func (*MemCertStore) Lookup added in v1.31.0

func (m *MemCertStore) Lookup(chainID uint32, height uint64, blockID [32]byte) (*qcert.ConsensusCert, bool)

Lookup returns the cert for the finalized position, or (nil, false).

func (*MemCertStore) Put added in v1.31.0

func (m *MemCertStore) Put(cert *qcert.ConsensusCert)

Put indexes a cert by its own (ChainID, Height, BlockHash). The ingest path MUST verify a cert before Put (verify-before-store), exactly as the gossip layer verifies before re-gossip; the gate re-verifies at the checkpoint so a store poisoned by an unverified Put still cannot finalize an invalid cert.

type Producer added in v1.31.0

type Producer interface {
	Produce(ctx context.Context, subject Subject) (*qcert.ConsensusCert, error)
}

Producer is the committee cert-signing service contract (the per-validator "pulsard" committee). At a checkpoint, a producing validator calls Produce to obtain the QuasarCert over the finalized subject, then gossips it so peers can verify and store it (via a CertStore).

SCAFFOLDING — this is the seam, not the service. This milestone wires the VERIFY half (gate.go) and this interface. luxd ships with a nil Producer (verify-only): a node VERIFIES certs it receives but does not itself produce them. A nil Producer is the correct default — most of the rollout window is verify-only, and the producer is brought up before activation is forward-dated.

Implementation path for the follow-on:

  • github.com/luxfi/consensus/protocol/quasar already defines the producer-side abstractions: PWitnessProducer / QWitnessProducer / ZWitnessProducer + NewWitnessSet, and ComposeDualPQEvidence. The concrete committee signer implements Producer over those.
  • The signer needs the live Pulsar key share + nonce pool + offline preprocessing + one-round sign + verify-before-gossip + nonce-erase (the no-reconstruct hyperball signer), which lands with pulsar v1.7.1.
  • REQUIRED CONSENSUS EXPORT: the ConsensusCert envelope + per-leg payload ENCODERS are package-private in consensus v1.29.0 (only the verifiers are exported). An external producer — and any end-to-end "valid cert verifies through the gate" test — needs those encoders exported (a small, additive consensus change). The verify path here needs no such export: it consumes a fully-formed *ConsensusCert.

type StaticValidatorSetProvider added in v1.31.0

type StaticValidatorSetProvider struct{ Set qcert.ConsensusValidatorSet }

StaticValidatorSetProvider returns the same committed set for every (chain, epoch). It is the single-era / test provider; the production provider resolves per-epoch sets from the P-Chain validator manager + KeyEra registry.

func (StaticValidatorSetProvider) ValidatorSet added in v1.31.0

ValidatorSet implements ValidatorSetProvider.

type Subject added in v1.31.0

type Subject struct {
	ChainID   uint32
	Epoch     uint64
	Height    uint64
	Round     uint32
	BlockID   [32]byte
	StateRoot [32]byte
}

Subject is the finalized-block position a cert must certify — the producer's input at a checkpoint. Mirrors Checkpoint (the verify side) so producer and verifier bind the SAME tuple.

type ValidatorSet added in v1.31.0

type ValidatorSet struct {
	// contains filtered or unexported fields
}

ValidatorSet is a concrete ConsensusValidatorSet for one epoch: the committed weighted-validator-set root plus the per-leg verification keys the cert legs verify against (the classical BLS aggregate key for the Beam leg and the Pulsar ML-DSA threshold group key for the Pulsar leg — the HYBRID_PQ pair).

Production wiring (the activation seam): in production these fields are populated from the P-Chain-pinned validator set (Root, Epoch) and the active KeyEra group keys for the epoch. That population is era/rotation-coupled and lands with the producer + KeyEra-registry wiring (see producer.go). Corona (STRICT_DUAL_PQ) and Magnetar/P3Q (POLARIS / RECOVERY) group keys + the weighted-sig-set config are populated by that same follow-on; until then this set serves the HYBRID_PQ pair and reports "no key" for the other lanes.

func NewValidatorSet added in v1.31.0

func NewValidatorSet(root [48]byte, epoch uint64, blsAggKey, pulsarGroup []byte) *ValidatorSet

NewValidatorSet builds a committed validator set for one epoch from its root and the HYBRID_PQ verification keys.

func (*ValidatorSet) ClassicalAggregateKey added in v1.31.0

func (v *ValidatorSet) ClassicalAggregateKey(scheme qcert.ClassicalScheme) ([]byte, bool)

ClassicalAggregateKey returns the classical aggregate verification key for a scheme. Serves the BLS-12-381 Beam leg.

func (*ValidatorSet) Epoch added in v1.31.0

func (v *ValidatorSet) Epoch() uint64

Epoch returns the epoch this set was committed under.

func (*ValidatorSet) Root added in v1.31.0

func (v *ValidatorSet) Root() [48]byte

Root returns the 48-byte weighted-validator-set commitment.

func (*ValidatorSet) ThresholdGroupKey added in v1.31.0

func (v *ValidatorSet) ThresholdGroupKey(kind qcert.LegKind) (qcert.ThresholdGroupKey, bool)

ThresholdGroupKey returns the threshold-signature group public key for a leg kind. Serves the Pulsar (ML-DSA) lane; reports (zero, false) for the others until their group keys are wired by the follow-on.

func (*ValidatorSet) WeightedConfig added in v1.31.0

func (v *ValidatorSet) WeightedConfig() qcert.QuorumVerifierConfig

WeightedConfig returns the QuorumVerifierConfig for the WeightedSigSet evidence mode. HYBRID_PQ does not use weighted-sig-set legs; the zero config is correct here and is populated by the POLARIS / RECOVERY follow-on.

func (*ValidatorSet) WeightedEnvelope added in v1.31.0

func (v *ValidatorSet) WeightedEnvelope() qcert.QuorumMessageEnvelope

WeightedEnvelope returns the round-digest posture axes for the inner WeightedQuorumCert. Zero for HYBRID_PQ (no weighted-sig-set leg); populated by the POLARIS / RECOVERY follow-on.

type ValidatorSetProvider added in v1.31.0

type ValidatorSetProvider interface {
	ValidatorSet(chainID uint32, epoch uint64) (qcert.ConsensusValidatorSet, error)
}

ValidatorSetProvider resolves the committed validator set the verifier pins a cert against, for a (chain, epoch). Post-activation the gate calls this once per verified checkpoint.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL