mirror of
https://github.com/luxfi/proofs.git
synced 2026-10-30 15:21:05 +00:00
Bylines, paper authorship, correspondence addresses and the founder blurb under each post named an individual. They name the organisation that published the work instead: the brand on posts and pages, the research byline on papers, and research@ in place of a personal address. Both are what these repositories already used elsewhere — nothing new was coined. Co-authors are untouched. Where a paper named someone else alongside, they stay named; only the one byline changed. Bibliography entries, running heads, PDF metadata and affiliations move with it, so a citation still resolves to whoever the cited paper names. Sample and fixture data uses the placeholder name these tests already use elsewhere, so no assertion changed meaning.
967 lines
48 KiB
TeX
967 lines
48 KiB
TeX
\documentclass[11pt]{article}
|
|
\usepackage[utf8]{inputenc}
|
|
\usepackage[T1]{fontenc}
|
|
\usepackage{amsmath,amssymb,amsthm,amsfonts}
|
|
\usepackage{booktabs}
|
|
\usepackage{enumitem}
|
|
\usepackage{hyperref}
|
|
\usepackage{graphicx}
|
|
\usepackage{xcolor}
|
|
\usepackage{geometry}
|
|
\geometry{margin=1in}
|
|
|
|
\hypersetup{colorlinks=true,linkcolor=black,citecolor=blue,urlcolor=blue}
|
|
|
|
% Absorb the few overfull boxes from long unbreakable \texttt{} identifiers
|
|
% (shieldedPoolTotal, RefuseUnderStrictPQ, MarkNullifierSpent) without
|
|
% loosening normal lines.
|
|
\emergencystretch=3em
|
|
|
|
\newtheorem{theorem}{Theorem}
|
|
\newtheorem{lemma}[theorem]{Lemma}
|
|
\newtheorem{corollary}[theorem]{Corollary}
|
|
\newtheorem{proposition}[theorem]{Proposition}
|
|
\theoremstyle{definition}
|
|
\newtheorem{definition}{Definition}
|
|
\newtheorem{assumption}{Assumption}
|
|
\theoremstyle{remark}
|
|
\newtheorem{remark}{Remark}
|
|
|
|
% Status macros, identical in spirit to the LP-225 specification: every
|
|
% claim is marked IMPLEMENTED (true of code today), DESIGN-ONLY (specified,
|
|
% not yet wired), or CRYPTO-REVIEW (a cryptographic obligation gated on
|
|
% sign-off). The proof is at the MODEL level; these macros keep the
|
|
% model/implementation boundary honest on every line that touches code.
|
|
\newcommand{\IMPL}{\textbf{[IMPLEMENTED]}}
|
|
\newcommand{\DESIGN}{\textbf{[DESIGN-ONLY]}}
|
|
\newcommand{\CRYPTO}{\textbf{[CRYPTO-REVIEW]}}
|
|
|
|
% Notation for the value function and the per-asset pools.
|
|
\newcommand{\Val}{\mathsf{V}}
|
|
\newcommand{\spend}{\mathsf{S}}
|
|
\newcommand{\lock}{\mathsf{L}}
|
|
\newcommand{\commit}{\mathsf{C}}
|
|
\newcommand{\pool}{\mathsf{P}}
|
|
\newcommand{\total}{\mathrm{total}}
|
|
\newcommand{\NF}{\mathsf{NF}}
|
|
\newcommand{\CM}{\mathsf{CM}}
|
|
|
|
\title{Double-Spend and Inflation Impossibility for the\\
|
|
X-Chain Settlement Spine with a Z-Chain Shielded Pool\\
|
|
{\large A model-level soundness proof, with the implementation
|
|
obligations it leaves open}}
|
|
\author{Lux Research \\
|
|
\textit{Lux Industries, Inc.}\\
|
|
\texttt{[email protected]}}
|
|
\date{}
|
|
|
|
\begin{document}
|
|
\maketitle
|
|
|
|
\begin{abstract}
|
|
The X-Chain Settlement Spine (XSS, LP-225) collapses Lux's parallel
|
|
spendable ledgers into one visible UTXO ledger on X plus one shielded
|
|
value pool on Z, joined by a shield/unshield bridge. This note proves,
|
|
\emph{at the model level}, that the XSS state machine makes double-spend
|
|
and inflation (unbounded mint) impossible \emph{provided} its primitives
|
|
are implemented to specification, and it states exactly which
|
|
cryptographic assumptions and proof obligations the implementation must
|
|
discharge for the model to bind to the deployed system. We formalise the
|
|
global state as a per-asset value function
|
|
$\Val = \spend + \lock + \commit + \pool$ over the spendable, locked,
|
|
committed, and shielded pools, and give the value-delta of every
|
|
transition. \textbf{Theorem~1} (no double-spend): every UTXO and every
|
|
shielded note is consumed at most once, from X's total order, the
|
|
completeness and persistence of the consumed/nullifier sets, and an
|
|
idempotent consume guard. \textbf{Theorem~2} (conservation / no
|
|
inflation): $\Val$ is invariant under every transition except a single
|
|
bounded, schedule-enforced \texttt{RewardMint}; in particular shield and
|
|
unshield are value-neutral because X tracks a scalar
|
|
\texttt{shieldedPoolTotal} that is debited and credited in lockstep.
|
|
\textbf{Theorem~3} (the turnstile backstop, the headline result):
|
|
\emph{even if the shielded validity-proof system is unsound}---an
|
|
adversary forges shielded proofs at will---the value extractable from the
|
|
shielded pool is bounded by \texttt{shieldedPoolTotal}, because X
|
|
independently maintains that scalar and rejects, at execution, any
|
|
unshield that would drive it negative. This converts the Zcash-class
|
|
counterfeiting failure (the 2018 BCTV14 soundness flaw, CVE-2019-7167,
|
|
which permitted \emph{unbounded} counterfeiting of shielded value below
|
|
the layer at which per-pool monitoring acts) into a bounded, contained
|
|
failure, by making the pool-total balance a first-class
|
|
\emph{consensus-layer transition precondition} rather than a monitoring
|
|
heuristic. We are explicit about scope: \textbf{the shield/unshield
|
|
execution is design-only today} (LP-225; the ZKVM handlers are stubs),
|
|
so what is proven is the implication ``spec-faithful primitives $\Rightarrow$
|
|
safety,'' not a claim about the current stubbed code. The five assumptions
|
|
A1--A5 and their discharge sites are tabulated; Theorem~3 is precisely the
|
|
statement that the safety floor degrades \emph{gracefully} under failure
|
|
of the strongest assumption (A4).
|
|
\end{abstract}
|
|
|
|
\tableofcontents
|
|
\newpage
|
|
|
|
%% ===================================================================
|
|
\section{Scope, and what is and is not claimed}
|
|
\label{sec:scope}
|
|
|
|
This is a \textbf{design-level soundness proof}. It proves a conditional:
|
|
\begin{quote}
|
|
\emph{If} the XSS primitives are implemented faithfully to the LP-225
|
|
specification and the assumptions A1--A5 of Section~\ref{sec:assumptions}
|
|
hold, \emph{then} the safety properties ``no double-spend'' (Theorem~1)
|
|
and ``no inflation'' (Theorem~2) hold, and the contingency bound
|
|
(Theorem~3) holds.
|
|
\end{quote}
|
|
It does \emph{not} claim that the current implementation has these
|
|
properties. Per LP-225~\cite{lp225}, the shield/unshield \emph{execution}
|
|
is a stub (\texttt{lux/chains/zkvm/handlers.go} returns
|
|
\texttt{"Not implemented"} on the proof-generation and conversion paths),
|
|
and \textbf{no code tracks the cross-pool total} that Theorems~2 and~3
|
|
depend on: a search of the ZKVM and precompile trees finds no
|
|
visible-plus-shielded accounting. The scalar this proof calls
|
|
\texttt{shieldedPoolTotal} is therefore a \DESIGN{} object; establishing
|
|
and enforcing it is the central new obligation the proof identifies.
|
|
|
|
What \emph{is} implemented, and what the proof builds on as ground truth,
|
|
is the X-side conservation primitive and the Z-side note/nullifier
|
|
objects:
|
|
\begin{itemize}[leftmargin=2em,nosep]
|
|
\item \IMPL{} X's syntactic conservation rule
|
|
$\mathrm{inputs}\ge\mathrm{outputs}+\mathrm{fee}$, per asset, applied to
|
|
every xvm transaction type through \texttt{lux.VerifyTx}
|
|
(\texttt{node/vms/xvm/txs/\allowbreak executor/\allowbreak syntactic\_verifier.go},
|
|
calling
|
|
\texttt{node/vms/components/\allowbreak lux/transferables.go:209}; the
|
|
per-asset flow check is \texttt{FlowChecker.Verify} in
|
|
\texttt{node/vms/components/\allowbreak lux/flow\_checker.go}).
|
|
\item \IMPL{} the Z note model: \texttt{Note} with \texttt{Commitment} and
|
|
\texttt{Nullifier}, the \texttt{TransactionTypeShield} /
|
|
\texttt{TransactionTypeUnshield} enum members, and persistent
|
|
spent-nullifier tracking
|
|
(\texttt{node/chains/zkvm/transaction.go:28--29,108--120};
|
|
\texttt{node/chains/zkvm/nullifier\_db.go},
|
|
\texttt{MarkNullifierSpent}/\texttt{IsNullifierSpent}).
|
|
\item \IMPL{} the commitment and nullifier primitives: a
|
|
\texttt{CommitmentScheme} interface with Poseidon2 (PQ-safe,
|
|
hash-based) and Pedersen instantiations, and a nullifier derived as
|
|
$\textsf{Poseidon2.NullifierHash}(\textit{nk},$ $\textit{commitment},$
|
|
$\textit{leafIndex})$
|
|
(\texttt{node/precompile/\allowbreak zk/commitment.go:15--75,156--163}).
|
|
\item \IMPL{} the two validity verifiers XSS composes at the boundary:
|
|
P3Q (ML-DSA-65 / FIPS-204~\cite{fips204}, precompile \texttt{0x012205},
|
|
\texttt{node/precompile/p3q/contract.go}; verifier core is
|
|
\texttt{mldsa.VerifySignatureCtx}) and starkfri (STARK/FRI, precompile
|
|
\texttt{0x012220}, magic header \texttt{"P3Q1"},
|
|
\texttt{node/precompile/starkfri/contract.go}).
|
|
\end{itemize}
|
|
|
|
\noindent We mark every model object with its status as we use it. The
|
|
reader should treat an \IMPL{} citation as ``this mechanism exists and the
|
|
model reuses it,'' a \DESIGN{} mark as ``this mechanism is specified but
|
|
not yet wired---the proof is conditional on it being wired to spec,'' and
|
|
a \CRYPTO{} mark as ``this is a cryptographic obligation gated on
|
|
sign-off (Section~\ref{sec:assumptions}).''
|
|
|
|
%% ===================================================================
|
|
\section{The model}
|
|
\label{sec:model}
|
|
|
|
We mirror the LP-225 model (\cite{lp225}, \S2, \S5, \S9) and make its
|
|
state machine precise enough to carry value-deltas. We fix a single asset
|
|
$a$ throughout; all sums are per-asset and all transitions preserve the
|
|
asset, so the multi-asset statement is the conjunction over assets (the
|
|
implemented \texttt{FlowChecker} is itself per-asset).
|
|
|
|
\subsection{State}
|
|
|
|
\begin{definition}[Global state]
|
|
\label{def:state}
|
|
A state $\Sigma$ consists of:
|
|
\begin{enumerate}[leftmargin=2em,nosep]
|
|
\item A finite \textbf{UTXO set} $U$. Each UTXO $u$ has a value
|
|
$\mathrm{val}(u)\in\mathbb{N}$ (a \texttt{uint64} amount in code) and a
|
|
\textbf{state} $\mathrm{st}(u)\in\{\textsc{spendable},\textsc{locked},
|
|
\textsc{consumed}\}$. \IMPL{} for \textsc{spendable}/\textsc{consumed}
|
|
(an xvm UTXO either exists and is spendable, or has been consumed as a
|
|
transaction input); \DESIGN{} for \textsc{locked} (the \texttt{XLock}
|
|
output type does not exist in xvm today, LP-225~\S3).
|
|
\item A set of \textbf{commitment objects} $K$ (the \texttt{XLock} and
|
|
\texttt{XAppCommitment} of LP-225 \S3--\S3b). Each $\kappa\in K$ carries
|
|
an amount $\mathrm{amt}(\kappa)$, a target $(\mathrm{chain},
|
|
\mathrm{module})$ scope, and a Boolean \texttt{consumed} flag, set true
|
|
at most once. \DESIGN{}.
|
|
\item A \textbf{shielded pool} on Z: a commitment set $\CM$ (the note
|
|
commitment tree), a spent-nullifier set $\NF$, and---this is the new
|
|
object---a scalar \texttt{shieldedPoolTotal}, written $\pool\in\mathbb{N}$,
|
|
\emph{maintained on X}. $\CM,\NF$ are \IMPL{}
|
|
(\texttt{state\_tree.go}, \texttt{nullifier\_db.go}); $\pool$ is
|
|
\DESIGN{} (no code tracks it, \S\ref{sec:scope}).
|
|
\end{enumerate}
|
|
\end{definition}
|
|
|
|
\begin{definition}[Pool sums and the value function]
|
|
\label{def:V}
|
|
For a state $\Sigma$, define the per-asset pool sums
|
|
\begin{align*}
|
|
\spend(\Sigma) &= \!\!\sum_{\substack{u\in U\\ \mathrm{st}(u)=\textsc{spendable}}}\!\!\mathrm{val}(u)
|
|
&&\text{(spendable visible value),}\\
|
|
\lock(\Sigma) &= \!\!\sum_{\substack{u\in U\\ \mathrm{st}(u)=\textsc{locked}}}\!\!\mathrm{val}(u)
|
|
&&\text{(value inside live UTXO locks),}\\
|
|
\commit(\Sigma) &= \!\!\sum_{\substack{\kappa\in K\\ \neg\,\kappa.\texttt{consumed}}}\!\!\mathrm{amt}(\kappa)
|
|
&&\text{(value inside live commitments),}\\
|
|
\pool(\Sigma) &= \texttt{shieldedPoolTotal}
|
|
&&\text{(X's scalar mirror of shielded value).}
|
|
\end{align*}
|
|
The \textbf{total value function} is
|
|
\[
|
|
\Val(\Sigma) \;=\; \spend(\Sigma) + \lock(\Sigma) + \commit(\Sigma) + \pool(\Sigma).
|
|
\]
|
|
\end{definition}
|
|
|
|
\begin{remark}[$\pool$ is a scalar, not a sum over notes]
|
|
\label{rem:scalar}
|
|
The decisive design choice is that $\pool$ is a single scalar X maintains,
|
|
\emph{not} a quantity X recomputes by summing note values inside the
|
|
shielded pool. X cannot read note values---they are hidden. X instead
|
|
tracks the pool total by \emph{bookkeeping the boundary}: every shield
|
|
credits $\pool$ by the (public) burned amount, every unshield debits
|
|
$\pool$ by the (public) minted amount. The shielded supply
|
|
$\sum_{\text{live notes}}\mathrm{val}$ is private and lives on Z; the
|
|
scalar $\pool$ is its public, X-enforced upper bound. The entire strength
|
|
of Theorem~3 comes from this: X's $\pool$ does not trust the proof system
|
|
to be sound; it trusts only its own arithmetic on public boundary
|
|
amounts. The \emph{soundness} of the proof system governs whether
|
|
$\pool=\sum_{\text{live notes}}\mathrm{val}$ holds with equality
|
|
(no \emph{internal} shielded inflation); its \emph{failure} can at worst
|
|
make the shielded side believe it holds more than $\pool$, and that excess
|
|
is exactly what the turnstile refuses to let out.
|
|
\end{remark}
|
|
|
|
\subsection{Transitions}
|
|
\label{sec:transitions}
|
|
|
|
A transition $t:\Sigma\to\Sigma'$ is one of the following. For each we
|
|
give its precondition, its effect, and its value-delta
|
|
$\Delta\Val(t)=\Val(\Sigma')-\Val(\Sigma)$. We write $\mathrm{val}$ of a
|
|
set of UTXOs for the sum of their values, $f\ge 0$ for the burned fee.
|
|
|
|
\begin{description}[leftmargin=1.5em,style=nextline]
|
|
|
|
\item[\textsc{spend}] Consume spendable inputs $I\subseteq U$, create
|
|
spendable outputs $O$. \textbf{Precondition (P-conserve):}
|
|
$\mathrm{val}(I) = \mathrm{val}(O) + f$, and every $u\in I$ is
|
|
\textsc{spendable}. \textbf{Effect:} each $u\in I$ becomes
|
|
\textsc{consumed}; $O$ are added \textsc{spendable}. The fee $f$ is
|
|
burned (leaves the asset's circulating value; we account for it
|
|
below). \IMPL{}: this is exactly \texttt{lux.VerifyTx} +
|
|
consume-once on inputs. $\Delta\Val = -(\mathrm{val}(I)) +
|
|
\mathrm{val}(O) = -f \le 0$.
|
|
|
|
\item[\textsc{lock}] Consume spendable inputs $I$; create one live
|
|
commitment $\kappa$ with $\mathrm{amt}(\kappa)=\mathrm{val}(I)-f$ (or,
|
|
in the \texttt{XLock} variant where the lock is the sole output and
|
|
carries the full amount, $\mathrm{amt}(\kappa)=\mathrm{val}(I)$ with
|
|
$f=0$). \textbf{Precondition:} P-conserve with $\kappa$ as the output;
|
|
$I$ all \textsc{spendable}. \textbf{Effect:} $I\to\textsc{consumed}$;
|
|
$\kappa$ live. \DESIGN{} (LP-225 \texttt{LockTx}). $\Delta\Val=-f\le0$
|
|
($\spend$ down by $\mathrm{val}(I)$, $\commit$ up by
|
|
$\mathrm{val}(I)-f$).
|
|
|
|
\item[\textsc{settle}] Consume a set of live commitments
|
|
$\{\kappa_i\}$ \emph{gated by an accepted proof}; create spendable
|
|
outputs $O$ and/or shielded outputs (handled by composing
|
|
\textsc{shield}, below). \textbf{Precondition:} (i) each $\kappa_i$ is
|
|
live and shares the one $(\mathrm{chain},\mathrm{module})$ the proof is
|
|
scoped to; (ii) the proof verifies under \texttt{VerifyChainCommitment}
|
|
(P3Q and/or starkfri); (iii) \textbf{settlement conservation}
|
|
$\sum_i\mathrm{amt}(\kappa_i) = \mathrm{val}(O) +
|
|
(\text{shielded outputs})$. \textbf{Effect:} each $\kappa_i.\texttt{consumed}
|
|
\gets\textsc{true}$; $O$ added \textsc{spendable}; shielded outputs go
|
|
through \textsc{shield}. \DESIGN{} (LP-225 \texttt{SettleTx}); verifiers
|
|
\IMPL{}. With no shielded leg, $\Delta\Val = 0$ ($\commit$ down,
|
|
$\spend$ up, equal). (With a shielded leg the delta is that of the
|
|
composed \textsc{shield}, i.e.\ still $0$.)
|
|
|
|
\item[\textsc{shield}] Burn a spendable amount $v$ on X; add a commitment
|
|
$C$ to $\CM$ on Z; credit $\pool \gets \pool + v$. \textbf{Precondition:}
|
|
a named spendable UTXO (or settlement leg) of value $v$ exists; a
|
|
validity proof binds $C$ to value exactly $v$ of the asset.
|
|
\textbf{Effect:} the named visible value is consumed
|
|
($\spend$ down by $v$); $C\in\CM$; $\pool\gets\pool+v$.
|
|
\DESIGN{} execution (handler stub); model objects \IMPL{}.
|
|
$\Delta\Val = -v + v = 0$.
|
|
|
|
\item[\textsc{unshield}] Spend a live Z note of value $v$: publish its
|
|
nullifier $N$; \emph{debit} $\pool \gets \pool - v$; mint a spendable
|
|
UTXO of value $v$ on X. \textbf{Precondition (U1--U3):} (U1) $N\notin\NF$;
|
|
(U2) a validity proof asserts the note was live and committed to value
|
|
$v$; (U3) \textbf{turnstile floor} $\pool \ge v$. \textbf{Effect:}
|
|
$N$ added to $\NF$ (the note is nullified); $\pool\gets\pool-v$; a
|
|
spendable UTXO of value $v$ added ($\spend$ up by $v$).
|
|
\DESIGN{} execution; $\NF$ tracking \IMPL{}; (U3) and $\pool$ \DESIGN{}.
|
|
$\Delta\Val = -v + v = 0$.
|
|
|
|
\item[\textsc{rewardMint}] The \emph{only} value-increasing transition.
|
|
Create a spendable amount $r$ where $r = \mathrm{Sched}(h)$ is the
|
|
amount the deterministic, X-enforced monetary schedule prescribes at
|
|
height $h$. \textbf{Precondition:} $r$ equals the scheduled amount for
|
|
$h$ and the per-height issuance has not already been minted.
|
|
\textbf{Effect:} $\spend$ up by $r$. \DESIGN{} as an \emph{X-level}
|
|
primitive (LP-225 \S10 flags that P's reward minting today lives on the
|
|
wrong chain and must move to an X-settled, schedule-gated result).
|
|
$\Delta\Val = +r$, with $r$ a bounded, deterministic function of
|
|
consensus height.
|
|
\end{description}
|
|
|
|
\begin{remark}[On the fee]
|
|
\label{rem:fee}
|
|
The fee $f$ is value removed from the asset's circulating supply (burned).
|
|
It makes \textsc{spend}/\textsc{lock} value-\emph{decreasing} by $f$, never
|
|
increasing. For the conservation theorem we treat the burned fee as a
|
|
distinguished sink: define the conserved quantity as $\Val(\Sigma) +
|
|
\mathrm{Burned}(\Sigma)$ where $\mathrm{Burned}$ accumulates fees. Then
|
|
$\Delta(\Val+\mathrm{Burned}) = 0$ for \textsc{spend}/\textsc{lock}. Inflation
|
|
is the property that $\Val$ never \emph{rises} except by \textsc{rewardMint};
|
|
fees can only lower it, so they never threaten the no-inflation bound and we
|
|
fold them into the ``$\le$'' direction without further comment. (In code the
|
|
fee burn is \texttt{fc.Produce(feeAssetID, feeAmount)} in \texttt{VerifyTx}:
|
|
the fee is counted on the produced/output side, so $\mathrm{inputs}\ge
|
|
\mathrm{outputs}+\mathrm{fee}$ is what \texttt{FlowChecker.Verify} enforces.)
|
|
\end{remark}
|
|
|
|
\subsection{Execution semantics}
|
|
\label{sec:exec}
|
|
|
|
\begin{definition}[Ledger execution]
|
|
\label{def:ledger}
|
|
The ledger is the sequence of states $\Sigma_0,\Sigma_1,\dots$ where
|
|
$\Sigma_0$ is genesis and $\Sigma_{j+1}$ results from applying the
|
|
transitions of block $j$, in the block's order, each only if its
|
|
precondition holds in the then-current state (a transition whose
|
|
precondition fails is \emph{rejected}: it is not applied and
|
|
$\Sigma$ is unchanged by it). X's consensus fixes a single total order on
|
|
all blocks and hence on all applied transitions (Assumption~A1).
|
|
\end{definition}
|
|
|
|
This is the operational content of LP-225's ``X owns the total ordering of
|
|
all asset movements'' and ``other chains compute, X settles'': every
|
|
state-moving transition is an X transition, applied in X's order, gated by
|
|
an X-checked precondition. Computing modules (P, D, B, C, Q) produce only
|
|
\emph{proofs} and \emph{settlement requests}; the value movement is the
|
|
\textsc{settle} transition on X (LP-225 \S2, property S3).
|
|
|
|
%% ===================================================================
|
|
\section{Assumptions and proof obligations}
|
|
\label{sec:assumptions}
|
|
|
|
The theorems are proven relative to the following assumptions. Each is the
|
|
implementation contract for one mechanism; each names where it must be
|
|
discharged and flags what is \DESIGN{} today. The numbering A1--A5 is
|
|
referenced throughout.
|
|
|
|
\begin{assumption}[Total order and atomic apply]
|
|
\label{a:order}
|
|
X consensus assigns all applied transitions a single total order, and each
|
|
transition is applied atomically: its precondition is evaluated against
|
|
the unique pre-state and, if it holds, its entire effect is applied before
|
|
the next transition; if it fails, none of its effect is applied. No two
|
|
conflicting histories are both finalised (no fork double-apply).
|
|
\\\textbf{Discharge:} Lux consensus safety/finality (proven separately:
|
|
\texttt{lean/Consensus/Safety.lean}, \texttt{Finality.lean}, BFT quorum
|
|
intersection; QuasarCert soundness~\cite{quasarsound}). Within a single
|
|
chain, transaction application is sequential and atomic (xvm block
|
|
execution). \IMPL{} (consensus + xvm execution).
|
|
\end{assumption}
|
|
|
|
\begin{assumption}[Consumed-set / nullifier-set completeness and persistence]
|
|
\label{a:sets}
|
|
(i) The set of consumed UTXO references is complete and persistent: a UTXO
|
|
consumed by any applied transition is, at every later height, recorded as
|
|
consumed and unavailable as an input. (ii) The spent-nullifier set $\NF$ is
|
|
complete and persistent: a nullifier published by any applied
|
|
\textsc{unshield} (or Z-internal spend) is, at every later height, in
|
|
$\NF$. (iii) Both are checked \emph{before} a consume is permitted.
|
|
\\\textbf{Discharge:} UTXO consume-once is \IMPL{} (xvm input semantics;
|
|
the DEX atomic rail's \texttt{MarkConsumed}/\texttt{IsConsumed} persisted
|
|
set, \texttt{node/chains/dexvm/atomic.go}). Nullifier persistence is
|
|
\IMPL{} (\texttt{node/chains/zkvm/nullifier\_db.go} writes each spent
|
|
nullifier to the backing \texttt{database.Database}; \texttt{IsNullifierSpent}
|
|
reads it). \textbf{Cross-boundary completeness}---that the \emph{same} $\NF$
|
|
is the arbiter for both X-side unshield and Z-side spend, with no partition
|
|
admitting two consumptions---is \CRYPTO{}/\DESIGN{} (LP-225 \S10 item 2, S4).
|
|
\end{assumption}
|
|
|
|
\begin{assumption}[Commitment scheme: binding and hiding]
|
|
\label{a:commit}
|
|
The note commitment scheme is computationally \emph{binding} (no efficient
|
|
adversary opens one commitment $C$ to two distinct $(v,\cdot)$ pairs) and
|
|
\emph{hiding} (a commitment reveals nothing about $v$). The nullifier is
|
|
\emph{deterministically and uniquely} derived from a note (one live note
|
|
$\Rightarrow$ exactly one nullifier), and \emph{unforgeable} (cannot
|
|
produce a valid nullifier for a note one cannot open).
|
|
\\\textbf{Discharge:} \texttt{CommitmentScheme} with Poseidon2 (binding
|
|
under collision-resistance of the Poseidon2 sponge; PQ-safe) and Pedersen
|
|
(binding under discrete-log; hiding information-theoretically)
|
|
(\texttt{node/precompile/zk/commitment.go:15--75}). Nullifier
|
|
determinism is \IMPL{} in form
|
|
($\textsf{NullifierHash}(\textit{nk},C,\textit{leafIndex})$,
|
|
\texttt{commitment.go:156--163}). \textbf{Binding/hiding as deployed},
|
|
and the unforgeability of the nullifier under the chosen $\textit{nk}$
|
|
derivation, are \CRYPTO{} (LP-225 \S10 item 1; the scheme must be pinned
|
|
and reviewed).
|
|
\end{assumption}
|
|
|
|
\begin{assumption}[Validity-proof soundness]
|
|
\label{a:proof}
|
|
The shielded validity-proof system (the STARK/FRI AIR verified by starkfri,
|
|
and/or the P3Q attestation) is \emph{sound}: an accepting proof implies the
|
|
asserted statement is true (the note was live and committed to value $v$;
|
|
the settled state transition was valid and the deltas are exactly the
|
|
claimed ones), except with negligible probability.
|
|
\\\textbf{Discharge:} starkfri verifies a STARK/FRI proof
|
|
(\texttt{node/precompile/starkfri/contract.go}); P3Q verifies an ML-DSA-65
|
|
attestation (\texttt{node/precompile/p3q/contract.go}). \textbf{The
|
|
settlement/shield AIR does not exist yet} and must be specified and
|
|
reviewed; the P3Q attestation's soundness reduces to honesty of the
|
|
attesting set (a trusted-operator assumption). Both are \CRYPTO{}
|
|
(LP-225 \S10 items 4--5). \textbf{Theorem~3 is precisely the statement
|
|
that the safety floor survives the failure of this assumption.}
|
|
\end{assumption}
|
|
|
|
\begin{assumption}[Collision-resistant hash]
|
|
\label{a:hash}
|
|
The hash used for UTXO identifiers, commitment-tree nodes, and nullifiers
|
|
is collision-resistant, so distinct objects have distinct identifiers
|
|
(no UTXO/note aliasing) except with negligible probability.
|
|
\\\textbf{Discharge:} the hash families in use (Poseidon2 for the shielded
|
|
side; the xvm UTXO id hashing on the visible side). Standard assumption;
|
|
the specific instantiations are \CRYPTO{}-pinned with the commitment scheme.
|
|
\end{assumption}
|
|
|
|
\begin{remark}[Why A4 is special]
|
|
\label{rem:a4special}
|
|
A1, A2, A5 are discharged by mechanisms that exist and are largely
|
|
\IMPL{}. A3 is a standard, well-understood primitive obligation. A4 is the
|
|
\emph{hardest and least settled}: the settlement/shield AIR is not yet
|
|
written, and the P3Q attestation path is an explicit trusted-operator
|
|
assumption. A system whose safety \emph{rests entirely} on A4 is exactly a
|
|
system with the Zcash failure mode: an A4 break is a counterfeiting break.
|
|
The architectural thesis of XSS, formalised in Theorem~3, is that the
|
|
turnstile (U3 plus X's independent $\pool$) bounds the damage of an A4
|
|
failure to $\pool$---so A4 governs \emph{privacy-pool internal} correctness
|
|
and the equality $\pool = \sum_{\text{live notes}}\mathrm{val}$, but not the
|
|
\emph{global} no-inflation floor.
|
|
\end{remark}
|
|
|
|
%% ===================================================================
|
|
\section{Theorem 1: No double-spend}
|
|
\label{sec:t1}
|
|
|
|
\begin{theorem}[No double-spend]
|
|
\label{thm:double}
|
|
Under A1 (total order, atomic apply), A2 (consumed/nullifier set
|
|
completeness, persistence, check-before-consume), and A5 (collision
|
|
resistance), every UTXO and every shielded note can be consumed by at most
|
|
one applied transition over the entire ledger history. Equivalently: no
|
|
applied transition consumes a UTXO already \textsc{consumed} or a
|
|
commitment already \texttt{consumed}, and no applied \textsc{unshield} (or
|
|
Z-spend) publishes a nullifier already in $\NF$.
|
|
\end{theorem}
|
|
|
|
\begin{proof}
|
|
Fix a UTXO $u$ (the note case is identical with ``nullifier $N$ in $\NF$''
|
|
in place of ``$\mathrm{st}(u)=\textsc{consumed}$'', and ``commitment
|
|
$\kappa$ with $\kappa.\texttt{consumed}$'' for the lock case). By A5,
|
|
$u$ has a unique identifier, so ``the same UTXO'' is well defined: two
|
|
references with the same id are the same object, and no two distinct
|
|
objects collide.
|
|
|
|
Suppose for contradiction that two applied transitions $t_1,t_2$ each
|
|
consume $u$. By A1 the applied transitions are totally ordered; without
|
|
loss of generality $t_1$ precedes $t_2$. Consider the moment $t_2$ is
|
|
evaluated. By the atomic-apply clause of A1, $t_1$'s \emph{entire} effect
|
|
was applied before $t_2$ is evaluated, and by A2(i) the consume effect of
|
|
$t_1$ is recorded and \emph{persistent}: at the height of $t_2$, $u$ is
|
|
recorded \textsc{consumed} (resp.\ $N\in\NF$, resp.\
|
|
$\kappa.\texttt{consumed}=\textsc{true}$). By A2(iii) the consume guard
|
|
checks this set \emph{before} permitting the consume: $t_2$'s precondition
|
|
requires its inputs be \textsc{spendable} (for \textsc{spend}/\textsc{lock}),
|
|
its commitments be live (for \textsc{settle}), or $N\notin\NF$ (for
|
|
\textsc{unshield}). Each of these fails for $u$ (resp.\ $\kappa$, $N$).
|
|
Hence $t_2$'s precondition is false; by Definition~\ref{def:ledger} a
|
|
transition with a false precondition is rejected and applies no effect.
|
|
This contradicts the assumption that $t_2$ is an \emph{applied} transition
|
|
consuming $u$.
|
|
|
|
Therefore at most one applied transition consumes $u$ (resp.\ $\kappa$,
|
|
$N$). As $u$ was arbitrary, this holds for every UTXO, every commitment,
|
|
and every note. $\qed$
|
|
\end{proof}
|
|
|
|
\begin{remark}[The three pillars are each necessary]
|
|
\label{rem:t1pillars}
|
|
The proof uses exactly three facts, and each is load-bearing:
|
|
(i) \emph{total order + atomicity} (A1) is what lets us speak of ``$t_1$
|
|
before $t_2$'' and guarantees $t_1$ fully landed before $t_2$ is judged---
|
|
a fork that finalised two conflicting histories would let both consume $u$,
|
|
which is why Theorem~1 \emph{reduces} double-spend safety to consensus
|
|
safety; (ii) \emph{completeness + persistence} (A2 i,ii) is what makes the
|
|
record of $t_1$'s consume visible at $t_2$'s height---a consumed-set that
|
|
forgot, or that lived only in one partition, would not block $t_2$; (iii)
|
|
\emph{check-before-consume} (A2 iii) is the idempotent guard---the
|
|
precondition reads the set and refuses. Drop any one and the proof fails,
|
|
which is the precise sense in which these are the implementation
|
|
obligations for double-spend safety. The cross-boundary case (a note both
|
|
unshielded on X and re-spent on Z) is the statement that A2(ii) holds for a
|
|
\emph{single} $\NF$ shared across the seam; LP-225 \S10(2) flags this as the
|
|
specific \CRYPTO{} obligation, and it is the hypothesis the theorem makes
|
|
explicit, not one it discharges.
|
|
\end{remark}
|
|
|
|
%% ===================================================================
|
|
\section{Theorem 2: Conservation and no inflation}
|
|
\label{sec:t2}
|
|
|
|
\begin{theorem}[Conservation / no inflation]
|
|
\label{thm:conserve}
|
|
Under A1, the value function $\Val$ of Definition~\ref{def:V} satisfies, for
|
|
every applied transition $t$,
|
|
\[
|
|
\Delta\Val(t) =
|
|
\begin{cases}
|
|
+\,\mathrm{Sched}(h) & t = \textsc{rewardMint at height } h,\\
|
|
-\,f \le 0 & t \in \{\textsc{spend},\textsc{lock}\}\ \text{(fee } f \ge 0),\\
|
|
0 & t \in \{\textsc{settle},\textsc{shield},\textsc{unshield}\}.
|
|
\end{cases}
|
|
\]
|
|
Consequently, over any run $\Sigma_0\to\cdots\to\Sigma_n$,
|
|
\[
|
|
\Val(\Sigma_n) \;=\; \Val(\Sigma_0)
|
|
\;+\; \sum_{\substack{j:\ t_j=\textsc{rewardMint}}}\!\!\mathrm{Sched}(h_j)
|
|
\;-\; \sum_{\substack{j:\ t_j\in\{\textsc{spend},\textsc{lock}\}}}\!\! f_j.
|
|
\]
|
|
In particular $\Val$ never increases except by \textsc{rewardMint}, and the
|
|
total increase up to height $H$ is exactly
|
|
$\sum_{h\le H}\mathrm{Sched}(h)$, a bounded, deterministic, X-enforced
|
|
quantity. No transition admits unbounded or out-of-schedule mint.
|
|
\end{theorem}
|
|
|
|
\begin{proof}
|
|
We compute $\Delta\Val$ transition-by-transition, using
|
|
Definition~\ref{def:V} ($\Val=\spend+\lock+\commit+\pool$) and the effects
|
|
of Section~\ref{sec:transitions}. By A1 each applied transition's effect is
|
|
applied atomically to a unique pre-state, so the deltas compose additively
|
|
along the run, giving the displayed telescoping sum once the per-transition
|
|
deltas are established.
|
|
|
|
\emph{\textsc{spend}.} Inputs $I$ (\textsc{spendable}) become
|
|
\textsc{consumed}: $\spend$ decreases by $\mathrm{val}(I)$. Outputs $O$
|
|
added \textsc{spendable}: $\spend$ increases by $\mathrm{val}(O)$. The
|
|
precondition P-conserve forces $\mathrm{val}(I)=\mathrm{val}(O)+f$. Hence
|
|
$\Delta\spend = \mathrm{val}(O)-\mathrm{val}(I) = -f$; $\lock,\commit,\pool$
|
|
unchanged. $\Delta\Val=-f\le0$. \emph{This is the implemented invariant:}
|
|
\texttt{FlowChecker.Verify} rejects unless $\mathrm{produced}\le
|
|
\mathrm{consumed}$ per asset, i.e.\ $\mathrm{val}(O)+f\le\mathrm{val}(I)$,
|
|
so a spend can never make $\Val$ rise.
|
|
|
|
\emph{\textsc{lock}.} $I$ (\textsc{spendable}) $\to$ \textsc{consumed}:
|
|
$\spend$ down by $\mathrm{val}(I)$. One commitment $\kappa$ with
|
|
$\mathrm{amt}(\kappa)=\mathrm{val}(I)-f$ becomes live: $\commit$ up by
|
|
$\mathrm{val}(I)-f$. $\Delta\Val = -\mathrm{val}(I)+(\mathrm{val}(I)-f)
|
|
= -f\le0$. (Value moves spendable~$\to$~committed, less the burned fee.)
|
|
|
|
\emph{\textsc{settle} (no shielded leg).} Commitments $\{\kappa_i\}$ go
|
|
\texttt{consumed}: $\commit$ down by $\sum_i\mathrm{amt}(\kappa_i)$. Outputs
|
|
$O$ added \textsc{spendable}: $\spend$ up by $\mathrm{val}(O)$. Precondition
|
|
(iii) settlement-conservation forces $\sum_i\mathrm{amt}(\kappa_i)=
|
|
\mathrm{val}(O)$. $\Delta\Val = -\sum_i\mathrm{amt}(\kappa_i)+\mathrm{val}(O)
|
|
= 0$. (With a shielded leg, the shielded portion is realised by composing
|
|
\textsc{shield}, whose delta is $0$ by the next case; settlement-conservation
|
|
then reads $\sum_i\mathrm{amt}(\kappa_i)=\mathrm{val}(O)+v_{\text{shielded}}$,
|
|
and the total delta is still $0$.) X checks the sum directly and does
|
|
\emph{not} re-execute the module---this is the LP-224 ``agree on the result,
|
|
check the sum'' discipline.
|
|
|
|
\emph{\textsc{shield}.} A visible $v$ is burned: $\spend$ down by $v$. A
|
|
commitment $C$ is added to $\CM$ and $\pool\gets\pool+v$: $\pool$ up by $v$.
|
|
$\commit,\lock$ unchanged. $\Delta\Val = -v + v = 0$. This is the turnstile
|
|
entry: the value does not vanish from $\Val$, it moves from the visible
|
|
term $\spend$ into the scalar term $\pool$. (Note the proof system is
|
|
\emph{not} invoked to compute the delta: the burned $v$ is a public X
|
|
amount, and $\pool$ is credited by that same public $v$. A4 governs only
|
|
whether $C$ \emph{inside} the pool is a faithful commitment to $v$, not the
|
|
$\Delta\Val=0$ accounting.)
|
|
|
|
\emph{\textsc{unshield}.} A note of value $v$ is nullified and $\pool\gets
|
|
\pool-v$: $\pool$ down by $v$ (and U3 guarantees $\pool\ge v$ beforehand, so
|
|
$\pool$ stays in $\mathbb{N}$). A spendable UTXO of value $v$ is minted:
|
|
$\spend$ up by $v$. $\Delta\Val = -v + v = 0$. The turnstile exit: value
|
|
moves from $\pool$ back to $\spend$, conserving $\Val$. Again the debit uses
|
|
the \emph{public} minted amount $v$, matched to the credit on $\spend$.
|
|
|
|
\emph{\textsc{rewardMint}.} A spendable $r=\mathrm{Sched}(h)$ is created:
|
|
$\spend$ up by $r$. No pool is debited. $\Delta\Val = +r$. By precondition,
|
|
$r$ is exactly the schedule's per-height amount and the per-height issuance
|
|
is minted at most once, so the cumulative increase to height $H$ is
|
|
$\sum_{h\le H}\mathrm{Sched}(h)$, bounded and deterministic.
|
|
|
|
Summing along the run (the deltas compose by A1's atomic apply) gives the
|
|
displayed equation. Every term except the \textsc{rewardMint} sum is
|
|
$\le 0$, so $\Val$ never rises except by \textsc{rewardMint}; and that rise
|
|
is the bounded schedule total. $\qed$
|
|
\end{proof}
|
|
|
|
\begin{corollary}[Boundary turnstile is value-neutral; visible $+$ shielded $=$ const]
|
|
\label{cor:turnstile}
|
|
Restricting to runs with no \textsc{rewardMint} and no fees (or folding fees
|
|
into $\mathrm{Burned}$ per Remark~\ref{rem:fee}), the LP-225 boundary
|
|
invariant holds: for every height $h$,
|
|
\[
|
|
\underbrace{[\,\spend(\Sigma_h)+\lock(\Sigma_h)+\commit(\Sigma_h)\,]}_{\text{visible}}
|
|
\;+\; \underbrace{\pool(\Sigma_h)}_{\text{shielded (X's scalar)}}
|
|
\;=\; \total(a),\quad\text{constant in }h.
|
|
\]
|
|
\end{corollary}
|
|
\begin{proof}
|
|
Immediate from Theorem~\ref{thm:conserve}: with no \textsc{rewardMint} and
|
|
no fee sink, every $\Delta\Val=0$, so $\Val=\spend+\lock+\commit+\pool$ is
|
|
constant; set $\total(a):=\Val(\Sigma_0)$. \textsc{shield}/\textsc{unshield}
|
|
shift mass between the visible terms and $\pool$ without changing the sum.
|
|
$\qed$
|
|
\end{proof}
|
|
|
|
\begin{remark}[What ``no inflation'' does and does not assert]
|
|
\label{rem:t2scope}
|
|
Theorem~\ref{thm:conserve} is an \emph{accounting} statement about $\Val$,
|
|
which uses the scalar $\pool$, \emph{not} the private sum of note values. It
|
|
proves: no XSS transition raises the total except the scheduled mint. It
|
|
does \emph{not} by itself prove that the shielded pool's \emph{internal}
|
|
contents are consistent ($\pool=\sum_{\text{live notes}}\mathrm{val}$); that
|
|
equality is what A4 (proof soundness) buys, and its failure is the subject
|
|
of Theorem~3. The separation is deliberate and is the whole point: global
|
|
no-inflation is provable from \emph{arithmetic X enforces on public boundary
|
|
amounts} (A1 alone, modulo the schedule), independent of the proof system.
|
|
\end{remark}
|
|
|
|
%% ===================================================================
|
|
\section{Theorem 3: The turnstile backstop (why XSS $>$ Zcash)}
|
|
\label{sec:t3}
|
|
|
|
This is the headline. Theorems~1 and~2 assume the proof system is sound
|
|
(A4). Theorem~3 \emph{drops} A4 and bounds the damage.
|
|
|
|
\subsection{The Zcash counterfeiting class}
|
|
\label{sec:zcash}
|
|
|
|
In 2018, Ariel Gabizon discovered a soundness flaw in the BCTV14 zk-SNARK
|
|
construction used by Zcash's original Sprout shielded pool: a spurious
|
|
element in the proving key allowed an attacker to produce \emph{accepting
|
|
proofs of false statements}, i.e.\ to forge a shielded ``spend'' of value
|
|
that was never deposited. Disclosed as CVE-2019-7167 and remediated by the
|
|
2018 Sapling upgrade, the flaw permitted---in principle---\emph{unbounded,
|
|
undetectable} counterfeiting of shielded value, because the only thing
|
|
standing between a forged proof and minted value was the soundness of the
|
|
proof system itself~\cite{ecc2019,zfnd2019}. Electric Coin Company found no
|
|
evidence the flaw was exploited.
|
|
|
|
The structural lesson: in the Sprout design, the proof system's soundness
|
|
was the \emph{sole} line of defence for the integrity of the shielded
|
|
supply. A break at that layer is a break of the whole supply. Zcash later
|
|
operated per-pool value-balance (``turnstile'') tracking, and ECC's own
|
|
analysis is that such tracking \emph{bounds} the damage of an undetected
|
|
break to the size of the affected pool---but in the relevant era this was
|
|
a monitoring/alerting mechanism layered \emph{above} the proof system, not a
|
|
hard per-transaction consensus reject derived from an independently
|
|
maintained pool total.
|
|
|
|
\begin{remark}[Honest framing of the contrast]
|
|
\label{rem:honestzcash}
|
|
We do \emph{not} claim Zcash had no turnstile. We claim a precise structural
|
|
difference: XSS makes the pool-total balance a \textbf{consensus-layer
|
|
precondition U3 of the unshield transition itself}---an unshield that would
|
|
drive X's independently maintained $\pool$ negative is \emph{rejected at
|
|
execution}, fail-closed, by the same X check that enforces
|
|
$\mathrm{inputs}\ge\mathrm{outputs}+\mathrm{fee}$ (Theorem~\ref{thm:conserve},
|
|
the \texttt{FlowChecker} discipline). The bound is therefore not a heuristic
|
|
that detects an anomaly after the fact; it is an invariant that no valid
|
|
state transition can violate. Where Zcash's defence-in-depth for the
|
|
\emph{integrity of supply} ultimately rested on A4, XSS's
|
|
\emph{global no-inflation floor} rests on A1 (X's arithmetic), with A4
|
|
demoted to governing only the pool's internal correctness.
|
|
\end{remark}
|
|
|
|
\subsection{The backstop theorem}
|
|
|
|
\begin{theorem}[Turnstile backstop under unsound proofs]
|
|
\label{thm:backstop}
|
|
Assume A1, A2, A5, and the turnstile precondition U3 (an \textsc{unshield}
|
|
of value $v$ requires $\pool \ge v$, and atomically sets
|
|
$\pool\gets\pool-v$), with $\pool$ maintained on X by the
|
|
\textsc{shield}/\textsc{unshield} bookkeeping of Section~\ref{sec:transitions}.
|
|
\textbf{Drop A4 entirely}: allow the adversary to produce accepting
|
|
shielded validity proofs for arbitrary (including false) statements. Then
|
|
over any run, the total value ever moved out of the shielded pool into the
|
|
visible ledger is bounded by the total value ever legitimately moved in:
|
|
\[
|
|
\sum_{\textsc{unshield}} v_{\text{out}}
|
|
\;\;\le\;\;
|
|
\pool(\Sigma_0) \;+\; \sum_{\textsc{shield}} v_{\text{in}},
|
|
\]
|
|
and at every height $\pool(\Sigma_h)\ge 0$. In particular the visible
|
|
supply $\spend+\lock+\commit$ can never exceed
|
|
$\total(a) = \Val(\Sigma_0) + (\text{scheduled mint})$: \textbf{a shielded
|
|
proof forgery cannot inflate the visible supply, and cannot extract from the
|
|
pool more than was put in.}
|
|
\end{theorem}
|
|
|
|
\begin{proof}
|
|
Track the scalar $\pool$ as an integer over the run. It changes only on
|
|
\textsc{shield} ($\pool\gets\pool+v_{\text{in}}$) and \textsc{unshield}
|
|
($\pool\gets\pool-v_{\text{out}}$); these updates are by A1 atomic and
|
|
applied in a single total order. By precondition U3, an applied
|
|
\textsc{unshield} of value $v_{\text{out}}$ requires
|
|
$\pool\ge v_{\text{out}}$ in the pre-state; hence after it $\pool\ge 0$.
|
|
\textsc{shield} only increases $\pool$. By induction over the totally
|
|
ordered run, $\pool(\Sigma_h)\ge 0$ for all $h$.
|
|
|
|
Now sum the updates. After the run,
|
|
\[
|
|
\pool(\Sigma_n) = \pool(\Sigma_0) + \sum_{\textsc{shield}}v_{\text{in}}
|
|
- \sum_{\textsc{unshield}}v_{\text{out}} \;\ge\; 0,
|
|
\]
|
|
which rearranges to exactly
|
|
$\sum_{\textsc{unshield}}v_{\text{out}}\le\pool(\Sigma_0)+
|
|
\sum_{\textsc{shield}}v_{\text{in}}$.
|
|
|
|
Crucially, \emph{nothing in this argument used A4}. The bound U3 is a check
|
|
X performs on its \emph{own} scalar $\pool$ against the \emph{public} minted
|
|
amount $v_{\text{out}}$; the adversary's forged proof may convince the
|
|
shielded side that some note is spendable, but it cannot change the value of
|
|
X's integer $\pool$, and it cannot make X's U3 comparison
|
|
$\pool\ge v_{\text{out}}$ pass when it would otherwise fail. The forgery's
|
|
power is confined to the shielded pool's internal belief about which notes
|
|
are live; the moment value attempts to \emph{leave} via \textsc{unshield},
|
|
it meets X's pool-total floor.
|
|
|
|
Finally, by Theorem~\ref{thm:conserve} every \textsc{unshield} has
|
|
$\Delta\Val=0$ \emph{regardless of A4} (its delta is the public
|
|
$-v_{\text{out}}$ on $\pool$ plus $+v_{\text{out}}$ on $\spend$), so the
|
|
visible supply rises by exactly what $\pool$ falls, and $\pool$ never goes
|
|
negative; hence the visible supply is bounded by $\total(a)$ as stated.
|
|
$\qed$
|
|
\end{proof}
|
|
|
|
\begin{corollary}[Graceful degradation; the failure is contained, not catastrophic]
|
|
\label{cor:degrade}
|
|
Under an A4 break, the worst an adversary can achieve is to redistribute
|
|
\emph{within the shielded pool's $\pool$ budget}---e.g.\ unshield value that,
|
|
inside the pool, ``belonged'' to another user---stealing up to $\pool$ from
|
|
honest shielded holders, but \textbf{minting zero net new supply}. The blast
|
|
radius of a total proof-soundness failure is therefore at most $\pool$, the
|
|
shielded pool total, and is borne as a redistribution among shielded users,
|
|
never as inflation of the asset. Contrast the Zcash-Sprout class, where the
|
|
same break is \emph{unbounded} counterfeiting of new supply.
|
|
\end{corollary}
|
|
\begin{proof}
|
|
By Theorem~\ref{thm:backstop}, total unshielded value $\le\pool(\Sigma_0)+
|
|
\sum v_{\text{in}}$, the value legitimately placed in the pool. An adversary
|
|
who can forge proofs can direct unshields to itself up to that ceiling,
|
|
draining at most the pool's contents; it cannot exceed the ceiling, so net
|
|
new supply is zero. The honest-user loss is bounded by $\pool$. $\qed$
|
|
\end{proof}
|
|
|
|
\begin{remark}[Where this leaves A4]
|
|
\label{rem:a4role}
|
|
Theorem~3 does not make A4 unnecessary---A4 is what guarantees that the
|
|
\emph{distribution} of value inside the pool is correct (your notes are
|
|
yours; the equality $\pool=\sum_{\text{live notes}}\mathrm{val}$ holds), and
|
|
hence that an honest shielded user is not robbed by a forger. It makes A4
|
|
\emph{non-catastrophic}: its failure is a bounded theft within the pool, not
|
|
an unbounded mint that debases every holder of the asset. This is the
|
|
precise sense in which the XSS turnstile, as a consensus invariant, is
|
|
strictly stronger than relying on proof soundness alone, and is the
|
|
soundness argument for ``XSS contains the Zcash counterfeiting class.''
|
|
\end{remark}
|
|
|
|
%% ===================================================================
|
|
\section{Model-level results vs.\ implementation obligations}
|
|
\label{sec:honest}
|
|
|
|
\subsection{What is proven, and at what layer}
|
|
|
|
\begin{itemize}[leftmargin=2em]
|
|
\item \textbf{Proven at the model level} (Theorems~1--3, from A1--A5 as
|
|
stated): given spec-faithful primitives, double-spend is impossible,
|
|
inflation is impossible beyond the scheduled mint, and a total
|
|
shielded-proof-soundness failure is contained to the shielded pool total
|
|
(no visible inflation, bounded intra-pool redistribution). These are
|
|
theorems about the \emph{state machine}, and they are unconditional given
|
|
the assumptions.
|
|
\item \textbf{Grounded in implemented code}: the visible-side conservation
|
|
primitive ($\mathrm{inputs}\ge\mathrm{outputs}+\mathrm{fee}$ via
|
|
\texttt{lux.VerifyTx}/\texttt{FlowChecker}), UTXO consume-once, the Z
|
|
note/commitment/nullifier objects and persistent $\NF$, the commitment
|
|
and nullifier primitives, and the P3Q and starkfri verifiers all exist
|
|
today. Theorem~1's machinery (A1, A2) is largely \IMPL{}.
|
|
\item \textbf{Design-only, and required before the model binds to the
|
|
system}: the items below. Until they are implemented to spec, the
|
|
theorems are statements about XSS-as-specified, not about the running
|
|
code.
|
|
\end{itemize}
|
|
|
|
\subsection{The implementation obligations, enumerated}
|
|
\label{sec:obligations}
|
|
|
|
\begin{enumerate}[leftmargin=2em]
|
|
\item \textbf{The scalar $\pool$ (\texttt{shieldedPoolTotal}) must be
|
|
implemented and X-enforced.} \DESIGN{}. This is the linchpin of Theorems~2
|
|
and~3 and \emph{no code tracks it today} (\S\ref{sec:scope}; LP-225 \S5,
|
|
\S9b/P2). The shield path must credit it by the public burned amount, the
|
|
unshield path must debit it by the public minted amount and enforce U3
|
|
($\pool\ge v$) as a hard, fail-closed precondition---in the same place and
|
|
with the same discipline as the existing \texttt{FlowChecker} conservation
|
|
check. Without U3, Theorem~3 is vacuous.
|
|
|
|
\item \textbf{The shield/unshield execution must be implemented.} \DESIGN{}.
|
|
The ZKVM handlers are stubs
|
|
(\texttt{node/chains/zkvm/handlers.go}: ``Not implemented'' / ``Would
|
|
implement shield proof generation''). The model's \textsc{shield} and
|
|
\textsc{unshield} transitions are conditional on these existing and
|
|
performing exactly the burn-credit and nullify-debit-mint effects above.
|
|
|
|
\item \textbf{A2 cross-boundary completeness (S4) must be discharged.}
|
|
\CRYPTO{}/\DESIGN{}. Theorem~1 assumes a \emph{single} $\NF$ arbitrates
|
|
both X-side unshield and Z-side spend with no partition admitting two
|
|
consumptions (LP-225 \S10 item 2). The persistent $\NF$ exists; the
|
|
cross-seam single-arbiter property must be designed and reviewed.
|
|
|
|
\item \textbf{A3 binding/hiding and nullifier unforgeability must be pinned
|
|
and reviewed as deployed.} \CRYPTO{}. The \texttt{CommitmentScheme}
|
|
interface and the Poseidon2/Pedersen instances exist; the deployed choice
|
|
and parameters require cryptographer sign-off (LP-225 \S10 item 1).
|
|
|
|
\item \textbf{A4 soundness: the settlement/shield AIR must be specified and
|
|
reviewed.} \CRYPTO{}. starkfri verifies a STARK/FRI proof but the
|
|
settlement-validity AIR does not yet exist (LP-225 \S10 items 4--5); the
|
|
P3Q attestation is an explicit trusted-operator assumption with a policy
|
|
boundary (when is attestation acceptable vs.\ when is a STARK mandatory?)
|
|
to be defined. \textbf{Theorem~3 is the reason an A4 gap is survivable,
|
|
not the reason it can be ignored}: A4 still governs intra-pool correctness
|
|
(Corollary~\ref{cor:degrade}, Remark~\ref{rem:a4role}).
|
|
|
|
\item \textbf{\textsc{rewardMint} must be moved to an X-level,
|
|
schedule-gated primitive.} \DESIGN{}. Today P mints rewards on its own
|
|
chain (LP-225 \S9/S3, \S10 item 2), contradicting ``X settles.''
|
|
Theorem~2's ``only value-increasing transition is bounded by an X-enforced
|
|
schedule'' holds only once issuance is an X-settled, deterministic,
|
|
per-height-once primitive.
|
|
\end{enumerate}
|
|
|
|
\subsection{Mapping to the LP-225 validation properties}
|
|
|
|
The three theorems are the formal core of LP-225's safety properties
|
|
S1--S5 and validation checklist P1--P8:
|
|
|
|
\begin{center}
|
|
\begin{tabular}{@{}l l p{4.6cm}@{}}
|
|
\toprule
|
|
This proof & LP-225 property & Status of the underlying mechanism \\
|
|
\midrule
|
|
Thm~1 (no double-spend) & S1, S4, S5; P1, P8 & A1/A2 mostly \IMPL{}; S4 seam \CRYPTO{} \\
|
|
Thm~2 (conservation/no inflation)& S2; P2 & visible \IMPL{}; $\pool$ \DESIGN{} \\
|
|
Thm~3 (turnstile backstop) & S2 shielded term; P2 & U3 $+$ $\pool$ \DESIGN{} (the new obligation) \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{center}
|
|
|
|
\noindent The single most important deliverable the proof identifies is
|
|
obligation~1: \textbf{implement and X-enforce \texttt{shieldedPoolTotal}
|
|
with the fail-closed U3 check}. It is the mechanism that turns the
|
|
Zcash-class failure from catastrophic (unbounded mint) into contained
|
|
(bounded intra-pool redistribution), and it costs one scalar and one
|
|
comparison, enforced in the same code path that already enforces visible
|
|
conservation. Everything else in the shielded design (A3, A4) then governs
|
|
\emph{who} holds the shielded value, never \emph{how much} can leave the
|
|
pool.
|
|
|
|
%% ===================================================================
|
|
\section{Conclusion}
|
|
\label{sec:conclusion}
|
|
|
|
We have proven, at the model level, that the XSS unified-settlement model
|
|
with a Z-Chain shielded pool makes double-spend and inflation impossible
|
|
under explicit, enumerated assumptions, and---the headline---that even a
|
|
total failure of the shielded validity-proof system (the assumption that
|
|
breaks Zcash-class designs) cannot inflate the asset or extract more than
|
|
the pool holds, because X maintains the shielded pool total as a scalar and
|
|
refuses, at the consensus layer and fail-closed, any unshield that would
|
|
drive it negative. The proof is honestly conditional: the shield/unshield
|
|
execution and the \texttt{shieldedPoolTotal} scalar are design-only today
|
|
(LP-225), and the cryptographic assumptions A3--A4 require sign-off. What
|
|
the proof establishes is the implication---\emph{spec-faithful primitives
|
|
$\Rightarrow$ safety, with graceful degradation under the hardest
|
|
assumption}---together with the exact contract (obligations~1--6) the
|
|
implementation must discharge for the running system to inherit the model's
|
|
guarantees.
|
|
|
|
\begin{thebibliography}{9}
|
|
|
|
\bibitem{lp225}
|
|
Lux Industries.
|
|
\emph{LP-225: XSS --- The X-Chain Settlement Spine: One Economic Ledger,
|
|
Many Computing Chains.} Lux Improvement Proposal, 2026.
|
|
(Design specification; \texttt{\textasciitilde/work/lux/papers/lp-225-xss-x-chain-settlement-spine}.)
|
|
|
|
\bibitem{nakamoto2008}
|
|
S. Nakamoto.
|
|
\emph{Bitcoin: A Peer-to-Peer Electronic Cash System.} 2008.
|
|
(The UTXO model and the inputs-equal-outputs conservation rule.)
|
|
|
|
\bibitem{sapling2018}
|
|
S. Bowe, A. Gabizon, et al.
|
|
\emph{Zcash Protocol Specification (Sapling).} 2018.
|
|
(Shielded notes, commitments, nullifiers, and the spend/output circuit.)
|
|
|
|
\bibitem{ecc2019}
|
|
Electric Coin Company.
|
|
\emph{Zcash Counterfeiting Vulnerability Successfully Remediated.}
|
|
Disclosure of CVE-2019-7167, the BCTV14 soundness flaw in the Sprout
|
|
shielded pool (discovered 2018-03-01 by A.\ Gabizon, remediated in the
|
|
Sapling upgrade 2018-10-28).
|
|
\url{https://electriccoin.co/blog/zcash-counterfeiting-vulnerability-successfully-remediated/}, 2019.
|
|
|
|
\bibitem{zfnd2019}
|
|
Zcash Foundation.
|
|
\emph{Concerning the Sprout Vulnerability CVE-2019-7167.}
|
|
\url{https://zfnd.org/concerning-the-sprout-vulnerability-cve-2019-7167/}, 2019.
|
|
|
|
\bibitem{fips204}
|
|
NIST.
|
|
\emph{FIPS 204: Module-Lattice-Based Digital Signature Standard (ML-DSA).}
|
|
2024. (The verifier core of the P3Q precompile, \texttt{0x012205}.)
|
|
|
|
\bibitem{lp218}
|
|
Lux Industries.
|
|
\emph{LP-218: ZAP P3Q Post-Quantum Rollup.} 2026.
|
|
|
|
\bibitem{lp221}
|
|
Lux Industries.
|
|
\emph{LP-221: STARK-FRI Verifier.} 2026.
|
|
(The starkfri precompile, \texttt{0x012220}.)
|
|
|
|
\bibitem{lp224}
|
|
Lux Industries.
|
|
\emph{LP-224: D-Chain Deposit/Withdraw Consensus-Wire Activation.} 2026.
|
|
(The ``agree on the result, check the sum'' settlement discipline.)
|
|
|
|
\bibitem{quasarsound}
|
|
Z. Kelling, Lux Industries.
|
|
\emph{QuasarCert Soundness: Canonical Formal Specification, Quasar 3.0.}
|
|
2025. (X-consensus safety/finality; companion proof
|
|
\texttt{quasar-cert-soundness.tex}.)
|
|
|
|
\end{thebibliography}
|
|
|
|
\end{document}
|