Files
zeekay 44f20309b9 FROST(Ed25519, SHA-512) — signatures Solana and TON will accept
The generic FROST challenge is BLAKE3 over big-endian scalars. RFC 8032 needs
SHA-512(R || A || M) reduced mod L with S encoded little-endian, so a threshold
signature over curve.Ed25519 was rejected by every real verifier — which is why
mpcd returned an empty eddsa_pub_key and SOL and TON had no signable key.

This follows the shape already used twice here: taproot and sr25519 each carry a
scheme through round1 -> round3, and Ed25519 is a third. StartSignCommon and
StartSignSR25519Common keep their exact signatures and both forward to an
unexported startSign, so those two paths are behaviourally untouched.

Only the SCALAR needed reversing. Ed25519Point.MarshalBinary was already the
canonical compressed Edwards encoding; Ed25519Scalar.MarshalBinary is big-endian
and is flipped at the signature boundary alone.

Verification delegates to crypto/ed25519 rather than reimplementing the equation.
An in-house verifier only ever proves we agree with ourselves — exactly how a
scheme that is not really Ed25519 passes its own tests. Round 3 gates on it, so a
signature can only leave the protocol if the verifier Solana runs accepts it.

Validated against all four RFC 8032 §7.1 vectors, each first re-derived with
ed25519.Sign so a transcription typo fails loudly instead of silently weakening
the suite; the production ed25519Challenge has ONE implementation and both round
2 and the vector test call it.

SECURITY, and it is the reason to take this seriously: keygen now rejects
non-prime-order points at Ed25519Point.UnmarshalBinary. The zksch proof on a
polynomial's constant term does NOT exclude torsion — z*G = C + e*phi can be
satisfied with torsion in phi by grinding C, since only e mod 8 matters, ~8
attempts. The payoff is not forgery, it is a BRICK: the group key carries
torsion, the address base58-encodes normally and accepts deposits, and no quorum
can ever sign, because z*G is always torsion-free. Unmarshal is the single wire
entry point (cbor decodes coefficients through BinaryUnmarshaler), and the test
splices an order-2 point into a real serialized commitment to prove it lands
there. Ed25519-specific: secp256k1 has cofactor 1 and Ristretto255 has no
torsion by construction.

Go's verifier is cofactorless and does not torsion-check A; ed25519-dalek's
verify_strict, which Solana runs, does. FROST satisfies both — R, A and [S]B are
all torsion-free.

115 frost tests green.
2026-08-06 12:37:02 -07:00
..

FROST — Lux-Profile Threshold Schnorr

Tier B — Lux-profile + integration spec gap. Production implementation of FROST (Flexible Round-Optimized Schnorr Threshold) for the Lux ecosystem. Lux-profile submission package being assembled in this directory; readiness gated per SUBMISSION-STATUS.md.

What this is

FROST is a 2-round threshold-Schnorr signature scheme. Threshold-t of n parties produce a signature that verifies under the single-party Schnorr verifier for the configured ciphersuite. Used in the Lux ecosystem for:

  • Cross-chain bridge custody (Cosmos Ed25519, Bitcoin Schnorr / Taproot)
  • Account-abstracted multi-party wallets
  • Validator-set threshold operations on non-PQ chains

Code location

Subdir Content
frost.go top-level orchestration
keygen/ distributed key generation
sign/ 2-round threshold signing
frost_*_test.go unit, math, suite, threshold, sr25519, fixed tests
frost_benchmark_test.go benchmarks
scale_benchmark_test.go committee-size scaling

Total: 20+ Go files, mature codebase.

Ciphersuites

The Lux profile pins two ciphersuites:

Ciphersuite LP Use case
FROST(Ed25519, SHA-512) LP-4711 Cosmos / Solana / SR25519 chains
FROST(secp256k1, SHA-256, Taproot) LP-4712 Bitcoin Schnorr / Taproot

See PARAMS.md for parameter-set details and threshold ranges.

Tier label

Tier B — Lux-profile + integration spec gap. Upstream IETF/CFRG draft (draft-irtf-cfrg-frost) is the construction; Lux adds the profile pinning + Lux-specific KAT manifest + integration with the threshold orchestration layer (internal/round, internal/party, pkg/protocol) and the LSS dynamic-resharing wrapper (lss/lss_frost.go).

Compare to siblings:

  • luxfi/pulsar — Tier A (mechanized refinement vs FIPS 204)
  • luxfi/corona — Tier B (no FIPS anchor, honest no-proof disclosure)
  • protocols/frost (this) — Tier B (upstream IETF draft is construction, Lux profile gap)
  • protocols/cmp — Tier B
  • protocols/bls — Tier B

Dependencies

Dep Role
luxfi/crypto/curve25519 (Ed25519 path) underlying Ed25519 primitive
luxfi/crypto/secp256k1 (Taproot path) underlying secp256k1 + Schnorr primitive
luxfi/threshold/internal/round round-state machine
luxfi/threshold/internal/party party-id ordering, validation
luxfi/threshold/internal/hash domain-separated hashing per ciphersuite
luxfi/threshold/pkg/protocol protocol type system

Consumed by

  • luxfi/threshold/protocols/lss/lss_frost.go — LSS-FROST adapter (dynamic resharing)
  • luxfi/mpc/ — production custody service
  • luxfi/threshold/cmd/threshold-cli/ — CLI

Cross-references

  • SPEC.md — construction spec + Lux profile
  • SUBMISSION-STATUS.md — Tier B → A gating items
  • PROOF-CLAIMS.md — honest scope (what's proved, what's not)
  • TEST-VECTORS.md — KAT format + upstream CFRG vectors
  • SECURITY.md — threat model + responsible disclosure
  • PARAMS.md — ciphersuite + threshold range registry
  • LP-4710 — FROST precompile
  • LP-4711 — Ed25519 ciphersuite
  • LP-4712 — secp256k1 Taproot
  • LP-4700 — threshold-MPC family umbrella