lux-consensus 1.22.7

Lux Consensus SDK — pure-Rust Quasar post-quantum probabilistic consensus (Wave / FPC / Photon / Focus / Quasar PQ finality via hybrid BLS12-381 + Pulsar = P3Q)
Documentation
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.

//! Who gets asked, and how hard the answer has to be.
//!
//! Two numbers decide a round before any vote is cast: the peers sampled, and
//! the threshold their answers are read against. Both are derived rather than
//! configured at the point of use, and both have a range they must stay inside —
//! a brightness that ran away would let one peer own the sample, and a θ outside
//! its band would make every round either unanimous or free.

use lux_consensus::{FpcSelector, Luminance, NodeID, PhotonSampler, QuasarConfig};

fn peer(n: u8) -> NodeID {
    NodeID([n; 20])
}

// -------------------------------------------------------------- the threshold band

/// A θ range outside (0,1) is replaced by the standard band, not accepted.
///
/// The bound matters because θ is the fraction of a committee that has to agree:
/// θ = 0 makes every round a quorum and θ = 1 demands unanimity from a sample
/// that is allowed to miss peers. A selector built from a mis-parsed config must
/// land on the standard band rather than on whichever of those two the bad value
/// happened to be.
#[test]
fn a_theta_outside_the_band_falls_back_to_the_standard_one() {
    let seed = [0u8; 32];
    let standard = (0.5, 0.8);

    for bad_min in [0.0, 1.0, -1.0, 2.0] {
        assert_eq!(
            FpcSelector::new(bad_min, 0.8, seed).range(),
            standard,
            "theta_min = {bad_min} was taken as given"
        );
    }

    // A maximum that is not above the minimum is not a band at all.
    for bad_max in [0.5, 0.4, 0.0, 1.5] {
        assert_eq!(
            FpcSelector::new(0.5, bad_max, seed).range(),
            standard,
            "theta_max = {bad_max} was taken as given"
        );
    }

    // A band inside the bounds is kept, so the fallback is a repair and not a
    // policy that overrides the operator.
    assert_eq!(FpcSelector::new(0.6, 0.9, seed).range(), (0.6, 0.9));
}

/// Every θ the selector draws lands inside its own band, at every phase. The
/// threshold is `ceil(θ·k)`, so a θ that escaped the band would put the quorum
/// above k — unreachable — or at zero, where no votes are a quorum.
#[test]
fn every_drawn_threshold_stays_inside_the_band_and_the_committee() {
    let selector = FpcSelector::default();
    let (lo, hi) = selector.range();
    let k = 21;

    for phase in 0..64u64 {
        let theta = selector.theta(phase);
        assert!(
            theta >= lo && theta <= hi,
            "phase {phase} drew theta {theta}, outside [{lo}, {hi}]"
        );

        let alpha = selector.select_threshold(phase, k);
        assert!(
            alpha >= 1 && alpha <= k,
            "phase {phase} asked for {alpha} of {k}"
        );
        assert!(
            alpha > k / 2,
            "phase {phase} asked for {alpha} of {k}, which is not a majority"
        );
    }
}

// -------------------------------------------------------------------- brightness

/// Brightness is clamped at both ends, and the clamp is what keeps sampling
/// weight bounded: the multipliers compound, so an unclamped run of successes
/// grows without limit until one peer owns every sample, and an unclamped run of
/// failures decays to zero, where a peer can never be picked again and can never
/// recover. Both are permanent, and both are one long run away.
#[test]
fn brightness_is_clamped_at_both_ends() {
    let config = QuasarConfig::default();
    let mut lux = Luminance::new(&config);
    let node = peer(1);

    for _ in 0..500 {
        lux.illuminate(&node, true);
    }
    assert_eq!(
        lux.lux(&node),
        config.max_luminance,
        "a long run of successes escaped the cap"
    );

    for _ in 0..500 {
        lux.illuminate(&node, false);
    }
    assert_eq!(
        lux.lux(&node),
        config.min_luminance,
        "a long run of failures dimmed past the floor"
    );

    // The floor is above zero, so a peer that has failed everything is still
    // sampleable and can climb back.
    assert!(config.min_luminance > 0.0);
    lux.illuminate(&node, true);
    assert!(
        lux.lux(&node) > config.min_luminance,
        "a peer at the floor could not recover"
    );
}

/// An unseen peer reads at the base rather than at zero, so a validator that has
/// not been sampled yet is not thereby unsampleable. Brightness is the ratio to
/// that base, which is what makes it comparable across configs.
#[test]
fn an_unseen_peer_reads_at_the_base() {
    let config = QuasarConfig::default();
    let mut lux = Luminance::new(&config);

    assert_eq!(lux.lux(&peer(1)), config.base_luminance);
    assert_eq!(lux.brightness(&peer(1)), 1.0);
    assert_eq!(lux.node_count(), 0, "asking about a peer tracked it");
    assert_eq!(lux.total_luminance(), 0.0);

    lux.illuminate(&peer(1), true);
    assert_eq!(lux.node_count(), 1);
    assert!(lux.brightness(&peer(1)) > 1.0);
    assert_eq!(lux.total_luminance(), lux.lux(&peer(1)));
}

/// The default tracker is the one the default config describes. The two used to
/// be written out separately, which is how a tracker ended up with a floor its
/// config did not have — the same drift the config presets are stated as diffs
/// to avoid.
#[test]
fn the_default_tracker_reads_the_default_config() {
    let config = QuasarConfig::default();
    let mut from_default = Luminance::default();
    let mut from_config = Luminance::new(&config);
    let node = peer(1);

    for step in 0..40 {
        let success = step % 3 != 0;
        from_default.illuminate(&node, success);
        from_config.illuminate(&node, success);
        assert_eq!(
            from_default.lux(&node),
            from_config.lux(&node),
            "the default tracker and the default config disagree after {step} rounds"
        );
    }
}

// ---------------------------------------------------------------------- sampling

/// A sample is distinct peers, and never more of them than there are. Asking for
/// more than the whole set returns the whole set once — a sampler that padded to
/// k by repeating would count one validator several times toward a quorum.
#[test]
fn a_sample_is_distinct_and_never_larger_than_the_set() {
    let config = QuasarConfig::default();
    let peers: Vec<NodeID> = (1..=5).map(peer).collect();
    let sampler = PhotonSampler::new(peers.clone(), &config);

    for k in 0..=8 {
        let drawn = sampler.sample(k);
        assert_eq!(
            drawn.len(),
            k.min(peers.len()),
            "asking for {k} of {} returned {}",
            peers.len(),
            drawn.len()
        );

        let mut distinct = drawn.clone();
        distinct.sort();
        distinct.dedup();
        assert_eq!(distinct.len(), drawn.len(), "a peer was sampled twice at k={k}");

        for d in &drawn {
            assert!(peers.contains(d), "a peer nobody registered was sampled");
        }
    }
}

/// An empty set samples nobody. A sampler that returned a placeholder here would
/// hand a round a committee of one imaginary peer.
#[test]
fn an_empty_set_samples_nobody() {
    let sampler = PhotonSampler::new(Vec::new(), &QuasarConfig::default());
    assert!(sampler.sample(5).is_empty());
}

/// Sampling is deterministic: the same peers in the same state draw the same
/// committee. Every node runs this selection independently, so a sampler that
/// consulted a hash map's iteration order or a clock would give two honest nodes
/// different committees for one round.
#[test]
fn the_same_state_draws_the_same_committee() {
    let config = QuasarConfig::default();
    let peers: Vec<NodeID> = (1..=7).map(peer).collect();
    let mut sampler = PhotonSampler::new(peers, &config);

    sampler.update_luminance(&peer(3), true);
    sampler.update_luminance(&peer(5), false);

    let first = sampler.sample(4);
    for _ in 0..8 {
        assert_eq!(sampler.sample(4), first, "two draws from one state disagreed");
    }
}

/// A peer joins once and leaves completely. A duplicate entry would be a second
/// seat in every sample it appears in, which is the same fault a duplicate
/// registration is, one layer up.
#[test]
fn a_peer_joins_once_and_leaves_completely() {
    let config = QuasarConfig::default();
    let mut sampler = PhotonSampler::new(vec![peer(1)], &config);

    sampler.add_peer(peer(2));
    sampler.add_peer(peer(2));
    assert_eq!(sampler.sample(9).len(), 2, "a peer was added twice");

    sampler.remove_peer(&peer(1));
    let remaining = sampler.sample(9);
    assert_eq!(remaining, vec![peer(2)]);

    // Removing a peer that was never there is not a change.
    sampler.remove_peer(&peer(200));
    assert_eq!(sampler.sample(9), remaining);
}

/// The sampler's own tracker is what its weights are read from, so an update
/// through the sampler is visible in the tracker it hands back. Two trackers
/// would mean the weights that select a committee and the weights an operator
/// inspects were different numbers.
#[test]
fn the_sampler_updates_the_tracker_it_reports() {
    let config = QuasarConfig::default();
    let mut sampler = PhotonSampler::new(vec![peer(1), peer(2)], &config);

    sampler.update_luminance(&peer(1), true);

    assert!(
        sampler.luminance().brightness(&peer(1)) > 1.0,
        "an update through the sampler did not reach its tracker"
    );
    assert_eq!(sampler.luminance().brightness(&peer(2)), 1.0);
}

/// When every weight has collapsed to zero the sampler still returns a
/// committee. Weighted selection has nothing to weigh here — the scores are all
/// zero and the choice between them is arbitrary — and the alternative to
/// falling back is returning no peers, which stalls the round forever. A
/// liveness floor, not a preference.
///
/// It is reachable only from a configuration that permits total darkness: a
/// floor of zero and a failure multiplier that reaches it. The default config
/// cannot get here, which is why the floor is above zero there.
#[test]
fn a_committee_is_still_drawn_when_every_weight_has_collapsed() {
    let dark = QuasarConfig {
        base_luminance: 100.0,
        min_luminance: 0.0,
        failure_multiplier: 0.0,
        ..QuasarConfig::default()
    };
    let peers: Vec<NodeID> = (1..=5).map(peer).collect();
    let mut sampler = PhotonSampler::new(peers.clone(), &dark);

    for p in &peers {
        sampler.update_luminance(p, false);
        assert_eq!(sampler.luminance().brightness(p), 0.0);
    }

    let drawn = sampler.sample(3);
    assert_eq!(drawn.len(), 3, "a fully dimmed set sampled nobody");
    let mut distinct = drawn.clone();
    distinct.sort();
    distinct.dedup();
    assert_eq!(distinct.len(), 3, "the fallback repeated a peer");
    for d in &drawn {
        assert!(peers.contains(d));
    }
}