mirror of
https://github.com/luxfi/lens.git
synced 2026-10-30 16:21:16 +00:00
Lens is the curve-based threshold signing kernel for Lux. It is the classical analogue of Pulsar (the lattice kernel at github.com/luxfi/pulsar). Both kernels share the same lifecycle shape — Bootstrap → Reshare* → Reanchor — and the same activation circuit-breaker contract. They differ only in the math field: Pulsar over R_q (Module-LWE), Lens over a prime-order curve group (discrete log). Curves shipped: Ed25519, secp256k1, Ristretto255. Each has a deterministically-derived secondary Pedersen generator H from a Lens-specific nothing-up-my-sleeve tag. Sign math: FROST 2-round Schnorr threshold signing per RFC 9591 (Komlo-Goldberg 2020). Verifier checks z·G ?= R + c·X under the unchanged group public key. Reshare math: HJKY97 zero-poly Refresh + Desmedt-Jajodia ReshareToNewSet over the curve scalar field. Master secret s is preserved; only the share distribution rotates per epoch. Activation cert message format: QUASAR-LENS-ACTIVATE-v1, byte-equivalent shape to QUASAR-PULSAR-ACTIVATE-v1. Hash suite: HashSuite interface with Lens-SHA3 (production, cSHAKE256 / KMAC256 / TupleHash256) and Lens-BLAKE3 (legacy) profiles. DKG: distributed FROST DKG with Feldman commitments. No trusted dealer required at genesis if the chain prefers proper distributed DKG. KAT oracles: cmd/reshare_oracle and cmd/dkg_oracle emit deterministic JSON vectors for cross-language byte-equality validation against a future luxcpp/crypto/lens/ port. Tests: full unit + integration coverage on every shipped curve. 60 unique tests, 0 failures.
88 lines
3.0 KiB
Bash
Executable File
88 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# regen-kats.sh — deterministic regeneration + verification of every
|
||
# Lens KAT consumed by cross-language ports.
|
||
#
|
||
# Lens oracles emit JSON to stdout (no canonical fixed path), so we
|
||
# capture into a per-script-run scripts/kat/ directory and write a
|
||
# manifest. The directory is checked into .gitignore so successive
|
||
# runs only validate determinism, not contents on disk.
|
||
#
|
||
# Coverage:
|
||
# - dkg_oracle: { ed25519, secp256k1, ristretto255 } × { (n=5,t=3),
|
||
# (n=7,t=5) } → 6 vectors
|
||
# - reshare_oracle: same curves × (n=5,t=3) → 3 vectors
|
||
# - hash determinism + tag-distinct tests → in-process
|
||
|
||
set -euo pipefail
|
||
|
||
LENS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
KAT_DIR="${LENS_DIR}/scripts/kat"
|
||
MANIFEST="${LENS_DIR}/scripts/regen-kats.manifest.sha256"
|
||
|
||
VERIFY=0
|
||
if [[ "${1:-}" == "--verify" ]]; then
|
||
VERIFY=1
|
||
fi
|
||
|
||
cd "${LENS_DIR}"
|
||
mkdir -p "${KAT_DIR}"
|
||
|
||
emit_dkg() {
|
||
local curve="$1" n="$2" t="$3" out="$4"
|
||
go run ./cmd/dkg_oracle -curve "${curve}" -n "${n}" -t "${t}" \
|
||
-seed "lens.dkg.kat.v1" > "${out}"
|
||
}
|
||
|
||
emit_reshare() {
|
||
local curve="$1" t_old="$2" t_new="$3" variant="$4" out="$5"
|
||
go run ./cmd/reshare_oracle -curve "${curve}" \
|
||
-t_old "${t_old}" -t_new "${t_new}" -variant "${variant}" \
|
||
-seed "lens.reshare.kat.v1" > "${out}"
|
||
}
|
||
|
||
echo "[1/3] dkg_oracle KAT vectors"
|
||
for curve in ed25519 secp256k1 ristretto255; do
|
||
emit_dkg "${curve}" 5 3 "${KAT_DIR}/dkg_${curve}_n5_t3.json"
|
||
emit_dkg "${curve}" 7 5 "${KAT_DIR}/dkg_${curve}_n7_t5.json"
|
||
done
|
||
|
||
echo "[2/3] reshare_oracle KAT vectors"
|
||
for curve in ed25519 secp256k1 ristretto255; do
|
||
emit_reshare "${curve}" 3 3 reshare \
|
||
"${KAT_DIR}/reshare_${curve}_told3_tnew3.json"
|
||
emit_reshare "${curve}" 3 5 reshare \
|
||
"${KAT_DIR}/reshare_${curve}_told3_tnew5.json"
|
||
emit_reshare "${curve}" 3 3 refresh \
|
||
"${KAT_DIR}/refresh_${curve}_t3.json"
|
||
done
|
||
|
||
echo "[3/3] in-tree hash suite tests"
|
||
go test -count=1 -run "TestSuiteIDsAreDistinct|TestSuiteOperationsAreDeterministic|TestTagsAreDistinct|TestPairwiseCanonicalizesPair|TestDerivePairwiseDistinguishesFields" ./hash >/dev/null
|
||
|
||
# Build sha256 manifest.
|
||
TMP_MANIFEST="$(mktemp)"
|
||
trap 'rm -f "${TMP_MANIFEST}"' EXIT
|
||
|
||
# Stable order regardless of glob expansion. Paths in the manifest
|
||
# are relative to LENS_DIR so the manifest is portable across hosts.
|
||
find "${KAT_DIR}" -maxdepth 1 -name "*.json" -type f | sort | while read -r f; do
|
||
rel="${f#${LENS_DIR}/}"
|
||
shasum -a 256 "$f" | awk -v p="${rel}" '{print $1" "p}'
|
||
done > "${TMP_MANIFEST}"
|
||
|
||
if [[ "${VERIFY}" == "1" ]]; then
|
||
if [[ ! -f "${MANIFEST}" ]]; then
|
||
echo "ERROR: --verify requested but no prior manifest at ${MANIFEST}"
|
||
exit 2
|
||
fi
|
||
if ! diff -u "${MANIFEST}" "${TMP_MANIFEST}"; then
|
||
echo "FAIL: manifest mismatch — Lens KAT regeneration is non-deterministic" >&2
|
||
exit 3
|
||
fi
|
||
echo "OK: Lens KAT regeneration is byte-equal across runs ($(wc -l < "${MANIFEST}") files)"
|
||
else
|
||
cp "${TMP_MANIFEST}" "${MANIFEST}"
|
||
echo "wrote manifest: ${MANIFEST}"
|
||
cat "${MANIFEST}"
|
||
fi
|