Independent review of luxfi/pulsar v1.0.7 (commit a2a4599) for both
live Lux Quasar consensus and the NIST MPTC v0.1 submission.
Approved with four disclosure / pre-publish gates:
GATE-1 operator runbook discloses v0.1 reconstruction-aggregator trust model
GATE-2 SUBMISSION.md cross-links the protocol-variant disclosure
GATE-3 dudect runs to documented sample target (current results preliminary)
GATE-4 minor doc updates (coverage %, spec text Ed25519 -> ML-DSA-65, etc.)
All gates are about documentation honesty or evidence-file completion;
none require algorithm or code changes. With those closed, the package
is fit to ship.
Construction is sound, identity-stage closure of CR-6/7/8 is uniform
across small and large committee paths, race-clean tests pass, KAT
vectors are deterministic, zeroization is in place, and the proof-
artifact gates (EasyCrypt admit budget 0/0, Lean<->EC bridge 5/5) are
green. Coverage measured at 84.2%.
Port the small-committee (GF(257)) identity stage to the large-
committee (GF(q)) path so the entire library is uniform. After this
work, legacyDeriveMACKeyLarge is gone and the wire-format / sealing
primitives are shared across both paths.
- identity.go: sealEnvelope / sealOpenEnvelope are now width-agnostic
over the inner shareWire slice (64 bytes GF(257), 128 bytes GF(q)).
The envelope key derivation, KEM ciphertext, KMAC256 auth tag and
cSHAKE256 stream cipher are reused as-is.
- large_types.go: drop LargeDKGShareEnvelope (use canonical
DKGShareEnvelope); drop the vestigial Commits field on
LargeDKGRound1Msg (CR-6 path A; binding comes from Round-2 digest).
- large_dkg.go: NewLargeDKGSession takes (myIdentity, directory);
Round1 KEM-wraps envelopes via sealEnvelope; Round3 opens them and
derives the master seed from per-envelope contributions over GF(q)
(no longer needs Lagrange interpolation of other recipients'
envelopes).
- large_threshold.go: NewLargeThresholdSigner takes sessionKeys;
MAC keys are built from per-pair ephemeral session keys (CR-7).
legacyDeriveMACKeyLarge deleted.
- large_reshare.go: NewLargeReshareSession takes
(myIdentity, newDirectory); Round1 KEM-wraps envelopes; Round3
opens them; SetPriorGroupPubkey ported for new-committee joiners.
Tests updated to use the identityFixture pattern; large + small +
identity test suites all green, no race warnings, no KAT drift on
the small path (KAT vectors only fixate FIPS 204 sign/verify; the
wire envelope shape was already KEM-wrapped on the small path post-
merge).
The "m" suffix originally stood for "Pulsar Module-LWE" to distinguish
it from the older Pulsar that was R-LWE (before Corona took over R-LWE
exclusively). With the rename complete — Corona owns Ring-LWE,
Pulsar owns Module-LWE — the suffix is dead naming overhead.
Renames:
Directory: ref/go/pkg/pulsarm/ → ref/go/pkg/pulsar/
Package: package pulsarm → package pulsar
Import: .../ref/go/pkg/pulsarm → .../ref/go/pkg/pulsar
Type: SigSchemePulsarM65 (etc.) → SigSchemePulsar65
Error tag: "pulsarm: ..." → "pulsar: ..."
File: pulsarm_test.go → pulsar_test.go
38 files renamed in-place via git mv. Build + tests PASS (89 PASS
sub-tests, 0 FAIL; full pulsar suite in 0.473s).
Single Verify is the only place this package touches FIPS 204
verification (Class N1 manifesto). VerifyBatch composes it across N
(groupPubkey, message, signature) tuples in parallel via a
GOMAXPROCS-bounded worker pool — no extra FIPS 204 surface.
Public surface added:
- VerifyBatch(params, gpks, msgs, sigs) -> ([]error, error)
- VerifyBatchCtx(params, gpks, msgs, ctx, sigs) -> ([]error, error)
- VerifyBatchAll(params, gpks, msgs, sigs) -> (bool, error)
- ErrBatchSizeMismatch
Pure Go: NO CGO / accel dep. The GPU fast-path
(accel.LatticeOps.DilithiumVerifyBatch) belongs at the engine layer
where the host's native libs are owned; this file is the portable
path everyone gets for free.
Tests (GOWORK=off go test ./pkg/pulsarm/ -run TestVerifyBatch):
TestVerifyBatch_AllValid_MultiMode (ModeP44, P65, P87 × n=8) PASS
TestVerifyBatch_OneCorrupt (single sig byte-flip) PASS
TestVerifyBatch_StructuralMismatch (slice len mismatch) PASS
TestVerifyBatch_Empty PASS
Full suite: ok 0.409s.
Single LICENSING.md file referencing the canonical three-tier IP and
licensing strategy at github.com/luxfi/.github/blob/main/profile/README.md.
LICENSE file is unchanged; this only adds a navigational pointer.
Symmetric with Corona's parallel rename (PULSAR-* -> CORONA-* in
luxfi/corona). The -M was the M-LWE qualifier from when Pulsar-M and
Pulsar-R were sibling constructions; Pulsar-R shipped as Corona, so
the -M qualifier is dead weight across the family.
Changes:
- spec/pulsar.tex: prose + tag strings PULSAR-M-* -> PULSAR-*
- ref/go: all "Pulsar-M" string literals -> "Pulsar" in mode names,
KAT message prefixes, and beacon strings (PULSAR-M-RESHARE-BEACON
-> PULSAR-RESHARE-BEACON, etc.)
- vectors/{sign,keygen,verify,threshold-sign,dkg}.json: regenerated
from genkat with new mode strings
Preserved (different scope):
- Go package directory name `pkg/pulsarm/` (renaming the dir is a
Go module break for any importer; punted to a separate cleanup)
- luxcpp/crypto/pulsar/ path references in comments (separate repo)
All 9 test packages pass: pulsarm (KAT replay, large e2e, reshare,
shamir, types) + the rest.
The 'Pulsar-M' qualifier was meant to distinguish M-LWE Pulsar from a
planned R-LWE 'Pulsar-R'. R-LWE shipped as Corona instead, so the -M
qualifier is dead weight. The pq.tex profile table already says
'Pulsar-65 (was Pulsar-M-65)' — this aligns the spec.
What's preserved (wire format / crypto compat):
- cSHAKE personalisation string 'Pulsar-M' on lines 459/600/720/733/867
- All PULSAR-M-*-V1 domain-separation tags (DKG-COMMIT, SIGN-R1, etc.)
What changed (prose only):
- Title, abstract, body references to the protocol
- Filename pulsar-m.tex -> pulsar.tex
- PDF pulsar-m.pdf -> pulsar.pdf
Pre-existing 'Paragraph ended before end' warning on line 76 is unchanged
and unrelated; PDF still builds (48 pages, 608 KB).
- spec/pulsar-m.tex: define \newcommand{\GF}{\mathrm{GF}} so any later
GF(q)/GF(2^k) usage doesn't trip an undefined control sequence.
- spec/references.bib: rename the Corona bibtex key from corona2024
to boschini2024corona — matches the catalogue-wide Corona->Corona
rename (Corona is the production name).
- go.mod: go directive 1.22.0 -> 1.26.3 (matches the rest of the stack).
Spec citations now use \cite{boschini2024corona}. The family
architecture text describes Corona as Lux's production R-LWE library
(formerly the upstream that the academic R-LWE construction descends
from); the academic line is referenced by author + ePrint number only.
The historical academic R-LWE fork at luxfi/nasua remains unlinked
from this repo's docs per directive.
Pulsar (Module-LWE) and Corona (Ring-LWE) are independently usable
threshold ML-DSA libraries — no shared types, no import line between
them. Each can be selected as a chain's sole PQ threshold layer.
Lux primary-network QuasarCert layers both as a Double-Lattice PQ
defence (Module + Ring), with optional BLS classical fast-path and
per-validator ML-DSA-65 rolled up via STARK/FRI through P3Q. Each
layer is checkable independently; a break in one lattice family does
not break finality.
The academic Corona upstream is referenced as luxfi/nasua (historical
reference fork, trusted-dealer DKG, not for public-chain use).
13 production-go-live blockers from 4-red-agent + 1-scientist
adversarial audit (2026-05). The prior known-limitations framing
was too lenient; canonical bug list now at BLOCKERS.md.
The full per-finding spec (file:line refs, attack models, fix
sketches) lives at the submission mirror:
github.com/luxfi/pulsar-mptc/blob/main/BLOCKERS.md
This pulsar library remains shippable as research/reference (89.7%
coverage, Lean OutputInterchange+Unforgeability+Shamir zero-sorry,
KAT replay green). Production strict-PQ go-live is blocked on
closing CR-1 through CR-13.
The legacy v0.1.0..v0.1.5 tags pointed at the prior Ring-LWE code line
and have been deleted from this repository to prevent
`go get github.com/luxfi/[email protected]` from silently pulling R-LWE
code under the new Module-LWE identity.
Ring-LWE code lives at github.com/luxfi/corona (inherits v0.1.x
history under its proper name). This repository is Module-LWE only,
starting at v1.0.0.
The Module-LWE threshold ML-DSA library claims its canonical name.
The legacy 'pulsar-m' suffix existed only because the Ring-LWE
library held the 'github.com/luxfi/pulsar' import path. That R-LWE
code has now moved to github.com/luxfi/corona; this library is the
sole Pulsar going forward.
NIST MPTC Class N1: byte-equal output to single-party FIPS 204
ML-DSA. Round-1 commit + Round-2 response + Combine produces a
signature that verifies under unmodified mldsa.Verify.
All tests pass under GOWORK=off.
Annulus is the academic-only, research-frozen root. The repo was
originally named Nasua and renamed to Annulus at the archive cut.
Production-enabled variants are Pulsar (M-LWE / FIPS 204) and
Corona (R-LWE production fork), both descending from Annulus.
Hard fork of all customization tags. Per the family rename
(Pulsar-M → Pulsar), the -M suffix is now redundant. Per the
compound-word discipline, LUXROUND braids brand+concept and is
replaced by ROUND.
PULSAR-M-DKG-COMMIT-V1 → PULSAR-DKG-COMMIT-V1
PULSAR-M-DKG-TRANSCRIPT-V1 → PULSAR-DKG-TRANSCRIPT-V1
PULSAR-M-DKG-DEALER-V1 → PULSAR-DKG-DEALER-V1
PULSAR-M-DKG-BLINDMASK-V1 → PULSAR-DKG-BLINDMASK-V1
PULSAR-M-COMMITTEE-V1 → PULSAR-COMMITTEE-V1
PULSAR-M-SIGN-{R1,R2,...}-V1 → PULSAR-SIGN-{R1,R2,...}-V1
PULSAR-M-RESHARE-*-V1 → PULSAR-RESHARE-*-V1
PULSAR-M-EXPANDB-V1 → PULSAR-EXPANDB-V1
PULSAR-M-COMPLAINT-V1 → PULSAR-COMPLAINT-V1
PULSAR-M-SEED-SHARE-V1 → PULSAR-SEED-SHARE-V1
PULSAR-M-LUXROUND-COMMITTEE-V1 → PULSAR-ROUND-COMMITTEE-V1
cSHAKE function-name "Pulsar-M" → "Pulsar"
Every prior signature with -M tags is invalidated. KAT vectors
need regeneration. Test suite passes (85 tests, 0.530s).
Family table now lists three variants under the Lux Quasar family
umbrella:
- Pulsar (Module-LWE / FIPS 204, production-enabled)
- Corona (Ring-LWE, Lux production fork, production-enabled)
- Annulus (Ring-LWE, academic root, code-name Nasua, not enabled)
Annulus is the academic-only research artifact tracking the
Corona upstream primitive (Boschini et al.) which itself builds
on the Raccoon FS-without-rejection template (del Pino et al.).
The implementation repo is github.com/luxfi/nasua.
Naming discipline now stellar/circular: Pulsar (rotating neutron
star), Corona (ring of light), Annulus (ring-shaped region). The
academic upstream's BLAKE3 hash profile is acknowledged but not
deployed; both Corona and Pulsar run on SHA-3 / SP 800-185.
LuxRoundContext / LuxRoundSessionID / LuxRoundCommitteeRoot /
LuxRoundSigShare / LuxRoundQuorumPolicy / DefaultLuxRoundQuorumPolicy
→ RoundContext / RoundSessionID / RoundCommitteeRoot / RoundSigShare /
RoundQuorumPolicy / DefaultRoundQuorumPolicy.
Files: luxround.go luxround_math.go luxround_test.go → round.go
round_test.go (math helpers folded into round.go). The protocol name
"Lux round" stays in prose / spec / paper titles -- only the Go
identifiers drop the brand prefix. The cSHAKE customization tag
PULSAR-M-LUXROUND-COMMITTEE-V1 is wire-format-stable and stays.
Per ~/.claude/CLAUDE.md ("papers/proofs/audits stay in LaTeX, never .md"
+ "NEVER write random summary files"), the six NIST MPTC submission
deliverables move from docs/ Markdown into spec/ LaTeX as
\input{...} chapters of pulsar-m.tex:
docs/nist-mptc-category.md -> spec/nist-mptc-category.tex
docs/patent-notes-draft.md -> spec/patent-notes.tex
docs/threat-model.md -> spec/threat-model.tex
docs/known-limitations.md -> spec/known-limitations.tex
docs/family-architecture.md -> spec/family-architecture.tex
docs/design-decisions.md -> spec/design-decisions.tex
Content preserved verbatim; only LaTeX-syntax stylistic edits.
pulsar-m.tex now \inputs each as its own section / appendix.
Go-source comments that referenced docs/* updated to spec/*.tex.
README + CONTRIBUTING refreshed.
GOWORK=off go test -count=1 ./... clean.
CRIT-2: the Class N1 manifesto claim that a Pulsar threshold
Combine output verifies as a single-party FIPS 204 ML-DSA
signature under the EVM precompile ctx
(`lux-evm-precompile-pulsar-v1`) had no end-to-end test. Every
prior Combine call site passed ctx=nil, so the ctx-propagation
guarantee Combine -> mldsaSign -> circl SignTo was never
exercised against the production precompile string.
New test file precompile_e2e_test.go covers both Combine paths:
- TestPrecompile_E2E_Combine_FIPS204_VerifyCtx exercises the
GF(257) path at (T,N)=(3,2) for ModeP65.
- TestPrecompile_E2E_LargeCombine_FIPS204_VerifyCtx exercises
the GF(q) path at (T,N)=(3,2) for ModeP65.
Each test:
1. Runs DKG to install a group public key.
2. Drives ThresholdSigner / LargeThresholdSigner Round1+Round2
on a message M.
3. Calls Combine / LargeCombine with ctx=precompileCtx,
randomized=false to produce the threshold signature.
4. Asserts that BOTH
(a) raw FIPS 204 cloudflare/circl mldsa65.Verify(pk, M,
ctx=precompileCtx, sig), and
(b) pulsarm.VerifyCtx(params, pk, M, ctx=precompileCtx,
sig)
accept the signature. This is the empirical Class N1
closure for the precompile ctx.
5. Negative control: the same signature must NOT verify under
ctx=nil, proving ctx is actually load-bearing in the
Combine output.
No ctx-propagation fix was required: threshold.go Combine and
large_threshold.go LargeCombine already forward ctx to
mldsaSign, which forwards to mldsa{44,65,87}.SignTo. The tests
verify this end-to-end.
Final v0.1 polish:
bench_test.go — reproducible benchmark harness covering KeyGen,
Sign, Verify across all three FIPS 204 parameter
sets, plus DKG, ThresholdSign, and Reshare at
representative committee sizes for ML-DSA-65.
The benchmark harness drives scripts/bench.sh; results land in
bench/results/{fingerprint.txt,go-bench.txt}. Apple M1 Max baseline
(Go 1.26.2, -benchtime=2s -count=3):
KeyGen P44 ~ 0.3 ms, P65 ~ 0.5 ms, P87 ~ 0.7 ms
Sign P44 ~ 1.6 ms, P65 ~ 2.5 ms, P87 ~ 3.0 ms
Verify P44 ~ 0.3 ms, P65 ~ 0.5 ms, P87 ~ 0.7 ms
DKG (5,3) ~ 3.5 ms, (7,4) ~ 7 ms, (10,7) ~ 12 ms
Threshold (5,3) ~ 2.2 ms, (7,4) ~ 4.5 ms, (10,7) ~ 7 ms
Reshare (5→5,t=3) ~ 0.5 ms
The threshold path is dominated by FIPS 204 Sign latency for small
quorums; at (n=10, t=7) the 2-round overhead becomes comparable to
the FIPS 204 cost.
This commit closes the v0.1 reference impl gates:
- scripts/build.sh passes
- scripts/test.sh passes (61 tests, race-clean)
- scripts/gen_vectors.sh passes; KATs deterministic
- scripts/bench.sh passes
- Class N1 interchangeability demonstrated by every threshold KAT
in vectors/threshold-sign.json passing under pulsarm.Verify
(i.e. under unmodified mldsa{44,65,87}.Verify)
docs/known-limitations.md updated to reflect v0.1 reality: the
reconstruction-aggregator path ships in v0.1; the Lagrange-linearity
sign and R_q^k Pedersen are documented v0.2 paths.
Signed-off-by: Lux Industries <[email protected]>
HJKY97-style proactive resharing: rotate the share distribution from
an old committee to a new committee without changing the master
public key and without reconstructing the master secret in any
party's memory. Implements the spec/pulsar-m.tex §4.4 protocol with
the DD-006 mitigation (beacon-randomized quorum).
Three rounds, structurally similar to DKG except dealer contributions
have constant term λ_i^Q · share_i (pre-multiplied Lagrange
coefficient over the OLD quorum, computed in GF(257)). By Lagrange
linearity, the sum of dealer polynomials evaluated at X=0 IS the
master byte-sum — guaranteeing pk invariance (Theorem reshare-pkinv).
Beacon-randomized quorum selection: the old-committee quorum is the
first t_old members under the cSHAKE256(beacon || NodeID) permutation.
This blocks the mobile-adversary corruption-set positioning that
deterministic smallest-ID selection allows (HIP-0077 finding F10).
Tests:
- SameCommittee_PubInvariant: a reshare with the same committee on
both sides produces new shares that recover the SAME master
public key via the canonical cSHAKE256 mix
- NewCommittee: a one-member-rotation reshare produces shares for
the new committee members
- BeaconPermutation: different beacons produce different quorums;
no-beacon falls back to canonical order
- LagrangeAtZero: numerical correctness of the GF(257) Lagrange
coefficients (sum to 1 mod p, individual values match algebra)
- RejectInvalidCommittees: empty / threshold-too-large rejection
Signed-off-by: Lux Industries <[email protected]>
Two-round threshold signing producing FIPS 204 ML-DSA signatures
byte-equal to what a single-party FIPS 204 signer would emit. This
is the Class N1 (signing) deliverable.
Protocol shape (v0.1 reconstruction-aggregator instantiation):
Round 1 (party i): sample per-round mask r_i ← {0,1}^512.
Compute masked share s'_i = share_i ⊕ r_i. Commit
D_i = cSHAKE256(r_i || s'_i || tau_1)
where tau_1 = (sid, kappa, T, i, pk, mu). Note: binding BOTH
halves under D_i closes the masked-half-rotation gap a v0.1
audit would otherwise expose.
MAC D_i to every peer j ∈ T\{i} under the long-lived MAC key
K_{i,j} via KMAC256 (PULSAR-M-SIGN-R1-MAC-V1). Broadcast
(D_i, {MAC_{i,j}}).
Round 2 (party i): verify every received MAC in constant time
against the locally-known K_{i,j}. On MAC mismatch, emit
ComplaintMACFailure. On success, reveal (r_i, s'_i) so peers
can re-derive D_i and combine.
Combine: aggregator gathers t Round-2 reveals, re-derives each
D_i = cSHAKE256(mask || masked || tau_1) and checks it equals
the Round-1 commit. Lagrange-interpolates the byte-sum at x=0
in GF(257), reduces it via the same cSHAKE256 mix the DKG
used, calls mldsa.SignTo on the recovered seed. Returns the
FIPS 204 signature.
The resulting signature satisfies pulsarm.Verify (which is FIPS 204
ML-DSA.Verify verbatim). The v0.2 path replaces the
reconstruction-aggregator step with the Lagrange-linearity sign of
spec/pulsar-m.tex §4.2, where the master secret is never
reconstructed in any party's memory; output bytes are identical.
Tests (vs. n,t ∈ {(5,3),(7,4),(10,7)}):
- RoundTrip: threshold-produced sig passes FIPS 204 Verify
- BadMAC: tampered Round-1 MAC triggers ComplaintMACFailure
- DifferentAttempt: kappa mismatch rejected at Round 2
- TamperedReveal: any byte-flip in Round-2 reveal caught at
Combine via commit-mismatch (both mask and masked are bound)
- DifferentQuorum_SameMessage: two disjoint quorums both produce
valid FIPS 204 sigs on the same message under the same pk
- QuorumTooSmall: empty / non-member rejection
Signed-off-by: Lux Industries <[email protected]>
Three-round Pedersen DKG over R_q with byte-wise Shamir share
distribution. Produces a FIPS 204-shaped group public key + a
per-party KeyShare; identifies the misbehaving party with a signed
AbortEvidence on detected deviation.
Protocol (matching spec/pulsar-m.tex §4.1):
Round 1: each party samples a 32-byte contribution c_i, broadcasts
an RO-binding cSHAKE256 commit C_i = cSHAKE256(c_i ||
blind_i) under the PULSAR-M-DKG-COMMIT-V1 customisation
tag, and Shamir-shares c_i byte-wise to the committee.
Round 2: each party broadcasts the digest of the Round-1 messages
it received from every dealer. The Round-1.5 equivocation
gate: cross-recipient digest mismatch produces a signed
ComplaintEquivocation with the offending party's NodeID.
Round 3: each party verifies digest agreement (constant-time over
48 bytes) and aggregates its share by summing per-byte
envelope shares in GF(257). The master public key is
derived by Lagrange-reconstructing the byte-sum from the
first t committee positions and feeding the cSHAKE256-
mixed result to FIPS 204 KeyFromSeed.
The output transcript hash is the 48-byte binding the chain pins to
the validator-set commitment. The KeyShare wire is parameter-set-
independent (64 bytes per share).
Identifiable abort (abort.go):
ComplaintEquivocation — distinct commits to distinct recipients
ComplaintBadDelivery — envelope fails recipient-side check
ComplaintMACFailure — Round-1 / Round-2 MAC mismatch
ComplaintRangeFailure — out-of-bounds aggregator contribution
The complaint wire format is forward-stable; new kinds append.
Tests:
- HappyPath sweep (n,t) ∈ {(3,2),(5,3),(7,4),(10,7)} — every
party arrives at the same group public key and the same
transcript hash
- Equivocation detection (tampered Round-2 digest produces a
ComplaintEquivocation with the correct accused party)
- ProducesValidPubkey_VerifiableSign: end-to-end demonstration
that the DKG output recovers a FIPS 204-verifiable signing key
- Committee duplicate / empty / non-member rejection
- AbortEvidence wire-format round-trip, self-accusation rejection,
transcript stability, and ComplaintKind string formatting
Signed-off-by: Lux Industries <[email protected]>
Foundation primitive for the threshold layer. Shamir-shares a
32-byte secret as 32 independent GF(257) instances, one per byte.
Each party's share is a 32 × uint16 wire blob (64 bytes total),
parameter-set-independent.
Why GF(257): 257 is the smallest prime > 255 so it admits every byte
value as a distinct field element. Per-byte sharing keeps the share
wire size minimal and audit-friendly. The DKG and Reshare layers
build directly on this; the cSHAKE256 final-mix step (in
DKG.reconstructByteSum and Combine) flattens any mod-256 vs. mod-257
byte-pattern bias before the resulting 32-byte seed is fed to FIPS
204 KeyFromSeed.
The GF(257) variant shamirDealRandomGF / shamirReconstructGF
preserves the 256-th element so HJKY97-style reshare can rotate
shares without changing the master public key.
Tests:
- DealAndReconstruct (5 quorum sizes)
- All-zero and all-0xff edge secrets
- Duplicate / zero / out-of-range eval-point rejection
- Bad threshold and oversize committee rejection
- shareToBytes / shareFromBytes wire round-trip
- modInvSmall correctness over the full GF(257) range
- EvalPointFromID non-zero guarantee
Signed-off-by: Lux Industries <[email protected]>
Initial commit. Holds the technical specification (LaTeX), the design
docs, the build/test/bench scripts, the package layout, and the empty
ref/go/pkg/pulsarm skeleton.
The spec at spec/pulsar-m.tex (11,300 words of LaTeX) is the canonical
description of the protocol. docs/nist-mptc-category.md states the
Class N1 + N4 claim. CONTRIBUTING.md and SECURITY.md pin the IP and
disclosure posture.
Subsequent commits land the reference implementation in stages.
Signed-off-by: Lux Industries <[email protected]>