mirror of
https://github.com/lux-apps/papers.git
synced 2026-11-02 11:39:52 +00:00
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.
165 lines
7.3 KiB
TeX
165 lines
7.3 KiB
TeX
\section{Pulsar: Module-LWE threshold finality}
|
|
\label{sec:pulsar}
|
|
|
|
\subsection{Why Pulsar and not BLS}
|
|
|
|
The finality lane in classical Lux Quasar 3.0 \cite{lp020} was BLS12-381
|
|
\cite{bls}: a 48-byte aggregate that closes a block in sub-second. BLS is the
|
|
right shape (linear aggregation, small certificate, short verification) but
|
|
the wrong primitive: it falls to Shor.
|
|
|
|
Pulsar is the PQ replacement. It is a two-round threshold signature over
|
|
the cyclotomic ring $R_q = \mathbb{Z}_q[X]/(X^\varphi+1)$ with $\varphi=256$
|
|
and a 48-bit NTT-friendly prime $q$. The structure mirrors FROST
|
|
\cite{frost}: Round 1 is offline, Round 2 binds the message, partial
|
|
signatures aggregate linearly. The lattice instantiation is closest to the
|
|
two-round threshold ML-DSA family \cite{tmldsa2025,dttf2024} but tracks the
|
|
hint-bound discipline of \cite{ringtail}.
|
|
|
|
The reference implementation is \texttt{luxfi/pulsar}. The
|
|
production canonical exposes \texttt{keygen}, \texttt{sign}, \texttt{verify},
|
|
\texttt{threshold}, \texttt{dkg}, \texttt{reshare}, and \texttt{abort}
|
|
operations.
|
|
|
|
\subsection{Three security levels}
|
|
|
|
Pulsar ships three security levels:
|
|
|
|
\begin{table}[H]
|
|
\centering
|
|
\caption{Pulsar security levels. Parameters from
|
|
\texttt{luxfi/pulsar/parameters.go}.}
|
|
\label{tab:pulsar-levels}
|
|
\begin{tabular}{lrrr}
|
|
\toprule
|
|
Variant & Module rank & Aggregate size & Use case \\
|
|
\midrule
|
|
Pulsar-44 & 4 & $\approx$ 22 KB & devnet / fuzzing only \\
|
|
Pulsar-65 & 6 & $\approx$ 33 KB & production finality lane \\
|
|
Pulsar-87 & 8 & $\approx$ 44 KB & high-value treasury / governance \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{table}
|
|
|
|
The strict-PQ profile pins \texttt{FinalitySchemeID = Pulsar-65} and
|
|
\texttt{HighValueSchemeID = Pulsar-65 or Pulsar-87}. Pulsar-44 is
|
|
\emph{forbidden} on locked profiles --- it exists for devnet stress testing
|
|
where the 22 KB cert and faster signing cost matter more than the 128-bit
|
|
security floor.
|
|
|
|
\subsection{Two-round protocol}
|
|
|
|
The protocol structure (Algorithm~\ref{alg:pulsar-two-round}) is
|
|
near-identical to the original Pulsar family \cite{lp073}; the difference is
|
|
the choice of NTT modulus and the hint-bound discipline. We sketch the
|
|
construction; the reference impl carries the byte-exact specification.
|
|
|
|
\begin{algorithm}
|
|
\caption{Pulsar-65 two-round signing}
|
|
\label{alg:pulsar-two-round}
|
|
\begin{algorithmic}[1]
|
|
\Require committee $\mathcal{C}$ of $n=64$ parties; threshold $t=43$
|
|
\Require message $m$ (typically the QBlock digest, Sec.~\ref{sec:qchain-finality})
|
|
\Require group public key $(\mathbf{A}, \tilde{\mathbf{b}})$ from DKG
|
|
\Require each party holds Shamir share $\mathbf{s}_i$
|
|
\State \textbf{Round 1 (offline, per party $i$):}
|
|
\State \hspace{1em} sample masking matrix $\hat{R}_i$ from Discrete-Gaussian $\sigma_E$
|
|
\State \hspace{1em} broadcast $D_i = \mathbf{A} \cdot \hat{R}_i + \hat{E}_i$
|
|
\State \hspace{1em} attach BLAKE3-keyed MAC $\textsc{MAC}_{i \to j}$ for each peer $j$
|
|
\State \textbf{Round 2 (online, per party $i$):}
|
|
\State \hspace{1em} aggregate $D = \sum_j D_j$
|
|
\State \hspace{1em} derive challenge vector $u = \textsc{GaussianHash}(D, m, \texttt{ctx})$
|
|
\State \hspace{1em} derive ternary challenge $c = \textsc{ChallengeHash}(u, m)$
|
|
\State \hspace{1em} compute partial signature $z_i = \mathbf{s}_i \cdot c + \hat{R}_i$
|
|
\State \hspace{1em} broadcast $z_i$
|
|
\State \textbf{Finalise:}
|
|
\State \hspace{1em} aggregate $z = \sum_i z_i$ (linear, no coordinator)
|
|
\State \hspace{1em} produce hint $\Delta$ in $R_\nu$
|
|
\State \hspace{1em} output certificate $(c, z, \Delta, \text{bitmap})$
|
|
\end{algorithmic}
|
|
\end{algorithm}
|
|
|
|
The verifier (\texttt{luxfi/pulsar/verify.go}) reconstructs
|
|
$\mathbf{A} z - \tilde{\mathbf{b}} c$ in the rounded-coefficient hint domain
|
|
$R_\nu$, applies the per-coefficient $\Delta$ correction, and accepts iff the
|
|
$L_2$ bound holds. The bitmap is the indicator vector for which parties
|
|
contributed --- at least 43 of 64 must be set.
|
|
|
|
The threshold $t=43$ is chosen against $n=64$ to give:
|
|
|
|
\begin{itemize}[leftmargin=2em,nosep]
|
|
\item BFT margin: $t > 2n/3$ closes the standard Byzantine quorum.
|
|
\item Identifiable abort: $n - t = 21$ allows up to 21 non-contributing
|
|
parties to be identified without aborting the round.
|
|
\item Lattice slack: the hint discipline tolerates $t$-of-$n$ aggregation
|
|
without rejection-sampling rerolls in the $\eta_\varepsilon = 2.65$ slack
|
|
regime.
|
|
\end{itemize}
|
|
|
|
\subsection{Identifiable abort}
|
|
|
|
A party that misbehaves in Round 1 (publishes a malformed $D_i$, fails its
|
|
MAC) or Round 2 (publishes a malformed $z_i$) is identified by the protocol
|
|
without halting the round. The reference impl exposes the
|
|
\texttt{abort} interface (\texttt{luxfi/pulsar/abort.go}) that
|
|
returns the identifier of the misbehaving party. The consensus engine then
|
|
ejects the party from the active committee and slashes their stake.
|
|
|
|
This is critical for liveness: a BLS threshold signature that fails to
|
|
aggregate has no identifiable culprit and the whole round must be re-run.
|
|
Pulsar rounds make progress against $n - t$ misbehaving parties without
|
|
re-runs, which is the practical difference between sub-second finality and
|
|
multi-second finality under partial failure.
|
|
|
|
\subsection{No BLS fallback}
|
|
|
|
The strict-PQ profile sets \texttt{ForbidFallbacks = true}. This bit
|
|
specifically refuses the ``fall back to BLS if Pulsar times out'' design
|
|
the early Quasar drafts considered. The reasoning: a Shor-capable adversary
|
|
could trigger Pulsar failure on purpose to force the fallback path, then
|
|
forge under BLS. Refusing the fallback closes the attack at the cost of
|
|
slower finality during a Pulsar misconfiguration.
|
|
|
|
The replacement for the BLS fallback is the identifiable-abort path above:
|
|
slow-but-correct under failure, not fast-but-classical.
|
|
|
|
\subsection{DKG and reshare}
|
|
|
|
Validator-set rotation requires resharing the Pulsar secret to a new
|
|
committee. The reference impl exposes \texttt{dkg}
|
|
(\texttt{luxfi/pulsar/dkg.go}) and \texttt{reshare}
|
|
(\texttt{reshare.go}). The DKG is a Pedersen-style protocol over $R_q$ with
|
|
hiding / binding proofs, closely following the construction in
|
|
\cite{krt24,gks24}. Reshare uses the LSS framework \cite{luxlssmpc} so the
|
|
group public key $(\mathbf{A}, \tilde{\mathbf{b}})$ is preserved across
|
|
the committee transition.
|
|
|
|
The activation certificate (HIP-0078 ยง6) gates each committee transition on
|
|
a Pulsar signature verifying under the unchanged group public key.
|
|
Activation proves the new committee \emph{can sign} before the old committee
|
|
loses signing capability; complaint and slashing-evidence pipelines are
|
|
independent.
|
|
|
|
\subsection{Reference impl status}
|
|
|
|
\texttt{luxfi/pulsar} ships:
|
|
|
|
\begin{itemize}[leftmargin=2em,nosep]
|
|
\item \texttt{keygen}: long-term signing key generation.
|
|
\item \texttt{sign}: single-party signing under a non-threshold key
|
|
(for testing).
|
|
\item \texttt{verify}: standalone verifier.
|
|
\item \texttt{threshold}: the two-round protocol of
|
|
Algorithm~\ref{alg:pulsar-two-round}.
|
|
\item \texttt{dkg}: distributed key generation.
|
|
\item \texttt{reshare}: secret-share resharing across committee
|
|
transitions.
|
|
\item \texttt{abort}: identifiable-abort detection.
|
|
\end{itemize}
|
|
|
|
Every operation has KAT (known-answer tests) vectors in the
|
|
\texttt{testdata/} directory. The KATs are generated by the reference impl
|
|
itself and cross-checked against the C++ port (\texttt{luxfi/pulsar-cpp},
|
|
in development) and against the GPU kernels (\texttt{luxfi/p3q-gpu} for the
|
|
NTT subroutines).
|