Files
zooqueen a1f77cacc9 papers: retire boschini2024corona key -> ringtail (third-party prior art); fix Pulsar/Corona/Ringtail provenance + lattice labels
Ringtail (Boschini et al., ePrint 2024/1113) is third-party prior art; Lux's
Corona (Ring-LWE = Module-LWE rank-1) builds on it; Pulsar is Module-LWE rank-k.
Retired the conflated boschini2024corona/corona2024/coronago/... bib keys to the
single canonical ringtail/corona/pulsar/magnetar keys, rewrote \cite + \bibitem
by context, and fixed 'Pulsar (Ring-LWE)' mislabels (Corona where corona.metal/
single-ring/Ringtail-derived; Pulsar where Module-LWE rank-k/ML-DSA). Cryptographer-led.
2026-06-19 22:33:10 -07:00

163 lines
8.9 KiB
TeX

%% ====================================================================
\section{Microbenchmarks}
\label{sec:microbenchmarks}
%% ====================================================================
This section covers per-operation sign and verify costs for every signing primitive in the Lux production stack. Numbers are from \texttt{github.com/luxfi/consensus} \cite{consensusgo}, \texttt{github.com/luxfi/crypto/$\langle$bls,mldsa,slhdsa$\rangle$}, \texttt{github.com/luxfi/pulsar} \cite{pulsar}, and \texttt{github.com/luxfi/lens} \cite{lensgo}, on Apple M1 Max single core.
\subsection{Single-signature primitives}
\begin{tabular}{@{}lrrr@{}}
\toprule
\textbf{Scheme} & \textbf{Sign} & \textbf{Verify} & \textbf{Verify (cached)} \\
\midrule
secp256k1 (C, native) & 658 ns & 658 ns & --- \\
Ed25519 (Go stdlib) & --- & 205 \textmu s & 1.1 \textmu s \\
P-256 (Go stdlib) & --- & 121 \textmu s & 1.0 \textmu s \\
ML-DSA-44 & --- & 140 \textmu s & --- \\
ML-DSA-65 & 495 \textmu s & 250 \textmu s & 3.0 \textmu s \\
ML-DSA-65 (via UTXO Fx context) & --- & 254 \textmu s & 3.0 \textmu s \\
ML-DSA-87 & --- & 420 \textmu s & --- \\
SLH-DSA-SHA2-192f & --- & 1.92 ms & 131 \textmu s \\
BLS12-381 (single) & 350 \textmu s & 820 \textmu s & --- \\
\bottomrule
\end{tabular}
Reproduction: \texttt{cd consensus \&\& GOWORK=off go test -bench=. -benchtime=1s ./crypto/bls/...} (and analogous for \texttt{mldsa}, \texttt{slhdsa}). Cached verify uses a process-local LRU; the cache hit is dominated by the LRU lookup, not the cryptographic verify.
\subsection{BLS aggregate verify}
\begin{tabular}{@{}lrr@{}}
\toprule
\textbf{Operation} & \textbf{Time} & \textbf{Source} \\
\midrule
BLS aggregate (100 sigs) & 5.3 ms & \texttt{protocol/quasar BenchmarkBLSAggregation/100} \\
BLS aggregated verify (100 signers) & 875 \textmu s & \texttt{protocol/quasar BenchmarkBLSAggregatedVerification/100} \\
\bottomrule
\end{tabular}
The aggregated verify is constant in signer count (the aggregate signature is 96 bytes regardless of $n$); the cost is dominated by the pairing computation. Reproduction: \texttt{GOWORK=off go test -bench=BLSAggregat -benchtime=2s ./protocol/quasar/...}.
\subsection{Pulsar (lattice threshold) per-party costs}
Measured timings on a single Apple M1 Max P-core (Darwin 25.4.0
arm64, Go 1.26.2), Go canonical, via \texttt{cd pulsar \&\& go run . l 5
K} which calls \texttt{sign.LocalRun(5)} (\texttt{pulsar/sign/local.go:21}).
Per-phase mean and median across 5 end-to-end runs at $K = 5$ and
$K = 21$ (2026-05-04 evening, post-fuzz battery, CPU quiescent):
\begin{center}
\begin{tabular}{@{}lrrrr@{}}
\toprule
\textbf{Phase} & \textbf{$K=5$ mean} & \textbf{$K=5$ med} & \textbf{$K=21$ mean} & \textbf{$K=21$ med} \\
\midrule
\texttt{Gen} (one party) & 3.272 & 3.272 & 8.475 & 8.475 \\
\texttt{SignRound1} (per party) & 17.471 & 17.550 & 40.789 & 40.742 \\
\texttt{SignRound2Preprocess} (per party) & 66.792 & 66.718 & 112.869 & 112.541 \\
\texttt{SignRound2} (per party) & 2.481 & 2.511 & 6.532 & 6.532 \\
\texttt{SignFinalize} & 0.068 & --- & 0.090 & --- \\
\texttt{Verify} & 0.931 & --- & 0.950 & --- \\
\texttt{Total Signing} (per party) & 86.743 & 86.718 & 160.190 & 159.987 \\
\bottomrule
\end{tabular}
\end{center}
All times in milliseconds. Reproduced 2026-05-04 03:56 PDT;
$K=21$ second-run total $159.879$ ms confirms stability ($\Delta < 0.5\%$).
Round 2 Preprocess dominates the per-party cost. The Pulsar
matrix-multiply scaling from $K=5$ to $K=21$ is roughly linear in
$K$ for Round 1 (17.5 -> 40.7, $2.3\times$ vs $K$ ratio $4.2\times$
-- matrix size grows but per-row work amortizes) and sub-linear for
Round 2 Preprocess (66.7 -> 112.5, $1.7\times$). Round 1 is
offline-preprocessable: it is independent of the message $m$, so a
node can run it ahead of time on quiescent CPU and store the output
until message-time. The C++ port at LP-137 \cite{lp137} closes the bulk
of the matrix-multiply gap; GPU acceleration is targeted to bring
Round 2 Preprocess below 50 ms at $K = 21$ (Section~\ref{sec:gpu-headroom}).
Reproduction: \texttt{cd pulsar \&\& GOWORK=off go run . l 5 21}.
\paragraph{Pulsar NTT C++ microbench (M1 Max).}
\texttt{luxcpp/crypto/build/pulsar/pulsar\_sign\_ntt\_bench} (single
NTT over $\mathbb{Z}/Q\mathbb{Z}$ with $Q = 0x1000000004A01$, $N = 256$,
LP-073 canonical Pulsar ring) reports the following CPU per-NTT cost
(2026-05-04 evening, M1 Max, batches independent):
\begin{center}
\begin{tabular}{@{}lrrrr@{}}
\toprule
\textbf{Batch} & \textbf{Reps} & \textbf{Median (\textmu s, total)} & \textbf{p99 (\textmu s)} & \textbf{Per-NTT (\textmu s)} \\
\midrule
1 & 2000 & 1.33 & 1.46 & 1.333 \\
8 & 500 & 11.21 & 11.37 & 1.401 \\
32 & 200 & 42.88 & 49.21 & 1.340 \\
128 & 50 & 168.13 & 176.21 & 1.313 \\
\bottomrule
\end{tabular}
\end{center}
The flat per-NTT $\sim 1.31$--$1.40$ \textmu s scaling shows the SIMD path is
saturated; further wins come from GPU dispatch (\texttt{LUX\_PULSAR\_NTT\_BACKEND=metal}
or \texttt{=cuda}; both unavailable on this host -- the bench prints
\texttt{METAL: backend unavailable} on every batch since the Metal
driver is gated behind \texttt{CRYPTO\_CORONA\_LATTICE\_RING\_METALLIB}
which is unset). Reproduction:
\texttt{./build/pulsar/pulsar\_sign\_ntt\_bench} from
\texttt{luxcpp/crypto/build/}.
\subsection{Lens (curve threshold) per-party costs}
Lens implements the FROST 2-round Schnorr protocol \cite{rfc9591} over three groups: Ed25519, secp256k1, and Ristretto255. Indicative single-party signing on M1 Max:
\begin{tabular}{@{}lrrr@{}}
\toprule
\textbf{Group} & \textbf{Sign1 (per party)} & \textbf{Sign2 (per party)} & \textbf{Aggregate + Verify} \\
\midrule
Ed25519 & 90 \textmu s & 110 \textmu s & 320 \textmu s \\
secp256k1 & 75 \textmu s & 95 \textmu s & 280 \textmu s \\
Ristretto255 & 95 \textmu s & 115 \textmu s & 340 \textmu s \\
\bottomrule
\end{tabular}
Lens is roughly $\sim 1000\times$ faster than Pulsar on a per-party basis (curve scalar mul vs lattice matrix-vector multiply). The trade-off is: Lens is classical (curve discrete log), broken in polynomial time by Shor; Pulsar is post-quantum (Module-LWE). Lens is the right primitive for control-plane operations (governance, parameter updates) where compactness and speed dominate; Pulsar is the right primitive for the consensus PQ floor. Reproduction: \texttt{cd lens \&\& go test -bench=. ./sign/...}.
\subsection{Hash primitives}
The Pulsar-SHA3 hash suite uses FIPS-202 / SP 800-185 primitives:
\begin{tabular}{@{}lr@{}}
\toprule
\textbf{Primitive} & \textbf{Throughput (single core)} \\
\midrule
SHA3-256 (\texttt{golang.org/x/crypto/sha3}) & 250 MB/s \\
cSHAKE256 (32-byte output) & 220 MB/s \\
TupleHash256 & 200 MB/s \\
KMAC256 & 240 MB/s \\
BLAKE3 (1 MB) & 4.2 GB/s \\
\bottomrule
\end{tabular}
The Pulsar-SHA3 suite is the production default; Pulsar-BLAKE3 is faster but non-normative. Reproduction: \texttt{go test -bench=. ./hash/...} from the pulsar root.
\subsection{Z-Chain Groth16 wrapper}
The optional Groth16 wrapper around the ML-DSA cert set (LP-307 \cite{lp307}) compresses verification of $N$ ML-DSA-65 signatures into a $\sim 192$-byte SNARK plus a 32-byte public-inputs hash:
\begin{tabular}{@{}lr@{}}
\toprule
\textbf{Operation} & \textbf{Time} \\
\midrule
Groth16 prover (ML-DSA-65 verification circuit, $\sim 2^{22.5}$ R1CS constraints) & $\sim 400$ ms CPU / $\sim 5$--$15$ ms GPU \\
Groth16 verifier (single proof) & 1--3 ms (pairing-dominated) \\
Groth16 verifier (batch of 64 via accel) & $\sim 200$--$500$ \textmu s/proof \\
\bottomrule
\end{tabular}
The Groth16 wrapper is classical (Remark~\ref{rem:groth16-wrapper-warp} of \cite{luxwarpv2}): pairing-based, broken by Shor. PQ finality lives in ML-DSA + Pulsar, not in the Groth16 proof. The wrapper is useful for compression and EVM verifier compatibility only.
\subsection{Note on the stale 357 \textmu s claim}
Earlier Lux drafts (lux-triple-proof-consensus, lux-master-security-model, lux-performance-security-tradeoffs) carried a ``357 \textmu s epoch finality'' number. That number does not match any measured operation in the current code. Closest real candidates: BLS single keygen (350 \textmu s), ML-DSA-65 sign (495 \textmu s); Groth16 prover time is not 357 \textmu s in any reasonable cost model.
\textbf{Recommendation.} Cite the measured numbers in this report. The QuasarCert verify cost is $\sim 2$--$5$ ms CPU on M1 Max (Section~\ref{sec:prism-composition}). The 357 \textmu s figure is removed from the production benchmark surface.