Files
zeekay cdfb27641d threshold: Pulsar/Lens kernel adapters + corona KAT + Pulsar-SHA3 wiring
Squashed batch covering:

- protocols/pulsar/: lattice threshold lane (round-based wrapper for
  github.com/luxfi/pulsar kernel); doc.go documents Photon/Lumen/Beam/
  Pulsar/Pulse/Prism/Horizon/Quasar vocabulary stack from LP-105
- protocols/lens/: planned curve threshold sister kernel (design
  intent only; mirrors Pulsar shape; replaces stub LSS-FROST)

- protocols/lss/lss_pulsar.go + tests: LSS-Pulsar adapter
  (DynamicResharePulsar + PulsarSnapshotManager + BuildActivationTranscript).
  Now SHA3-suite-aware: PulsarConfig carries NebulaRoot, HashSuiteID,
  ImplementationVersion as optional transcript-binding fields that
  flow through to the activation message.

  10/10 acceptance tests pass:
    1. GroupKey preservation
    2. KeyEraID preservation
    3. Generation +1
    4. RollbackFrom=0 on forward
    5. t_old != t_new
    6. Disjoint set rotation
    7. Valid signature under unchanged GroupKey
    8. Pairwise material regenerated
    9. Rollback semantics
   10. Error surface
  Plus 1 new test for BuildActivationTranscript Nebula+suite fields.

- protocols/lss/lss_frost.go: marked DEPRECATED (placeholder Sign()/
  Refresh(), single-process simulation, hardcoded ChainKey/RID); will
  be replaced by lss_lens.go.

- corona KAT cross-oracle vs Go reference (N=16 deterministic seeds)
- corona+protocol+harness hardening against parallel-run flakes
- lss/adapters: drop NewXRPL/NewCardano panic; ship real XRPL address
  derivation
- corona SignWithConfig API expansion + test fixes
- v1.6.5 changelog
- go.sum h1 hashes for luxfi/log and 4 deps

Architecture (LP-105 / pulsar/DESIGN.md):
  LSS owns lifecycle (Generation, Rollback, snapshots, dealer/
  coordinator role separation). Pulsar owns lattice math (R_q shares,
  lattice Pedersen commits, Sign1/Sign2/Combine, Pulsar-SHA3 hash
  profile). The lss_pulsar adapter wires them. lss_lens (planned) does
  the same for curve math.

go.mod adds local replace github.com/luxfi/pulsar => ../pulsar.
2026-03-03 12:00:00 -08:00

3.8 KiB
Raw Permalink Blame History

mldsa-bench

Benchmarks PQ signing patterns for Lux quasar consensus and the hierarchical quorum architecture of LP-045.

Build

cd github.com/luxfi/threshold
go build ./cmd/mldsa-bench/

Modes

individual

Every validator signs the block hash; verifier verifies all sigs. Baseline — "what it costs if we never aggregate."

committee

Sample k of n validators; those k sign individually. Represents one cluster in the hierarchical design.

hierarchical

n validators partitioned into clusters. Each cluster signs, clusters combine into a root QC. Models LP-045 two-layer aggregation.

Measured on a MacBook M3 (10 cores, arm64)

Individual signing (pre-aggregation baseline)

n Keygen Sign (parallel) Verify (parallel) Per-validator sign Sig total
3 587 µs 1.78 ms 366 µs 592 µs 7.3 kB
5 1.72 ms 2.20 ms 637 µs 439 µs 12.1 kB
10 1.02 ms 1.70 ms 693 µs 170 µs 24.2 kB
100 14.4 ms 8.87 ms 3.57 ms 89 µs 242 kB

Per-validator latency drops as n grows because keygen/sign run in parallel across 10 cores. Raw cost per signature: ~430 µs sign, ~40 µs verify.

Committee (sampled subset signs)

n k Sign Verify Sig size
100 32 3.57 ms 4.14 ms 77 kB
100 64 8.05 ms 6.34 ms 155 kB

Hierarchical (LP-045 two-layer)

n clusters cluster size Sign Verify Sig total
100 4 25 14.7 ms 5.35 ms 242 kB
100 10 10 10.0 ms 5.09 ms 242 kB

ML-DSA-65 (NIST Level III)

n mode Sign Verify Sig size
100 individual 25.1 ms 9.4 ms 331 kB
100 hierarchical (4 clusters) 21.3 ms 22.6 ms 331 kB

Key findings

  1. 100 validators sign in under 10 ms on a single laptop at ML-DSA-44. No threshold math needed at this stage — it's just parallel individual signatures.

  2. Committee sampling (k=32) cuts signing work by 3× vs all-100 signing. This is the LP-045 primary optimization.

  3. Hierarchical aggregation is a workload-shaping tool, not a compute reduction. Total compute is the same; it's parallelizable across cluster aggregators and moves the verification cost off the chain's hot path.

  4. ML-DSA-65 is ~3× slower than ML-DSA-44 on this hardware. Level III at 100 validators is still under 30 ms per block — fine for Quasar finality at any realistic block time.

Light mnemonic

The harness derives 100 deterministic keypairs from a single 32-byte master seed. No interactive keygen, no mainnet wallet material, no network I/O. Reproducible across runs — same seed yields the same validators.

To use a real mnemonic instead (for localnet tests that need persistence), swap the seed source for BIP39 → BIP32 → per-validator child derivation.

Running on localnet

The same harness can drive a real network. Start a localnet with netrunner and the bench calls the validator RPCs for actual block-signing timing:

# Start 3-node localnet
cd $LUX/netrunner
./bin/netrunner start-local --num-nodes=3 --network-id=1337

# (After extending mldsa-bench with a --rpc-endpoints flag)
./mldsa-bench -mode=individual -n=3 -level=44 \
  -rpc-endpoints=http://127.0.0.1:9650,http://127.0.0.1:9652,http://127.0.0.1:9654

The benchmark then issues quasar.signBlock RPCs to the localnet validators instead of running in-process.

Usage

# Minimal
./mldsa-bench -mode=individual -n=10

# Full
./mldsa-bench -mode=hierarchical -n=100 -clusters=4 -level=65 -runs=5