From 2691110e0d3918714d0397f182da4d65a19f4fbe Mon Sep 17 00:00:00 2001 From: ristik Date: Mon, 6 Jul 2026 17:54:36 +0300 Subject: [PATCH 1/6] rmt6a (draft) --- aggregation-layer.tex | 342 +++++++++++++++++++++++++++++++++--------- 1 file changed, 270 insertions(+), 72 deletions(-) diff --git a/aggregation-layer.tex b/aggregation-layer.tex index 8c7dbdb..cfe7582 100644 --- a/aggregation-layer.tex +++ b/aggregation-layer.tex @@ -31,7 +31,12 @@ \algnewcommand{\Assert}{\textbf{assert}\xspace} \MakeRobust{\Call} % for nested Calls +\usepackage{amsthm} \newtheorem{definition}{Definition} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}{Lemma} +\newtheorem{corollary}{Corollary} +\newtheorem{remark}{Remark} \tikzset{ block/.style={rectangle, draw, text centered, minimum height=2em, minimum width=5cm}, @@ -65,7 +70,7 @@ \maketitle \begin{abstract} -Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify a single critical property that the Consensus Layer must verify on each round---\emph{prior-state preservation}---and observe that the remaining desirable properties of the trustless Key-Value store (canonical tree shape, batch incorporation, no phantom inserts, completeness) are not required by the Unicity Aggregator's security model. This statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. +Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT3 consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. A critical review shows that the coherent-placement half is not optional: we exhibit a concrete equivocation attack against the structure-only proof. The remaining desirable properties of the trustless Key-Value store (batch incorporation, no phantom inserts, completeness) are not required by the Unicity Aggregator's security model. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. \end{abstract} @@ -77,13 +82,13 @@ \section{Motivation} To scale further, we use cryptographic zero-knowledge proofs (ZKPs) to compress the size of the consistency proofs. As an application of ZKPs, this use-case is fundamentally more efficient than using ZKPs to process the transaction data itself, as is done in many privacy coins and ZK-rollups: the statement being proved is a single tree-update, with the batch as a private witness, not the whole execution trace of a virtual machine. -A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer only needs to be convinced that \emph{no previously-recorded leaf was deleted or modified}. The remaining desirable properties of the Aggregation Layer---canonical tree shape, batch incorporation, no phantom inserts, completeness---are self-policed by the protocol layer that lives around the public root commitment: any deviation by a dishonest aggregator at insert time only damages its own ability to serve subsequent inclusion proofs against that root, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. +A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer needs to be convinced that \emph{no previously-recorded leaf was deleted or modified} and that \emph{every new leaf is placed coherently with its key}; the critical review of Section~\ref{sec:critical-review} shows, by a concrete attack, that the second half cannot be dropped. The remaining desirable properties of the Aggregation Layer---batch incorporation, no phantom inserts, completeness---are self-policed by the protocol layer that lives around the public root commitment: their violation only damages the dishonest aggregator's own ability to serve users, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument, and Section~\ref{sec:consistency-formal} proves that the resulting statement is sufficient. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. In this paper, we show how to scale the Aggregation Layer to $10\,000$ tx/s \emph{per shard} and beyond. This figure was the original design target; the measured proving throughput of our reference implementation exceeds it by roughly $3\times$ on a single consumer-class CPU (Section~\ref{sec:custom-air-circuit}). Due to the small proof size and efficient verification, the Consensus Layer can support a practically unlimited number of such trustless shards. Table~\ref{tab:zk-comparison} compares different ZKP technologies. We have picked subjectively the most appropriate ZK schemes and supporting front-ends (``stacks''); the Plonky3 AIR rows now report measured numbers from our implementation~\cite{rsmtair}. \begin{table*}[h!] \centering -\caption{Comparison of zero-knowledge proof technologies for compression of non-deletion proofs.} +\caption{Comparison of zero-knowledge proof technologies for compression of consistency proofs.} \label{tab:zk-comparison} \begin{tabular}{@{}lccccccc@{}} \toprule @@ -125,7 +130,7 @@ \subsection{Authenticated Append-Only Dictionaries} Sparse Merkle Trees originate as an extension of binary Merkle hash trees to large key spaces: every potential key is assigned a deterministic position, and the proof that a key is absent is just the root computation taken over canonical-empty subtrees. The systematic study of their cost and engineering trade-offs is more recent. Dahlberg, Pulls, and Peeters~\cite{dahlberg2016smt} present efficient SMT constructions and caching strategies for membership and non-membership proofs with realistic key-space sizes; their analysis is part of the foundation that makes deep-keyed SMTs practical. The path-compressed (radix) variant we use in the Aggregation Layer (Section~\ref{sec:custom-air-circuit}) is a constant-factor refinement of the same line of work. -A related and operationally closer system is Certificate Transparency (CT)~\cite{rfc6962}, which maintains append-only Merkle logs of TLS certificates and provides both inclusion and \emph{consistency} proofs between successive signed tree heads. The cryptographic role of the CT consistency proof is conceptually the same as our non-deletion proof: it convinces an auditor that a new log state extends the previous one without rewriting it. The differences are operational: CT logs are chronologically append-only with no key-determined position, log entries are not deduplicated against double-spending semantics, and there is no per-round ZK compression of the consistency witness. Our use of SMTs adds a key-determined position (so that double-spending becomes a key collision) and our use of ZK compresses the per-round witness to a constant size. +A related and operationally closer system is Certificate Transparency (CT)~\cite{rfc6962}, which maintains append-only Merkle logs of TLS certificates and provides both inclusion and \emph{consistency} proofs between successive signed tree heads. The cryptographic role of the CT consistency proof is conceptually the same as our consistency proof: it convinces an auditor that a new log state extends the previous one without rewriting it. The differences are operational: CT logs are chronologically append-only with no key-determined position, log entries are not deduplicated against double-spending semantics, and there is no per-round ZK compression of the consistency witness. Our use of SMTs adds a key-determined position (so that double-spending becomes a key collision) and our use of ZK compresses the per-round witness to a constant size. \subsection{Comparison with ZK-Rollups on Ethereum L1} @@ -220,7 +225,7 @@ \subsection{Aggregation Layer} The Aggregation layer is sharded based on keyspace slices and can be made hierarchical, as shown in Figure~\ref{fig:sharding}. -\emph{Proof of non-deletion}: Once a key is set, it has to remain there forever. Every state change of the Aggregation Layer (or a slice thereof) is accompanied by a cryptographic proof establishing that pre-existing keys have not been removed or their values altered, only new keys were added. The size of this proof is logarithmic with respect to the tree's capacity and linear with respect to the size of the inclusion batch. This can be reduced to a constant size using a SNARK. Assuming correct validation of the non-deletion proof and chaining of the Aggregation Layer's state roots by the Consensus Layer, the Aggregation Layer can be considered trustless. +\emph{Consistency proof}: Once a key is set, it has to remain there forever. Every state change of the Aggregation Layer (or a slice thereof) is accompanied by a cryptographic proof establishing that pre-existing keys have not been removed or their values altered, and that new keys were added at the positions determined by the keys themselves. (In earlier documents this artifact is also called a \emph{non-deletion proof}; we use \emph{consistency proof} throughout.) The size of this proof is logarithmic with respect to the tree's capacity and linear with respect to the size of the inclusion batch. This can be reduced to a constant size using a SNARK. Assuming correct validation of the consistency proof and chaining of the Aggregation Layer's state roots by the Consensus Layer, the Aggregation Layer can be considered trustless. \subsection{Execution Layer} @@ -321,7 +326,7 @@ \section{Security Model of the Aggregation Layer} The Consensus Layer must guarantee data availability. If recent state roots were lost, it would become impossible to reject duplicate state transition requests, potentially allowing malicious actors to double-spend against an old, un-extendable state. The Aggregation Layer itself does not require an internal consensus mechanism; protocols like Raft could be used for replication and coordination among its redundant nodes. The decentralized consensus is provided by the external Consensus Layer. -If each state transition is accompanied by a cryptographic proof of non-deletion (see Section~\ref{sec:consistency-proof}), the Aggregation Layer can be considered trustless. +If each state transition is accompanied by a cryptographic consistency proof (see Section~\ref{sec:consistency-proof}), the Aggregation Layer can be considered trustless. \subsection{``Maximalist'' Security Assumptions} @@ -337,7 +342,7 @@ \subsection{``Maximalist'' Security Assumptions} \item The Aggregation Layer has not certified conflicting states of the same token. \end{enumerate} -The second and third points are covered by the aggregated history proof of Section~\ref{sec:aggregation-audit}: a fixed-size STARK, updated periodically, attesting that the entire sequence of certified states---from the genesis configuration up to a recent round $n$---forms a single non-forking chain in which every round of every shard satisfies the consistency property of Definition~\ref{def:append-only-accumulator}. In particular, no inclusion proof can exist for a token state that is absent from the recorded history. Verifying the aggregate proof requires only the genesis parameters of the network instance and takes milliseconds on commodity hardware; neither replay of history nor trust in the validator set is involved. +The second and third points are covered by the aggregated history proof of Section~\ref{sec:aggregation-audit}: a fixed-size STARK, updated periodically, attesting that the entire sequence of certified states---from the genesis configuration up to a recent round $n$---forms a single non-forking chain in which every round of every shard satisfies append-only consistency (Definition~\ref{def:aoc}, established by Theorem~\ref{thm:history}). In particular, no inclusion proof can exist for a token state that is absent from the recorded history. Verifying the aggregate proof requires only the genesis parameters of the network instance and takes milliseconds on commodity hardware; neither replay of history nor trust in the validator set is involved. The aggregate proof is produced with a latency of minutes to hours behind the certified tip, so maximalist verification is not instantaneous. It is best understood as an audit mechanism: it retrospectively confirms---or refutes, with the failure round pinpointed---the correctness of operation of the Consensus and Aggregation Layers. The validation procedure is given in Section~\ref{sec:maxi-validation}. @@ -354,41 +359,43 @@ \subsection{Practical Security Assumptions} \subsection{Scope of the In-Circuit Statement} \label{sec:scope} -A core engineering choice in the design of the Aggregation Layer's consistency proof is to push as much of the per-round security argument out of the cryptographic proof as possible, leaving only a small kernel inside the circuit. The observation behind this choice is not deep: an aggregator node is an operationally disposable component, and misbehavior outside the critical property manifests as denial of service against itself, remedied by failover to a replica rather than by cryptography. The value of the scoping is engineering economy---it keeps the circuit small. We make it explicit below. +A core engineering choice in the design of the Aggregation Layer's consistency proof is to push as much of the per-round security argument out of the cryptographic proof as possible, leaving only a small kernel inside the circuit. The value of the scoping is engineering economy---it keeps the circuit small. Drawing the boundary correctly, however, requires care: it is tempting to place \emph{all} placement-related properties outside the kernel, on the argument that a misplaced insertion only damages the aggregator's own ability to serve proofs. Section~\ref{sec:critical-review} refutes that argument by a concrete attack; the boundary is drawn below and proved sufficient in Section~\ref{sec:consistency-formal}. -Let $M_{i-1}, M_i \colon \{0,1\}^* \to \{0,1\}^* \cup \{\bot\}$ be the partial maps of recorded key-value bindings committed by, respectively, the previous and the new state roots $r_{i-1}, r_i$. We say the round update $r_{i-1} \to r_i$ satisfies \emph{prior-state preservation} iff +Let $M_{i-1}, M_i \colon \{0,1\}^* \to \{0,1\}^* \cup \{\bot\}$ be the partial maps of recorded key-value bindings committed by, respectively, the previous and the new state roots $r_{i-1}, r_i$ (Section~\ref{sec:consistency-formal} makes ``committed by'' precise). We say the round update $r_{i-1} \to r_i$ satisfies \emph{prior-state preservation} iff \begin{equation} \forall k \in \mathrm{dom}(M_{i-1})\colon\quad M_i(k) = M_{i-1}(k). \label{eq:psp} \end{equation} That is, every key already recorded under $r_{i-1}$ is bound to the same value under $r_i$. Equivalently, the round adds a (possibly empty) set of fresh keys and modifies nothing. -\begin{definition}[Minimal in-circuit statement] +\begin{definition}[In-circuit statement, informal] \label{def:minimal} -For an SMT-instantiated Aggregation Layer, the cryptographic per-round consistency proof needs to enforce only \eqref{eq:psp}, given authentic roots $(r_{i-1}, r_i)$. +For the Aggregation Layer, the cryptographic per-round consistency proof must enforce, given authentic roots $(r_{i-1}, r_i)$: (i) prior-state preservation \eqref{eq:psp}, and (ii) \emph{coherent placement}: every leaf inserted in the round sits at the position determined by its own key. Definition~\ref{def:aoc} states this formally. \end{definition} -The other desirable properties of the Aggregation Layer can be enumerated and accounted for as follows: +Clause (ii) is important. Because the maps $M_i$ are realized by \emph{provability} against the root---a binding is ``recorded'' exactly when an inclusion proof for it verifies---an incoherently placed insertion changes which bindings are provable, for old keys as well as new ones. Section~\ref{sec:critical-review} shows that dropping (ii) admits verifying round transitions under which an already-recorded key becomes re-recordable with a different value: the equivocation that \eqref{eq:psp} is meant to exclude. + +The remaining desirable properties of the Aggregation Layer stay outside the kernel, and can be enumerated and accounted for as follows: \begin{description}[nosep] - \item[Completeness] (\emph{every well-formed user request appears in the next round}). A censoring aggregator does not violate prior-state preservation; it merely fails to serve some users. The protocol mitigates this by replication (highly-available cluster) and by allowing users to resubmit through alternative aggregators in the same shard. + \item[Completeness] (\emph{every well-formed user request appears in the next round}). A censoring aggregator does not violate the in-circuit statement; it merely fails to serve some users. The protocol mitigates this by replication (highly-available cluster) and by allowing users to resubmit through alternative aggregators in the same shard. \item[Batch incorporation proof] (\emph{the round proof testifies to inclusion of every batch element}). Rather than have the consistency proof carry per-element inclusion claims, we let the Aggregation Layer serve fresh inclusion proofs on demand against the certified root. An aggregator that does not actually insert the batch will simply fail to produce valid inclusion proofs later, which is detectable by recipients. - \item[No phantom inserts] (\emph{nothing is recorded that was not a user request}). At worst, an aggregator does free recording work for itself or third parties; it cannot affect any honest user's tokens, because their state IDs are unrelated to the phantom entries. - \item[Canonical tree shape] (\emph{the post-state tree is the unique one prescribed by the SMT rules}). A non-canonical insertion produces a root that the aggregator cannot subsequently extend by canonical inclusion proofs for those keys; downstream verifiers reject. The aggregator only denies service to itself. - \item[Non-deletion / prior-state preservation] (\emph{equation \eqref{eq:psp}}). \emph{Critical.} If this fails, the operator can rewrite history and double-spending becomes possible. This is the property that must be cryptographically enforced \emph{before} round certification. + \item[No phantom inserts] (\emph{nothing is recorded that was not a user request}). At worst, an aggregator does free recording work for itself or third parties; phantom entries carry fresh keys (coherent placement forbids re-recording), so they cannot affect any honest user's tokens. + \item[Global canonical shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: as Theorem~\ref{thm:history} shows, coherent placement, applied round by round from the empty genesis tree, already forces every certified tree to be canonical. + \item[Append-only consistency] (\emph{\eqref{eq:psp} together with coherent placement; Definition~\ref{def:aoc}}). \emph{Critical.} If this fails, the operator can rewrite history and double-spending becomes possible. This is the property that must be cryptographically enforced \emph{before} round certification. \end{description} -Restricting the in-circuit statement to \eqref{eq:psp} has several useful consequences. First, the witness need not contain the actual batch contents---the prover may keep them entirely private and bind them to the proof through the soundness chain of the circuit (Section~\ref{sec:custom-air-circuit}). This shrinks the public statement to the two root digests. Second, the circuit does not have to encode the canonical-shape rules of the underlying SMT variant, which is by far the most constraint-heavy aspect of any naive arithmetization (cf.~\cite{rsmtair}, ``cost-of-canonical detour''). Third, the proof scales with the batch size alone, not with the total tree capacity. +Restricting the in-circuit statement to append-only consistency has several useful consequences. First, the witness need not contain the actual batch contents---the prover may keep them entirely private and bind them to the proof through the soundness chain of the circuit (Section~\ref{sec:custom-air-circuit}). This shrinks the public statement to the two root digests. Second, the circuit does not have to \emph{reconstruct} canonical shape from scratch, which is by far the most constraint-heavy aspect of any naive arithmetization (cf.~\cite{rsmtair}, ``cost-of-canonical detour''); with the region-committing hash of Section~\ref{sec:stack-verifier}, coherent placement is checked by local constraints on the touched nodes only. Third, the proof scales with the batch size alone, not with the total tree capacity. -\section{Non-deletion Proof} +\section{Consistency Proof} \label{sec:consistency-proof} -A non-deletion proof is a cryptographic construction that validates one round of operation of the append-only accumulator. +A \emph{consistency proof} is a cryptographic construction that validates one round of operation of the append-only accumulator. We have the $i$-th batch of insertions $B_i = (k_1, k_2, \dots, k_j)$, where $k$ is an inserted item; all insertions are applied within a single operational round. The root hash before the round is $r_{i-1}$, and after the round is $r_i$. The accumulator is implemented as a Sparse Merkle Tree (SMT). -The non-deletion proof generation for batch $B_i$ works as follows: +The consistency proof generation for batch $B_i$ works as follows: \begin{enumerate} \item The new leaves in batch $B_i$ are inserted into the SMT. @@ -414,9 +421,9 @@ \section{Non-deletion Proof} Due to the sparseness of the SMT we can further improve the encoding, for example, instead of checking if a node's sibling is the next item in layer's nodes or the next item in proof array or empty element otherwise, we just record a number--how many of the next siblings are empty elements (frequent close to the leaves when SMT is sparsely populated); and same with siblings (frequent close to the root). \begin{algorithm}[htb] - \caption{Verification of non-deletion proof}\label{alg:verifynondeletion} + \caption{Layer-by-layer verification of the consistency proof (plain SMT)}\label{alg:verifynondeletion} \begin{algorithmic}[0] - \Function{VerifyNonDeletion}{$\pi, r_{i-1}, r_i, P$} + \Function{VerifyConsistencySMT}{$\pi, r_{i-1}, r_i, P$} \State \Comment{Proof $\pi$ is a by-layer array of ...} \State \Comment{... sorted arrays of k-v tuples} \State \Comment{Insertion batch $P$ is ...} @@ -466,74 +473,265 @@ \section{Non-deletion Proof} \subsection{Stack-Machine Verification for the Path-Compressed Tree} \label{sec:stack-verifier} -Algorithm~\ref{alg:verifynondeletion} is formulated for the plain, fixed-depth SMT used as the model throughout this paper. Later implementations use the path-compressed RSMT3 tree (Section~\ref{sec:custom-air-circuit}) and a redesigned proof encoding, which replaces the layer-by-layer forest computation with a stack machine executing a flat opcode stream. This encoding is what the production verifier and the AIR arithmetization of Section~\ref{sec:custom-air-circuit} operate on. +Algorithm~\ref{alg:verifynondeletion} is formulated for the plain, fixed-depth SMT used as the model throughout this paper; it is also the encoding on which the early ZK experiments of the following sections were built, and it is retained for that reason. Production implementations use the path-compressed RSMT3 tree (Section~\ref{sec:custom-air-circuit}) and a transcript-based encoding, executed by a stack machine. This subsection specifies the encoding and its verifier; Section~\ref{sec:critical-review} explains why the coherence machinery is necessary, and Sections~\ref{sec:consistency-formal}--\ref{sec:consistency-theorem} prove the construction sufficient. -In RSMT3, a leaf hashes the full key together with the value, -\[ h_L = H(\texttt{0x00} \parallel k \parallel v), \] -and an internal (junction) node hashes its two children together with its explicit bifurcation depth $d$, -\[ h_N = H(\texttt{0x01} \parallel d \parallel h_l \parallel h_r). \] -The domain-separation prefixes make leaf and node hashes disjoint; the depth commitment prevents re-attaching a subtree at a different level; and placing $h_l$ and $h_r$ at fixed positions prevents swapping children. Crucially, neither hash depends on the edge (common-prefix) structure above the node: inserting new keys may split an edge above an existing node, but never changes the hash of any pre-existing node---it only creates new leaf and junction hashes. This immutability of pre-state hashes is what the proof encoding exploits. (The hash function is an instantiation detail: the portable reference implementation uses SHA-256, the AIR uses a Poseidon2 sponge.) +A leaf hashes the full key together with the value, and a junction hashes its two children together with its bifurcation depth $d$ and its \emph{region} $p$: +\begin{align*} + h_L &= H(\texttt{0x00} \parallel k \parallel v),\\ + h_N &= H(\texttt{0x01} \parallel \langle d\rangle \parallel \langle p\rangle \parallel h_l \parallel h_r). +\end{align*} +The region $p \in \{0,1\}^d$ is the key prefix that addresses the node: every key below the junction extends $p$, with $p\|0$ leading left and $p\|1$ leading right; $\langle\cdot\rangle$ are fixed-length injective encodings. A leaf's region is its full key, and its depth is $\kappa = 256$. (We write $\varrho[j]$ for bit $j$ of a region and $\varrho[0..d)$ for its first $d$ bits.) The domain-separation prefixes make leaf and junction hashes disjoint; the depth commitment prevents re-attaching a subtree at a different level; the region commitment pins the node to its key-space position; and fixed child positions prevent swapping. Crucially, depth and region are \emph{absolute} properties of a node---splitting an edge above it changes neither---so inserting new keys never re-hashes any pre-existing node: an insertion creates only new leaf and junction hashes. This immutability of pre-state hashes is what the proof encoding exploits. (The hash function is an instantiation detail: the portable reference implementation uses SHA-256, the AIR a Poseidon2 sponge.) Inclusion proofs transmit only junction depths and sibling digests: the verifier reconstructs the expected region of every junction on the path from the queried key itself, as $k[0..d_j)$. -The consistency proof $\pi$ for round $i$ is the post-order serialization of the \emph{touched} part of the post-state tree, over a three-opcode alphabet: +The consistency proof $\pi$ for round $i$ is the post-order serialization of the \emph{touched} part of the post-state tree, over a five-opcode alphabet: \begin{description}[nosep] - \item[$S(h)$:] an untouched pre-state subtree with digest $h$; + \item[$S(c)$:] an untouched pre-state subtree, as an opaque digest; + \item[$O(d', p', c_l, c_r)$:] an untouched pre-state junction, opened one level; the verifier hashes the opening, so the annotations are collision-bound to the digest; + \item[$O_L(k', v')$:] an untouched pre-state leaf, opened; \item[$L$:] a leaf newly inserted in this round; its key and value are not part of the proof, but are consumed from the batch $B_i$; - \item[$N(d)$:] a junction at bifurcation depth $d$, whose two children are the two preceding stack entries. + \item[$N(d)$:] a junction at bifurcation depth $d$, over the two preceding stack entries. Junction regions do not travel in the proof; the verifier derives them. \end{description} -The verifier (Algorithm~\ref{alg:stackverify}) executes the stream against a stack of digest pairs $(h^{\mathsf{old}}, h^{\mathsf{new}})$, evaluating every subtree in the pre-state and the post-state simultaneously. The batch is sorted by the verifier itself into tree-traversal order (depth-first, by key bits from the root), so the prover has no freedom in associating $L$ opcodes with batch elements. The pre-state digest of a junction follows a four-way rule: if both children existed in the pre-state, the junction existed too and its old digest is recomputed; if exactly one child existed, the junction did not exist in the pre-state, and the old digest of the existing child passes through unchanged; if neither existed, the old digest is the empty marker $\varnothing$. The pass-through cases are what keep add-only proofs short: no hashing is performed on the parts of the tree that did not change. +The verifier (Algorithm~\ref{alg:stackverify}) executes the stream against a stack of triples: the subtree's pre-state digest, its post-state digest, and an \emph{advice tuple} $(\delta, \varrho)$---the depth and region of the subtree's top node, $(\kappa, k)$ for leaves, absent ($\bot$) for opaque $S$ entries. The batch is sorted by the verifier itself into tree-traversal order and must be strictly increasing, so the prover has no freedom in associating $L$ opcodes with batch elements. Processing $N(d)$ combines three rule families: +\begin{enumerate}[nosep] + \item \emph{Edge coherence.} Every child that carries advice must satisfy $\delta > d$ and $\varrho[d] = \beta$, where $\beta$ is the child's side. The first $d$ bits of $\varrho$ yield the junction's region $p$; all advised children must agree on it, and at least one child must be advised, so $p$ is always defined. + \item \emph{Confinement of opaque subtrees.} If the junction is absent from the pre-state---its old side arises by pass-through or $\varnothing$---then \emph{both} children must carry advice. An opaque $S$ may therefore appear only under pre-existing junctions, whose edges were checked in the round that created them and are frozen by the hashes; wherever a preserved subtree meets a new junction, the prover must present its opened form. + \item \emph{Digest algebra.} The pre-state digest of a junction follows a four-way rule: if both children existed in the pre-state, the junction existed too and its old digest is recomputed; if exactly one child existed, the junction is new and the old digest of the existing child passes through unchanged; if neither existed, the old digest is the empty marker $\varnothing$. The post-state digest is always recomputed. The pass-through cases are what keep consistency proofs short: no hashing is performed on the parts of the tree that did not change. +\end{enumerate} \begin{algorithm}[H] \caption{Stack-machine verification of the RSMT3 consistency proof}\label{alg:stackverify} - \small + \footnotesize \begin{algorithmic}[0] \Function{VerifyConsistency}{$\pi, r_{i-1}, r_i, B$} \If{$B = [\,]$} - \State \Return $r_{i-1} = r_i$ + \State \Return $r_{i-1} = r_i \;\land\; \pi = [\,]$ \EndIf \State $B \gets \Call{SortTraversalOrder}{B}$ + \State \textbf{assert} keys of $B$ strictly increasing \State $\mathit{st} \gets [\,]$; \quad $b \gets 0$ \Comment{stack; batch index} \For{opcode $o$ \textbf{in} $\pi$} - \If{$o = S(h)$} - \State \Call{Push}{$\mathit{st}, (h, h)$} - \ElsIf{$o = L$} + \If{$o = S(c)$, $c \neq \varnothing$} \Comment{opaque subtree} + \State \Call{Push}{$\mathit{st}, (c, c, \bot)$} + \ElsIf{$o = O(d', p', c_l, c_r)$} \Comment{opening} + \State $c \gets H(\texttt{0x01} \| \langle d'\rangle \| \langle p'\rangle \| c_l \| c_r)$ + \State \Call{Push}{$\mathit{st}, (c, c, (d', p'))$} + \ElsIf{$o = O_L(k', v')$} \Comment{opened leaf} + \State \Call{Push}{$\mathit{st}, (c, c, (\kappa, k'))$}, $c = H(\texttt{0x00} \| k' \| v')$ + \ElsIf{$o = L$} \Comment{new leaf} \State $(k, v) \gets B[b]$; \quad $b \gets b + 1$ - \State \Call{Push}{$\mathit{st}, (\varnothing,\; H(\texttt{0x00} \| k \| v))$} - \ElsIf{$o = N(d)$} - \State $(h^{\mathsf{o}}_r, h^{\mathsf{n}}_r) \gets \Call{Pop}{\mathit{st}}$ - \State $(h^{\mathsf{o}}_l, h^{\mathsf{n}}_l) \gets \Call{Pop}{\mathit{st}}$ - \If{$h^{\mathsf{o}}_l = \varnothing \land h^{\mathsf{o}}_r = \varnothing$} - \State $h^{\mathsf{o}} \gets \varnothing$ - \ElsIf{$h^{\mathsf{o}}_l = \varnothing$} - \State $h^{\mathsf{o}} \gets h^{\mathsf{o}}_r$ \Comment{pass-through} - \ElsIf{$h^{\mathsf{o}}_r = \varnothing$} - \State $h^{\mathsf{o}} \gets h^{\mathsf{o}}_l$ \Comment{pass-through} + \State \Call{Push}{$\mathit{st}, (\varnothing,\; H(\texttt{0x00} \| k \| v),\; (\kappa, k))$} + \ElsIf{$o = N(d)$} \Comment{junction} + \State $(c^{\mathsf o}_r, c^{\mathsf n}_r, a_r) \gets \Call{Pop}{\mathit{st}}$ + \State $(c^{\mathsf o}_l, c^{\mathsf n}_l, a_l) \gets \Call{Pop}{\mathit{st}}$ + \State $p \gets \bot$ + \For{$x \in \{l, r\}$ with side bit $\beta \in \{0, 1\}$} + \If{$a_x = (\delta_x, \varrho_x) \neq \bot$} \Comment{coherence} + \State \textbf{assert} $\delta_x > d \;\land\; \varrho_x[d] = \beta$ + \State \textbf{assert} $p = \bot \;\lor\; p = \varrho_x[0..d)$ + \State $p \gets \varrho_x[0..d)$ + \EndIf + \EndFor + \State \textbf{assert} $p \neq \bot$ + \If{$c^{\mathsf o}_l = \varnothing \lor c^{\mathsf o}_r = \varnothing$} \Comment{new junction} + \State \textbf{assert} $a_l \neq \bot \;\land\; a_r \neq \bot$ + \EndIf + \If{$c^{\mathsf o}_l = \varnothing \land c^{\mathsf o}_r = \varnothing$} + \State $c^{\mathsf o} \gets \varnothing$ + \ElsIf{$c^{\mathsf o}_l = \varnothing$} + \State $c^{\mathsf o} \gets c^{\mathsf o}_r$ \Comment{pass-through} + \ElsIf{$c^{\mathsf o}_r = \varnothing$} + \State $c^{\mathsf o} \gets c^{\mathsf o}_l$ \Comment{pass-through} \Else - \State $h^{\mathsf{o}} \gets H(\texttt{0x01} \| d \| h^{\mathsf{o}}_l \| h^{\mathsf{o}}_r)$ + \State $c^{\mathsf o} \gets H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| c^{\mathsf o}_l \| c^{\mathsf o}_r)$ \EndIf - \State $h^{\mathsf{n}} \gets H(\texttt{0x01} \| d \| h^{\mathsf{n}}_l \| h^{\mathsf{n}}_r)$ - \State \Call{Push}{$\mathit{st}, (h^{\mathsf{o}}, h^{\mathsf{n}})$} + \State $c^{\mathsf n} \gets H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| c^{\mathsf n}_l \| c^{\mathsf n}_r)$ + \State \Call{Push}{$\mathit{st}, (c^{\mathsf o}, c^{\mathsf n}, (d, p))$} \Else \State \Return $0$ \Comment{unknown opcode} \EndIf \EndFor \State \textbf{assert} $b = |B| \;\land\; |\mathit{st}| = 1$ - \State $(h^{\mathsf{o}}, h^{\mathsf{n}}) \gets \mathit{st}[0]$ - \State \Return $h^{\mathsf{o}} = r_{i-1} \,\land\, h^{\mathsf{n}} = r_i$ + \State \Return $\mathit{st}[0].(c^{\mathsf o}, c^{\mathsf n}) = (r_{i-1}, r_i)$ \EndFunction \end{algorithmic} \end{algorithm} -Verification accepts iff the opcode stream and the batch are both fully consumed, the stack holds exactly one pair, and that pair equals $(r_{i-1}, r_i)$; any stack underflow or batch overrun rejects. The verifier is a short loop ($\sim$60 lines in the reference implementation) with no recursion; its memory use is bounded by the tree depth, and the post-order format makes verification a natural streaming computation. +Verification accepts iff the opcode stream and the batch are both fully consumed, the stack holds exactly one triple, and its digest pair equals $(r_{i-1}, r_i)$; any stack underflow or batch overrun rejects. The verifier is a short loop with no recursion and no control flow beyond opcode dispatch---one uniform rule per opcode; its memory use is bounded by the tree depth, and the post-order format makes verification a natural streaming computation. This regularity is deliberate: it is what the AIR arithmetization of Section~\ref{sec:custom-air-circuit} exploits, one trace row per opcode with a fixed constraint family. In-circuit, deriving the junction regions costs nothing extra---the derivation equalities \emph{are} the edge-coherence constraints, and the region limbs appear as hash inputs either way. Relative to the structural fragment of the statement (opcodes $S$, $L$, $N$ and the digest algebra alone), the coherence machinery costs region limbs in the Poseidon2 junction preimage (roughly one additional permutation per junction hash), the bit-prefix comparisons, and the openings ($\approx$ one extra hash per batch element); we estimate the dominant Poseidon2 table grows by a factor of at most $1.5$. The measured throughput of Section~\ref{sec:measured}, which covers the structural fragment, leaves ample headroom above the $10\,000$\,tx/s design target. + +For the honest prover, the transcript differs from a bare depth-only encoding only in the openings: one opened junction or leaf per split edge---the node the insertion descends past last. Measured with the reference implementation on a batch of $1\,000$ insertions into a tree of $10^4$ keys, the transcript is within $15\%$ of the size of the depth-only encoding; the derived regions cost nothing on the wire. + +\subsection{Why Coherent Placement Is Necessary} +\label{sec:critical-review} + +Everything in Algorithm~\ref{alg:stackverify} beyond the digest algebra---the region in the junction hash, the openings, the edge-coherence checks---exists to enforce coherent placement, and it is legitimate to ask whether the expense is necessary. Consider the natural minimal alternative, the \emph{structure-only} proof: the junction hash commits the depth alone, $h_N = H(\texttt{0x01} \| \langle d\rangle \| h_l \| h_r)$; the alphabet shrinks to $S(h)$, $L$, $N(d)$; and the verifier keeps only the four-way digest algebra. This variant does enforce \emph{structural preservation}: reconstructing $r_{i-1}$ forces the proof to cover every branch of the pre-state tree; every covered subtree reappears, unmodified, under $r_i$ (depth commitment and child ordering exclude relocation and swapping); each $L$ is bound to exactly one batch element by the sorting and exhaustion checks; and there is no third source of leaves. It even binds values under any \emph{single} root: two verifying inclusion proofs for $(k,v)$ and $(k,v')$ against the same digest force, level by level from the root, equal hash preimages (anything else is a collision) and---because the descent direction is recomputed from $k$'s bits---the same path, terminating in $H(\texttt{0x00}\,\|\,k\,\|\,v) = H(\texttt{0x00}\,\|\,k\,\|\,v')$, i.e., $v = v'$ or a collision. + +What structural preservation does not do is relate the batch's keys to the \emph{positions} at which the new leaves are attached. The Aggregation Layer's security model, however, is stated in terms of provability: a binding $(k,v)$ is \emph{recorded} under a certified root $r$ exactly when an inclusion proof for it verifies against $r$---this is what a Proof of Unicity is. Under this semantics, the structure-only guarantee fails, and it fails \emph{across} rounds. + +\paragraph{The shadow-insertion attack.} +Let the pre-state be any tree containing the recorded binding $(k,v)$, with certified root $r_{i-1}$; for concreteness, the tree consisting of that single leaf. A Byzantine aggregator (prompted, say, by a user attempting a double-spend of the token state $k$) picks any depth $d^{*}$ with $k[d^{*}] = 1$ and submits the batch $B_i = \{(k, v')\}$, $v' \neq v$, with the three-opcode proof +\[ \pi = \big(\,S(r_{i-1}),\; L,\; N(d^{*})\,\big). \] +The structure-only verifier accepts: the old side of $N(d^{*})$ is the pass-through of $S$'s digest, reproducing $r_{i-1}$ exactly, and the new side yields +$r_i = H\big(\texttt{0x01} \| d^{*} \| r_{i-1} \| H(\texttt{0x00} \| k \| v')\big)$. +Against the certified $r_i$, the one-step inclusion proof for $(k, v')$---sibling $r_{i-1}$, depth $d^{*}$, direction $k[d^{*}] = 1$---verifies. The construction is depicted in Figure~\ref{fig:shadow}. The consequences: +\begin{enumerate}[nosep] + \item \emph{Cross-round equivocation.} $(k,v)$ is recorded under $r_{i-1}$ and $(k,v')$ is recorded under $r_i$: two conflicting spends of the same token state, both anchored to certified roots. This is precisely the event the Aggregation Layer exists to prevent. + \item \emph{Retroactive orphaning.} Under $r_i$, the binding $(k,v)$ is no longer provable: any path to it now passes the new junction in direction $0 \neq k[d^{*}]$. More generally, a single misdirected junction placed above any preserved subtree orphans \emph{every} binding in that subtree---third parties' tokens, not the operator's own. + \item \emph{Undetectability.} Every structure-only check passes: the BFT Core would certify the round, and even the full-history audit of Section~\ref{sec:aggregation-audit}, which verifies exactly these consistency proofs, would accept. +\end{enumerate} +We have confirmed the attack against a reference implementation of the structure-only verifier. Placement, in short, is not a self-regarding property: a misplaced junction damages third parties, undetectably. + +\begin{figure}[!htbp] + \centering +\begin{tikzpicture}[font=\small, + lf/.style={rectangle, draw, align=center, minimum height=1.8em, inner sep=4pt}, + jn/.style={circle, draw, inner sep=2pt}] + % pre-state + \node[lf] (pre) {$\mathsf{Leaf}(k,v)$}; + \node[above=0.35cm of pre, font=\scriptsize] {$r_{i-1}$}; + % post-state + \node[jn, right=2.6cm of pre, yshift=0.55cm] (top) {$d^{*}$}; + \node[above=0.15cm of top, font=\scriptsize] {$r_i$}; + \node[lf, below left=0.7cm and 0.35cm of top] (old) {$\mathsf{Leaf}(k,v)$}; + \node[lf, below right=0.7cm and 0.35cm of top] (new) {$\mathsf{Leaf}(k,v')$}; + \draw (top) -- node[left, font=\scriptsize] {$0$} (old); + \draw (top) -- node[right, font=\scriptsize] {$1$} (new); + \node[below=0.15cm of old, font=\scriptsize] {orphaned}; + \node[below=0.15cm of new, font=\scriptsize] {provable}; + \draw[arrow, dashed] ([xshift=0.35cm]pre.east) -- node[above, font=\scriptsize] {$\pi$ verifies} ([xshift=-0.12cm]old.west|-pre.east); +\end{tikzpicture} + \caption{Shadow insertion: with $k[d^{*}] = 1$, the verifier's key-directed descent under $r_i$ reaches $(k,v')$; the preserved $(k,v)$ is unreachable. The structure-only consistency proof $(S(r_{i-1}), L, N(d^{*}))$ verifies.}\label{fig:shadow} +\end{figure} + +\paragraph{Repair.} +The root cause is that the depth commitment binds nodes to \emph{levels}, not to \emph{key-space positions}, while $S$ subtrees are opaque digests---so no verifier-side constraint can relate the batch's keys to the regions of key space already occupied. Two repairs present themselves. The \emph{witness route} keeps the hashes and requires, per inserted key, an opened descent into the pre-state establishing freshness of the key and the canonical split point; this costs an opened path ($O(\log n)$ hash openings) per insertion. The \emph{commitment route} moves the region into the junction hash, after which coherence becomes a local check over the touched nodes, with a single one-level opening per split edge; it is cheaper in-circuit, yields simpler invariants, and preserves the insert-immutability of pre-existing hashes, because a node's region---unlike its edge structure---is invariant under insertions above it. Algorithm~\ref{alg:stackverify} is the commitment route. Revisiting the attack against it: the new junction $N(d^{*})$ must present its preserved child opened, and edge coherence demands that the opened child's region extend $p\|0$ while the new leaf's key extends $p\|1$; since the preserved subtree containing $(k,v)$ has a region that is a prefix of $k$, both conditions cannot hold with the leaf key $k$ on the other side. The attack---and, as Theorem~\ref{thm:round} shows, every attack of its kind---is excluded. A further consequence (Theorem~\ref{thm:history}) is that globally canonical shape comes for free: what naively looks like the heavyweight obligation of proving canonical construction reduces to one opening per insertion and a family of local bit-comparisons. + +\subsection{Formal Model} +\label{sec:consistency-formal} + +We fix the key length $\kappa = 256$, key space $\mathcal{K} = \{0,1\}^{\kappa}$, a value space $\mathcal{V} \subseteq \{0,1\}^{*}$, and a hash function $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$. For bit strings, $p \sqsubseteq q$ denotes that $p$ is a prefix of $q$, $q[j]$ the $j$-th bit, and $q[0..d)$ the first $d$ bits. All statements below are unconditional reductions: they conclude either the stated property, or that two distinct strings with equal $H$-images (\emph{a collision}) are computable in time linear in the size of the objects at hand. $\varnothing$ is a distinguished constant outside $\{0,1\}^{\lambda}$. + +\begin{definition}[Hash trees] +\label{def:hashtree} +Trees are generated by $T ::= \mathsf{Leaf}(k, v) \mid \mathsf{Node}(d, p, T_l, T_r)$ with $k \in \mathcal{K}$, $v \in \mathcal{V}$, $0 \le d < \kappa$, $p \in \{0,1\}^{d}$; $\varepsilon$ denotes the empty tree. Digest, region, and depth: +\begin{align*} +\mathsf{dig}(\mathsf{Leaf}(k,v)) &= H(\texttt{0x00} \| k \| v),\\ +\mathsf{dig}(\mathsf{Node}(d,p,l,r)) &= H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| \mathsf{dig}(l) \| \mathsf{dig}(r)), +\end{align*} +$\mathsf{dig}(\varepsilon) = \varnothing$; $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$, $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$, $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. +\end{definition} + +\begin{definition}[Well-formed and canonical trees] +\label{def:wf} +$\varepsilon$ and leaves are well-formed; $\mathsf{Node}(d,p,l,r)$ is well-formed iff $l, r$ are, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. A well-formed tree is \emph{canonical} iff, for every junction, $p$ is the longest common prefix of the keys of the leaves below it. +\end{definition} + +\begin{lemma}[Represented map] +\label{lem:map} +In a well-formed tree $T$, every leaf key extends the region of each of its ancestors, and distinct leaves carry distinct keys; hence $T$ represents a partial map $\mathsf{map}(T) = \{k \mapsto v \mid \mathsf{Leaf}(k,v) \in T\}$. Moreover, for every finite key-value map there is exactly one canonical tree. +\end{lemma} +\begin{proof} +The first claim is immediate by induction over the well-formedness conditions. For distinctness: two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d, p, \cdot, \cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$---impossible. Uniqueness of the canonical tree follows by induction on the key set: a singleton forces a leaf; otherwise the root junction's region and depth are forced to the longest common prefix and its length, which also splits the key set into the two forced child sets. +\end{proof} + +\begin{definition}[Inclusion verification] +\label{def:incl} +An inclusion proof for $(k, v)$ against a root $r$ is a sequence $\gamma = \big((d_1, s_1), \ldots, (d_m, s_m)\big)$ with $\kappa > d_1 > \cdots > d_m \ge 0$. The verifier computes $c_0 = H(\texttt{0x00} \| k \| v)$ and, for $j = 1, \ldots, m$, +\[ +c_j = \begin{cases} +H(\texttt{0x01} \| \langle d_j\rangle \| \langle k[0..d_j)\rangle \| c_{j-1} \| s_j) & \text{if } k[d_j] = 0,\\ +H(\texttt{0x01} \| \langle d_j\rangle \| \langle k[0..d_j)\rangle \| s_j \| c_{j-1}) & \text{if } k[d_j] = 1, +\end{cases} +\] +and accepts iff $c_m = r$. (Regions are not transmitted; the verifier derives them from $k$.) A \emph{non-inclusion witness} for $k$ against $r$ is a chain of openings from the root along $k$'s descent: junction openings $(d_j, p_j, c^0_j, c^1_j)$ whose $H$-images chain from $r$ downward through the $k[d_j]$-side child, with $p_j = k[0..d_j)$ for all but the last element, terminating either in a junction opening whose region is \emph{not} a prefix of $k$, or in an opened leaf with key $\neq k$; also, $r = \varnothing$ is a witness for every $k$. +\end{definition} + +\begin{definition}[Append-only consistency] +\label{def:aoc} +A \emph{certified history} is a sequence $(B_1, \pi_1, r_1), \ldots, (B_n, \pi_n, r_n)$ with $r_0 = \varnothing$ and Algorithm~\ref{alg:stackverify} accepting $(\pi_i, r_{i-1}, r_i, B_i)$ for every $i$. The history is \emph{append-only consistent} if there exist well-formed trees $T_0 = \varepsilon, T_1, \ldots, T_n$ with $\mathsf{dig}(T_i) = r_i$ and +\[ +\mathsf{map}(T_i) \;=\; \mathsf{map}(T_{i-1}) \uplus B_i \qquad \text{for } i = 1, \ldots, n, +\] +where $\uplus$ is disjoint union of partial maps; in particular the keys of $B_i$ are pairwise distinct and absent from $\mathsf{map}(T_{i-1})$. +\end{definition} -The soundness argument, informally: reconstructing $r_{i-1}$ forces the proof to cover every branch of the pre-state tree, with every covered subtree contributed as $S(h)$---which, by construction, reappears unchanged under $r_i$; depth commitment and child ordering exclude relocation and swapping; and the independent sorting plus the exhaustion checks bind each $L$ opcode to exactly one batch element. The algorithm deliberately does \emph{not} establish that the post-state is the canonical radix tree of its key set; as discussed in Section~\ref{sec:scope}, a non-canonical post-state only damages the operator's own ability to serve inclusion proofs. A formal, machine-checkable proof that Algorithm~\ref{alg:stackverify} enforces prior-state preservation~\eqref{eq:psp} is left for future work; this section fixes the model and the algorithm that such a proof will target. +Definition~\ref{def:aoc} is the formal counterpart of Definition~\ref{def:append-only-accumulator}: map monotonicity is clause~1, and Corollaries~\ref{cor:unicity}--\ref{cor:service} below deliver clauses~2 and~3. It subsumes prior-state preservation~\eqref{eq:psp}, with the committed maps $M_i$ of Section~\ref{sec:scope} realized as $\mathsf{map}(T_i)$. + +\subsection{Security} +\label{sec:consistency-theorem} + +\begin{lemma}[Digest binding] +\label{lem:binding} +From trees $T \neq T'$ with $\mathsf{dig}(T) = \mathsf{dig}(T') \neq \varnothing$, a collision is computable. +\end{lemma} +\begin{proof} +The two digest preimages are equal strings or a collision is found. If equal, the domain-separation tag and the injective fixed-length encodings force the same constructor with equal components: for leaves, $T = T'$, a contradiction; for junctions, equal $(d, p)$ and equal child digests, and since $T \neq T'$ some child pair differs while sharing a digest---recurse into it. The recursion terminates in a collision. +\end{proof} + +\begin{lemma}[Run decomposition] +\label{lem:run} +An accepting run of Algorithm~\ref{alg:stackverify} on $(\pi, r_{i-1}, r_i, B)$ determines, in linear time: an ordered binary \emph{proof tree} $P$ with internal nodes the $N(d)$ opcodes and terminals the $S$, $O$, $O_L$, $L$ opcodes, the $L$ terminals consuming the strictly sorted batch left to right; pre- and post-digests for every node of $P$ per the verifier's algebra, with the root pair equal to $(r_{i-1}, r_i)$; a unique \emph{region label} $p$ for every junction, derived from the advice of its children---all advised children yield the same $p$, and at least one child is advised; and a validated advice tuple at every junction--child edge where the child carries advice: the child's depth exceeds the junction's and the child's region extends $p\|\beta$, the advice being $(\kappa, k)$ for $L$ and $O_L$ terminals, the opened $(d', p')$ for $O$ terminals, and the child's own $(d, p)$ label for $N$ children. At every junction whose old side arose from a pass-through or $\varnothing$ case, both children carry advice; consequently, opaque $S$ terminals occur only as children of junctions whose old side was hashed. +\end{lemma} +\begin{proof} +By construction of the algorithm; each clause restates a check or an assignment made during the run. +\end{proof} + +\begin{theorem}[Round soundness] +\label{thm:round} +Let $T$ be a well-formed tree (possibly $\varepsilon$) with $\mathsf{dig}(T) = r_{i-1}$, and let Algorithm~\ref{alg:stackverify} accept $(\pi, r_{i-1}, r_i, B)$. Then from $T$, $\pi$, $B$ one can either compute a collision, or construct a well-formed tree $T'$ with $\mathsf{dig}(T') = r_i$ and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. If $T$ is canonical, then $T'$ is canonical. +\end{theorem} +\begin{proof} +Let $P$ be the proof tree of Lemma~\ref{lem:run}. Define the \emph{old projection} $P_0$ by structural recursion: $S$, $O$, $O_L$ terminals map to themselves; $L$ maps to nothing; a junction whose old side was hashed (both children's old digests $\neq \varnothing$) maps to a junction over the projections of its children; a pass-through junction maps to the projection of its surviving child; an all-$\varnothing$ junction maps to nothing. By the verifier's algebra, evaluating $P_0$---with $S$ digests and $O$/$O_L$ openings as given---yields $r_{i-1}$. + +\emph{Step 1: matching.} If $r_{i-1} = \varnothing$ then $P_0$ is empty (a non-$\varnothing$ old digest propagates to the root through every case of the four-way rule) and $T = \varepsilon$; proceed to Step~2 with no grafts. Otherwise walk $P_0$ and $T$ together from their roots. At an explicit junction of $P_0$ labeled $(d, p)$ with children's old digests $(c_l, c_r)$: the current $T$-node's digest equals $H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\| c_l \| c_r)$; if the current $T$-node is a leaf or carries a different label or different child digests, its own preimage differs---a collision; otherwise the labels agree and the walk recurses into both children. At an $O_L(k', v')$ terminal, the current $T$-node must be $\mathsf{Leaf}(k', v')$ by the same argument. At an opaque hole ($S(c)$, or a digest child of an $O$ opening): assign to it the current $T$-subtree, whose digest is $c$. The outcome, barring a collision: every explicit node of $P_0$ coincides in label and position with a node of $T$; every hole is assigned the $T$-subtree at its position; and $T$ is exactly the grafting of $P_0$'s explicit structure with the assigned subtrees. + +\emph{Step 2: construction.} Let $T'$ be the grafting of $P$: $N(d) \mapsto \mathsf{Node}(d, p, \cdot, \cdot)$, with $p$ its derived region label; $L$ and $O_L$ terminals $\mapsto$ the corresponding leaves; $O(d', p', \cdot, \cdot) \mapsto \mathsf{Node}(d', p', \cdot, \cdot)$ over its assigned child subtrees; $S(c) \mapsto$ its assigned subtree. Then $\mathsf{dig}(T') = r_i$, because the post-digest algebra agrees with $\mathsf{dig}$ on terminals and junctions. + +\emph{Step 3: well-formedness.} Classify the edges of $T'$. Edges inside an assigned subtree satisfy the conditions because $T$ is well-formed. An edge whose child is an opaque $S$ terminal has, by Lemma~\ref{lem:run}, a parent whose old side was hashed; by Step~1 that parent, its labels, and its child digests coincide with a node of $T$, so the edge is an edge of $T$ at the same position, and well-formedness of $T$ applies. Every other edge has an advised child and was checked by the verifier; it remains to note that the validated advice equals the true $(\mathsf{dep}, \mathsf{reg})$ of the child's top node in $T'$: exact for $L$ and $O_L$ children by construction, for $O$ children by Step~1, and for $N$ children by the definition of their derived labels. Hence $T'$ is well-formed. + +\emph{Step 4: map.} The terminals of $P$ partition the leaves of $T'$ into leaves of assigned subtrees, $O_L$ leaves, and $L$ leaves. By Step~1 the first two groups are exactly the leaves of $T$; the third is exactly $B$, fully consumed and with pairwise distinct keys. By Lemma~\ref{lem:map} applied to the well-formed $T'$, all leaf keys of $T'$ are distinct, so the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. (Consequently, no accepting run exists for a batch that re-records a present key: it would produce a well-formed tree with a repeated leaf key, which does not exist.) + +\emph{Step 5: canonicity.} Assume $T$ canonical. For an old junction of $T'$, the keys added below it extend its region (well-formedness), so the longest common prefix of the enlarged key set still equals the region. For a new junction $\mathsf{Node}(d, p, l, r)$, the regions of $l$ and $r$ equal the longest common prefixes of their own key sets (by canonicity of assigned subtrees and induction over the new structure) and extend $p\|0$ and $p\|1$ respectively, so the longest common prefix of the union is exactly $p$. Hence every junction of $T'$ is canonical. +\end{proof} + +\begin{theorem}[History soundness] +\label{thm:history} +For every certified history (Definition~\ref{def:aoc}), either a collision is computable from its transcript, or the history is append-only consistent, with all $T_i$ canonical. +\end{theorem} +\begin{proof} +Induction on rounds: $T_0 = \varepsilon$ is canonical with $\mathsf{dig}(T_0) = \varnothing$, and Theorem~\ref{thm:round} supplies the step. +\end{proof} + +\begin{corollary}[Unicity] +\label{cor:unicity} +From a certified history together with verifying inclusion proofs for $(k, v)$ against $r_i$ and for $(k, v')$ against $r_j$ with $v \neq v'$, a collision is computable. +\end{corollary} +\begin{proof} +By Theorem~\ref{thm:history}, obtain the trees $T_i, T_j$ (or a collision, and we are done). A verifying inclusion proof against $\mathsf{dig}(T)$ matches into $T$ from the root exactly as in Step~1 of Theorem~\ref{thm:round}: each chain element's preimage must agree with the corresponding node of $T$ (else a collision), and the terminal comparison places $\mathsf{Leaf}(k, v)$ in $T$. Hence $v = \mathsf{map}(T_i)(k)$ and $v' = \mathsf{map}(T_j)(k)$; taking $i \le j$, monotonicity ($\mathsf{map}(T_j) \supseteq \mathsf{map}(T_i)$) gives $v' = v$, a contradiction---so a collision was computed along the way. +\end{proof} + +\begin{corollary}[No false non-inclusion] +\label{cor:noninc} +From a certified history, a verifying inclusion proof for $(k, v)$ against $r_i$, and a verifying non-inclusion witness for $k$ against $r_j$ with $j \ge i$, a collision is computable. +\end{corollary} +\begin{proof} +As above, $(k, v) \in \mathsf{map}(T_j)$, so $r_j \neq \varnothing$ and $T_j$ contains the leaf of $k$, all of whose ancestors carry regions that are prefixes of $k$. The witness's openings match into $T_j$ (else a collision) and, by construction, follow the descent directed by $k$'s bits through junctions whose regions are prefixes of $k$---which is precisely the path to $k$'s leaf. Its terminal therefore matches a node on that path: every such junction has a region that is a prefix of $k$, and the only leaf on it has key $k$, contradicting the witness's terminal condition in either case. +\end{proof} + +\begin{corollary}[Service completeness] +\label{cor:service} +Let $T_i$ be the canonical trees of Theorem~\ref{thm:history}. For every $(k, v) \in \mathsf{map}(T_i)$, the path data of $T_i$ yields a verifying inclusion proof; for every $k \notin \mathrm{dom}(\mathsf{map}(T_i))$, the canonical descent of $T_i$ yields a verifying non-inclusion witness. Producing them requires only possession of the tree data, an availability rather than an integrity concern. +\end{corollary} + +\begin{remark} +Theorems~\ref{thm:round} and~\ref{thm:history} together with Corollaries~\ref{cor:unicity}--\ref{cor:service} establish that the coherent consistency proof realizes the accumulator interface of Definition~\ref{def:append-only-accumulator}. The proofs are elementary---structural inductions with explicit collision extraction---precisely because the region commitment localizes every invariant to an edge of the touched structure. A machine-checked formalization is planned and should follow the proof structure given here. +\end{remark} \section{(ZK)-SNARKs} -By using an appropriate cryptographic SNARK system, the size of the non-deletion proof can be reduced to a constant. +By using an appropriate cryptographic SNARK system, the size of the consistency proof can be reduced to a constant. -The statement to be proven in zero-knowledge is the correct execution of the non-deletion proof verification algorithm described in the previous section. The public inputs to the proof (the instance) are the pre- and post-update roots $(r_{i-1}, r_i)$. The private input (the witness) $\omega$ is the insertion batch $B_i$ and the set of sibling nodes (proof) $\pi_i$. While ZK-SNARKs can hide the witness, this zero-knowledge property is not a requirement for our use case; we are primarily interested in the proof's succinctness. +The statement to be proven in zero-knowledge is the correct execution of the consistency proof verification algorithm described in the previous section. The public inputs to the proof (the instance) are the pre- and post-update roots $(r_{i-1}, r_i)$. The private input (the witness) $\omega$ is the insertion batch $B_i$ and the set of sibling nodes (proof) $\pi_i$. While ZK-SNARKs can hide the witness, this zero-knowledge property is not a requirement for our use case; we are primarily interested in the proof's succinctness. In an experiment~\cite{snark}, the statement is implemented as a constraint system $R$ using the CIRCOM domain-specific language. The witness is generated based on $\pi_i$ and $B_i$, and is supplemented by control wires that define how individual hashing blocks in the circuit are connected to the previous layer and to the inputs. If all constraints are satisfied, the proof is valid. @@ -542,7 +740,7 @@ \section{(ZK)-SNARKs} When the Consensus Layer verifies these succinct proofs, the Aggregation Layer operates trustlessly. However, certain redundancy is still required to ensure data availability of the SMT itself. -\section{Circuit-Based SNARK Definition} +\subsection{Circuit-Based SNARK Definition} Due to the limited expressivity of an arithmetic circuit (e.g., no data-dependent loops or real branching), the entire computation flow must be fixed at circuit-creation time. It is therefore helpful to pre-process the inputs to create a fixed execution trace. @@ -600,16 +798,16 @@ \section{Circuit-Based SNARK Definition} Both halves' MUXes are controlled by the same wiring signal. -\subsection{Performance Indication} +\subsubsection{Performance Indication} -Initial benchmarks on a consumer laptop (Apple M1) using the Poseidon hash function indicate a proving throughput of up to $25$ transactions per second. +Initial benchmarks on a consumer laptop (Apple M1) using the Poseidon hash function indicate a proving throughput of up to $25$ transactions per second; achievable with large batch sizes. Both the fixed circuit size, the parameters of key setup ceremony, and available prover memory present hard limits to the batch size. -\section{Execution Trace-Based STARK} +\subsection{Execution Trace-Based STARK} -An alternative to a bespoke arithmetic circuit is to use a general-purpose zero-knowledge virtual machine (zkVM). In this approach, the verification logic is written as a traditional imperative program (e.g., in Rust). The zkVM then generates a proof of correct execution for that program. +An alternative to a low-level arithmetic circuit is to use a general-purpose zero-knowledge virtual machine (zkVM). In this approach, the verification logic is written as a traditional imperative program (e.g., in Rust). The zkVM then generates a proof of correct execution for that program. -We have implemented the non-deletion proof verification algorithm as a Rust program~\cite{stark} to be proved by the SP1 zkVM~\cite{sp1}. As a commitment to the ``right'' program we use a prover key, generated during program setup. Its contents are: a commitment to the preprocessed traces, the starting Program Counter register, the starting global digest of the program, after incorporating the initial memory; the chip information, the chip ordering; and prover configuration. +We have implemented the consistency proof verification algorithm as a Rust program~\cite{stark} to be proved by the SP1 zkVM~\cite{sp1}. As a commitment to the ``right'' program we use a prover key, generated during program setup. Its contents are: a commitment to the preprocessed traces, the starting Program Counter register, the starting global digest of the program, after incorporating the initial memory; the chip information, the chip ordering; and prover configuration. For verification, we obtain the prover key hash and authenticate it off-band. @@ -619,7 +817,7 @@ \section{Execution Trace-Based STARK} The privacy of the witness (the zero-knowledge property) is not a requirement for this application. The primary goal is to achieve computational integrity and succinctness. Therefore, while the underlying technology is often referred to as ``ZK'', we are using it as a Scalable Transparent ARgument of Knowledge (STARK). -\subsection{zkVM Performance} +\subsubsection{zkVM Performance} On a 10-core Apple M1 CPU, proving a 500-transaction batch using SHA-256 within the SP1 zkVM takes approximately 5 minutes. However, the SP1 framework is robust and designed for scalability, supporting distributed prover networks, industrial-grade GPUs, proof chunking and recursion, and other advanced features to tackle larger problems with brute force. @@ -630,10 +828,10 @@ \subsection{Optimization Ideas} At the time of writing, the SP1 zkVM\footnote{\url{https://docs.succinct.xyz/docs/sp1/introduction}} offers precompiles for standard hash functions like SHA-256, which accelerates their execution compared to a direct RISC-V implementation. The use of these precompiles (also known as coprocessors or chips) can be observed in the prover's output, which details the number of calls to each specialized circuit (e.g., \lstinline|SHA_EXTEND|, \lstinline|SHA_COMPRESS|). However, even with acceleration, proving SHA-256 is computationally expensive. -A possible optimization is to use ``ZK-friendly'' hash functions. These functions are highly efficient when implemented directly in arithmetic circuits, where there is direct access to the native field elements. Their performance advantage in a RISC-V zkVM is more nuanced, as there is an overhead in translating between the VM's 32-bit integer registers and the underlying finite field elements as used by the prover. Operations like range-checking, which are necessary to prevent overflows, are expensive in ZK. There are attempts to create precompiles for ZK-friendly hash functions\footnote{\url{https://github.com/Okm165/sp1-poseidon2/pull/8}}, with limited real-world effect. +A possible optimization is to use ``ZK-friendly'' hash functions. These functions are highly efficient when implemented directly in arithmetic circuits, where there is direct access to the native field elements. Their performance advantage in a RISC-V zkVM is more nuanced, as there is an overhead in translating between the VM's 32-bit integer registers and the underlying finite field elements as used by the prover. Operations like range-checking, which are necessary to prevent overflows, are expensive in ZK. -\subsection{More on ZK and Hash Functions} +\subsubsection{More on ZK and Hash Functions} Standardized cryptographic hash algorithms like SHA-2 were optimized mostly for minimal physical chip area, a design choice driven by NIST. Others, like the Blake family, were designed for fast execution on CPUs. They all include numerous bitwise operations (e.g., rotations, XOR) that are silicon logic-native but are notoriously inefficient to prove in ZK. Proving such operations is expensive, because a full field element (e.g., a 254-bit value on the BN254 curve) must be used to represent a single bit.\footnote{See e.g. \url{https://github.com/iden3/circomlib/blob/master/circuits/sha256/sha256.circom}} ZK provers are most efficient with arithmetic operations native to the underlying finite field, such as addition and multiplication (and lookups on some ZK stacks). Other operations must be implemented indirectly. @@ -642,7 +840,7 @@ \subsection{More on ZK and Hash Functions} A key advantage of these hashes is that they operate directly on field elements, avoiding the costly translation from integer representations. The security level is defined by the underlying field and instantiation parameters. While some VMs, like the Cairo VM used by Starknet, provide direct access to field elements, they are often highly specialized for particular use cases, such as L2 rollups. -\subsection{Performance Roadmap} +\subsubsection{Performance Roadmap} The overall approach of the zkVM path is sound: the proving time depends on the size of the addition batch, and notably, it does not have linear relationship to the total capacity of the data structure. The verification algorithm is tight. The performance bottleneck is, as discussed, the cost of arithmetizing a general-purpose execution trace that includes integer-to-field translations for every bitwise operation in the hash function. @@ -657,11 +855,11 @@ \section{Custom AIR Circuit} \subsection{Underlying Tree Variant} -The implementation proves consistency for a path-compressed Patricia trie over 256-bit keys, which we call RSMT3 (radix sparse Merkle tree, third iteration). RSMT3 has three node kinds: leaves (which hash key and value together via an additive Poseidon2 sponge), internal junctions (each is the unique point where two non-empty subtrees diverge; the junction hash includes the bifurcation depth so that subtrees cannot be silently re-attached at a different level), and empty subtrees (denoted by a canonical zero digest). Path compression eliminates single-child chains, drastically reducing the number of hash evaluations relative to a depth-256 indexed SMT, while preserving the standard SMT property that the key uniquely determines the leaf position. As established in Section~\ref{sec:scope}, the in-circuit statement does not need to enforce the canonical-shape rules of RSMT3---it only needs to enforce prior-state preservation. +The implementation proves consistency for a path-compressed Patricia trie over 256-bit keys, which we call RSMT6 (radix sparse Merkle tree, sixth iteration). RSMT6 has three node kinds: leaves (which hash key and value together via an additive Poseidon2 sponge), internal junctions (each is the unique point where two non-empty subtrees diverge; the junction hash includes the bifurcation depth so that subtrees cannot be silently re-attached at a different level), and empty subtrees (denoted by a canonical zero digest). Path compression eliminates single-child chains, drastically reducing the number of hash evaluations relative to a depth-256 indexed SMT, while preserving the standard SMT property that the key uniquely determines the leaf position. As established in Sections~\ref{sec:scope} and~\ref{sec:critical-review}, the in-circuit statement must enforce append-only consistency (Definition~\ref{def:aoc}); the circuit described in this section implements its structural core (prior-state preservation), with the edge-coherence constraint family of Section~\ref{sec:stack-verifier} as a specified extension. \subsection{From Stack Verifier to AIR Arithmetization} -The consistency proof is the flat post-order opcode stream over the alphabet $\{S(h), L, N(d)\}$ described in Section~\ref{sec:stack-verifier}, and the AIR is the arithmetization of the stack-machine verifier of Algorithm~\ref{alg:stackverify}: one execution of the verifier becomes one trace, and verification accepts iff the final stack is exactly $(r_{i-1}, r_i)$. The four-way pre-state rule on $N(d)$ is the only branching primitive of the machine, which keeps the constraint system small. +The consistency proof is the flat post-order opcode stream of Section~\ref{sec:stack-verifier}, and the AIR is the arithmetization of the stack machine of Algorithm~\ref{alg:stackverify}: one execution of the verifier becomes one trace, and verification accepts iff the final stack is exactly $(r_{i-1}, r_i)$. The implemented circuit covers the structural fragment of the statement---opcodes $S$, $L$, $N$ and the four-way digest algebra over the depth-only junction hash---whose pre-state rule is the machine's only branching primitive, keeping the constraint system small. Extending the trace with the region limbs, the openings, and the edge-coherence constraint family follows the same arithmetization pattern; the cost estimate is given in Section~\ref{sec:stack-verifier}. \subsection{AIR Tables} @@ -798,7 +996,7 @@ \subsection{The Aggregate Statement} \[ \mathsf{pv}_n = (\alpha,\, g,\, n,\, R_n,\, D_n). \] Everything else---shard roots, per-round proofs, MMR witnesses---is private witness data, so the proof and its statement have constant size regardless of $n$ and of the number of shards. -Note what is deliberately absent from the statement: signatures. The aggregate proof does not verify the committee's quorum signatures, because the truth of $\mathcal{A}_n$ does not depend on \emph{who} certified the transitions; consistency is a property of the data itself. The link to the certified reality is made by the verifier, outside the proof, by checking that the roots it cares about coincide with Unicity Certificates validated against the Trust Base (Section~\ref{sec:maxi-validation}). Folding signature verification into the circuit is possible but adds cost without adding security: it still could not prevent a quorum from signing two divergent histories, which remains the only residual attack (Section~\ref{sec:residual-trust}). +Note that validator signatures are absent from the statement. The aggregate proof does not verify the committee's quorum signatures, because the truth of $\mathcal{A}_n$ does not depend on \emph{who} certified the transitions; consistency is a property of the data itself. The link to the certified reality is made by the verifier, outside the proof, by checking that the roots it cares about coincide with Unicity Certificates validated against the Trust Base (Section~\ref{sec:maxi-validation}). Folding signature verification into the circuit is possible but adds cost without adding security: it still could not prevent a quorum from signing two divergent histories, which remains the only residual attack (Section~\ref{sec:residual-trust}). \subsection{Recursive Aggregation} @@ -866,7 +1064,7 @@ \subsection{Residual Trust Analysis} The procedure above makes the reduction of assumptions precise. Under collision resistance of the hash function and soundness of the two proof systems (the shard STARKs and the aggregation zkVM), the following hold \emph{unconditionally}, with no assumption about the validator set: \begin{enumerate}[nosep] - \item every round transition in the proven history preserved prior state~\eqref{eq:psp}---no recorded token state was ever deleted or modified, hence no double-spend is representable within that history; and + \item every round transition in the proven history satisfied append-only consistency (Definition~\ref{def:aoc}, Theorem~\ref{thm:history})---no recorded token state was ever deleted, modified, or re-recorded, hence no double-spend is representable within that history; and \item the proven history is linear: each round extends its predecessor, and $D_n$ commits to the unique sequence of global roots. \end{enumerate} @@ -878,9 +1076,9 @@ \section{Summary} Different proof systems offer different trade-offs. The relevant properties are proving effort, necessity (and generality) of trusted setup, interactivity, recursion-friendliness, and the maturity and trustworthiness of available tooling. STARKs are comparatively fast to prove but have larger proofs, and avoid undesirable properties such as trusted setup. Groth16 SNARKs produce small proofs but require more proving effort and a circuit-specific trusted setup. For more complex applications, hybrid approaches and proof recursion can be employed. Figure~\ref{fig:comp} illustrates the proof size trade-off. -A second axis of optimization is the scope of the in-circuit statement itself. The scoping argument of Section~\ref{sec:scope}---only \emph{prior-state preservation} needs cryptographic enforcement, with the remaining SMT properties self-policed by the protocol around the public root, since their violation amounts to self-inflicted denial of service by a replaceable component---turns a verification problem that naively would require encoding the full canonical tree-construction rules into one with a tight, hand-built AIR. The result is the measured order-of-magnitude proving-throughput advantage of the Plonky3 AIR over zkVM-based approaches reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. +A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Section~\ref{sec:critical-review}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the full canonical tree-construction rules into one with a tight, hand-built AIR. The result is the measured order-of-magnitude proving-throughput advantage of the Plonky3 AIR over zkVM-based approaches reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. -Above the per-round proofs sits the aggregation mechanism of Section~\ref{sec:aggregation-audit}: the consistency proofs of all shards and the Consensus Layer's own state transitions are folded, by recursion on a zkVM, into a single fixed-size transparent proof of the correctness of the system's entire operating history. The two validation paths complement each other. The pragmatic path, anchored in the Unicity Trust Base, delivers finality within seconds under an accountable honest-majority-of-stake assumption; the audit path, available with a delay of minutes to hours, retrospectively removes that assumption, leaving stake with only the roles of liveness and tip uniqueness. A formal, machine-checked correctness proof of the consistency-proof mechanism (Algorithm~\ref{alg:stackverify} enforcing prior-state preservation) is the natural next step; this paper fixes the model and the algorithms that such a proof will target. +Above the per-round proofs sits the aggregation mechanism of Section~\ref{sec:aggregation-audit}: the consistency proofs of all shards and the Consensus Layer's own state transitions are folded, by recursion on a zkVM, into a single fixed-size transparent proof of the correctness of the system's entire operating history. The two validation paths complement each other. The pragmatic path, anchored in the Unicity Trust Base, delivers finality within seconds under an accountable honest-majority-of-stake assumption; the audit path, available with a delay of minutes to hours, retrospectively removes that assumption, leaving stake with only the roles of liveness and tip uniqueness. The consistency-proof mechanism now carries a formal correctness proof (Theorem~\ref{thm:history} and its corollaries): append-only consistency of the entire certified history reduces to the collision resistance of the underlying hash function. A machine-checked formalization of this proof is the natural next step. \begin{figure}[!htbp] \centering From cc062de993806a861c88c726a8fdf81db0e10333 Mon Sep 17 00:00:00 2001 From: ristik Date: Mon, 13 Jul 2026 21:22:03 +0300 Subject: [PATCH 2/6] less canonicalilty, completeness --- aggregation-layer.tex | 75 ++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/aggregation-layer.tex b/aggregation-layer.tex index cfe7582..8f24c66 100644 --- a/aggregation-layer.tex +++ b/aggregation-layer.tex @@ -155,7 +155,7 @@ \subsection{Why ZK Proving in Unicity Is Comparatively Efficient} The combined effect of the design choices above is a proving workload that is one to three orders of magnitude smaller than in comparable ZK systems. The principal reasons: \begin{enumerate}[nosep] - \item \emph{Narrow in-circuit statement.} Only prior-state preservation needs to be enforced; canonical shape, batch incorporation, and freshness are self-policed by the protocol layer (Section~\ref{sec:scope}). + \item \emph{Narrow in-circuit statement.} Only prior-state preservation needs to be enforced; unique tree shape, batch incorporation, and freshness are self-policed by the protocol layer (Section~\ref{sec:scope}). \item \emph{No in-circuit transaction execution.} Validation of signatures, predicates, and business logic happens off-chain at the Execution Layer~\cite{exemodel}; the ZK circuit does not see any of it. \item \emph{Batch-amortized proving.} One proof per Aggregation Layer round covers thousands of insertions; there is no per-transaction ZK proof and no anonymity-set scaling. \item \emph{Local update, sublinear cost in tree capacity.} The proof attests only to the modification of a small subset of the SMT---the paths and siblings touched by the batch---rather than the whole tree. Proving effort scales with the batch size and only logarithmically with the current tree capacity, so a single shard can grow without inflating the per-round prover work. @@ -381,11 +381,11 @@ \subsection{Scope of the In-Circuit Statement} \item[Completeness] (\emph{every well-formed user request appears in the next round}). A censoring aggregator does not violate the in-circuit statement; it merely fails to serve some users. The protocol mitigates this by replication (highly-available cluster) and by allowing users to resubmit through alternative aggregators in the same shard. \item[Batch incorporation proof] (\emph{the round proof testifies to inclusion of every batch element}). Rather than have the consistency proof carry per-element inclusion claims, we let the Aggregation Layer serve fresh inclusion proofs on demand against the certified root. An aggregator that does not actually insert the batch will simply fail to produce valid inclusion proofs later, which is detectable by recipients. \item[No phantom inserts] (\emph{nothing is recorded that was not a user request}). At worst, an aggregator does free recording work for itself or third parties; phantom entries carry fresh keys (coherent placement forbids re-recording), so they cannot affect any honest user's tokens. - \item[Global canonical shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: as Theorem~\ref{thm:history} shows, coherent placement, applied round by round from the empty genesis tree, already forces every certified tree to be canonical. + \item[Unique Patricia shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: the local well-formedness conditions already force that shape (Lemma~\ref{lem:map}), and Theorem~\ref{thm:history} preserves those conditions from the empty genesis tree. \item[Append-only consistency] (\emph{\eqref{eq:psp} together with coherent placement; Definition~\ref{def:aoc}}). \emph{Critical.} If this fails, the operator can rewrite history and double-spending becomes possible. This is the property that must be cryptographically enforced \emph{before} round certification. \end{description} -Restricting the in-circuit statement to append-only consistency has several useful consequences. First, the witness need not contain the actual batch contents---the prover may keep them entirely private and bind them to the proof through the soundness chain of the circuit (Section~\ref{sec:custom-air-circuit}). This shrinks the public statement to the two root digests. Second, the circuit does not have to \emph{reconstruct} canonical shape from scratch, which is by far the most constraint-heavy aspect of any naive arithmetization (cf.~\cite{rsmtair}, ``cost-of-canonical detour''); with the region-committing hash of Section~\ref{sec:stack-verifier}, coherent placement is checked by local constraints on the touched nodes only. Third, the proof scales with the batch size alone, not with the total tree capacity. +Restricting the in-circuit statement to append-only consistency has several useful consequences. First, the witness need not contain the actual batch contents---the prover may keep them entirely private and bind them to the proof through the soundness chain of the circuit (Section~\ref{sec:custom-air-circuit}). This shrinks the public statement to the two root digests. Second, the circuit does not have to \emph{reconstruct} the unique global tree shape from scratch, which is by far the most constraint-heavy aspect of any naive arithmetization (cf.~\cite{rsmtair}, ``cost-of-canonical detour''); with the region-committing hash of Section~\ref{sec:stack-verifier}, coherent placement is checked by local constraints on the touched nodes only. Third, the proof scales with the batch size alone, not with the total tree capacity. \section{Consistency Proof} @@ -603,7 +603,7 @@ \subsection{Why Coherent Placement Is Necessary} \end{figure} \paragraph{Repair.} -The root cause is that the depth commitment binds nodes to \emph{levels}, not to \emph{key-space positions}, while $S$ subtrees are opaque digests---so no verifier-side constraint can relate the batch's keys to the regions of key space already occupied. Two repairs present themselves. The \emph{witness route} keeps the hashes and requires, per inserted key, an opened descent into the pre-state establishing freshness of the key and the canonical split point; this costs an opened path ($O(\log n)$ hash openings) per insertion. The \emph{commitment route} moves the region into the junction hash, after which coherence becomes a local check over the touched nodes, with a single one-level opening per split edge; it is cheaper in-circuit, yields simpler invariants, and preserves the insert-immutability of pre-existing hashes, because a node's region---unlike its edge structure---is invariant under insertions above it. Algorithm~\ref{alg:stackverify} is the commitment route. Revisiting the attack against it: the new junction $N(d^{*})$ must present its preserved child opened, and edge coherence demands that the opened child's region extend $p\|0$ while the new leaf's key extends $p\|1$; since the preserved subtree containing $(k,v)$ has a region that is a prefix of $k$, both conditions cannot hold with the leaf key $k$ on the other side. The attack---and, as Theorem~\ref{thm:round} shows, every attack of its kind---is excluded. A further consequence (Theorem~\ref{thm:history}) is that globally canonical shape comes for free: what naively looks like the heavyweight obligation of proving canonical construction reduces to one opening per insertion and a family of local bit-comparisons. +The root cause is that the depth commitment binds nodes to \emph{levels}, not to \emph{key-space positions}, while $S$ subtrees are opaque digests---so no verifier-side constraint can relate the batch's keys to the regions of key space already occupied. Two repairs present themselves. The \emph{witness route} keeps the hashes and requires, per inserted key, an opened descent into the pre-state establishing freshness of the key and the correct split point; this costs an opened path ($O(\log n)$ hash openings) per insertion. The \emph{commitment route} moves the region into the junction hash, after which coherence becomes a local check over the touched nodes, with a single one-level opening per split edge; it is cheaper in-circuit, yields simpler invariants, and preserves the insert-immutability of pre-existing hashes, because a node's region---unlike its edge structure---is invariant under insertions above it. Algorithm~\ref{alg:stackverify} is the commitment route. Revisiting the attack against it: the new junction $N(d^{*})$ must present its preserved child opened, and edge coherence demands that the opened child's region extend $p\|0$ while the new leaf's key extends $p\|1$; since the preserved subtree containing $(k,v)$ has a region that is a prefix of $k$, both conditions cannot hold with the leaf key $k$ on the other side. The attack---and, as Theorem~\ref{thm:round} shows, every attack of its kind---is excluded. A further consequence (Lemma~\ref{lem:map} and Theorem~\ref{thm:history}) is that the globally unique Patricia shape comes for free: what naively looks like the heavyweight obligation of proving global construction reduces to one opening per insertion and a family of local bit-comparisons. \subsection{Formal Model} \label{sec:consistency-formal} @@ -620,17 +620,21 @@ \subsection{Formal Model} $\mathsf{dig}(\varepsilon) = \varnothing$; $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$, $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$, $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. \end{definition} -\begin{definition}[Well-formed and canonical trees] +\begin{definition}[Well-formed trees] \label{def:wf} -$\varepsilon$ and leaves are well-formed; $\mathsf{Node}(d,p,l,r)$ is well-formed iff $l, r$ are, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. A well-formed tree is \emph{canonical} iff, for every junction, $p$ is the longest common prefix of the keys of the leaves below it. +$\varepsilon$ and leaves are well-formed; $\mathsf{Node}(d,p,l,r)$ is well-formed iff $l$ and $r$ are nonempty and well-formed, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. \end{definition} -\begin{lemma}[Represented map] +\begin{lemma}[Represented map and unique shape] \label{lem:map} -In a well-formed tree $T$, every leaf key extends the region of each of its ancestors, and distinct leaves carry distinct keys; hence $T$ represents a partial map $\mathsf{map}(T) = \{k \mapsto v \mid \mathsf{Leaf}(k,v) \in T\}$. Moreover, for every finite key-value map there is exactly one canonical tree. +In a well-formed tree $T$, every leaf key extends the region of each of its ancestors, and distinct leaves carry distinct keys; hence $T$ represents a partial map $\mathsf{map}(T) = \{k \mapsto v \mid \mathsf{Leaf}(k,v) \in T\}$. At every junction $\mathsf{Node}(d,p,l,r)$, the region $p$ is the longest common prefix of the keys below it. Consequently, every finite key-value map has exactly one well-formed tree. \end{lemma} \begin{proof} -The first claim is immediate by induction over the well-formedness conditions. For distinctness: two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d, p, \cdot, \cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$---impossible. Uniqueness of the canonical tree follows by induction on the key set: a singleton forces a leaf; otherwise the root junction's region and depth are forced to the longest common prefix and its length, which also splits the key set into the two forced child sets. +The ancestor claim is immediate by induction over the well-formedness conditions. For distinctness, two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d,p,\cdot,\cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$, which is impossible. + +Now consider a junction $\mathsf{Node}(d,p,l,r)$. Every key below it extends $p$. Since both children are nonempty, some key below $l$ extends $p\|0$ and some key below $r$ extends $p\|1$. Thus the common prefix ends exactly after the $d$ bits of $p$, so $p$ is the longest common prefix. + +Existence and uniqueness follow by induction on the finite key set. The empty set gives $\varepsilon$, and a singleton forces its leaf. Otherwise the root region is forced to be the longest common prefix of all keys; its next bit partitions them into two nonempty child sets. Applying the induction hypothesis to those sets constructs the two unique children. Their regions extend $p\|0$ and $p\|1$, respectively, and their depths exceed $|p|$, so joining them at $(|p|,p)$ is well-formed. Conversely, every well-formed root must use this same region, partition, and pair of inductively unique children. Values label the already determined leaves and do not affect the shape. \end{proof} \begin{definition}[Inclusion verification] @@ -645,6 +649,17 @@ \subsection{Formal Model} and accepts iff $c_m = r$. (Regions are not transmitted; the verifier derives them from $k$.) A \emph{non-inclusion witness} for $k$ against $r$ is a chain of openings from the root along $k$'s descent: junction openings $(d_j, p_j, c^0_j, c^1_j)$ whose $H$-images chain from $r$ downward through the $k[d_j]$-side child, with $p_j = k[0..d_j)$ for all but the last element, terminating either in a junction opening whose region is \emph{not} a prefix of $k$, or in an opened leaf with key $\neq k$; also, $r = \varnothing$ is a witness for every $k$. \end{definition} +\begin{definition}[Honest transition generator] +\label{def:generator} +Let $T$ be a well-formed tree and let $B$ be a finite batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. The honest generator first inserts the pairs of $B$ in increasing key order by the usual Patricia rule: follow matching regions, and when a key diverges from the current subtree, create a junction at their first divergent bit. Denote the resulting tree by $T_B$. + +The generator obtains the opcode stream $\pi_B$ by a simultaneous post-order traversal of $T$ and $T_B$. A new leaf emits $L$. A maximal unchanged pre-state subtree below a pre-existing junction emits $S$; if that subtree is instead attached directly below a junction newly created by the insertion, it emits $O$ when its root is a junction and $O_L$ when its root is a leaf. Every remaining junction of $T_B$ emits the streams of its left and right children followed by $N(d)$, where $d$ is its bifurcation depth. For $B = [\,]$, the generator returns $(T, [\,])$. We write +\[ + \mathsf{Gen}(T,B) = (T_B, \pi_B). +\] +This is the tree-difference traversal implemented by the reference generator: an opaque subtree is opened exactly when its old root first meets a new edge, after which the derived advice propagates through any further new junctions. +\end{definition} + \begin{definition}[Append-only consistency] \label{def:aoc} A \emph{certified history} is a sequence $(B_1, \pi_1, r_1), \ldots, (B_n, \pi_n, r_n)$ with $r_0 = \varnothing$ and Algorithm~\ref{alg:stackverify} accepting $(\pi_i, r_{i-1}, r_i, B_i)$ for every $i$. The history is \emph{append-only consistent} if there exist well-formed trees $T_0 = \varepsilon, T_1, \ldots, T_n$ with $\mathsf{dig}(T_i) = r_i$ and @@ -677,7 +692,7 @@ \subsection{Security} \begin{theorem}[Round soundness] \label{thm:round} -Let $T$ be a well-formed tree (possibly $\varepsilon$) with $\mathsf{dig}(T) = r_{i-1}$, and let Algorithm~\ref{alg:stackverify} accept $(\pi, r_{i-1}, r_i, B)$. Then from $T$, $\pi$, $B$ one can either compute a collision, or construct a well-formed tree $T'$ with $\mathsf{dig}(T') = r_i$ and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. If $T$ is canonical, then $T'$ is canonical. +Let $T$ be a well-formed tree (possibly $\varepsilon$) with $\mathsf{dig}(T) = r_{i-1}$, and let Algorithm~\ref{alg:stackverify} accept $(\pi, r_{i-1}, r_i, B)$. Then from $T$, $\pi$, $B$ one can either compute a collision, or construct a well-formed tree $T'$ with $\mathsf{dig}(T') = r_i$ and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. \end{theorem} \begin{proof} Let $P$ be the proof tree of Lemma~\ref{lem:run}. Define the \emph{old projection} $P_0$ by structural recursion: $S$, $O$, $O_L$ terminals map to themselves; $L$ maps to nothing; a junction whose old side was hashed (both children's old digests $\neq \varnothing$) maps to a junction over the projections of its children; a pass-through junction maps to the projection of its surviving child; an all-$\varnothing$ junction maps to nothing. By the verifier's algebra, evaluating $P_0$---with $S$ digests and $O$/$O_L$ openings as given---yields $r_{i-1}$. @@ -686,19 +701,43 @@ \subsection{Security} \emph{Step 2: construction.} Let $T'$ be the grafting of $P$: $N(d) \mapsto \mathsf{Node}(d, p, \cdot, \cdot)$, with $p$ its derived region label; $L$ and $O_L$ terminals $\mapsto$ the corresponding leaves; $O(d', p', \cdot, \cdot) \mapsto \mathsf{Node}(d', p', \cdot, \cdot)$ over its assigned child subtrees; $S(c) \mapsto$ its assigned subtree. Then $\mathsf{dig}(T') = r_i$, because the post-digest algebra agrees with $\mathsf{dig}$ on terminals and junctions. -\emph{Step 3: well-formedness.} Classify the edges of $T'$. Edges inside an assigned subtree satisfy the conditions because $T$ is well-formed. An edge whose child is an opaque $S$ terminal has, by Lemma~\ref{lem:run}, a parent whose old side was hashed; by Step~1 that parent, its labels, and its child digests coincide with a node of $T$, so the edge is an edge of $T$ at the same position, and well-formedness of $T$ applies. Every other edge has an advised child and was checked by the verifier; it remains to note that the validated advice equals the true $(\mathsf{dep}, \mathsf{reg})$ of the child's top node in $T'$: exact for $L$ and $O_L$ children by construction, for $O$ children by Step~1, and for $N$ children by the definition of their derived labels. Hence $T'$ is well-formed. +\emph{Step 3: well-formedness.} Every terminal of $P$ constructs or is assigned a nonempty subtree, so every $N$ junction of $T'$ has two nonempty children. It remains to classify its edges. Edges inside an assigned subtree satisfy the conditions because $T$ is well-formed. The two edges exposed by an $O$ terminal coincide, by Step~1, with the corresponding edges of $T$. An edge whose child is an opaque $S$ terminal has, by Lemma~\ref{lem:run}, a parent whose old side was hashed; by Step~1 that parent, its labels, and its child digests coincide with a node of $T$, so this too is an edge of $T$ at the same position. Every remaining edge has an advised child and was checked by the verifier; the validated advice equals the true $(\mathsf{dep}, \mathsf{reg})$ of the child's top node in $T'$: exact for $L$ and $O_L$ children by construction, for $O$ children by Step~1, and for $N$ children by the definition of their derived labels. Hence $T'$ is well-formed. + +\emph{Step 4: map.} The terminals of $P$ partition the leaves of $T'$ into leaves of assigned subtrees, $O_L$ leaves, and $L$ leaves. By Step~1 the first two groups are exactly the leaves of $T$; the third is exactly $B$, fully consumed and with pairwise distinct keys. By Lemma~\ref{lem:map} applied to the well-formed $T'$, all leaf keys of $T'$ are distinct, so the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. (Consequently, no accepting run exists for a batch that re-records a present key: it would produce a well-formed tree with a repeated leaf key, which does not exist.) The same lemma shows that $T'$ already has the unique shape determined by this map; no separate canonicity argument is needed. +\end{proof} + +\begin{theorem}[Algorithmic completeness] +\label{thm:complete} +Let $T$ be a well-formed tree (possibly $\varepsilon$), and let $B$ be a finite batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. If $\mathsf{Gen}(T,B) = (T_B, \pi_B)$, then $T_B$ is well-formed, +\[ + \mathsf{map}(T_B) = \mathsf{map}(T) \uplus B, +\] +and Algorithm~\ref{alg:stackverify} accepts +\[ + (\pi_B,\, \mathsf{dig}(T),\, \mathsf{dig}(T_B),\, B). +\] +The generator and verifier run in time linear in the generated stream, in addition to sorting $B$. +\end{theorem} +\begin{proof} +If $B=[\,]$, Definition~\ref{def:generator} returns $(T,[\,])$, and the verifier's empty-batch branch accepts. Assume henceforth that $B$ is nonempty. + +\emph{Insertion.} Consider first one fresh key. While its bits extend the current junction's region, Patricia insertion follows the child selected by the bifurcation bit. At the first divergence from a subtree, it creates a junction at the longest common prefix of the new key and that subtree's region. The old subtree and the new leaf extend the two opposite sides of this prefix, and their depths are greater than the new junction's depth. Thus the new edges are well-formed, while all old nodes and edges are unchanged. The represented map gains exactly the new binding. Induction over the sorted, pairwise-distinct batch proves that $T_B$ is well-formed and that $\mathsf{map}(T_B)=\mathsf{map}(T)\uplus B$. By uniqueness in Lemma~\ref{lem:map}, the result is independent of the insertion order; in particular it is the result of the batched Patricia merge used by the generator. + +\emph{Transcript evaluation.} We prove by structural induction over the simultaneous traversal of Definition~\ref{def:generator} that each emitted fragment evaluates to the digest pair of its pre- and post-state fragments and carries correct top-node advice whenever advice is present. The terminal cases are immediate. An $S$ terminal evaluates to the unchanged digest pair and deliberately carries no advice. An $O$ or $O_L$ terminal recomputes the unchanged digest and carries its authenticated depth and region. An $L$ terminal evaluates to $(\varnothing, H(\texttt{0x00}\|k\|v))$ and carries $(\kappa,k)$. + +For a junction, apply the induction hypothesis to its left and right fragments. If the junction already existed, both old child digests are present and the verifier recomputes its old digest. If the junction is new around one preserved subtree, exactly one old child digest is present and the four-way rule passes that digest through. If the whole subtree is new, both old child digests are $\varnothing$. In every case the verifier recomputes the post-state junction digest. Well-formedness of $T_B$ gives $\delta_x>d$, the required side bit, and the same prefix $p$ for every advised child. A new junction has advice on both children: a preserved child was emitted as $O$ or $O_L$, and a new child obtains advice from $L$ or from its top $N$. Hence both the coherence and confinement checks pass. At a changed pre-existing junction at least one child is non-opaque, so its region also determines $p$; an untouched junction would have been emitted as one $S$ terminal instead. The fragment therefore pushes the claimed digest pair and correct advice. -\emph{Step 4: map.} The terminals of $P$ partition the leaves of $T'$ into leaves of assigned subtrees, $O_L$ leaves, and $L$ leaves. By Step~1 the first two groups are exactly the leaves of $T$; the third is exactly $B$, fully consumed and with pairwise distinct keys. By Lemma~\ref{lem:map} applied to the well-formed $T'$, all leaf keys of $T'$ are distinct, so the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. (Consequently, no accepting run exists for a batch that re-records a present key: it would produce a well-formed tree with a repeated leaf key, which does not exist.) +At the root, this induction yields $(\mathsf{dig}(T),\mathsf{dig}(T_B))$ and a single stack entry. Finally, left-to-right leaf order in a well-formed tree is increasing key order: at each junction every left key has bit $0$ and every right key bit $1$ at the first position on which the sides differ. The $L$ terminals are therefore encountered in exactly the verifier's sorted order of $B$, once each. The batch and opcode stream are fully consumed, so all final acceptance conditions hold. -\emph{Step 5: canonicity.} Assume $T$ canonical. For an old junction of $T'$, the keys added below it extend its region (well-formedness), so the longest common prefix of the enlarged key set still equals the region. For a new junction $\mathsf{Node}(d, p, l, r)$, the regions of $l$ and $r$ equal the longest common prefixes of their own key sets (by canonicity of assigned subtrees and induction over the new structure) and extend $p\|0$ and $p\|1$ respectively, so the longest common prefix of the union is exactly $p$. Hence every junction of $T'$ is canonical. +The traversal emits a constant amount of data and performs constant verifier work per opcode. The only additional cost is sorting $B$, as claimed. \end{proof} \begin{theorem}[History soundness] \label{thm:history} -For every certified history (Definition~\ref{def:aoc}), either a collision is computable from its transcript, or the history is append-only consistent, with all $T_i$ canonical. +For every certified history (Definition~\ref{def:aoc}), either a collision is computable from its transcript, or the history is append-only consistent. In the latter case each $T_i$ is the unique well-formed tree representing its map. \end{theorem} \begin{proof} -Induction on rounds: $T_0 = \varepsilon$ is canonical with $\mathsf{dig}(T_0) = \varnothing$, and Theorem~\ref{thm:round} supplies the step. +Induction on rounds: $T_0 = \varepsilon$ is well-formed with $\mathsf{dig}(T_0) = \varnothing$, and Theorem~\ref{thm:round} supplies the step. Uniqueness follows from Lemma~\ref{lem:map}. \end{proof} \begin{corollary}[Unicity] @@ -719,11 +758,11 @@ \subsection{Security} \begin{corollary}[Service completeness] \label{cor:service} -Let $T_i$ be the canonical trees of Theorem~\ref{thm:history}. For every $(k, v) \in \mathsf{map}(T_i)$, the path data of $T_i$ yields a verifying inclusion proof; for every $k \notin \mathrm{dom}(\mathsf{map}(T_i))$, the canonical descent of $T_i$ yields a verifying non-inclusion witness. Producing them requires only possession of the tree data, an availability rather than an integrity concern. +Let $T_i$ be the well-formed trees of Theorem~\ref{thm:history}. For every $(k, v) \in \mathsf{map}(T_i)$, the path data of $T_i$ yields a verifying inclusion proof; for every $k \notin \mathrm{dom}(\mathsf{map}(T_i))$, the key-directed descent of $T_i$ yields a verifying non-inclusion witness. Producing them requires only possession of the tree data, an availability rather than an integrity concern. \end{corollary} \begin{remark} -Theorems~\ref{thm:round} and~\ref{thm:history} together with Corollaries~\ref{cor:unicity}--\ref{cor:service} establish that the coherent consistency proof realizes the accumulator interface of Definition~\ref{def:append-only-accumulator}. The proofs are elementary---structural inductions with explicit collision extraction---precisely because the region commitment localizes every invariant to an edge of the touched structure. A machine-checked formalization is planned and should follow the proof structure given here. +Theorems~\ref{thm:round} and~\ref{thm:complete} establish soundness and algorithmic completeness of each transition, while Theorem~\ref{thm:history} and Corollaries~\ref{cor:unicity}--\ref{cor:service} establish the history and query properties of the accumulator interface in Definition~\ref{def:append-only-accumulator}. The proofs are structural inductions with explicit collision extraction; the region commitment localizes every invariant to an edge of the touched structure. A machine-checked formalization is planned and should follow the proof structure given here. \end{remark} @@ -1076,7 +1115,7 @@ \section{Summary} Different proof systems offer different trade-offs. The relevant properties are proving effort, necessity (and generality) of trusted setup, interactivity, recursion-friendliness, and the maturity and trustworthiness of available tooling. STARKs are comparatively fast to prove but have larger proofs, and avoid undesirable properties such as trusted setup. Groth16 SNARKs produce small proofs but require more proving effort and a circuit-specific trusted setup. For more complex applications, hybrid approaches and proof recursion can be employed. Figure~\ref{fig:comp} illustrates the proof size trade-off. -A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Section~\ref{sec:critical-review}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the full canonical tree-construction rules into one with a tight, hand-built AIR. The result is the measured order-of-magnitude proving-throughput advantage of the Plonky3 AIR over zkVM-based approaches reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. +A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Section~\ref{sec:critical-review}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the globally unique tree shape into one with a tight, hand-built AIR. The result is the measured order-of-magnitude proving-throughput advantage of the Plonky3 AIR over zkVM-based approaches reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. Above the per-round proofs sits the aggregation mechanism of Section~\ref{sec:aggregation-audit}: the consistency proofs of all shards and the Consensus Layer's own state transitions are folded, by recursion on a zkVM, into a single fixed-size transparent proof of the correctness of the system's entire operating history. The two validation paths complement each other. The pragmatic path, anchored in the Unicity Trust Base, delivers finality within seconds under an accountable honest-majority-of-stake assumption; the audit path, available with a delay of minutes to hours, retrospectively removes that assumption, leaving stake with only the roles of liveness and tip uniqueness. The consistency-proof mechanism now carries a formal correctness proof (Theorem~\ref{thm:history} and its corollaries): append-only consistency of the entire certified history reduces to the collision resistance of the underlying hash function. A machine-checked formalization of this proof is the natural next step. From fa633c5a4359a5a58adcfcbec532afd777736b63 Mon Sep 17 00:00:00 2001 From: ristik Date: Tue, 14 Jul 2026 00:10:01 +0300 Subject: [PATCH 3/6] rewrite, cleanup the how-did-we-get-there part --- aggregation-layer.tex | 663 ++++++++++++++++++------------------------ 1 file changed, 289 insertions(+), 374 deletions(-) diff --git a/aggregation-layer.tex b/aggregation-layer.tex index 8f24c66..8cca0f2 100644 --- a/aggregation-layer.tex +++ b/aggregation-layer.tex @@ -34,6 +34,7 @@ \usepackage{amsthm} \newtheorem{definition}{Definition} \newtheorem{theorem}{Theorem} +\newtheorem{proposition}{Proposition} \newtheorem{lemma}{Lemma} \newtheorem{corollary}{Corollary} \newtheorem{remark}{Remark} @@ -70,7 +71,7 @@ \maketitle \begin{abstract} -Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT3 consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. A critical review shows that the coherent-placement half is not optional: we exhibit a concrete equivocation attack against the structure-only proof. The remaining desirable properties of the trustless Key-Value store (batch incorporation, no phantom inserts, completeness) are not required by the Unicity Aggregator's security model. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. +Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. The remaining desirable properties of the trustless Key-Value store (batch incorporation, no phantom inserts, completeness) are not required by the Unicity Aggregator's security model. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. \end{abstract} @@ -82,43 +83,9 @@ \section{Motivation} To scale further, we use cryptographic zero-knowledge proofs (ZKPs) to compress the size of the consistency proofs. As an application of ZKPs, this use-case is fundamentally more efficient than using ZKPs to process the transaction data itself, as is done in many privacy coins and ZK-rollups: the statement being proved is a single tree-update, with the batch as a private witness, not the whole execution trace of a virtual machine. -A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer needs to be convinced that \emph{no previously-recorded leaf was deleted or modified} and that \emph{every new leaf is placed coherently with its key}; the critical review of Section~\ref{sec:critical-review} shows, by a concrete attack, that the second half cannot be dropped. The remaining desirable properties of the Aggregation Layer---batch incorporation, no phantom inserts, completeness---are self-policed by the protocol layer that lives around the public root commitment: their violation only damages the dishonest aggregator's own ability to serve users, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument, and Section~\ref{sec:consistency-formal} proves that the resulting statement is sufficient. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. +A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer needs to be convinced that \emph{no previously-recorded leaf was deleted or modified} and that \emph{every new leaf is placed coherently with its key}; Remark~\ref{rem:placement} shows, by a concrete attack, that the second half cannot be dropped. The remaining desirable properties of the Aggregation Layer---batch incorporation, no phantom inserts, completeness---are self-policed by the protocol layer that lives around the public root commitment: their violation only damages the dishonest aggregator's own ability to serve users, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument, and Section~\ref{sec:consistency-formal} proves that the resulting statement is sufficient. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. -In this paper, we show how to scale the Aggregation Layer to $10\,000$ tx/s \emph{per shard} and beyond. This figure was the original design target; the measured proving throughput of our reference implementation exceeds it by roughly $3\times$ on a single consumer-class CPU (Section~\ref{sec:custom-air-circuit}). Due to the small proof size and efficient verification, the Consensus Layer can support a practically unlimited number of such trustless shards. Table~\ref{tab:zk-comparison} compares different ZKP technologies. We have picked subjectively the most appropriate ZK schemes and supporting front-ends (``stacks''); the Plonky3 AIR rows now report measured numbers from our implementation~\cite{rsmtair}. - -\begin{table*}[h!] -\centering -\caption{Comparison of zero-knowledge proof technologies for compression of consistency proofs.} -\label{tab:zk-comparison} -\begin{tabular}{@{}lccccccc@{}} -\toprule -\textbf{ZK Stack} & -\makecell{\textbf{Hash}\\\textbf{Function}} & -\makecell{\textbf{Proving}\\\textbf{Speed (tx/s)}} & -\makecell{\textbf{Proof}\\\textbf{Size}} & -\makecell{\textbf{Proof Size}\\\textbf{Asymptotics}} & -\makecell{\textbf{Trusted}\\\textbf{Setup}} & -\makecell{\textbf{Impl.}\\\textbf{Effort}} \\ -\midrule -None (``hash based'') & SHA-256 & 10\,000\textsuperscript{*} & 10\;MB & $O(n)$ & No & N/A \\ -CIRCOM + Groth16 & Poseidon & 25 & 250\;B & $O(1)$ & Yes & Lower \\ -Gnark + Groth16 & Poseidon & 30 & 250\;B & $O(1)$ & Yes & Low \\ -SP1 zkVM & SHA-256 & 1.5 & 2\;MB & $O(\log n)$ & No & Lowest \\ -Cairo + STwo & Poseidon & 100 & 2.4\;MB & $O(\log n)$ & No & Medium \\ -\textbf{AIR + Plonky3}\textsuperscript{‡} & Poseidon2 & \textbf{28\,000} & 1.76\;MB & $O(\log n)$ & No & High \\ -AIR + Plonky3 (small proof) & Poseidon2 & 21\,000 & 0.93\;MB & $O(\log n)$ & No & High \\ -AIR + Plonky3 (Blake3 FRI) & Poseidon2 & 31\,000 & 1.69\;MB & $O(\log n)$ & No & High \\ -\bottomrule -\end{tabular} - -\vspace{0.5em} -\raggedright -\textsuperscript{*} Bandwidth-limited at the Consensus Layer; no verification-effort reduction.\\ -\textsuperscript{‡} Measured; see Section~\ref{sec:custom-air-circuit} for details and \cite{rsmtair} for the reference implementation. The internal tree hash is always Poseidon2; ``Blake3 FRI'' refers to the choice of hash inside FRI, Merkle commitments and the Fiat--Shamir transcript. -\end{table*} - - -The estimated implementation effort reflects the perceived maturity and learning curve, and the difficulty of producing safe implementations. Custom AIR designs sit at the high end of effort because the circuit is hand-built rather than synthesized from a general-purpose program; this is the cost we pay for the order-of-magnitude proving-throughput advantage over zkVM-based stacks. +In this paper, we show how to scale the Aggregation Layer to $10\,000$ tx/s \emph{per shard} and beyond. This figure was the original design target; the measured proving throughput of our reference implementation exceeds it by roughly $3\times$ on a single consumer-class CPU (Section~\ref{sec:custom-air-circuit}). Due to the small proof size and efficient verification, the Consensus Layer can support a practically unlimited number of such trustless shards. \section{State of the Art and Comparison} @@ -171,7 +138,7 @@ \section{System Architecture} The rest of the processing---executing transactions, running smart contracts, etc.---can happen at the client layer, executed by users or ``agents''. Agents are themselves the interested parties in data availability and transaction validation, and they choose the ordering of incoming messages for processing. Thus, the Unicity Infrastructure is relieved of these duties, removing a major scaling bottleneck of traditional L1 blockchains. -The Unicity Infrastructure operates in a trust-minimized way by utilizing distributed authenticated data structures and cryptographic zero-knowledge tools (SNARKs) for extra succinctness of messages and tokens. The Proof of Unicity is a fresh \emph{proof of inclusion} of the token state being spent. This can be efficiently generated based on a Merkle Tree data structure. The proof size is logarithmic with respect to the tree's capacity, making it highly efficient. If the root of the tree is securely fixed, the integrity of the rest of the tree can be verified trustlessly: it is computationally infeasible to generate a valid inclusion proof for an element not present in the tree, without changing the root, or breaking underlying cryptographic assumptions. The infrastructure also supports \textit{non-inclusion proofs}, making it possible to prove to other parties that a particular token state has not yet been spent. The Unicity Infrastructure can thus be conceptualized as a large-scale, distributed Sparse Merkle Tree (SMT). Specifically, the production tree is implemented as a path-compressed radix variant (the RSMT3 design, see Section~\ref{sec:custom-air-circuit}) that eliminates single-child internal chains while preserving the standard property that the key uniquely determines the leaf position. In this paper, without the loss of generality, we model the distributed tree as a plain SMT. Furthermore, an SMT is straightforward to shard: the tree is partitionable vertically into slices. Leaves remain at their deterministically computed positions, as an SMT is an indexed data structure. Each leaf's identifier encodes its address in the tree, and the leaf's shard address is a prefix of the identifier. +The Unicity Infrastructure operates in a trust-minimized way by utilizing distributed authenticated data structures and cryptographic zero-knowledge tools (SNARKs) for extra succinctness of messages and tokens. The Proof of Unicity is a fresh \emph{proof of inclusion} of the token state being spent. This can be efficiently generated based on a Merkle Tree data structure. The proof size is logarithmic with respect to the tree's capacity, making it highly efficient. If the root of the tree is securely fixed, the integrity of the rest of the tree can be verified trustlessly: it is computationally infeasible to generate a valid inclusion proof for an element not present in the tree, without changing the root, or breaking underlying cryptographic assumptions. The infrastructure also supports \textit{non-inclusion proofs}, making it possible to prove to other parties that a particular token state has not yet been spent. The Unicity Infrastructure can thus be conceptualized as a large-scale, distributed Sparse Merkle Tree (SMT). Specifically, the tree is implemented as a path-compressed radix variant, the RSMT (Section~\ref{sec:stack-verifier}), which eliminates single-child internal chains while preserving the standard property that the key uniquely determines the leaf position. Furthermore, an SMT is straightforward to shard: the tree is partitionable vertically into slices. Leaves remain at their deterministically computed positions, as an SMT is an indexed data structure. Each leaf's identifier encodes its address in the tree, and the leaf's shard address is a prefix of the identifier. Aggregation Layer connects to the Consensus Layer. For fully trustless operation, each request is accompanied by a cryptographic proof of SMT consistency. @@ -266,7 +233,7 @@ \section{Security Model of the Aggregation Layer} \label{def:append-only-accumulator} \end{definition} -When instantiated as a Sparse Merkle Tree (SMT), then $v_k \leadsto r$ is the hash chain from the value at $k$-th position to root $c$, and $\varnothing_k \leadsto r$ denotes the hash chain from the ``empty'' value at $k$-th position to root $c$. +In the tree instantiation, $v_k \leadsto r$ is the hash chain from the leaf holding the value of key $k$ to the root, and $\varnothing_k \leadsto r$ is a chain of openings witnessing that key $k$ is unoccupied; Definition~\ref{def:incl} makes both precise. After each batch of additions, the new root of the Aggregation Layer's SMT is certified by the BFT Core, ensuring its uniqueness and immutability. This provides a secure trust anchor for all consistency, inclusion, and non-inclusion proofs. The idealized Consensus Layer is modeled as Algorithm~\ref{alg:consensuslayer}. @@ -359,7 +326,7 @@ \subsection{Practical Security Assumptions} \subsection{Scope of the In-Circuit Statement} \label{sec:scope} -A core engineering choice in the design of the Aggregation Layer's consistency proof is to push as much of the per-round security argument out of the cryptographic proof as possible, leaving only a small kernel inside the circuit. The value of the scoping is engineering economy---it keeps the circuit small. Drawing the boundary correctly, however, requires care: it is tempting to place \emph{all} placement-related properties outside the kernel, on the argument that a misplaced insertion only damages the aggregator's own ability to serve proofs. Section~\ref{sec:critical-review} refutes that argument by a concrete attack; the boundary is drawn below and proved sufficient in Section~\ref{sec:consistency-formal}. +A core engineering choice in the design of the Aggregation Layer's consistency proof is to push as much of the per-round security argument out of the cryptographic proof as possible, leaving only a small kernel inside the circuit. The value of the scoping is engineering economy---it keeps the circuit small. Drawing the boundary correctly, however, requires care: it is tempting to place \emph{all} placement-related properties outside the kernel, on the argument that a misplaced insertion only damages the aggregator's own ability to serve proofs. Remark~\ref{rem:placement} refutes that argument by a concrete attack; the boundary is drawn below and proved sufficient in Section~\ref{sec:consistency-formal}. Let $M_{i-1}, M_i \colon \{0,1\}^* \to \{0,1\}^* \cup \{\bot\}$ be the partial maps of recorded key-value bindings committed by, respectively, the previous and the new state roots $r_{i-1}, r_i$ (Section~\ref{sec:consistency-formal} makes ``committed by'' precise). We say the round update $r_{i-1} \to r_i$ satisfies \emph{prior-state preservation} iff \begin{equation} @@ -373,7 +340,7 @@ \subsection{Scope of the In-Circuit Statement} For the Aggregation Layer, the cryptographic per-round consistency proof must enforce, given authentic roots $(r_{i-1}, r_i)$: (i) prior-state preservation \eqref{eq:psp}, and (ii) \emph{coherent placement}: every leaf inserted in the round sits at the position determined by its own key. Definition~\ref{def:aoc} states this formally. \end{definition} -Clause (ii) is important. Because the maps $M_i$ are realized by \emph{provability} against the root---a binding is ``recorded'' exactly when an inclusion proof for it verifies---an incoherently placed insertion changes which bindings are provable, for old keys as well as new ones. Section~\ref{sec:critical-review} shows that dropping (ii) admits verifying round transitions under which an already-recorded key becomes re-recordable with a different value: the equivocation that \eqref{eq:psp} is meant to exclude. +Clause (ii) is important. Because the maps $M_i$ are realized by \emph{provability} against the root---a binding is ``recorded'' exactly when an inclusion proof for it verifies---an incoherently placed insertion changes which bindings are provable, for old keys as well as new ones. Remark~\ref{rem:placement} shows that dropping (ii) admits verifying round transitions under which an already-recorded key becomes re-recordable with a different value: the equivocation that \eqref{eq:psp} is meant to exclude. The remaining desirable properties of the Aggregation Layer stay outside the kernel, and can be enumerated and accounted for as follows: @@ -381,7 +348,7 @@ \subsection{Scope of the In-Circuit Statement} \item[Completeness] (\emph{every well-formed user request appears in the next round}). A censoring aggregator does not violate the in-circuit statement; it merely fails to serve some users. The protocol mitigates this by replication (highly-available cluster) and by allowing users to resubmit through alternative aggregators in the same shard. \item[Batch incorporation proof] (\emph{the round proof testifies to inclusion of every batch element}). Rather than have the consistency proof carry per-element inclusion claims, we let the Aggregation Layer serve fresh inclusion proofs on demand against the certified root. An aggregator that does not actually insert the batch will simply fail to produce valid inclusion proofs later, which is detectable by recipients. \item[No phantom inserts] (\emph{nothing is recorded that was not a user request}). At worst, an aggregator does free recording work for itself or third parties; phantom entries carry fresh keys (coherent placement forbids re-recording), so they cannot affect any honest user's tokens. - \item[Unique Patricia shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: the local well-formedness conditions already force that shape (Lemma~\ref{lem:map}), and Theorem~\ref{thm:history} preserves those conditions from the empty genesis tree. + \item[Unique Patricia shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: the local validity conditions already force that shape (Proposition~\ref{prop:canon}), and Theorem~\ref{thm:history} preserves those conditions from the empty genesis tree. \item[Append-only consistency] (\emph{\eqref{eq:psp} together with coherent placement; Definition~\ref{def:aoc}}). \emph{Critical.} If this fails, the operator can rewrite history and double-spending becomes possible. This is the property that must be cryptographically enforced \emph{before} round certification. \end{description} @@ -391,91 +358,16 @@ \subsection{Scope of the In-Circuit Statement} \section{Consistency Proof} \label{sec:consistency-proof} -A \emph{consistency proof} is a cryptographic construction that validates one round of operation of the append-only accumulator. - -We have the $i$-th batch of insertions $B_i = (k_1, k_2, \dots, k_j)$, where $k$ is an inserted item; all insertions are applied within a single operational round. The root hash before the round is $r_{i-1}$, and after the round is $r_i$. The accumulator is implemented as a Sparse Merkle Tree (SMT). - -The consistency proof generation for batch $B_i$ works as follows: - -\begin{enumerate} - \item The new leaves in batch $B_i$ are inserted into the SMT. - \item For each newly inserted leaf, the sibling nodes on the path from the leaf to the root are collected. Siblings present or computable from other leaves in the batch are discarded. Siblings can be further organized by dividing them into layers, for more efficient verification. We denote the set as $\pi_i$. - \item Record $(B_i, r_{i-1}, r_i, \pi_i)$. -\end{enumerate} - -Proof verification works as follows: - -\begin{enumerate} - \item Verify the authenticity of the state roots $r_{i-1}$ and $r_i$ (e.g., by checking their certification by the Consensus Layer). - \item Build an incomplete SMT tree: for each item in $B_i$, insert the value of an empty leaf at the appropriate position. - \item All non-computable siblings needed to compute the root are available in $\pi_i$. Compute the root, compare with $r_{i-1}$; if not equal then the proof is not valid. - \item Build again an incomplete SMT tree; for each item in $B_i$, insert the value of the key into the appropriate position. - \item Compute the root based on siblings in $\pi_i$. If the root is not equal to $r_i$ then the proof is not valid. - \item The proof is valid if the checks above passed. -\end{enumerate} - -A valid proof demonstrates that, given authentic roots $r_{i-1}$ and $r_i$, the keys in $B_i$ corresponded to empty leaves prior to the update, and that after the update, the values in $B_i$ were recorded at the positions defined by their respective keys, and there were no other changes. - -Complete verification algorithm is presented as Algorithm~\ref{alg:verifynondeletion}. Note that there are several assumptions: that the batch is sorted by keys; and the proof is an array of arrays of tuples, outer array divides siblings into depth layers and inner array is sorted by keys (first element of tuple). - -Due to the sparseness of the SMT we can further improve the encoding, for example, instead of checking if a node's sibling is the next item in layer's nodes or the next item in proof array or empty element otherwise, we just record a number--how many of the next siblings are empty elements (frequent close to the leaves when SMT is sparsely populated); and same with siblings (frequent close to the root). - -\begin{algorithm}[htb] - \caption{Layer-by-layer verification of the consistency proof (plain SMT)}\label{alg:verifynondeletion} - \begin{algorithmic}[0] - \Function{VerifyConsistencySMT}{$\pi, r_{i-1}, r_i, P$} - \State \Comment{Proof $\pi$ is a by-layer array of ...} - \State \Comment{... sorted arrays of k-v tuples} - \State \Comment{Insertion batch $P$ is ...} - \State \Comment{... sorted array of k-v tuples} - \State $p_\varnothing \gets \{(k, \varnothing) \mid (k, v) \in P\}$ \Comment{Empty leaves} - \State $r_\varnothing \gets$ \Call{ComputeForest}{$\pi, p_\varnothing$} - \State \textbf{assert} $r_\varnothing = r_{i-1}$ - \State \Comment{Same with batch's leaves populated} - \State $r_B \gets$ \Call{ComputeForest}{$\pi, P$} - \State \textbf{assert} $r_B = r_i$ - \State \Return $1$ \Comment{Success} - \EndFunction - - \Function{ComputeForest}{$\pi, p$} - \For{$\ell \in \text{tree\_depth}$} - \State $p' \gets [\,]$ \Comment{computed nodes of parent layer} - \State $m \gets 0 ; n \gets 0$ \Comment{indices} - \While{$m < |p|$} - \State $(k, v) \gets p[m]$ - \State $k_p \gets \lfloor k / 2 \rfloor$ \Comment{Parent key} - \State $\text{is\_right} \gets k \bmod 2$ - \State $k_s \gets 2k_p + (1 - \text{is\_right})$ \Comment{Sibling key} - \If{$\lnot \text{is\_right} \land |p| > m+1 \land p[m+1].k = k_s$\\ \hskip 4em} - \Comment{Right sibling is next} - \State $v_s \gets p[m+1].v$ - \State $m \gets m + 1$ \Comment{Jump over} - % j < len(lproof) and lproof[j][0] == sibling - \ElsIf{$|\pi[\ell]| > n \land \pi[\ell][n].k = k_s$} - \State $v_s \gets \pi[\ell][n].k$ - \State $n \gets n + 1$ - \Else - \State $v_s \gets \varnothing$ - \EndIf - \State $v_p \gets h(v_s, v)$ \textbf{if} is\_right \textbf{else} $h(v, v_s)$ - \State $p' \gets p' \| (k_p, v_p)$ - \State $m \gets m + 1$ - \EndWhile - \State $p \gets p'$ - \EndFor - \State \textbf{assert} $|p| = 1$ \Comment{One root!} - \State \Return $p[0].v$ \Comment{Value of the root} - \EndFunction - \end{algorithmic} -\end{algorithm} +A \emph{consistency proof} is a cryptographic construction that validates one round of operation of the append-only accumulator. Round $i$ inserts the batch $B_i = ((k_1, v_1), \ldots, (k_j, v_j))$ of key--value pairs into the tree; the root digest before the round is $r_{i-1}$, and after the round it is $r_i$. The consistency proof $\pi_i$ is a transcript of the part of the tree touched by the insertions. The Consensus Layer verifies $(\pi_i, r_{i-1}, r_i)$ before certifying $r_i$ (Algorithm~\ref{alg:consensuslayer}). +The property that verification enforces is \emph{append-only consistency} (Definition~\ref{def:minimal}; formally Definition~\ref{def:aoc}): every binding recorded under $r_{i-1}$ is recorded unchanged under $r_i$, and every new leaf sits at the position determined by its own key. Section~\ref{sec:stack-verifier} specifies the tree, the proof encoding, and the verifier; Section~\ref{sec:consistency-formal} develops the formal model; Section~\ref{sec:consistency-theorem} proves soundness and completeness, assuming only collision resistance of the hash function. -\subsection{Stack-Machine Verification for the Path-Compressed Tree} +\subsection{The Region-Committing Tree and Its Verifier} \label{sec:stack-verifier} -Algorithm~\ref{alg:verifynondeletion} is formulated for the plain, fixed-depth SMT used as the model throughout this paper; it is also the encoding on which the early ZK experiments of the following sections were built, and it is retained for that reason. Production implementations use the path-compressed RSMT3 tree (Section~\ref{sec:custom-air-circuit}) and a transcript-based encoding, executed by a stack machine. This subsection specifies the encoding and its verifier; Section~\ref{sec:critical-review} explains why the coherence machinery is necessary, and Sections~\ref{sec:consistency-formal}--\ref{sec:consistency-theorem} prove the construction sufficient. +The accumulator is implemented as the \emph{RSMT} (radix sparse Merkle tree): a binary Patricia tree over fixed-length keys, path-compressed, with a region-committing node hash. The consistency proof is a transcript of the touched part of the tree, executed by a stack machine. -A leaf hashes the full key together with the value, and a junction hashes its two children together with its bifurcation depth $d$ and its \emph{region} $p$: +Let $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$ be the hash function. A leaf hashes the full key together with the value, and a junction hashes its two children together with its bifurcation depth $d$ and its \emph{region} $p$: \begin{align*} h_L &= H(\texttt{0x00} \parallel k \parallel v),\\ h_N &= H(\texttt{0x01} \parallel \langle d\rangle \parallel \langle p\rangle \parallel h_l \parallel h_r). @@ -491,15 +383,15 @@ \subsection{Stack-Machine Verification for the Path-Compressed Tree} \item[$N(d)$:] a junction at bifurcation depth $d$, over the two preceding stack entries. Junction regions do not travel in the proof; the verifier derives them. \end{description} -The verifier (Algorithm~\ref{alg:stackverify}) executes the stream against a stack of triples: the subtree's pre-state digest, its post-state digest, and an \emph{advice tuple} $(\delta, \varrho)$---the depth and region of the subtree's top node, $(\kappa, k)$ for leaves, absent ($\bot$) for opaque $S$ entries. The batch is sorted by the verifier itself into tree-traversal order and must be strictly increasing, so the prover has no freedom in associating $L$ opcodes with batch elements. Processing $N(d)$ combines three rule families: +The verifier (Algorithm~\ref{alg:stackverify-core}; the complete form is Algorithm~\ref{alg:stackverify} in Appendix~\ref{app:verifier}) executes the stream against a stack of triples: the subtree's pre-state digest, its post-state digest, and an \emph{advice tuple} $(\delta, \varrho)$---the depth and region of the subtree's top node, $(\kappa, k)$ for leaves, absent ($\bot$) for opaque $S$ entries. The batch is sorted by the verifier itself into tree-traversal order and must be strictly increasing, so the prover has no freedom in associating $L$ opcodes with batch elements. Processing $N(d)$ combines three rule families: \begin{enumerate}[nosep] \item \emph{Edge coherence.} Every child that carries advice must satisfy $\delta > d$ and $\varrho[d] = \beta$, where $\beta$ is the child's side. The first $d$ bits of $\varrho$ yield the junction's region $p$; all advised children must agree on it, and at least one child must be advised, so $p$ is always defined. \item \emph{Confinement of opaque subtrees.} If the junction is absent from the pre-state---its old side arises by pass-through or $\varnothing$---then \emph{both} children must carry advice. An opaque $S$ may therefore appear only under pre-existing junctions, whose edges were checked in the round that created them and are frozen by the hashes; wherever a preserved subtree meets a new junction, the prover must present its opened form. \item \emph{Digest algebra.} The pre-state digest of a junction follows a four-way rule: if both children existed in the pre-state, the junction existed too and its old digest is recomputed; if exactly one child existed, the junction is new and the old digest of the existing child passes through unchanged; if neither existed, the old digest is the empty marker $\varnothing$. The post-state digest is always recomputed. The pass-through cases are what keep consistency proofs short: no hashing is performed on the parts of the tree that did not change. \end{enumerate} -\begin{algorithm}[H] - \caption{Stack-machine verification of the RSMT3 consistency proof}\label{alg:stackverify} +\begin{algorithm}[t!] + \caption{Stack-machine verification of the RSMT consistency proof (operand-domain checks omitted)}\label{alg:stackverify-core} \footnotesize \begin{algorithmic}[0] \Function{VerifyConsistency}{$\pi, r_{i-1}, r_i, B$} @@ -507,16 +399,16 @@ \subsection{Stack-Machine Verification for the Path-Compressed Tree} \State \Return $r_{i-1} = r_i \;\land\; \pi = [\,]$ \EndIf \State $B \gets \Call{SortTraversalOrder}{B}$ - \State \textbf{assert} keys of $B$ strictly increasing \State $\mathit{st} \gets [\,]$; \quad $b \gets 0$ \Comment{stack; batch index} \For{opcode $o$ \textbf{in} $\pi$} - \If{$o = S(c)$, $c \neq \varnothing$} \Comment{opaque subtree} + \If{$o = S(c)$} \Comment{opaque subtree} \State \Call{Push}{$\mathit{st}, (c, c, \bot)$} \ElsIf{$o = O(d', p', c_l, c_r)$} \Comment{opening} \State $c \gets H(\texttt{0x01} \| \langle d'\rangle \| \langle p'\rangle \| c_l \| c_r)$ \State \Call{Push}{$\mathit{st}, (c, c, (d', p'))$} \ElsIf{$o = O_L(k', v')$} \Comment{opened leaf} - \State \Call{Push}{$\mathit{st}, (c, c, (\kappa, k'))$}, $c = H(\texttt{0x00} \| k' \| v')$ + \State $c \gets H(\texttt{0x00} \| k' \| v')$ + \State \Call{Push}{$\mathit{st}, (c, c, (\kappa, k'))$} \ElsIf{$o = L$} \Comment{new leaf} \State $(k, v) \gets B[b]$; \quad $b \gets b + 1$ \State \Call{Push}{$\mathit{st}, (\varnothing,\; H(\texttt{0x00} \| k \| v),\; (\kappa, k))$} @@ -556,113 +448,115 @@ \subsection{Stack-Machine Verification for the Path-Compressed Tree} \end{algorithmic} \end{algorithm} -Verification accepts iff the opcode stream and the batch are both fully consumed, the stack holds exactly one triple, and its digest pair equals $(r_{i-1}, r_i)$; any stack underflow or batch overrun rejects. The verifier is a short loop with no recursion and no control flow beyond opcode dispatch---one uniform rule per opcode; its memory use is bounded by the tree depth, and the post-order format makes verification a natural streaming computation. This regularity is deliberate: it is what the AIR arithmetization of Section~\ref{sec:custom-air-circuit} exploits, one trace row per opcode with a fixed constraint family. In-circuit, deriving the junction regions costs nothing extra---the derivation equalities \emph{are} the edge-coherence constraints, and the region limbs appear as hash inputs either way. Relative to the structural fragment of the statement (opcodes $S$, $L$, $N$ and the digest algebra alone), the coherence machinery costs region limbs in the Poseidon2 junction preimage (roughly one additional permutation per junction hash), the bit-prefix comparisons, and the openings ($\approx$ one extra hash per batch element); we estimate the dominant Poseidon2 table grows by a factor of at most $1.5$. The measured throughput of Section~\ref{sec:measured}, which covers the structural fragment, leaves ample headroom above the $10\,000$\,tx/s design target. +Algorithm~\ref{alg:stackverify-core} omits only the operand-domain assertions ($c \in \{0,1\}^{\lambda}$, $0 \le d < \kappa$, $p \in \{0,1\}^{d}$, $k \in \{0,1\}^{\kappa}$), for readability. The complete verifier, Algorithm~\ref{alg:stackverify} in Appendix~\ref{app:verifier}, includes them; the formal statements refer to it. Verification accepts iff the opcode stream and the batch are both fully consumed, the stack holds exactly one triple, and its digest pair equals $(r_{i-1}, r_i)$; any failed assertion, malformed opcode, stack underflow, or batch overrun rejects. The verifier is a short loop with no recursion and no control flow beyond opcode dispatch---one uniform rule per opcode; its memory use is bounded by the tree depth, and the post-order format makes verification a natural streaming computation. This regularity is deliberate: it is what the AIR arithmetization of Section~\ref{sec:custom-air-circuit} exploits, one trace row per opcode with a fixed constraint family. In-circuit, deriving the junction regions costs nothing extra---the derivation equalities \emph{are} the edge-coherence constraints, and the region limbs appear as hash inputs either way. Relative to the structural fragment of the statement (opcodes $S$, $L$, $N$ and the digest algebra alone), the coherence machinery costs region limbs in the Poseidon2 junction preimage (roughly one additional permutation per junction hash), the bit-prefix comparisons, and the openings ($\approx$ one extra hash per batch element); we estimate the dominant Poseidon2 table grows by a factor of at most $1.5$. The measured throughput of Section~\ref{sec:measured}, which covers the structural fragment, leaves ample headroom above the $10\,000$\,tx/s design target. For the honest prover, the transcript differs from a bare depth-only encoding only in the openings: one opened junction or leaf per split edge---the node the insertion descends past last. Measured with the reference implementation on a batch of $1\,000$ insertions into a tree of $10^4$ keys, the transcript is within $15\%$ of the size of the depth-only encoding; the derived regions cost nothing on the wire. -\subsection{Why Coherent Placement Is Necessary} -\label{sec:critical-review} +\begin{remark}[Why the region commitment is necessary] +\label{rem:placement} +Everything in Algorithm~\ref{alg:stackverify-core} beyond the digest algebra exists to enforce coherent placement. Consider the minimal alternative: the junction hash commits the depth alone, $h_N = H(\texttt{0x01} \| \langle d\rangle \| h_l \| h_r)$, the alphabet shrinks to $S$, $L$, $N$, and only the digest algebra is checked. Let the pre-state with certified root $r_{i-1}$ contain the recorded binding $(k, v)$, and pick any depth $d^{*}$ with $k[d^{*}] = 1$. The three-opcode stream $(S(r_{i-1}), L, N(d^{*}))$ then verifies for the batch $\{(k, v')\}$, $v' \ne v$: the old side of $N(d^{*})$ passes $r_{i-1}$ through, and the new side hangs the entire pre-state tree on the $0$-side of the new junction, while the key-directed descent for $k$ leads to the $1$-side. Under the certified $r_i$, a one-step inclusion proof for $(k, v')$ verifies, and the preserved binding $(k, v)$ is no longer provable: cross-round equivocation on $k$, invisible to every structural check, including the full-history audit of Section~\ref{sec:aggregation-audit}. Algorithm~\ref{alg:stackverify-core} rejects the stream: the preserved child of a new junction must be presented opened, and edge coherence requires its region to extend $p\|0$ while the new leaf's key extends $p\|1$---impossible, since the preserved subtree's region is a prefix of $k$. Theorem~\ref{thm:round} shows that every attack of this kind is excluded. +\end{remark} -Everything in Algorithm~\ref{alg:stackverify} beyond the digest algebra---the region in the junction hash, the openings, the edge-coherence checks---exists to enforce coherent placement, and it is legitimate to ask whether the expense is necessary. Consider the natural minimal alternative, the \emph{structure-only} proof: the junction hash commits the depth alone, $h_N = H(\texttt{0x01} \| \langle d\rangle \| h_l \| h_r)$; the alphabet shrinks to $S(h)$, $L$, $N(d)$; and the verifier keeps only the four-way digest algebra. This variant does enforce \emph{structural preservation}: reconstructing $r_{i-1}$ forces the proof to cover every branch of the pre-state tree; every covered subtree reappears, unmodified, under $r_i$ (depth commitment and child ordering exclude relocation and swapping); each $L$ is bound to exactly one batch element by the sorting and exhaustion checks; and there is no third source of leaves. It even binds values under any \emph{single} root: two verifying inclusion proofs for $(k,v)$ and $(k,v')$ against the same digest force, level by level from the root, equal hash preimages (anything else is a collision) and---because the descent direction is recomputed from $k$'s bits---the same path, terminating in $H(\texttt{0x00}\,\|\,k\,\|\,v) = H(\texttt{0x00}\,\|\,k\,\|\,v')$, i.e., $v = v'$ or a collision. +\subsection{Formal Model} +\label{sec:consistency-formal} -What structural preservation does not do is relate the batch's keys to the \emph{positions} at which the new leaves are attached. The Aggregation Layer's security model, however, is stated in terms of provability: a binding $(k,v)$ is \emph{recorded} under a certified root $r$ exactly when an inclusion proof for it verifies against $r$---this is what a Proof of Unicity is. Under this semantics, the structure-only guarantee fails, and it fails \emph{across} rounds. +We fix the key length $\kappa = 256$, key space $\mathcal{K} = \{0,1\}^{\kappa}$, a value space $\mathcal{V} \subseteq \{0,1\}^{*}$, and a hash function $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$. For bit strings, $p \sqsubseteq q$ denotes that $p$ is a prefix of $q$, $q[j]$ is the $j$-th bit, and $q[0..d)$ is the first $d$ bits; $\langle\cdot\rangle$ are fixed-length injective encodings; $\varnothing$ is a distinguished constant outside $\{0,1\}^{\lambda}$. All statements below are unconditional reductions: each concludes either the stated property, or that two distinct strings with equal $H$-images (a \emph{collision}) are computable in time linear in the size of the objects at hand. We do not repeat this disjunction in every statement. -\paragraph{The shadow-insertion attack.} -Let the pre-state be any tree containing the recorded binding $(k,v)$, with certified root $r_{i-1}$; for concreteness, the tree consisting of that single leaf. A Byzantine aggregator (prompted, say, by a user attempting a double-spend of the token state $k$) picks any depth $d^{*}$ with $k[d^{*}] = 1$ and submits the batch $B_i = \{(k, v')\}$, $v' \neq v$, with the three-opcode proof -\[ \pi = \big(\,S(r_{i-1}),\; L,\; N(d^{*})\,\big). \] -The structure-only verifier accepts: the old side of $N(d^{*})$ is the pass-through of $S$'s digest, reproducing $r_{i-1}$ exactly, and the new side yields -$r_i = H\big(\texttt{0x01} \| d^{*} \| r_{i-1} \| H(\texttt{0x00} \| k \| v')\big)$. -Against the certified $r_i$, the one-step inclusion proof for $(k, v')$---sibling $r_{i-1}$, depth $d^{*}$, direction $k[d^{*}] = 1$---verifies. The construction is depicted in Figure~\ref{fig:shadow}. The consequences: -\begin{enumerate}[nosep] - \item \emph{Cross-round equivocation.} $(k,v)$ is recorded under $r_{i-1}$ and $(k,v')$ is recorded under $r_i$: two conflicting spends of the same token state, both anchored to certified roots. This is precisely the event the Aggregation Layer exists to prevent. - \item \emph{Retroactive orphaning.} Under $r_i$, the binding $(k,v)$ is no longer provable: any path to it now passes the new junction in direction $0 \neq k[d^{*}]$. More generally, a single misdirected junction placed above any preserved subtree orphans \emph{every} binding in that subtree---third parties' tokens, not the operator's own. - \item \emph{Undetectability.} Every structure-only check passes: the BFT Core would certify the round, and even the full-history audit of Section~\ref{sec:aggregation-audit}, which verifies exactly these consistency proofs, would accept. +\begin{definition}[Valid trees] +\label{def:tree} +Trees are generated by +\[ T ::= \mathsf{Leaf}(k, v) \mid \mathsf{Node}(d, p, T_l, T_r) \] +with $k \in \mathcal{K}$, $v \in \mathcal{V}$, $0 \le d < \kappa$, $p \in \{0,1\}^{d}$; $\varepsilon$ denotes the empty tree. Digests: +\begin{align*} +\mathsf{dig}(\mathsf{Leaf}(k,v)) &= H(\texttt{0x00} \| k \| v),\\ +\mathsf{dig}(\mathsf{Node}(d,p,l,r)) &= H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| \mathsf{dig}(l) \| \mathsf{dig}(r)), +\end{align*} +and $\mathsf{dig}(\varepsilon) = \varnothing$. Region and depth: $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$ and $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$ and $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. A tree is \emph{valid} if every junction $\mathsf{Node}(d,p,l,r)$ in it satisfies: $l$ and $r$ are nonempty, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. The trees $\varepsilon$ and $\mathsf{Leaf}(k,v)$ are valid. +\end{definition} + +The validity conditions are local: one condition per edge. The first proposition shows that they force the global canonical shape. + +\begin{proposition}[Canonical form] +\label{prop:canon} +Let $T$ be a valid tree. Then: +\begin{enumerate}[nosep,label=(\roman*)] + \item every leaf key extends the region of each of its ancestors, and distinct leaves carry distinct keys; hence $T$ represents the partial map $\mathsf{map}(T) = \{k \mapsto v \mid \mathsf{Leaf}(k,v) \in T\}$; + \item at every junction, the region $p$ is the longest common prefix of the keys below it; + \item every finite map $M$ has exactly one valid tree, written $\mathsf{Tree}(M)$; + \item the left-to-right leaf order of $T$ is the strictly increasing key order; + \item $\mathsf{Tree}(M)$ contains a junction with region $p$ iff $M$ contains keys extending $p\|0$ and keys extending $p\|1$. \end{enumerate} -We have confirmed the attack against a reference implementation of the structure-only verifier. Placement, in short, is not a self-regarding property: a misplaced junction damages third parties, undetectably. +Consequently, the junctions of $\mathsf{Tree}(M)$, with their depths and regions, persist in $\mathsf{Tree}(M \uplus B)$; and if no key of $B$ extends the region of a node of $\mathsf{Tree}(M)$, the whole subtree at that node recurs verbatim in $\mathsf{Tree}(M \uplus B)$. For a valid $T$ and a batch $B$ whose keys are pairwise distinct and absent from $\mathsf{map}(T)$, we write $T \oplus B = \mathsf{Tree}(\mathsf{map}(T) \uplus B)$. +\end{proposition} +\begin{proof} +(i) Validity gives $p\|\beta \sqsubseteq \mathsf{reg}(\text{child})$ at every edge, so by induction every node's region, and every leaf key, extends the region of each ancestor. Two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d,p,\cdot,\cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$, which is impossible. -\begin{figure}[!htbp] - \centering -\begin{tikzpicture}[font=\small, - lf/.style={rectangle, draw, align=center, minimum height=1.8em, inner sep=4pt}, - jn/.style={circle, draw, inner sep=2pt}] - % pre-state - \node[lf] (pre) {$\mathsf{Leaf}(k,v)$}; - \node[above=0.35cm of pre, font=\scriptsize] {$r_{i-1}$}; - % post-state - \node[jn, right=2.6cm of pre, yshift=0.55cm] (top) {$d^{*}$}; - \node[above=0.15cm of top, font=\scriptsize] {$r_i$}; - \node[lf, below left=0.7cm and 0.35cm of top] (old) {$\mathsf{Leaf}(k,v)$}; - \node[lf, below right=0.7cm and 0.35cm of top] (new) {$\mathsf{Leaf}(k,v')$}; - \draw (top) -- node[left, font=\scriptsize] {$0$} (old); - \draw (top) -- node[right, font=\scriptsize] {$1$} (new); - \node[below=0.15cm of old, font=\scriptsize] {orphaned}; - \node[below=0.15cm of new, font=\scriptsize] {provable}; - \draw[arrow, dashed] ([xshift=0.35cm]pre.east) -- node[above, font=\scriptsize] {$\pi$ verifies} ([xshift=-0.12cm]old.west|-pre.east); -\end{tikzpicture} - \caption{Shadow insertion: with $k[d^{*}] = 1$, the verifier's key-directed descent under $r_i$ reaches $(k,v')$; the preserved $(k,v)$ is unreachable. The structure-only consistency proof $(S(r_{i-1}), L, N(d^{*}))$ verifies.}\label{fig:shadow} -\end{figure} +(ii) Every key below $\mathsf{Node}(d,p,l,r)$ extends $p$. Both children are nonempty, so some key below extends $p\|0$ and some extends $p\|1$. The common prefix therefore ends after exactly the $d$ bits of $p$. -\paragraph{Repair.} -The root cause is that the depth commitment binds nodes to \emph{levels}, not to \emph{key-space positions}, while $S$ subtrees are opaque digests---so no verifier-side constraint can relate the batch's keys to the regions of key space already occupied. Two repairs present themselves. The \emph{witness route} keeps the hashes and requires, per inserted key, an opened descent into the pre-state establishing freshness of the key and the correct split point; this costs an opened path ($O(\log n)$ hash openings) per insertion. The \emph{commitment route} moves the region into the junction hash, after which coherence becomes a local check over the touched nodes, with a single one-level opening per split edge; it is cheaper in-circuit, yields simpler invariants, and preserves the insert-immutability of pre-existing hashes, because a node's region---unlike its edge structure---is invariant under insertions above it. Algorithm~\ref{alg:stackverify} is the commitment route. Revisiting the attack against it: the new junction $N(d^{*})$ must present its preserved child opened, and edge coherence demands that the opened child's region extend $p\|0$ while the new leaf's key extends $p\|1$; since the preserved subtree containing $(k,v)$ has a region that is a prefix of $k$, both conditions cannot hold with the leaf key $k$ on the other side. The attack---and, as Theorem~\ref{thm:round} shows, every attack of its kind---is excluded. A further consequence (Lemma~\ref{lem:map} and Theorem~\ref{thm:history}) is that the globally unique Patricia shape comes for free: what naively looks like the heavyweight obligation of proving global construction reduces to one opening per insertion and a family of local bit-comparisons. +(iii) Induction on the key set. The empty set gives $\varepsilon$; a singleton forces its leaf. Otherwise, by (ii) the root region is forced to be the longest common prefix $p$ of all keys; the bit at position $|p|$ splits the keys into two nonempty sets; the induction hypothesis gives the unique valid trees for the two sets; joining them at $(|p|, p)$ is valid, and any valid root must use exactly this region, this partition, and these children. Values label the determined leaves and do not affect the shape. -\subsection{Formal Model} -\label{sec:consistency-formal} +(iv) At every junction, keys on the left have bit $0$ and keys on the right have bit $1$ at position $d$, and both sides agree on the first $d$ bits. So every left key precedes every right key, and the claim follows by induction. + +(v) ($\Leftarrow$) Descend from the root of $\mathsf{Tree}(M)$. Let the current junction have region $q$. The keys extending $p\|0$ and $p\|1$ lie below it, so by (ii) $q \sqsubseteq p$. If $q = p$, done. Otherwise all keys extending $p$ agree on the bit at position $|q|$, so they lie below one child; recurse into it. Depths increase, so the descent terminates, and it can terminate only at $q = p$. ($\Rightarrow$) At a junction with region $p$, validity and (i) give keys below it extending $p\|0$ and $p\|1$. -We fix the key length $\kappa = 256$, key space $\mathcal{K} = \{0,1\}^{\kappa}$, a value space $\mathcal{V} \subseteq \{0,1\}^{*}$, and a hash function $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$. For bit strings, $p \sqsubseteq q$ denotes that $p$ is a prefix of $q$, $q[j]$ the $j$-th bit, and $q[0..d)$ the first $d$ bits. All statements below are unconditional reductions: they conclude either the stated property, or that two distinct strings with equal $H$-images (\emph{a collision}) are computable in time linear in the size of the objects at hand. $\varnothing$ is a distinguished constant outside $\{0,1\}^{\lambda}$. +For the consequences: the characterization (v) is monotone in $M$, so junctions persist with their regions (and depths $d = |p|$). The subtree at a node with region $\varrho$ is the unique valid tree over the keys of $M$ extending $\varrho$: those keys and no others lie below it, because the descent from the root directed by any such key passes through the same ancestors. If $B$ adds no key extending $\varrho$, this key set is unchanged, and by (iii) so is the subtree. +\end{proof} -\begin{definition}[Hash trees] -\label{def:hashtree} -Trees are generated by $T ::= \mathsf{Leaf}(k, v) \mid \mathsf{Node}(d, p, T_l, T_r)$ with $k \in \mathcal{K}$, $v \in \mathcal{V}$, $0 \le d < \kappa$, $p \in \{0,1\}^{d}$; $\varepsilon$ denotes the empty tree. Digest, region, and depth: +\begin{definition}[Opening trees] +\label{def:opening} +Opening trees are generated by +\[ F ::= \mathsf{Hole}(c) \mid \mathsf{OLeaf}(k, v) \mid \mathsf{ONode}(d, p, F_l, F_r) \] +with $c \in \{0,1\}^{\lambda}$ and the other operands as in Definition~\ref{def:tree}. Evaluation mirrors $\mathsf{dig}$: writing $e_x = \mathsf{eval}(F_x)$, \begin{align*} -\mathsf{dig}(\mathsf{Leaf}(k,v)) &= H(\texttt{0x00} \| k \| v),\\ -\mathsf{dig}(\mathsf{Node}(d,p,l,r)) &= H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| \mathsf{dig}(l) \| \mathsf{dig}(r)), +\mathsf{eval}(\mathsf{Hole}(c)) &= c,\\ +\mathsf{eval}(\mathsf{OLeaf}(k,v)) &= H(\texttt{0x00} \| k \| v),\\ +\mathsf{eval}(\mathsf{ONode}(d,p,F_l,F_r)) &= H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| e_l \| e_r). \end{align*} -$\mathsf{dig}(\varepsilon) = \varnothing$; $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$, $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$, $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. \end{definition} -\begin{definition}[Well-formed trees] -\label{def:wf} -$\varepsilon$ and leaves are well-formed; $\mathsf{Node}(d,p,l,r)$ is well-formed iff $l$ and $r$ are nonempty and well-formed, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. -\end{definition} +An opening tree is a partially opened commitment: $\mathsf{OLeaf}$ and $\mathsf{ONode}$ present hash preimages, while a $\mathsf{Hole}$ stands for an unopened subtree. The following lemma is the workhorse of every argument below: an opening tree that evaluates to the digest of a known tree is an exact partial copy of that tree. -\begin{lemma}[Represented map and unique shape] -\label{lem:map} -In a well-formed tree $T$, every leaf key extends the region of each of its ancestors, and distinct leaves carry distinct keys; hence $T$ represents a partial map $\mathsf{map}(T) = \{k \mapsto v \mid \mathsf{Leaf}(k,v) \in T\}$. At every junction $\mathsf{Node}(d,p,l,r)$, the region $p$ is the longest common prefix of the keys below it. Consequently, every finite key-value map has exactly one well-formed tree. +\begin{lemma}[Matching] +\label{lem:match} +Let $T \neq \varepsilon$ be a tree and $F$ an opening tree with $\mathsf{eval}(F) = \mathsf{dig}(T)$. Then: +\begin{enumerate}[nosep,label=(\alph*)] + \item every $\mathsf{ONode}(d,p,\cdot,\cdot)$ of $F$ coincides with a junction $\mathsf{Node}(d,p,\cdot,\cdot)$ of $T$ at the same position, with equal child digests; + \item every $\mathsf{OLeaf}(k,v)$ of $F$ coincides with $\mathsf{Leaf}(k,v)$ of $T$ at the same position; + \item every $\mathsf{Hole}(c)$ is \emph{assigned} the subtree of $T$ at its position, and that subtree has digest $c$; + \item replacing every hole by its assigned subtree turns $F$ into $T$. +\end{enumerate} \end{lemma} \begin{proof} -The ancestor claim is immediate by induction over the well-formedness conditions. For distinctness, two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d,p,\cdot,\cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$, which is impossible. - -Now consider a junction $\mathsf{Node}(d,p,l,r)$. Every key below it extends $p$. Since both children are nonempty, some key below $l$ extends $p\|0$ and some key below $r$ extends $p\|1$. Thus the common prefix ends exactly after the $d$ bits of $p$, so $p$ is the longest common prefix. +Induction on $F$, with the invariant $\mathsf{eval}(F) = \mathsf{dig}(T)$ for the current pair. A hole is assigned the current subtree of $T$. Otherwise, compare the two $H$-preimages. If they differ, they are a collision. If they are equal, the domain-separation tag and the injective encodings force the same constructor with equal components: an $\mathsf{OLeaf}$ meets $\mathsf{Leaf}(k,v)$ with the same $k$ and $v$; an $\mathsf{ONode}$ meets a junction with the same $(d,p)$ and equal child digests, and the induction continues in both children. Clause (d) restates that the recursion covers $F$ and $T$ simultaneously and completely. Each step is one comparison, so the reduction is linear. +\end{proof} -Existence and uniqueness follow by induction on the finite key set. The empty set gives $\varepsilon$, and a singleton forces its leaf. Otherwise the root region is forced to be the longest common prefix of all keys; its next bit partitions them into two nonempty child sets. Applying the induction hypothesis to those sets constructs the two unique children. Their regions extend $p\|0$ and $p\|1$, respectively, and their depths exceed $|p|$, so joining them at $(|p|,p)$ is well-formed. Conversely, every well-formed root must use this same region, partition, and pair of inductively unique children. Values label the already determined leaves and do not affect the shape. +\begin{corollary}[Digest binding] +\label{cor:binding} +Trees $T \neq T'$ with $\mathsf{dig}(T) = \mathsf{dig}(T') \neq \varnothing$ yield a collision. +\end{corollary} +\begin{proof} +Open $T'$ fully into an opening tree without holes and apply Lemma~\ref{lem:match}: if no collision is found, clause (d) gives $T' = T$. \end{proof} -\begin{definition}[Inclusion verification] +\begin{definition}[Inclusion proofs; non-inclusion witnesses] \label{def:incl} -An inclusion proof for $(k, v)$ against a root $r$ is a sequence $\gamma = \big((d_1, s_1), \ldots, (d_m, s_m)\big)$ with $\kappa > d_1 > \cdots > d_m \ge 0$. The verifier computes $c_0 = H(\texttt{0x00} \| k \| v)$ and, for $j = 1, \ldots, m$, +An \emph{inclusion proof} for $(k, v)$ against a root $r$ is a sequence $\gamma = \big((d_1, s_1), \ldots, (d_m, s_m)\big)$ with $\kappa > d_1 > \cdots > d_m \ge 0$ and $s_j \in \{0,1\}^{\lambda}$. The verifier computes $c_0 = H(\texttt{0x00} \| k \| v)$ and, for $j = 1, \ldots, m$, \[ c_j = \begin{cases} H(\texttt{0x01} \| \langle d_j\rangle \| \langle k[0..d_j)\rangle \| c_{j-1} \| s_j) & \text{if } k[d_j] = 0,\\ H(\texttt{0x01} \| \langle d_j\rangle \| \langle k[0..d_j)\rangle \| s_j \| c_{j-1}) & \text{if } k[d_j] = 1, \end{cases} \] -and accepts iff $c_m = r$. (Regions are not transmitted; the verifier derives them from $k$.) A \emph{non-inclusion witness} for $k$ against $r$ is a chain of openings from the root along $k$'s descent: junction openings $(d_j, p_j, c^0_j, c^1_j)$ whose $H$-images chain from $r$ downward through the $k[d_j]$-side child, with $p_j = k[0..d_j)$ for all but the last element, terminating either in a junction opening whose region is \emph{not} a prefix of $k$, or in an opened leaf with key $\neq k$; also, $r = \varnothing$ is a witness for every $k$. -\end{definition} - -\begin{definition}[Honest transition generator] -\label{def:generator} -Let $T$ be a well-formed tree and let $B$ be a finite batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. The honest generator first inserts the pairs of $B$ in increasing key order by the usual Patricia rule: follow matching regions, and when a key diverges from the current subtree, create a junction at their first divergent bit. Denote the resulting tree by $T_B$. +and accepts iff $c_m = r$. Junction regions are not transmitted; the verifier derives them from $k$. -The generator obtains the opcode stream $\pi_B$ by a simultaneous post-order traversal of $T$ and $T_B$. A new leaf emits $L$. A maximal unchanged pre-state subtree below a pre-existing junction emits $S$; if that subtree is instead attached directly below a junction newly created by the insertion, it emits $O$ when its root is a junction and $O_L$ when its root is a leaf. Every remaining junction of $T_B$ emits the streams of its left and right children followed by $N(d)$, where $d$ is its bifurcation depth. For $B = [\,]$, the generator returns $(T, [\,])$. We write -\[ - \mathsf{Gen}(T,B) = (T_B, \pi_B). -\] -This is the tree-difference traversal implemented by the reference generator: an opaque subtree is opened exactly when its old root first meets a new edge, after which the derived advice propagates through any further new junctions. +A \emph{non-inclusion witness} for $k$ against $r$ is a chain of openings from the root along the descent directed by $k$: junction openings $(d_j, p_j, c^0_j, c^1_j)$ whose $H$-images chain from $r$ downward through the $k[d_j]$-side child, with $p_j = k[0..d_j)$ for all but the last element. The chain terminates either in a junction opening whose region is \emph{not} a prefix of $k$, or in an opened leaf with key $\neq k$. Additionally, $r = \varnothing$ is a witness for every $k$. \end{definition} -\begin{definition}[Append-only consistency] +Both objects are opening trees: an inclusion proof is a chain of $\mathsf{ONode}$s with regions derived from $k$, sibling holes $\mathsf{Hole}(s_j)$, and the terminal $\mathsf{OLeaf}(k, v)$; a non-inclusion witness is a chain of $\mathsf{ONode}$s with holes at the off-path children. Lemma~\ref{lem:match} therefore applies to both. + +\begin{definition}[Certified history; append-only consistency] \label{def:aoc} -A \emph{certified history} is a sequence $(B_1, \pi_1, r_1), \ldots, (B_n, \pi_n, r_n)$ with $r_0 = \varnothing$ and Algorithm~\ref{alg:stackverify} accepting $(\pi_i, r_{i-1}, r_i, B_i)$ for every $i$. The history is \emph{append-only consistent} if there exist well-formed trees $T_0 = \varepsilon, T_1, \ldots, T_n$ with $\mathsf{dig}(T_i) = r_i$ and +A \emph{certified history} is a sequence $(B_1, \pi_1, r_1), \ldots, (B_n, \pi_n, r_n)$ with $r_0 = \varnothing$ and Algorithm~\ref{alg:stackverify} accepting $(\pi_i, r_{i-1}, r_i, B_i)$ for every $i$. The history is \emph{append-only consistent} if there exist valid trees $T_0 = \varepsilon, T_1, \ldots, T_n$ with $\mathsf{dig}(T_i) = r_i$ and \[ \mathsf{map}(T_i) \;=\; \mathsf{map}(T_{i-1}) \uplus B_i \qquad \text{for } i = 1, \ldots, n, \] @@ -674,227 +568,184 @@ \subsection{Formal Model} \subsection{Security} \label{sec:consistency-theorem} -\begin{lemma}[Digest binding] -\label{lem:binding} -From trees $T \neq T'$ with $\mathsf{dig}(T) = \mathsf{dig}(T') \neq \varnothing$, a collision is computable. +The verifier's checks are node-local. We make this explicit by giving the proof stream a typed syntax tree with recursively defined attributes; the checks become a local predicate on that tree. All reasoning below is structural induction. The algorithm itself appears only in Lemma~\ref{lem:parse}. + +\begin{definition}[Proof terms] +\label{def:pterm} +Proof terms are generated by +\begin{align*} +P ::={} & S(c) \mid O(d, p, c_l, c_r) \mid O_L(k, v) \mid{}\\ + & L(k, v) \mid N(d, P_l, P_r) +\end{align*} +with operands in their domains: $c, c_l, c_r \in \{0,1\}^{\lambda}$, $k \in \mathcal{K}$, $v \in \mathcal{V}$, $0 \le d < \kappa$, $p \in \{0,1\}^{d}$. In $N(d, P_l, P_r)$, the subterm $P_l$ has side $\beta = 0$ and $P_r$ has side $\beta = 1$. + +The \emph{advice} attribute is +\begin{align*} +\mathsf{adv}(S(c)) &= \bot, & \mathsf{adv}(O(d,p,\cdot,\cdot)) &= (d, p),\\ +\mathsf{adv}(O_L(k,v)) &= (\kappa, k), & \mathsf{adv}(L(k,v)) &= (\kappa, k), +\end{align*} +and $\mathsf{adv}(N(d, P_l, P_r)) = (d, p)$ with the \emph{derived region} $p = \varrho_x[0..d)$, computed from any child with $\mathsf{adv}(P_x) = (\delta_x, \varrho_x) \neq \bot$. (The predicate $\mathsf{ok}$ below makes this well-defined.) + +The \emph{old digest} attribute is +\begin{align*} +\mathsf{old}(S(c)) &= c,\\ +\mathsf{old}(O(d,p,c_l,c_r)) &= H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\|c_l\|c_r),\\ +\mathsf{old}(O_L(k,v)) &= H(\texttt{0x00}\|k\|v),\\ +\mathsf{old}(L(k,v)) &= \varnothing, +\end{align*} +and, for a junction $N = N(d, P_l, P_r)$ with derived region $p$, writing $o_x = \mathsf{old}(P_x)$, the \emph{four-way rule} +\[ +\mathsf{old}(N) = \begin{cases} +\varnothing & o_l = o_r = \varnothing,\\ +o_r & o_l = \varnothing \neq o_r,\\ +o_l & o_r = \varnothing \neq o_l,\\ +H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\|o_l\|o_r) & \text{otherwise}. +\end{cases} +\] +The \emph{new digest} attribute equals $\mathsf{old}$ on $S$, $O$, and $O_L$; further, writing $n_x = \mathsf{new}(P_x)$, +\begin{align*} +\mathsf{new}(L(k,v)) &= H(\texttt{0x00}\|k\|v),\\ +\mathsf{new}(N(d,P_l,P_r)) &= H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\|n_l\|n_r). +\end{align*} + +The predicate $\mathsf{ok}(P)$ holds if every junction $N(d, P_l, P_r)$ in $P$ satisfies: +\begin{enumerate}[nosep,label=(\alph*)] + \item \emph{coherence}: every advised child, $\mathsf{adv}(P_x) = (\delta_x, \varrho_x)$, has $\delta_x > d$ and $\varrho_x[d] = \beta_x$; + \item \emph{agreement}: at least one child is advised, and all advised children yield the same $\varrho_x[0..d)$; + \item \emph{confinement}: if $\mathsf{old}(P_l) = \varnothing$ or $\mathsf{old}(P_r) = \varnothing$, then both children are advised. +\end{enumerate} +$P$ \emph{accepts} $(r_{\mathsf o}, r_{\mathsf n}, B)$ if $\mathsf{ok}(P)$, $\mathsf{old}(P) = r_{\mathsf o}$, $\mathsf{new}(P) = r_{\mathsf n}$, and the labels of the $L$ leaves of $P$, read left to right, are exactly the elements of $B$ sorted, with strictly increasing keys. +\end{definition} + +\begin{lemma}[Stream--term correspondence] +\label{lem:parse} +Let $B \neq [\,]$. Algorithm~\ref{alg:stackverify} accepts $(\pi, r_{i-1}, r_i, B)$ iff $\pi$ is the post-order serialization of a proof term that accepts $(r_{i-1}, r_i, B)$. The term is unique and the translation is linear-time. \end{lemma} \begin{proof} -The two digest preimages are equal strings or a collision is found. If equal, the domain-separation tag and the injective fixed-length encodings force the same constructor with equal components: for leaves, $T = T'$, a contradiction; for junctions, equal $(d, p)$ and equal child digests, and since $T \neq T'$ some child pair differs while sharing a digest---recurse into it. The recursion terminates in a collision. +Each of $S$, $O$, $O_L$, $L$ pushes one stack entry; $N$ pops two and pushes one. A run without underflow that ends with one entry parses the stream uniquely as the post-order serialization of a term; conversely, the serialization of any term replays without underflow and ends with one entry. By induction over the run, the triple pushed for a subterm is exactly $(\mathsf{old}, \mathsf{new}, \mathsf{adv})$ of that subterm, and the checks executed per opcode are exactly the operand-domain conditions of Definition~\ref{def:pterm} plus, at $N$, clauses (a)--(c) of $\mathsf{ok}$. The final comparisons equate the root digest pair with $(r_{i-1}, r_i)$; the batch consumption at $L$ and the final $b = |B|$ check equate the left-to-right $L$ labels with the sorted batch. \end{proof} -\begin{lemma}[Run decomposition] -\label{lem:run} -An accepting run of Algorithm~\ref{alg:stackverify} on $(\pi, r_{i-1}, r_i, B)$ determines, in linear time: an ordered binary \emph{proof tree} $P$ with internal nodes the $N(d)$ opcodes and terminals the $S$, $O$, $O_L$, $L$ opcodes, the $L$ terminals consuming the strictly sorted batch left to right; pre- and post-digests for every node of $P$ per the verifier's algebra, with the root pair equal to $(r_{i-1}, r_i)$; a unique \emph{region label} $p$ for every junction, derived from the advice of its children---all advised children yield the same $p$, and at least one child is advised; and a validated advice tuple at every junction--child edge where the child carries advice: the child's depth exceeds the junction's and the child's region extends $p\|\beta$, the advice being $(\kappa, k)$ for $L$ and $O_L$ terminals, the opened $(d', p')$ for $O$ terminals, and the child's own $(d, p)$ label for $N$ children. At every junction whose old side arose from a pass-through or $\varnothing$ case, both children carry advice; consequently, opaque $S$ terminals occur only as children of junctions whose old side was hashed. +\begin{lemma}[Old projection] +\label{lem:proj} +For a proof term $P$, define the \emph{old projection} $P_0$ by structural recursion: $S(c) \mapsto \mathsf{Hole}(c)$; $O(d,p,c_l,c_r) \mapsto \mathsf{ONode}(d,p,\mathsf{Hole}(c_l),\mathsf{Hole}(c_r))$; $O_L(k,v) \mapsto \mathsf{OLeaf}(k,v)$; $L(k,v) \mapsto$ nothing; $N(d,P_l,P_r)$ with derived region $p$: nothing if both children project to nothing, the surviving child's projection if exactly one does, and $\mathsf{ONode}(d,p,\cdot,\cdot)$ over the two projections otherwise. Then $P_0$ is empty iff $\mathsf{old}(P) = \varnothing$, and otherwise $P_0$ is an opening tree with $\mathsf{eval}(P_0) = \mathsf{old}(P)$. \end{lemma} \begin{proof} -By construction of the algorithm; each clause restates a check or an assignment made during the run. +Induction on $P$. A subterm projects to nothing iff its old digest is $\varnothing$: immediate for the terminals, and for $N$ the three projection cases match the four-way rule ($\varnothing$, the two pass-throughs, hashed). In the surviving cases, $\mathsf{eval}$ of the projection recomputes exactly the $\mathsf{old}$ value; the pass-through case forwards both the projection and the digest of the surviving child. \end{proof} -\begin{theorem}[Round soundness] -\label{thm:round} -Let $T$ be a well-formed tree (possibly $\varepsilon$) with $\mathsf{dig}(T) = r_{i-1}$, and let Algorithm~\ref{alg:stackverify} accept $(\pi, r_{i-1}, r_i, B)$. Then from $T$, $\pi$, $B$ one can either compute a collision, or construct a well-formed tree $T'$ with $\mathsf{dig}(T') = r_i$ and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. -\end{theorem} +\begin{lemma}[Reconstruction] +\label{lem:graft} +Let $T$ be a valid tree and let the proof term $P$ accept $(\mathsf{dig}(T), r_{\mathsf n}, B)$. Then there is a valid tree $T'$ with $\mathsf{dig}(T') = r_{\mathsf n}$ and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. +\end{lemma} \begin{proof} -Let $P$ be the proof tree of Lemma~\ref{lem:run}. Define the \emph{old projection} $P_0$ by structural recursion: $S$, $O$, $O_L$ terminals map to themselves; $L$ maps to nothing; a junction whose old side was hashed (both children's old digests $\neq \varnothing$) maps to a junction over the projections of its children; a pass-through junction maps to the projection of its surviving child; an all-$\varnothing$ junction maps to nothing. By the verifier's algebra, evaluating $P_0$---with $S$ digests and $O$/$O_L$ openings as given---yields $r_{i-1}$. +First obtain a subtree of $T$ for every digest operand of $P$. If $\mathsf{dig}(T) = \varnothing$ then $T = \varepsilon$, and by Lemma~\ref{lem:proj} $P_0$ is empty; since a non-$\varnothing$ old digest survives every case of the four-way rule, $P$ then contains no $S$, $O$, or $O_L$, and no assignment is needed. Otherwise $\mathsf{eval}(P_0) = \mathsf{dig}(T)$, and Lemma~\ref{lem:match} matches $P_0$ into $T$: every $O$ and $O_L$ of $P$ coincides with the node of $T$ at its position, and every hole---an $S$ operand or a child digest of an $O$---is assigned the subtree of $T$ at its position. + +Define $T' = \mathsf{graft}(P)$ by structural recursion: $S(c) \mapsto$ its assigned subtree; $O(d,p,\cdot,\cdot) \mapsto \mathsf{Node}(d,p,\cdot,\cdot)$ over its two assigned subtrees; $O_L(k,v) \mapsto \mathsf{Leaf}(k,v)$; $L(k,v) \mapsto \mathsf{Leaf}(k,v)$; $N(d,P_l,P_r) \mapsto \mathsf{Node}(d,p,\cdot,\cdot)$ with its derived region $p$, over the grafts of its children. -\emph{Step 1: matching.} If $r_{i-1} = \varnothing$ then $P_0$ is empty (a non-$\varnothing$ old digest propagates to the root through every case of the four-way rule) and $T = \varepsilon$; proceed to Step~2 with no grafts. Otherwise walk $P_0$ and $T$ together from their roots. At an explicit junction of $P_0$ labeled $(d, p)$ with children's old digests $(c_l, c_r)$: the current $T$-node's digest equals $H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\| c_l \| c_r)$; if the current $T$-node is a leaf or carries a different label or different child digests, its own preimage differs---a collision; otherwise the labels agree and the walk recurses into both children. At an $O_L(k', v')$ terminal, the current $T$-node must be $\mathsf{Leaf}(k', v')$ by the same argument. At an opaque hole ($S(c)$, or a digest child of an $O$ opening): assign to it the current $T$-subtree, whose digest is $c$. The outcome, barring a collision: every explicit node of $P_0$ coincides in label and position with a node of $T$; every hole is assigned the $T$-subtree at its position; and $T$ is exactly the grafting of $P_0$'s explicit structure with the assigned subtrees. +\emph{Digests.} By induction, $\mathsf{dig}(\mathsf{graft}(Q)) = \mathsf{new}(Q)$ for every subterm $Q$: $\mathsf{new}$ agrees with $\mathsf{dig}$ on the terminals and recomputes every junction. Hence $\mathsf{dig}(T') = r_{\mathsf n}$. -\emph{Step 2: construction.} Let $T'$ be the grafting of $P$: $N(d) \mapsto \mathsf{Node}(d, p, \cdot, \cdot)$, with $p$ its derived region label; $L$ and $O_L$ terminals $\mapsto$ the corresponding leaves; $O(d', p', \cdot, \cdot) \mapsto \mathsf{Node}(d', p', \cdot, \cdot)$ over its assigned child subtrees; $S(c) \mapsto$ its assigned subtree. Then $\mathsf{dig}(T') = r_i$, because the post-digest algebra agrees with $\mathsf{dig}$ on terminals and junctions. +\emph{Advice.} Wherever $\mathsf{adv}(Q) = (\delta, \varrho) \neq \bot$, the top node of $\mathsf{graft}(Q)$ has depth $\delta$ and region $\varrho$. This holds by construction for $O$, $O_L$, $L$, and $N$. -\emph{Step 3: well-formedness.} Every terminal of $P$ constructs or is assigned a nonempty subtree, so every $N$ junction of $T'$ has two nonempty children. It remains to classify its edges. Edges inside an assigned subtree satisfy the conditions because $T$ is well-formed. The two edges exposed by an $O$ terminal coincide, by Step~1, with the corresponding edges of $T$. An edge whose child is an opaque $S$ terminal has, by Lemma~\ref{lem:run}, a parent whose old side was hashed; by Step~1 that parent, its labels, and its child digests coincide with a node of $T$, so this too is an edge of $T$ at the same position. Every remaining edge has an advised child and was checked by the verifier; the validated advice equals the true $(\mathsf{dep}, \mathsf{reg})$ of the child's top node in $T'$: exact for $L$ and $O_L$ children by construction, for $O$ children by Step~1, and for $N$ children by the definition of their derived labels. Hence $T'$ is well-formed. +\emph{Validity.} Every subterm grafts to a nonempty tree, so every junction of $T'$ has two nonempty children. Classify the edges of $T'$. +(1)~Edges inside assigned subtrees are edges of $T$. +(2)~The two edges below an $O$ graft: by the matching, the $O$ coincides with a junction of $T$ and its assigned children are the children of that junction in $T$; these are edges of $T$. +(3)~An edge whose child is an $S$ graft: the parent is an $N$; the $S$ child is unadvised, so by confinement both old digests at the parent are non-$\varnothing$, and the parent appears in $P_0$ as an $\mathsf{ONode}$ with its derived region. The matching places this junction, and the $T$-subtree assigned to the $S$ hole below it, in $T$; this is an edge of $T$. +(4)~Every remaining edge has an advised child. Coherence gives $\delta > d$ and, with agreement, $p\|\beta \sqsubseteq \varrho$; by the advice claim, $(\delta, \varrho)$ is the true depth and region of the child's top node. Edges of $T$ satisfy the validity conditions because $T$ is valid; edges of kind (4) satisfy them directly. Hence $T'$ is valid. + +\emph{Map.} The leaves of $T'$ are the leaves of assigned subtrees, the $O_L$ leaves, and the $L$ leaves. By clause (d) of the matching, the first two groups are exactly the leaves of $T$. The $L$ leaves carry exactly the elements of $B$. By Proposition~\ref{prop:canon}(i), all leaf keys of the valid $T'$ are distinct; hence the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. +\end{proof} -\emph{Step 4: map.} The terminals of $P$ partition the leaves of $T'$ into leaves of assigned subtrees, $O_L$ leaves, and $L$ leaves. By Step~1 the first two groups are exactly the leaves of $T$; the third is exactly $B$, fully consumed and with pairwise distinct keys. By Lemma~\ref{lem:map} applied to the well-formed $T'$, all leaf keys of $T'$ are distinct, so the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. (Consequently, no accepting run exists for a batch that re-records a present key: it would produce a well-formed tree with a repeated leaf key, which does not exist.) The same lemma shows that $T'$ already has the unique shape determined by this map; no separate canonicity argument is needed. +\begin{theorem}[Round soundness] +\label{thm:round} +Let $T$ be a valid tree with $\mathsf{dig}(T) = r_{i-1}$, and let Algorithm~\ref{alg:stackverify} accept $(\pi, r_{i-1}, r_i, B)$. Then there is a valid tree $T'$ with $\mathsf{dig}(T') = r_i$ and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. In particular, the keys of $B$ are fresh: no accepting run exists for a batch that re-records a present key, short of a collision. +\end{theorem} +\begin{proof} +If $B = [\,]$, acceptance forces $\pi = [\,]$ and $r_i = r_{i-1}$; take $T' = T$. Otherwise Lemma~\ref{lem:parse} yields a proof term accepting $(r_{i-1}, r_i, B)$, and Lemma~\ref{lem:graft} yields $T'$. \end{proof} -\begin{theorem}[Algorithmic completeness] +\begin{theorem}[Completeness] \label{thm:complete} -Let $T$ be a well-formed tree (possibly $\varepsilon$), and let $B$ be a finite batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. If $\mathsf{Gen}(T,B) = (T_B, \pi_B)$, then $T_B$ is well-formed, -\[ - \mathsf{map}(T_B) = \mathsf{map}(T) \uplus B, -\] -and Algorithm~\ref{alg:stackverify} accepts -\[ - (\pi_B,\, \mathsf{dig}(T),\, \mathsf{dig}(T_B),\, B). -\] -The generator and verifier run in time linear in the generated stream, in addition to sorting $B$. +Let $T$ be a valid tree and $B$ a batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. Then a stream $\pi_B$ such that Algorithm~\ref{alg:stackverify} accepts $(\pi_B, \mathsf{dig}(T), \mathsf{dig}(T \oplus B), B)$ is computable from $T$ and $B$ in linear time after sorting $B$. \end{theorem} \begin{proof} -If $B=[\,]$, Definition~\ref{def:generator} returns $(T,[\,])$, and the verifier's empty-batch branch accepts. Assume henceforth that $B$ is nonempty. +If $B = [\,]$ then $T \oplus B = T$ and $\pi_B = [\,]$ is accepted. Assume $B \neq [\,]$, write $T' = T \oplus B$ and $M = \mathsf{map}(T)$; $T'$ is valid with $\mathsf{map}(T') = M \uplus B$ by Proposition~\ref{prop:canon}(iii). For a region $\varrho$ let $M_\varrho$ be the set of keys of $M$ extending $\varrho$. By Proposition~\ref{prop:canon}(v), a junction with region $p$ is in $T$ iff $M_{p\|0} \neq \emptyset \neq M_{p\|1}$, and a subtree of $T'$ containing no batch key equals the subtree of $T$ over the same keys. Call such subtrees of $T'$, taken maximal, \emph{preserved}; call a junction of $T'$ \emph{new} if it is not a junction of $T$. -\emph{Insertion.} Consider first one fresh key. While its bits extend the current junction's region, Patricia insertion follows the child selected by the bifurcation bit. At the first divergence from a subtree, it creates a junction at the longest common prefix of the new key and that subtree's region. The old subtree and the new leaf extend the two opposite sides of this prefix, and their depths are greater than the new junction's depth. Thus the new edges are well-formed, while all old nodes and edges are unchanged. The represented map gains exactly the new binding. Induction over the sorted, pairwise-distinct batch proves that $T_B$ is well-formed and that $\mathsf{map}(T_B)=\mathsf{map}(T)\uplus B$. By uniqueness in Lemma~\ref{lem:map}, the result is independent of the insertion order; in particular it is the result of the batched Patricia merge used by the generator. +Define the \emph{difference term} $P_B$ over $T'$, top down: a preserved subtree becomes $S(\mathsf{dig})$ if its parent junction is a junction of $T$, and its opened root---$O$ with the true labels and child digests, or $O_L$---if its parent is new; a leaf with key in $B$ becomes $L(k, v)$; every other node $\mathsf{Node}(d,p,\cdot,\cdot)$ becomes $N(d, \cdot, \cdot)$ over the terms of its children. $P_B$ is computed by one simultaneous traversal of $T$ and $T'$. We check that $P_B$ accepts $(\mathsf{dig}(T), \mathsf{dig}(T'), B)$; Lemma~\ref{lem:parse} then concludes. -\emph{Transcript evaluation.} We prove by structural induction over the simultaneous traversal of Definition~\ref{def:generator} that each emitted fragment evaluates to the digest pair of its pre- and post-state fragments and carries correct top-node advice whenever advice is present. The terminal cases are immediate. An $S$ terminal evaluates to the unchanged digest pair and deliberately carries no advice. An $O$ or $O_L$ terminal recomputes the unchanged digest and carries its authenticated depth and region. An $L$ terminal evaluates to $(\varnothing, H(\texttt{0x00}\|k\|v))$ and carries $(\kappa,k)$. +\emph{Advice.} By construction, every subterm except an $S$ is advised, and every advised subterm carries the true depth and region of its top node in $T'$. At every $N$, some child is not an $S$: if both children were preserved, the junction and its whole subtree would be preserved, contradicting maximality. So agreement holds, the derived region is the true region $p$, and coherence holds because $T'$ is valid. -For a junction, apply the induction hypothesis to its left and right fragments. If the junction already existed, both old child digests are present and the verifier recomputes its old digest. If the junction is new around one preserved subtree, exactly one old child digest is present and the four-way rule passes that digest through. If the whole subtree is new, both old child digests are $\varnothing$. In every case the verifier recomputes the post-state junction digest. Well-formedness of $T_B$ gives $\delta_x>d$, the required side bit, and the same prefix $p$ for every advised child. A new junction has advice on both children: a preserved child was emitted as $O$ or $O_L$, and a new child obtains advice from $L$ or from its top $N$. Hence both the coherence and confinement checks pass. At a changed pre-existing junction at least one child is non-opaque, so its region also determines $p$; an untouched junction would have been emitted as one $S$ terminal instead. The fragment therefore pushes the claimed digest pair and correct advice. +\emph{Old digests.} By induction, $\mathsf{old}$ of the subterm at a node with region $\varrho$ equals $\mathsf{dig}(\mathsf{Tree}(M_\varrho))$, with the values of $M$. For terminals: a preserved subtree is $\mathsf{Tree}(M_\varrho)$ itself; an $L$ leaf has $M_k = \emptyset$ and $\mathsf{old} = \varnothing$. For a junction at region $p$: if $M_{p\|0} = M_{p\|1} = \emptyset$ then $M_p = \emptyset$; if exactly one is empty, $\mathsf{Tree}(M_p) = \mathsf{Tree}(M_{p\|\beta})$ and the pass-through applies; if neither is empty, $T$ has this junction with the same $(d, p)$ and with the trees over $M_{p\|0}$, $M_{p\|1}$ as children, and the hashed case recomputes its digest. At the root, $\mathsf{old}(P_B) = \mathsf{dig}(T)$. -At the root, this induction yields $(\mathsf{dig}(T),\mathsf{dig}(T_B))$ and a single stack entry. Finally, left-to-right leaf order in a well-formed tree is increasing key order: at each junction every left key has bit $0$ and every right key bit $1$ at the first position on which the sides differ. The $L$ terminals are therefore encountered in exactly the verifier's sorted order of $B$, once each. The batch and opcode stream are fully consumed, so all final acceptance conditions hold. +\emph{Confinement.} If $\mathsf{old} = \varnothing$ on some side of an $N$ at region $p$, then $M_{p\|0}$ or $M_{p\|1}$ is empty, so the junction is new; its preserved child, if any, was emitted opened, and every other subterm kind is advised. -The traversal emits a constant amount of data and performs constant verifier work per opcode. The only additional cost is sorting $B$, as claimed. +\emph{New digests and batch order.} $\mathsf{new}$ agrees with $\mathsf{dig}$ on the terminals and recomputes every junction, so $\mathsf{new}(P_B) = \mathsf{dig}(T')$ by induction. The $L$ leaves, left to right, are the leaves of $T'$ with keys in $B$, in strictly increasing key order by Proposition~\ref{prop:canon}(iv). \end{proof} \begin{theorem}[History soundness] \label{thm:history} -For every certified history (Definition~\ref{def:aoc}), either a collision is computable from its transcript, or the history is append-only consistent. In the latter case each $T_i$ is the unique well-formed tree representing its map. +Every certified history (Definition~\ref{def:aoc}) is append-only consistent, and each $T_i$ is the unique valid tree representing its map---or a collision is computable from the transcript. \end{theorem} \begin{proof} -Induction on rounds: $T_0 = \varepsilon$ is well-formed with $\mathsf{dig}(T_0) = \varnothing$, and Theorem~\ref{thm:round} supplies the step. Uniqueness follows from Lemma~\ref{lem:map}. +Induction on rounds: $T_0 = \varepsilon$ is valid with $\mathsf{dig}(T_0) = \varnothing$, and Theorem~\ref{thm:round} supplies the step. Uniqueness is Proposition~\ref{prop:canon}(iii). +\end{proof} + +\begin{lemma}[Query soundness] +\label{lem:query} +Let $T$ be a valid tree with $\mathsf{dig}(T) = r$. (i) If an inclusion proof for $(k, v)$ verifies against $r$, then $(k, v) \in \mathsf{map}(T)$. (ii) If a non-inclusion witness for $k$ verifies against $r$, then $k \notin \mathrm{dom}(\mathsf{map}(T))$. +\end{lemma} +\begin{proof} +(i) No $H$-image equals $\varnothing$, so $r \neq \varnothing$ and $T \neq \varepsilon$. The proof is an opening tree evaluating to $r$; Lemma~\ref{lem:match} places its junction chain and its terminal $\mathsf{OLeaf}(k, v)$ in $T$. Hence $\mathsf{Leaf}(k, v) \in T$. + +(ii) If $r = \varnothing$ then $T = \varepsilon$ and the claim holds. Otherwise assume no collision was found and suppose $k \in \mathrm{dom}(\mathsf{map}(T))$. Lemma~\ref{lem:match} places the witness chain in $T$. By Proposition~\ref{prop:canon}(i), every ancestor of $k$'s leaf carries a region that is a prefix of $k$, and the leaf lies on the side $k[d]$ of each. The witness starts at the root and follows the $k[d_j]$-side child of junctions whose regions are prefixes of $k$; by induction, every node it visits is an ancestor of $k$'s leaf, or the leaf itself. Its terminal is therefore a junction whose region is a prefix of $k$, or the leaf with key $k$. Both terminal conditions of Definition~\ref{def:incl} fail: a contradiction. \end{proof} \begin{corollary}[Unicity] \label{cor:unicity} -From a certified history together with verifying inclusion proofs for $(k, v)$ against $r_i$ and for $(k, v')$ against $r_j$ with $v \neq v'$, a collision is computable. +In a certified history, verifying inclusion proofs for $(k, v)$ against $r_i$ and for $(k, v')$ against $r_j$ imply $v = v'$. +\end{corollary} +\begin{proof} +Take $i \le j$. By Theorem~\ref{thm:history} and Lemma~\ref{lem:query}(i), $v = \mathsf{map}(T_i)(k)$ and $v' = \mathsf{map}(T_j)(k)$. Maps grow monotonically, so $\mathsf{map}(T_i) \subseteq \mathsf{map}(T_j)$ and $v = v'$. +\end{proof} + +\begin{corollary}[No phantom bindings] +\label{cor:nophantom} +In a certified history, if an inclusion proof for $(k, v)$ verifies against $r_i$, then $(k, v) \in B_1 \uplus \cdots \uplus B_i$. In particular, no inclusion proof verifies for a key that was never inserted. \end{corollary} \begin{proof} -By Theorem~\ref{thm:history}, obtain the trees $T_i, T_j$ (or a collision, and we are done). A verifying inclusion proof against $\mathsf{dig}(T)$ matches into $T$ from the root exactly as in Step~1 of Theorem~\ref{thm:round}: each chain element's preimage must agree with the corresponding node of $T$ (else a collision), and the terminal comparison places $\mathsf{Leaf}(k, v)$ in $T$. Hence $v = \mathsf{map}(T_i)(k)$ and $v' = \mathsf{map}(T_j)(k)$; taking $i \le j$, monotonicity ($\mathsf{map}(T_j) \supseteq \mathsf{map}(T_i)$) gives $v' = v$, a contradiction---so a collision was computed along the way. +By Theorem~\ref{thm:history}, $\mathsf{map}(T_i) = B_1 \uplus \cdots \uplus B_i$; apply Lemma~\ref{lem:query}(i). \end{proof} \begin{corollary}[No false non-inclusion] \label{cor:noninc} -From a certified history, a verifying inclusion proof for $(k, v)$ against $r_i$, and a verifying non-inclusion witness for $k$ against $r_j$ with $j \ge i$, a collision is computable. +In a certified history, a verifying inclusion proof for $(k, v)$ against $r_i$ and a verifying non-inclusion witness for $k$ against $r_j$ with $j \ge i$ together yield a collision. \end{corollary} \begin{proof} -As above, $(k, v) \in \mathsf{map}(T_j)$, so $r_j \neq \varnothing$ and $T_j$ contains the leaf of $k$, all of whose ancestors carry regions that are prefixes of $k$. The witness's openings match into $T_j$ (else a collision) and, by construction, follow the descent directed by $k$'s bits through junctions whose regions are prefixes of $k$---which is precisely the path to $k$'s leaf. Its terminal therefore matches a node on that path: every such junction has a region that is a prefix of $k$, and the only leaf on it has key $k$, contradicting the witness's terminal condition in either case. +By Lemma~\ref{lem:query}, $k \in \mathrm{dom}(\mathsf{map}(T_i)) \subseteq \mathrm{dom}(\mathsf{map}(T_j))$ and $k \notin \mathrm{dom}(\mathsf{map}(T_j))$. Both cannot hold, so one of the reductions produced a collision. \end{proof} \begin{corollary}[Service completeness] \label{cor:service} -Let $T_i$ be the well-formed trees of Theorem~\ref{thm:history}. For every $(k, v) \in \mathsf{map}(T_i)$, the path data of $T_i$ yields a verifying inclusion proof; for every $k \notin \mathrm{dom}(\mathsf{map}(T_i))$, the key-directed descent of $T_i$ yields a verifying non-inclusion witness. Producing them requires only possession of the tree data, an availability rather than an integrity concern. +Let $T_i$ be the trees of Theorem~\ref{thm:history}. For every $(k, v) \in \mathsf{map}(T_i)$, the path data of $T_i$ yields a verifying inclusion proof; for every $k \notin \mathrm{dom}(\mathsf{map}(T_i))$, the key-directed descent of $T_i$ yields a verifying non-inclusion witness. Producing them requires only possession of the tree data: an availability concern, not an integrity concern. \end{corollary} +\begin{proof} +For $(k, v) \in \mathsf{map}(T_i)$: list the junctions on the path from the root to $k$'s leaf, with their depths and the digests of the off-path children. By Proposition~\ref{prop:canon}(i)--(ii), the region of the $j$-th such junction is $k[0..d_j)$ and the leaf lies on side $k[d_j]$, so the verifier of Definition~\ref{def:incl} recomputes exactly the digests along the path, ending in $r_i$. For $k \notin \mathrm{dom}(\mathsf{map}(T_i))$: if $T_i = \varepsilon$, the empty witness verifies. Otherwise descend from the root, following bit $k[d]$ while the junction region is a prefix of $k$. Depths strictly increase, so the descent ends: at a junction whose region is not a prefix of $k$, or at a leaf, whose key is not $k$ because $k$ is absent. The recorded openings form a verifying witness. +\end{proof} \begin{remark} -Theorems~\ref{thm:round} and~\ref{thm:complete} establish soundness and algorithmic completeness of each transition, while Theorem~\ref{thm:history} and Corollaries~\ref{cor:unicity}--\ref{cor:service} establish the history and query properties of the accumulator interface in Definition~\ref{def:append-only-accumulator}. The proofs are structural inductions with explicit collision extraction; the region commitment localizes every invariant to an edge of the touched structure. A machine-checked formalization is planned and should follow the proof structure given here. +Theorems~\ref{thm:round} and~\ref{thm:complete} establish soundness and completeness of each transition; Theorem~\ref{thm:history} and Corollaries~\ref{cor:unicity}--\ref{cor:service} establish the history and query properties of the accumulator interface in Definition~\ref{def:append-only-accumulator}. Every proof is a structural induction over an inductive datatype---trees, opening trees, or proof terms---with recursively defined attributes and explicit collision extraction. The verification algorithm appears only in Lemma~\ref{lem:parse}; a re-arithmetization of the verifier, such as the AIR of Section~\ref{sec:custom-air-circuit}, only needs to be proven equivalent to Algorithm~\ref{alg:stackverify}, and the rest of the argument carries over unchanged. \end{remark} -\section{(ZK)-SNARKs} - -By using an appropriate cryptographic SNARK system, the size of the consistency proof can be reduced to a constant. - -The statement to be proven in zero-knowledge is the correct execution of the consistency proof verification algorithm described in the previous section. The public inputs to the proof (the instance) are the pre- and post-update roots $(r_{i-1}, r_i)$. The private input (the witness) $\omega$ is the insertion batch $B_i$ and the set of sibling nodes (proof) $\pi_i$. While ZK-SNARKs can hide the witness, this zero-knowledge property is not a requirement for our use case; we are primarily interested in the proof's succinctness. - -In an experiment~\cite{snark}, the statement is implemented as a constraint system $R$ using the CIRCOM domain-specific language. The witness is generated based on $\pi_i$ and $B_i$, and is supplemented by control wires that define how individual hashing blocks in the circuit are connected to the previous layer and to the inputs. If all constraints are satisfied, the proof is valid. - -The proving system used is Groth16~\cite{cryptoeprint:2016/260}, which is known for its small proof size. The proving time depends on the depth of the SMT (logarithmic in its capacity) and the maximum size of the insertion batch. Importantly, the proving effort does not depend on the total capacity of the SMT, enabling fairly large instantiations. - -When the Consensus Layer verifies these succinct proofs, the Aggregation Layer operates trustlessly. However, certain redundancy is still required to ensure data availability of the SMT itself. - - -\subsection{Circuit-Based SNARK Definition} - -Due to the limited expressivity of an arithmetic circuit (e.g., no data-dependent loops or real branching), the entire computation flow must be fixed at circuit-creation time. It is therefore helpful to pre-process the inputs to create a fixed execution trace. - -This pre-processing generates a ``wiring'' signal, which is supplied as part of the witness. This signal dictates the data flow between the hashing units within the circuit. - -To preprocess the proof: - -\begin{enumerate} - \item The hash forest, which includes the proof's sibling nodes and the new batch leaves, is flattened. - \item The nodes are sorted first by layer (from leaves to root) and then lexicographically within each layer. - \item A wiring signal is generated to control the multiplexers (MUXes) at the input of each hashing unit in the circuit. -\end{enumerate} - -Let the maximum batch size be $k_{max}$ and the SMT depth be $d$. Since the arithmetic circuit is static, it must be designed to accommodate the maximum possible batch size, $k_{max}$. - -The circuit has two halves, both controlled by the same wiring signal. It is critical to security that the control signal and the proof are the same for both halves. The first half of the circuit computes the pre-update root by treating all leaves in the insertion batch as zero (the value of empty leaf). The second half computes the post-update root using the actual values from the batch. The number of hashing units in each half of the circuit is approximately $O(k_{max} \cdot d)$. - -Each hashing unit takes its inputs either from the outputs of the previous layer's units or from the set of sibling nodes provided in the proof. The pre-processing step encodes the positions of batch and proof elements into these control signals, which are then supplied as part of the witness. - -\begin{figure*}[!t] - \centering - \includegraphics[width=0.9\textwidth]{pic/smt-circuit.drawio} - \caption{Circuit structure.}\label{fi:smt-circuit} -\end{figure*} - -Each hashing cell in the circuit, as depicted in Figure~\ref{fi:smt-circuit-cell}, is a template consisting of two input multiplexers and one 2-to-1 compressing hash function. - -\begin{figure}[t] - \centering - \includegraphics[width=.6\columnwidth]{pic/smt-circuit-cell.drawio} - \caption{One hashing cell of the circuit.}\label{fi:smt-circuit-cell} -\end{figure} - - -The MUX inputs for the leaf layer of the first half are connected to a vector containing: -\begin{itemize} - \item The ``empty'' leaf value ($0$). - \item All new leaves in the batch, which are mapped to `empty' ($0$). - \item The ``proof'' or sibling hashes ($\pi_i$). -\end{itemize} - -The MUX inputs for the leaf layer of the second half are connected to a vector containing: -\begin{itemize} - \item The ``empty'' leaf value ($0$). - \item The batch of new leaves ($I$). - \item The identical ``proof'' or sibling hashes ($\pi_i$). -\end{itemize} - -The MUXes for internal layers are connected to a vector containing: -\begin{itemize} - \item The ``empty'' leaf value ($0$). - \item Output hashes from the previous layer's cells. - \item The ``proof'' or sibling hashes ($\pi_i$). -\end{itemize} - -Both halves' MUXes are controlled by the same wiring signal. - -\subsubsection{Performance Indication} - -Initial benchmarks on a consumer laptop (Apple M1) using the Poseidon hash function indicate a proving throughput of up to $25$ transactions per second; achievable with large batch sizes. Both the fixed circuit size, the parameters of key setup ceremony, and available prover memory present hard limits to the batch size. - - -\subsection{Execution Trace-Based STARK} - -An alternative to a low-level arithmetic circuit is to use a general-purpose zero-knowledge virtual machine (zkVM). In this approach, the verification logic is written as a traditional imperative program (e.g., in Rust). The zkVM then generates a proof of correct execution for that program. - -We have implemented the consistency proof verification algorithm as a Rust program~\cite{stark} to be proved by the SP1 zkVM~\cite{sp1}. As a commitment to the ``right'' program we use a prover key, generated during program setup. Its contents are: a commitment to the preprocessed traces, the starting Program Counter register, the starting global digest of the program, after incorporating the initial memory; the chip information, the chip ordering; and prover configuration. - -For verification, we obtain the prover key hash and authenticate it off-band. - -%\begin{sloppypar} -After verifying the proof (\lstinline|client.verify(&proof, &vk)|), we can be sure that \lstinline|proof: SP1ProofWithPublicValues| is valid. The proof data structure embeds its validated ``instance'', or public parameters. Based on these parameters we check that indeed, the right thing was executed. In our case the instance is defined by the old root hash and the new root hash, which must be authenticated independently (i.e., using the certificate from Consensus Layer). -%\end{sloppypar} - -The privacy of the witness (the zero-knowledge property) is not a requirement for this application. The primary goal is to achieve computational integrity and succinctness. Therefore, while the underlying technology is often referred to as ``ZK'', we are using it as a Scalable Transparent ARgument of Knowledge (STARK). - -\subsubsection{zkVM Performance} - -On a 10-core Apple M1 CPU, proving a 500-transaction batch using SHA-256 within the SP1 zkVM takes approximately 5 minutes. However, the SP1 framework is robust and designed for scalability, supporting distributed prover networks, industrial-grade GPUs, proof chunking and recursion, and other advanced features to tackle larger problems with brute force. - - -\subsection{Optimization Ideas} - -The ZK proving performance is dominated by the cryptographic hashing primitive used by the program. - -At the time of writing, the SP1 zkVM\footnote{\url{https://docs.succinct.xyz/docs/sp1/introduction}} offers precompiles for standard hash functions like SHA-256, which accelerates their execution compared to a direct RISC-V implementation. The use of these precompiles (also known as coprocessors or chips) can be observed in the prover's output, which details the number of calls to each specialized circuit (e.g., \lstinline|SHA_EXTEND|, \lstinline|SHA_COMPRESS|). However, even with acceleration, proving SHA-256 is computationally expensive. - -A possible optimization is to use ``ZK-friendly'' hash functions. These functions are highly efficient when implemented directly in arithmetic circuits, where there is direct access to the native field elements. Their performance advantage in a RISC-V zkVM is more nuanced, as there is an overhead in translating between the VM's 32-bit integer registers and the underlying finite field elements as used by the prover. Operations like range-checking, which are necessary to prevent overflows, are expensive in ZK. - - -\subsubsection{More on ZK and Hash Functions} - -Standardized cryptographic hash algorithms like SHA-2 were optimized mostly for minimal physical chip area, a design choice driven by NIST. Others, like the Blake family, were designed for fast execution on CPUs. They all include numerous bitwise operations (e.g., rotations, XOR) that are silicon logic-native but are notoriously inefficient to prove in ZK. Proving such operations is expensive, because a full field element (e.g., a 254-bit value on the BN254 curve) must be used to represent a single bit.\footnote{See e.g. \url{https://github.com/iden3/circomlib/blob/master/circuits/sha256/sha256.circom}} ZK provers are most efficient with arithmetic operations native to the underlying finite field, such as addition and multiplication (and lookups on some ZK stacks). Other operations must be implemented indirectly. - -There are some newer cryptographic hash functions specifically designed for ZK efficiency in mind. Functions like Poseidon and Poseidon2 are gaining acceptance but are still relatively new. Some are better on large fields (e.g., Reinforced Concrete), some on smaller (e.g., Monolith) and depending on the proof system's lookup table support. Even newer and exhibiting even higher performance examples are Griffin, Anemoi. Some, like GMiMC, are offering a compromise with better silicon CPU performance. - -A key advantage of these hashes is that they operate directly on field elements, avoiding the costly translation from integer representations. The security level is defined by the underlying field and instantiation parameters. While some VMs, like the Cairo VM used by Starknet, provide direct access to field elements, they are often highly specialized for particular use cases, such as L2 rollups. - - -\subsubsection{Performance Roadmap} - -The overall approach of the zkVM path is sound: the proving time depends on the size of the addition batch, and notably, it does not have linear relationship to the total capacity of the data structure. The verification algorithm is tight. The performance bottleneck is, as discussed, the cost of arithmetizing a general-purpose execution trace that includes integer-to-field translations for every bitwise operation in the hash function. - -To overcome this bottleneck, a ZK-friendly hash function and direct access to native field elements are essential---a combination not typically available in general-purpose zkVMs. The remaining ingredients are an efficient execution-trace generator (a criterion that excludes older frameworks like Cairo~0), a fast prover over a small prime field (e.g., BabyBear, Mersenne-31), and a transparent FRI-based polynomial commitment scheme, possibly with Circle-STARK~\cite{cryptoeprint:2024/278} optimizations. Two implementations meeting these criteria are Plonky3~\cite{plonky3} and STwo\footnote{\url{https://github.com/starkware-libs/stwo}}. Considering the need for maturity, modularity, the support for batch-STARK composition, and an open-source license, Plonky3 emerged as the strongest option. - -To utilize the Plonky3 framework, the verification logic must be implemented as a custom AIR circuit (Algebraic Intermediate Representation) rather than as a general-purpose program. The remainder of this paper reports the resulting design and its measured performance. - \section{Custom AIR Circuit} \label{sec:custom-air-circuit} -We implemented the consistency-proof verification logic as a Plonky3 AIR over the BabyBear~\cite{babybear} 31-bit prime field, using Poseidon2~\cite{cryptoeprint:2023/323} (width 16, $\alpha=7$) as the in-circuit hash function. The reference implementation is open-source~\cite{rsmtair} and is the source of all measured numbers reported below. +By proving correct execution of the consistency-proof verifier inside a succinct proof system, the proof shipped to the Consensus Layer becomes nearly independent of the batch size: the public statement shrinks to the root pair $(r_{i-1}, r_i)$, and the batch and the opcode stream remain a private witness. ZK proving cost is dominated by the hash function: bit-oriented hashes such as SHA-256 are expensive to arithmetize, while ZK-friendly permutations such as Poseidon2 operate directly on field elements. A hand-built AIR (Algebraic Intermediate Representation) circuit over a small prime field, with a transparent FRI-based polynomial commitment scheme, exploits both effects and avoids the integer-to-field translation overhead of general-purpose zkVMs. + +We implemented the consistency-proof verification logic as a Plonky3~\cite{plonky3} AIR over the BabyBear~\cite{babybear} 31-bit prime field, using Poseidon2~\cite{cryptoeprint:2023/323} (width 16, $\alpha=7$) as the in-circuit hash function. The reference implementation is open-source~\cite{rsmtair} and is the source of all measured numbers reported below. \subsection{Underlying Tree Variant} -The implementation proves consistency for a path-compressed Patricia trie over 256-bit keys, which we call RSMT6 (radix sparse Merkle tree, sixth iteration). RSMT6 has three node kinds: leaves (which hash key and value together via an additive Poseidon2 sponge), internal junctions (each is the unique point where two non-empty subtrees diverge; the junction hash includes the bifurcation depth so that subtrees cannot be silently re-attached at a different level), and empty subtrees (denoted by a canonical zero digest). Path compression eliminates single-child chains, drastically reducing the number of hash evaluations relative to a depth-256 indexed SMT, while preserving the standard SMT property that the key uniquely determines the leaf position. As established in Sections~\ref{sec:scope} and~\ref{sec:critical-review}, the in-circuit statement must enforce append-only consistency (Definition~\ref{def:aoc}); the circuit described in this section implements its structural core (prior-state preservation), with the edge-coherence constraint family of Section~\ref{sec:stack-verifier} as a specified extension. +The implementation proves consistency for the RSMT of Section~\ref{sec:stack-verifier}: a path-compressed Patricia trie over 256-bit keys, with three node kinds: leaves (which hash key and value together via an additive Poseidon2 sponge), internal junctions (each is the unique point where two non-empty subtrees diverge; the junction hash includes the bifurcation depth so that subtrees cannot be silently re-attached at a different level), and empty subtrees (denoted by a canonical zero digest). Path compression eliminates single-child chains, drastically reducing the number of hash evaluations relative to a depth-256 indexed SMT, while preserving the standard SMT property that the key uniquely determines the leaf position. As established in Section~\ref{sec:scope} and Remark~\ref{rem:placement}, the in-circuit statement must enforce append-only consistency (Definition~\ref{def:aoc}); the circuit described in this section implements its structural core (prior-state preservation), with the edge-coherence constraint family of Section~\ref{sec:stack-verifier} as a specified extension. \subsection{From Stack Verifier to AIR Arithmetization} @@ -998,15 +849,9 @@ \subsection{Measured Performance} Determinism is preserved across serial and parallel builds: \texttt{prove\_batch} output is byte-identical between the two, for the same challenger seed. -\subsection{Comparison with Alternative ZK Stacks} - -The measured Poseidon2/Plonky3 AIR throughput is roughly $250\times$ faster than the SP1 zkVM implementation of the same verification logic, and $1000\times$ faster than the CIRCOM/Groth16 design (Table~\ref{tab:zk-comparison}). The proof is larger than Groth16's 250-byte constant ($\sim$1.7\,MB vs.\ 250\,B), but well below the Consensus Layer's bandwidth budget of $\sim$10\,MB per shard per round; and the verification time, measured at $\sim$45\,ms (Poseidon2 FRI) or $\sim$12\,ms (Blake3 FRI), is acceptable in the BFT block-validation critical path. - -The much-larger constant in Groth16's proof size is essentially the only metric on which the Plonky3 AIR is worse than the circuit-based approach. In return we get a transparent setup (no per-circuit trusted ceremony), post-quantum-friendly assumptions (hash-only, no curve pairings), and an order-of-magnitude better prover throughput---which is the bottleneck of practical interest. - \subsection{Deployment} -Operationally, the AIR is a drop-in replacement for the prior hash-based or SP1-based consistency-proof producer in the Unicity aggregator implementation. The proof's public statement is unchanged ($r_{i-1}, r_i$); only the proof bytes shipped from the Aggregation Layer to the Consensus Layer change. Speculative execution of the next round overlaps with the unicity-certificate wait of the current round, so the AIR's prover latency does not lengthen the user-visible round time. +Operationally, the AIR-based consistency-proof producer is a drop-in component of the Unicity aggregator implementation. The proof's public statement is unchanged ($r_{i-1}, r_i$); only the proof bytes shipped from the Aggregation Layer to the Consensus Layer change. Speculative execution of the next round overlaps with the unicity-certificate wait of the current round, so the AIR's prover latency does not lengthen the user-visible round time. The entire proving stack runs on a single CPU. Unlike L1 ZK-rollup proving pipelines, there is no GPU farm, no proving market, no proving service in the critical path of a round. A single Aggregator that sustains $10\,000$ insertions per second fits within the power budget of a laptop charger. The one place where heavier proving does occur---the recursive aggregation of the next section---runs off the critical path, at checkpoint cadence, and by an independently incentivized party. @@ -1115,7 +960,7 @@ \section{Summary} Different proof systems offer different trade-offs. The relevant properties are proving effort, necessity (and generality) of trusted setup, interactivity, recursion-friendliness, and the maturity and trustworthiness of available tooling. STARKs are comparatively fast to prove but have larger proofs, and avoid undesirable properties such as trusted setup. Groth16 SNARKs produce small proofs but require more proving effort and a circuit-specific trusted setup. For more complex applications, hybrid approaches and proof recursion can be employed. Figure~\ref{fig:comp} illustrates the proof size trade-off. -A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Section~\ref{sec:critical-review}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the globally unique tree shape into one with a tight, hand-built AIR. The result is the measured order-of-magnitude proving-throughput advantage of the Plonky3 AIR over zkVM-based approaches reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. +A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Remark~\ref{rem:placement}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the globally unique tree shape into one with a tight, hand-built AIR. The result is the measured proving throughput reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. Above the per-round proofs sits the aggregation mechanism of Section~\ref{sec:aggregation-audit}: the consistency proofs of all shards and the Consensus Layer's own state transitions are folded, by recursion on a zkVM, into a single fixed-size transparent proof of the correctness of the system's entire operating history. The two validation paths complement each other. The pragmatic path, anchored in the Unicity Trust Base, delivers finality within seconds under an accountable honest-majority-of-stake assumption; the audit path, available with a delay of minutes to hours, retrospectively removes that assumption, leaving stake with only the roles of liveness and tip uniqueness. The consistency-proof mechanism now carries a formal correctness proof (Theorem~\ref{thm:history} and its corollaries): append-only consistency of the entire certified history reduces to the collision resistance of the underlying hash function. A machine-checked formalization of this proof is the natural next step. @@ -1156,6 +1001,76 @@ \section{Summary} \caption{Proof size vs. use of ZK compression. Dotted line is bandwidth limit, dashed line is compute limit (ZK scheme specific). Not to scale.}\label{fig:comp} \end{figure} +\clearpage +\appendix +\section{The Complete Verifier} +\label{app:verifier} + +Algorithm~\ref{alg:stackverify} is the complete form of Algorithm~\ref{alg:stackverify-core}: identical, with the operand-domain assertions shown. + +\begin{algorithm}[H] + \caption{Stack-machine verification of the RSMT consistency proof, complete}\label{alg:stackverify} + \scriptsize + \begin{algorithmic}[0] + \Function{VerifyConsistency}{$\pi, r_{i-1}, r_i, B$} + \If{$B = [\,]$} + \State \Return $r_{i-1} = r_i \;\land\; \pi = [\,]$ + \EndIf + \State $B \gets \Call{SortTraversalOrder}{B}$ + \State \textbf{assert} keys of $B$ in $\{0,1\}^{\kappa}$, strictly increasing + \State $\mathit{st} \gets [\,]$; \quad $b \gets 0$ \Comment{stack; batch index} + \For{opcode $o$ \textbf{in} $\pi$} + \If{$o = S(c)$} \Comment{opaque subtree} + \State \textbf{assert} $c \in \{0,1\}^{\lambda}$ + \State \Call{Push}{$\mathit{st}, (c, c, \bot)$} + \ElsIf{$o = O(d', p', c_l, c_r)$} \Comment{opening} + \State \textbf{assert} $0 \le d' < \kappa \land p' \in \{0,1\}^{d'} \land c_l, c_r \in \{0,1\}^{\lambda}$ + \State $c \gets H(\texttt{0x01} \| \langle d'\rangle \| \langle p'\rangle \| c_l \| c_r)$ + \State \Call{Push}{$\mathit{st}, (c, c, (d', p'))$} + \ElsIf{$o = O_L(k', v')$} \Comment{opened leaf} + \State \textbf{assert} $k' \in \{0,1\}^{\kappa}$ + \State $c \gets H(\texttt{0x00} \| k' \| v')$ + \State \Call{Push}{$\mathit{st}, (c, c, (\kappa, k'))$} + \ElsIf{$o = L$} \Comment{new leaf} + \State $(k, v) \gets B[b]$; \quad $b \gets b + 1$ + \State \Call{Push}{$\mathit{st}, (\varnothing,\; H(\texttt{0x00} \| k \| v),\; (\kappa, k))$} + \ElsIf{$o = N(d)$} \Comment{junction} + \State \textbf{assert} $0 \le d < \kappa$ + \State $(c^{\mathsf o}_r, c^{\mathsf n}_r, a_r) \gets \Call{Pop}{\mathit{st}}$ + \State $(c^{\mathsf o}_l, c^{\mathsf n}_l, a_l) \gets \Call{Pop}{\mathit{st}}$ + \State $p \gets \bot$ + \For{$x \in \{l, r\}$ with side bit $\beta \in \{0, 1\}$} + \If{$a_x = (\delta_x, \varrho_x) \neq \bot$} \Comment{coherence} + \State \textbf{assert} $\delta_x > d \;\land\; \varrho_x[d] = \beta$ + \State \textbf{assert} $p = \bot \;\lor\; p = \varrho_x[0..d)$ + \State $p \gets \varrho_x[0..d)$ + \EndIf + \EndFor + \State \textbf{assert} $p \neq \bot$ + \If{$c^{\mathsf o}_l = \varnothing \lor c^{\mathsf o}_r = \varnothing$} \Comment{new junction} + \State \textbf{assert} $a_l \neq \bot \;\land\; a_r \neq \bot$ + \EndIf + \If{$c^{\mathsf o}_l = \varnothing \land c^{\mathsf o}_r = \varnothing$} + \State $c^{\mathsf o} \gets \varnothing$ + \ElsIf{$c^{\mathsf o}_l = \varnothing$} + \State $c^{\mathsf o} \gets c^{\mathsf o}_r$ \Comment{pass-through} + \ElsIf{$c^{\mathsf o}_r = \varnothing$} + \State $c^{\mathsf o} \gets c^{\mathsf o}_l$ \Comment{pass-through} + \Else + \State $c^{\mathsf o} \gets H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| c^{\mathsf o}_l \| c^{\mathsf o}_r)$ + \EndIf + \State $c^{\mathsf n} \gets H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| c^{\mathsf n}_l \| c^{\mathsf n}_r)$ + \State \Call{Push}{$\mathit{st}, (c^{\mathsf o}, c^{\mathsf n}, (d, p))$} + \Else + \State \Return $0$ \Comment{unknown opcode} + \EndIf + \EndFor + \State \textbf{assert} $b = |B| \;\land\; |\mathit{st}| = 1$ + \State \Return $\mathit{st}[0].(c^{\mathsf o}, c^{\mathsf n}) = (r_{i-1}, r_i)$ + \EndFunction + \end{algorithmic} +\end{algorithm} + \bibliographystyle{plain} \bibliography{aggregation-layer} From 59dc0577daaec66cee32bc27bf3ee390434e3799 Mon Sep 17 00:00:00 2001 From: ristik Date: Tue, 14 Jul 2026 13:03:37 +0300 Subject: [PATCH 4/6] Split up Canonical Form. Incorporate inclusion, non-inclusion certs --- aggregation-layer.tex | 292 +++++++++++++++++++++++++++++++----------- 1 file changed, 217 insertions(+), 75 deletions(-) diff --git a/aggregation-layer.tex b/aggregation-layer.tex index 8cca0f2..a502c70 100644 --- a/aggregation-layer.tex +++ b/aggregation-layer.tex @@ -71,7 +71,7 @@ \maketitle \begin{abstract} -Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. The remaining desirable properties of the trustless Key-Value store (batch incorporation, no phantom inserts, completeness) are not required by the Unicity Aggregator's security model. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. +Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. Request liveness, submitted-request accountability, and exclusion of unauthorized inserts remain properties of the service surrounding that cryptographic kernel. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. \end{abstract} @@ -83,7 +83,7 @@ \section{Motivation} To scale further, we use cryptographic zero-knowledge proofs (ZKPs) to compress the size of the consistency proofs. As an application of ZKPs, this use-case is fundamentally more efficient than using ZKPs to process the transaction data itself, as is done in many privacy coins and ZK-rollups: the statement being proved is a single tree-update, with the batch as a private witness, not the whole execution trace of a virtual machine. -A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer needs to be convinced that \emph{no previously-recorded leaf was deleted or modified} and that \emph{every new leaf is placed coherently with its key}; Remark~\ref{rem:placement} shows, by a concrete attack, that the second half cannot be dropped. The remaining desirable properties of the Aggregation Layer---batch incorporation, no phantom inserts, completeness---are self-policed by the protocol layer that lives around the public root commitment: their violation only damages the dishonest aggregator's own ability to serve users, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument, and Section~\ref{sec:consistency-formal} proves that the resulting statement is sufficient. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. +A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer needs to be convinced that \emph{no previously-recorded leaf was deleted or modified} and that \emph{every new leaf is placed coherently with its key}; Remark~\ref{rem:placement} shows, by a concrete attack, that the second half cannot be dropped. Request liveness, submitted-request accountability, and exclusion of unauthorized inserts are self-policed by the protocol layer around the public root commitment: their violation only damages the dishonest aggregator's own ability to serve users, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument, and Section~\ref{sec:consistency-formal} proves that the resulting statement is sufficient. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. In this paper, we show how to scale the Aggregation Layer to $10\,000$ tx/s \emph{per shard} and beyond. This figure was the original design target; the measured proving throughput of our reference implementation exceeds it by roughly $3\times$ on a single consumer-class CPU (Section~\ref{sec:custom-air-circuit}). Due to the small proof size and efficient verification, the Consensus Layer can support a practically unlimited number of such trustless shards. @@ -122,7 +122,7 @@ \subsection{Why ZK Proving in Unicity Is Comparatively Efficient} The combined effect of the design choices above is a proving workload that is one to three orders of magnitude smaller than in comparable ZK systems. The principal reasons: \begin{enumerate}[nosep] - \item \emph{Narrow in-circuit statement.} Only prior-state preservation needs to be enforced; unique tree shape, batch incorporation, and freshness are self-policed by the protocol layer (Section~\ref{sec:scope}). + \item \emph{Narrow in-circuit statement.} The circuit enforces only append-only consistency: prior-state preservation and coherent placement. Unique tree shape follows from those local constraints, while request liveness, accountability, and authorization remain in the surrounding protocol (Section~\ref{sec:scope}). \item \emph{No in-circuit transaction execution.} Validation of signatures, predicates, and business logic happens off-chain at the Execution Layer~\cite{exemodel}; the ZK circuit does not see any of it. \item \emph{Batch-amortized proving.} One proof per Aggregation Layer round covers thousands of insertions; there is no per-transaction ZK proof and no anonymity-set scaling. \item \emph{Local update, sublinear cost in tree capacity.} The proof attests only to the modification of a small subset of the SMT---the paths and siblings touched by the batch---rather than the whole tree. Proving effort scales with the batch size and only logarithmically with the current tree capacity, so a single shard can grow without inflating the per-round prover work. @@ -229,11 +229,16 @@ \section{Security Model of the Aggregation Layer} It authenticates incoming state transfer certification requests by verifying that the sender possesses the private key corresponding to the public key that identifies the current token owner. The specific authentication protocol is beyond the scope of this paper. \begin{definition}[Consistency] -An append-only accumulator operates in batches $B = (k_1, k_2, \ldots, k_j)$, accepting new keys. The append-only accumulator is \emph{consistent}, if 1) during the insertion of a batch of updates, no existing element was deleted or modified; 2) it is possible to generate inclusion proofs $\pi^{\textsf{inc}}_{k \in \{B_1, \dots, B_i\}} = (v_k \leadsto r, c)$ for all previously inserted elements, but not for non-existent elements; 3) it is possible to generate non-inclusion proofs $\pi^{\overline{\textsf {inc}}}_{k \notin \{B_1, \dots, B_i\}} = (\varnothing_k \leadsto r, c)$ for all elements not so far inserted to the accumulator, and not for those already inserted. +An append-only accumulator starts from the empty partial map $M_0$ and incorporates batches of fresh key--value bindings, producing cumulative maps $M_1,M_2,\ldots$ and authenticated roots $r_1,r_2,\ldots$. It is \emph{consistent} if, for every state $i$: +\begin{enumerate}[nosep,label=(\roman*)] + \item $M_i$ extends $M_{i-1}$ without deleting or changing a binding; + \item a verifying inclusion certificate for $(k,v)$ against $r_i$ exists exactly when $M_i(k)=v$; + \item a verifying non-inclusion certificate for $k$ against $r_i$ exists exactly when $k\notin\mathrm{dom}(M_i)$. +\end{enumerate} \label{def:append-only-accumulator} \end{definition} -In the tree instantiation, $v_k \leadsto r$ is the hash chain from the leaf holding the value of key $k$ to the root, and $\varnothing_k \leadsto r$ is a chain of openings witnessing that key $k$ is unoccupied; Definition~\ref{def:incl} makes both precise. +In the RSMT instantiation, an inclusion certificate is the hash path from the leaf $(k,v)$ to the root. A non-inclusion certificate follows the key-directed path from the root until the path reaches either a different leaf or a subtree whose region excludes $k$. Definition~\ref{def:query-cert} gives both verifiers, and Theorem~\ref{thm:query} proves the two exactness claims. After each batch of additions, the new root of the Aggregation Layer's SMT is certified by the BFT Core, ensuring its uniqueness and immutability. This provides a secure trust anchor for all consistency, inclusion, and non-inclusion proofs. The idealized Consensus Layer is modeled as Algorithm~\ref{alg:consensuslayer}. @@ -345,10 +350,10 @@ \subsection{Scope of the In-Circuit Statement} The remaining desirable properties of the Aggregation Layer stay outside the kernel, and can be enumerated and accounted for as follows: \begin{description}[nosep] - \item[Completeness] (\emph{every well-formed user request appears in the next round}). A censoring aggregator does not violate the in-circuit statement; it merely fails to serve some users. The protocol mitigates this by replication (highly-available cluster) and by allowing users to resubmit through alternative aggregators in the same shard. - \item[Batch incorporation proof] (\emph{the round proof testifies to inclusion of every batch element}). Rather than have the consistency proof carry per-element inclusion claims, we let the Aggregation Layer serve fresh inclusion proofs on demand against the certified root. An aggregator that does not actually insert the batch will simply fail to produce valid inclusion proofs later, which is detectable by recipients. + \item[Request liveness] (\emph{every well-formed user request is eventually recorded}). A censoring aggregator does not violate the in-circuit statement; it merely fails to serve some users. The protocol mitigates this by replication (highly-available cluster) and by allowing users to resubmit through alternative aggregators in the same shard. + \item[Submitted-request accountability] (\emph{omission of an accepted request is detectable}). The consistency proof binds every element of its witness batch to the new root, but it does not prove that this private witness equals the external queue of authenticated requests. A recipient detects omission by requesting an inclusion certificate against the certified root. \item[No phantom inserts] (\emph{nothing is recorded that was not a user request}). At worst, an aggregator does free recording work for itself or third parties; phantom entries carry fresh keys (coherent placement forbids re-recording), so they cannot affect any honest user's tokens. - \item[Unique Patricia shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: the local validity conditions already force that shape (Proposition~\ref{prop:canon}), and Theorem~\ref{thm:history} preserves those conditions from the empty genesis tree. + \item[Unique Patricia shape] (\emph{the post-state tree is the unique tree prescribed by the data structure's rules for its key set}). This does not need to be postulated as a separate in-circuit obligation: the local validity conditions already force that shape (Lemma~\ref{lem:shape} and Proposition~\ref{prop:unique}), and Theorem~\ref{thm:history} preserves those conditions from the empty genesis tree. \item[Append-only consistency] (\emph{\eqref{eq:psp} together with coherent placement; Definition~\ref{def:aoc}}). \emph{Critical.} If this fails, the operator can rewrite history and double-spending becomes possible. This is the property that must be cryptographically enforced \emph{before} round certification. \end{description} @@ -462,6 +467,8 @@ \subsection{Formal Model} We fix the key length $\kappa = 256$, key space $\mathcal{K} = \{0,1\}^{\kappa}$, a value space $\mathcal{V} \subseteq \{0,1\}^{*}$, and a hash function $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$. For bit strings, $p \sqsubseteq q$ denotes that $p$ is a prefix of $q$, $q[j]$ is the $j$-th bit, and $q[0..d)$ is the first $d$ bits; $\langle\cdot\rangle$ are fixed-length injective encodings; $\varnothing$ is a distinguished constant outside $\{0,1\}^{\lambda}$. All statements below are unconditional reductions: each concludes either the stated property, or that two distinct strings with equal $H$-images (a \emph{collision}) are computable in time linear in the size of the objects at hand. We do not repeat this disjunction in every statement. +\subsubsection{Tree commitments} + \begin{definition}[Valid trees] \label{def:tree} Trees are generated by @@ -474,34 +481,71 @@ \subsection{Formal Model} and $\mathsf{dig}(\varepsilon) = \varnothing$. Region and depth: $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$ and $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$ and $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. A tree is \emph{valid} if every junction $\mathsf{Node}(d,p,l,r)$ in it satisfies: $l$ and $r$ are nonempty, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. The trees $\varepsilon$ and $\mathsf{Leaf}(k,v)$ are valid. \end{definition} -The validity conditions are local: one condition per edge. The first proposition shows that they force the global canonical shape. +The validity conditions are local: one condition per edge. The next three results separate their global consequences from the stronger persistence facts needed only for completeness. -\begin{proposition}[Canonical form] -\label{prop:canon} +\begin{lemma}[Local-to-global shape] +\label{lem:shape} Let $T$ be a valid tree. Then: \begin{enumerate}[nosep,label=(\roman*)] \item every leaf key extends the region of each of its ancestors, and distinct leaves carry distinct keys; hence $T$ represents the partial map $\mathsf{map}(T) = \{k \mapsto v \mid \mathsf{Leaf}(k,v) \in T\}$; \item at every junction, the region $p$ is the longest common prefix of the keys below it; - \item every finite map $M$ has exactly one valid tree, written $\mathsf{Tree}(M)$; - \item the left-to-right leaf order of $T$ is the strictly increasing key order; - \item $\mathsf{Tree}(M)$ contains a junction with region $p$ iff $M$ contains keys extending $p\|0$ and keys extending $p\|1$. + \item the left-to-right leaf order of $T$ is the strictly increasing key order. \end{enumerate} -Consequently, the junctions of $\mathsf{Tree}(M)$, with their depths and regions, persist in $\mathsf{Tree}(M \uplus B)$; and if no key of $B$ extends the region of a node of $\mathsf{Tree}(M)$, the whole subtree at that node recurs verbatim in $\mathsf{Tree}(M \uplus B)$. For a valid $T$ and a batch $B$ whose keys are pairwise distinct and absent from $\mathsf{map}(T)$, we write $T \oplus B = \mathsf{Tree}(\mathsf{map}(T) \uplus B)$. -\end{proposition} +\end{lemma} \begin{proof} (i) Validity gives $p\|\beta \sqsubseteq \mathsf{reg}(\text{child})$ at every edge, so by induction every node's region, and every leaf key, extends the region of each ancestor. Two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d,p,\cdot,\cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$, which is impossible. (ii) Every key below $\mathsf{Node}(d,p,l,r)$ extends $p$. Both children are nonempty, so some key below extends $p\|0$ and some extends $p\|1$. The common prefix therefore ends after exactly the $d$ bits of $p$. -(iii) Induction on the key set. The empty set gives $\varepsilon$; a singleton forces its leaf. Otherwise, by (ii) the root region is forced to be the longest common prefix $p$ of all keys; the bit at position $|p|$ splits the keys into two nonempty sets; the induction hypothesis gives the unique valid trees for the two sets; joining them at $(|p|, p)$ is valid, and any valid root must use exactly this region, this partition, and these children. Values label the determined leaves and do not affect the shape. +(iii) At every junction, keys on the left have bit $0$ and keys on the right have bit $1$ at position $d$, and both sides agree on the first $d$ bits. So every left key precedes every right key, and the claim follows by induction. +\end{proof} -(iv) At every junction, keys on the left have bit $0$ and keys on the right have bit $1$ at position $d$, and both sides agree on the first $d$ bits. So every left key precedes every right key, and the claim follows by induction. +For a finite partial map $M$ and a bit string $q$, write +\[ + M_q = \{\,k \mapsto v \in M \mid q \sqsubseteq k\,\} +\] +for the restriction of $M$ to the key-space cone below $q$. -(v) ($\Leftarrow$) Descend from the root of $\mathsf{Tree}(M)$. Let the current junction have region $q$. The keys extending $p\|0$ and $p\|1$ lie below it, so by (ii) $q \sqsubseteq p$. If $q = p$, done. Otherwise all keys extending $p$ agree on the bit at position $|q|$, so they lie below one child; recurse into it. Depths increase, so the descent terminates, and it can terminate only at $q = p$. ($\Rightarrow$) At a junction with region $p$, validity and (i) give keys below it extending $p\|0$ and $p\|1$. +\begin{proposition}[Unique representation] +\label{prop:unique} +Every finite partial map $M$ has exactly one valid RSMT, written $\mathsf{Tree}(M)$. +\end{proposition} +\begin{proof} +Induction on the key set. The empty map gives $\varepsilon$, and a singleton forces its leaf. Otherwise let $p$ be the longest common prefix of all keys. Its next bit partitions $M$ into the two nonempty maps $M_{p\|0}$ and $M_{p\|1}$. By induction these maps have unique valid trees $T_l$ and $T_r$. Their root regions extend $p\|0$ and $p\|1$, respectively, and their root depths exceed $|p|$, so $\mathsf{Node}(|p|,p,T_l,T_r)$ is valid. -For the consequences: the characterization (v) is monotone in $M$, so junctions persist with their regions (and depths $d = |p|$). The subtree at a node with region $\varrho$ is the unique valid tree over the keys of $M$ extending $\varrho$: those keys and no others lie below it, because the descent from the root directed by any such key passes through the same ancestors. If $B$ adds no key extending $\varrho$, this key set is unchanged, and by (iii) so is the subtree. +Conversely, Lemma~\ref{lem:shape}(ii) forces any valid root representing $M$ to have region $p$; validity forces its two children to represent exactly $M_{p\|0}$ and $M_{p\|1}$; and the induction hypothesis forces those children. Values label the determined leaves and do not affect the shape. +\end{proof} + +\begin{lemma}[Extension persistence] +\label{lem:persist} +Let $M$ and $B$ be finite partial maps with disjoint domains. +For any finite partial map $A$, a subtree with region $\varrho$ in +$\mathsf{Tree}(A)$ represents exactly $A_\varrho$. Moreover: +\begin{enumerate}[nosep,label=(\roman*)] + \item $\mathsf{Tree}(M)$ contains a junction with region $p$ iff $M_{p\|0} \neq \emptyset \neq M_{p\|1}$; + \item every junction of $\mathsf{Tree}(M)$ persists, with the same depth and region, in $\mathsf{Tree}(M \uplus B)$; + \item if a node with region $\varrho$ occurs in either $\mathsf{Tree}(M)$ or $\mathsf{Tree}(M \uplus B)$ and $B_\varrho = \emptyset$, then it occurs in both trees and the two rooted subtrees are identical. +\end{enumerate} +\end{lemma} +\begin{proof} +First consider a subtree $U$ with region $\varrho$ in $\mathsf{Tree}(A)$. Lemma~\ref{lem:shape}(i) shows that every key below $U$ extends $\varrho$. Conversely, key-directed descent places every key of $A_\varrho$ below $U$. Hence $\mathsf{map}(U)=A_\varrho$. + +(i) For the forward direction, the cone identity just proved and the two nonempty children supply keys extending $p\|0$ and $p\|1$. Conversely, suppose both restricted maps are nonempty and descend from the root of $\mathsf{Tree}(M)$. At a current junction with region $q$, the two selected key sets lie below it, so Lemma~\ref{lem:shape}(ii) gives $q \sqsubseteq p$. If $q \neq p$, all keys extending $p$ select the same child at depth $|q|$; recurse into that child. Depths increase, the two selected sets prevent termination at a leaf, and the descent therefore reaches the junction with region $p$. + +(ii) The condition in (i) is monotone under extension from $M$ to $M \uplus B$, and a junction's depth is the length of its region. + +(iii) Suppose first that the node occurs in $\mathsf{Tree}(M)$. A junction persists by (ii), while a leaf persists because its binding remains in the extended map. Conversely, suppose the node occurs in $\mathsf{Tree}(M \uplus B)$. If it is a junction, the two sides of $(M \uplus B)_\varrho$ are nonempty; because $B_\varrho=\emptyset$, clause (i) places the same junction in $\mathsf{Tree}(M)$. If it is a leaf, its binding belongs to $M$ and the same leaf occurs in $\mathsf{Tree}(M)$. In either direction, the two rooted subtrees represent the same map +\[ + (M \uplus B)_\varrho=M_\varrho. +\] +Proposition~\ref{prop:unique} makes them identical. \end{proof} +For a valid tree $T$ and a batch $B$ whose keys are pairwise distinct and absent from $\mathsf{map}(T)$, we identify $B$ with its induced partial map and write +\[ + T \oplus B = \mathsf{Tree}(\mathsf{map}(T) \uplus B). +\] + \begin{definition}[Opening trees] \label{def:opening} Opening trees are generated by @@ -530,42 +574,102 @@ \subsection{Formal Model} Induction on $F$, with the invariant $\mathsf{eval}(F) = \mathsf{dig}(T)$ for the current pair. A hole is assigned the current subtree of $T$. Otherwise, compare the two $H$-preimages. If they differ, they are a collision. If they are equal, the domain-separation tag and the injective encodings force the same constructor with equal components: an $\mathsf{OLeaf}$ meets $\mathsf{Leaf}(k,v)$ with the same $k$ and $v$; an $\mathsf{ONode}$ meets a junction with the same $(d,p)$ and equal child digests, and the induction continues in both children. Clause (d) restates that the recursion covers $F$ and $T$ simultaneously and completely. Each step is one comparison, so the reduction is linear. \end{proof} -\begin{corollary}[Digest binding] -\label{cor:binding} -Trees $T \neq T'$ with $\mathsf{dig}(T) = \mathsf{dig}(T') \neq \varnothing$ yield a collision. -\end{corollary} -\begin{proof} -Open $T'$ fully into an opening tree without holes and apply Lemma~\ref{lem:match}: if no collision is found, clause (d) gives $T' = T$. -\end{proof} +\subsubsection{Authenticated queries} -\begin{definition}[Inclusion proofs; non-inclusion witnesses] -\label{def:incl} -An \emph{inclusion proof} for $(k, v)$ against a root $r$ is a sequence $\gamma = \big((d_1, s_1), \ldots, (d_m, s_m)\big)$ with $\kappa > d_1 > \cdots > d_m \ge 0$ and $s_j \in \{0,1\}^{\lambda}$. The verifier computes $c_0 = H(\texttt{0x00} \| k \| v)$ and, for $j = 1, \ldots, m$, +Query certificates concern one committed map and do not depend on how that map was reached. We therefore define and prove them before introducing certified update histories. + +\begin{definition}[Query certificates] +\label{def:query-cert} +An \emph{inclusion certificate} for $(k,v)$ is a possibly empty sequence +\[ + \gamma=\big((d_1,s_1),\ldots,(d_m,s_m)\big), \qquad m\geq 0. +\] +When $m>0$, the depths satisfy +\[ + \kappa>d_1>\cdots>d_m\geq 0, +\] +where every $s_j\in\{0,1\}^{\lambda}$. The order is from the leaf toward the root. To verify $\gamma$ against $r$, set $c_0=H(\texttt{0x00}\|k\|v)$ and, for $j=1,\ldots,m$, compute \[ c_j = \begin{cases} -H(\texttt{0x01} \| \langle d_j\rangle \| \langle k[0..d_j)\rangle \| c_{j-1} \| s_j) & \text{if } k[d_j] = 0,\\ -H(\texttt{0x01} \| \langle d_j\rangle \| \langle k[0..d_j)\rangle \| s_j \| c_{j-1}) & \text{if } k[d_j] = 1, +H(\texttt{0x01}\|\langle d_j\rangle\|\langle p_j\rangle\|c_{j-1}\|s_j) & \text{if } k[d_j] = 0,\\ +H(\texttt{0x01}\|\langle d_j\rangle\|\langle p_j\rangle\|s_j\|c_{j-1}) & \text{if } k[d_j] = 1, \end{cases} \] -and accepts iff $c_m = r$. Junction regions are not transmitted; the verifier derives them from $k$. +where $p_j=k[0..d_j)$. Accept iff $c_m=r$. When $m=0$, this means accepting iff $c_0=r$. -A \emph{non-inclusion witness} for $k$ against $r$ is a chain of openings from the root along the descent directed by $k$: junction openings $(d_j, p_j, c^0_j, c^1_j)$ whose $H$-images chain from $r$ downward through the $k[d_j]$-side child, with $p_j = k[0..d_j)$ for all but the last element. The chain terminates either in a junction opening whose region is \emph{not} a prefix of $k$, or in an opened leaf with key $\neq k$. Additionally, $r = \varnothing$ is a witness for every $k$. +For later use, $\gamma$ determines an opening tree $F_\gamma$. Start with $F_0=\mathsf{OLeaf}(k,v)$ and wrap it once per pair $(d_j,s_j)$: +\[ +F_j=\begin{cases} +\mathsf{ONode}(d_j,p_j,F_{j-1},\mathsf{Hole}(s_j)) & k[d_j]=0,\\ +\mathsf{ONode}(d_j,p_j,\mathsf{Hole}(s_j),F_{j-1}) & k[d_j]=1. +\end{cases} +\] +Thus $\mathsf{eval}(F_\gamma)=c_m$, so inclusion verification is exactly the check $\mathsf{eval}(F_\gamma)=r$. + +A \emph{non-inclusion certificate} is a list $\eta$ read from the root downward. Its entries are junction openings +\[ + J(d,p,c^0,c^1) + \quad\text{or opened leaves}\quad + E(k',v'), +\] +with operands in the domains of Definition~\ref{def:opening}. Verification of $\eta$ for $k$ against $r$ is deterministic: +\begin{enumerate}[nosep,label=(\roman*)] + \item The empty list accepts iff $r=\varnothing$. + \item For a nonempty list, set the expected digest to $q=r$ and read entries from left to right. Junction depths must strictly increase. + \item At $J(d,p,c^0,c^1)$, require + \[ + q=H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\|c^0\|c^1). + \] + If $p\not\sqsubseteq k$, accept iff this is the final entry. If $p\sqsubseteq k$, require $p=k[0..d)$ and another entry, set $q=c^{k[d]}$, and continue. + \item At $E(k',v')$, accept iff this is the final entry, + $q=H(\texttt{0x00}\|k'\|v')$, and $k'\neq k$. +\end{enumerate} +Any unmet requirement rejects. + +Every accepted nonempty $\eta$ determines an opening tree $F_\eta$. The final entry becomes either $\mathsf{OLeaf}(k',v')$ or an $\mathsf{ONode}$ with two holes. Working backward, replace the $k[d]$-side hole of each preceding junction by the opening already constructed and leave its other child as a hole. The digest checks above give $\mathsf{eval}(F_\eta)=r$. \end{definition} -Both objects are opening trees: an inclusion proof is a chain of $\mathsf{ONode}$s with regions derived from $k$, sibling holes $\mathsf{Hole}(s_j)$, and the terminal $\mathsf{OLeaf}(k, v)$; a non-inclusion witness is a chain of $\mathsf{ONode}$s with holes at the off-path children. Lemma~\ref{lem:match} therefore applies to both. +\begin{theorem}[Query correctness] +\label{thm:query} +Let $M$ be a finite partial map, $T=\mathsf{Tree}(M)$, and $r=\mathsf{dig}(T)$. +\begin{enumerate}[nosep,label=(\roman*)] + \item An inclusion certificate for $(k,v)$ verifies against $r$ only if $M(k)=v$; if $M(k)=v$, the leaf-to-root path in $T$ gives a verifying inclusion certificate. + \item A non-inclusion certificate for $k$ verifies against $r$ only if $k\notin\mathrm{dom}(M)$; if $k\notin\mathrm{dom}(M)$, key-directed descent in $T$ gives a verifying non-inclusion certificate. +\end{enumerate} +Both certificates contain at most $\kappa$ junction openings and are constructed in time linear in the path length. +\end{theorem} +\begin{proof} +(i) Let $\gamma$ verify. Its opening tree satisfies $\mathsf{eval}(F_\gamma)=r$. Since an opening tree evaluates to an $H$-image, $r\neq\varnothing$ and $T\neq\varepsilon$. Lemma~\ref{lem:match} places the terminal $\mathsf{OLeaf}(k,v)$ at the corresponding leaf of $T$, so $M(k)=v$. + +Conversely, suppose $M(k)=v$. Starting at $\mathsf{Leaf}(k,v)$, list its ancestors toward the root. For each ancestor record its depth and the digest of the sibling subtree. Depths strictly decrease in this leaf-to-root order, Lemma~\ref{lem:shape}(ii) gives the region $k[0..d)$, and the side is $k[d]$. The verifier therefore recomputes the digest of each ancestor and ends at $r$. A singleton tree gives the empty certificate. + +(ii) The empty certificate verifies only when $r=\varnothing$, which means $T=\varepsilon$ and the key is absent. Now let a nonempty $\eta$ verify. Its opening tree satisfies $\mathsf{eval}(F_\eta)=r$, so Lemma~\ref{lem:match} places the entire opened path in $T$. Suppose for contradiction that $T$ contains the leaf for $k$. At every nonterminal junction, the certificate requires the junction region to be a prefix of $k$ and continues through side $k[d]$. The matched path therefore remains on the unique path to that leaf. Its terminal cannot be a junction whose region excludes $k$, because every ancestor region is a prefix of $k$ by Lemma~\ref{lem:shape}(i); and it cannot be a leaf with a different key. This contradicts the verifier's terminal check. + +Conversely, suppose $k$ is absent. If $T=\varepsilon$, use the empty certificate. Otherwise open the root and descend while the current junction region is a prefix of $k$, following side $k[d]$. Stop and open the first junction whose region is not a prefix of $k$, or the first leaf. The descent is finite because junction depths strictly increase. The terminal leaf cannot have key $k$, and the recorded openings satisfy every digest, path, and terminal check of Definition~\ref{def:query-cert}. + +A valid root-to-leaf path has strictly increasing depths in $\{0,\ldots,\kappa\}$, which gives the size bound; both constructions visit each path node once. +\end{proof} + +\subsubsection{Certified histories} + +We now turn from queries against one root to the sequence of roots accepted by the consistency verifier. \begin{definition}[Certified history; append-only consistency] \label{def:aoc} -A \emph{certified history} is a sequence $(B_1, \pi_1, r_1), \ldots, (B_n, \pi_n, r_n)$ with $r_0 = \varnothing$ and Algorithm~\ref{alg:stackverify} accepting $(\pi_i, r_{i-1}, r_i, B_i)$ for every $i$. The history is \emph{append-only consistent} if there exist valid trees $T_0 = \varepsilon, T_1, \ldots, T_n$ with $\mathsf{dig}(T_i) = r_i$ and +A \emph{certified history} is a sequence $(B_1, \pi_1, r_1), \ldots, (B_n, \pi_n, r_n)$ with $r_0 = \varnothing$ and Algorithm~\ref{alg:stackverify} accepting $(\pi_i, r_{i-1}, r_i, B_i)$ for every $i$. Define cumulative maps by \[ -\mathsf{map}(T_i) \;=\; \mathsf{map}(T_{i-1}) \uplus B_i \qquad \text{for } i = 1, \ldots, n, + M_0 = \emptyset, \qquad M_i = M_{i-1} \uplus B_i \quad (i=1,\ldots,n), \] -where $\uplus$ is disjoint union of partial maps; in particular the keys of $B_i$ are pairwise distinct and absent from $\mathsf{map}(T_{i-1})$. +identifying a batch with its induced partial map. The history is \emph{append-only consistent} if every disjoint union above is defined and +\[ + r_i = \mathsf{dig}(\mathsf{Tree}(M_i)) \qquad \text{for } i=0,\ldots,n. +\] +Thus definedness requires every batch to have pairwise distinct keys absent from all earlier batches. By Proposition~\ref{prop:unique}, this definition is equivalent to the existence of valid state trees with the previous round-by-round map-extension property. \end{definition} -Definition~\ref{def:aoc} is the formal counterpart of Definition~\ref{def:append-only-accumulator}: map monotonicity is clause~1, and Corollaries~\ref{cor:unicity}--\ref{cor:service} below deliver clauses~2 and~3. It subsumes prior-state preservation~\eqref{eq:psp}, with the committed maps $M_i$ of Section~\ref{sec:scope} realized as $\mathsf{map}(T_i)$. +Definition~\ref{def:aoc} is the formal counterpart of clause~(i) in Definition~\ref{def:append-only-accumulator}; Theorem~\ref{thm:query} gives clauses~(ii) and~(iii) for every canonical state tree. Theorem~\ref{thm:history} links those trees to the roots of a certified history. Definition~\ref{def:aoc} also subsumes prior-state preservation~\eqref{eq:psp}, with the committed maps of Section~\ref{sec:scope} realized as the cumulative maps $M_i$. -\subsection{Security} +\subsection{Certified Update Security} \label{sec:consistency-theorem} The verifier's checks are node-local. We make this explicit by giving the proof stream a typed syntax tree with recursively defined attributes; the checks become a local predicate on that tree. All reasoning below is structural induction. The algorithm itself appears only in Lemma~\ref{lem:parse}. @@ -652,7 +756,7 @@ \subsection{Security} (3)~An edge whose child is an $S$ graft: the parent is an $N$; the $S$ child is unadvised, so by confinement both old digests at the parent are non-$\varnothing$, and the parent appears in $P_0$ as an $\mathsf{ONode}$ with its derived region. The matching places this junction, and the $T$-subtree assigned to the $S$ hole below it, in $T$; this is an edge of $T$. (4)~Every remaining edge has an advised child. Coherence gives $\delta > d$ and, with agreement, $p\|\beta \sqsubseteq \varrho$; by the advice claim, $(\delta, \varrho)$ is the true depth and region of the child's top node. Edges of $T$ satisfy the validity conditions because $T$ is valid; edges of kind (4) satisfy them directly. Hence $T'$ is valid. -\emph{Map.} The leaves of $T'$ are the leaves of assigned subtrees, the $O_L$ leaves, and the $L$ leaves. By clause (d) of the matching, the first two groups are exactly the leaves of $T$. The $L$ leaves carry exactly the elements of $B$. By Proposition~\ref{prop:canon}(i), all leaf keys of the valid $T'$ are distinct; hence the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. +\emph{Map.} The leaves of $T'$ are the leaves of assigned subtrees, the $O_L$ leaves, and the $L$ leaves. By clause (d) of the matching, the first two groups are exactly the leaves of $T$. The $L$ leaves carry exactly the elements of $B$. By Lemma~\ref{lem:shape}(i), all leaf keys of the valid $T'$ are distinct; hence the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. \end{proof} \begin{theorem}[Round soundness] @@ -663,76 +767,114 @@ \subsection{Security} If $B = [\,]$, acceptance forces $\pi = [\,]$ and $r_i = r_{i-1}$; take $T' = T$. Otherwise Lemma~\ref{lem:parse} yields a proof term accepting $(r_{i-1}, r_i, B)$, and Lemma~\ref{lem:graft} yields $T'$. \end{proof} -\begin{theorem}[Completeness] -\label{thm:complete} -Let $T$ be a valid tree and $B$ a batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. Then a stream $\pi_B$ such that Algorithm~\ref{alg:stackverify} accepts $(\pi_B, \mathsf{dig}(T), \mathsf{dig}(T \oplus B), B)$ is computable from $T$ and $B$ in linear time after sorting $B$. -\end{theorem} +\begin{definition}[Difference generator] +\label{def:generator} +Let $T$ be valid, let $B \neq [\,]$ have pairwise distinct keys absent from $M=\mathsf{map}(T)$, and put $T'=T\oplus B$. For a subtree $U$ of $T'$, let +\[ + M[U] = \{\,k \mapsto v \in M \mid \mathsf{Leaf}(k,v)\text{ occurs below }U\,\}. +\] +The difference generator traverses $T'$ from the root. On reaching a maximal subtree $U$ containing no key of $B$, it stops: Lemma~\ref{lem:persist}(iii) identifies $U$ as a preserved subtree of $T$. It emits $S(\mathsf{dig}(U))$ when the parent junction also occurs in $T$; when the parent is new, it emits the opened root of $U$, namely $O$ with the true node labels and child digests or $O_L$ with the true leaf. A leaf from $B$ emits $L(k,v)$. Every other node $U=\mathsf{Node}(d,p,U_l,U_r)$ emits $N(d,Q_l,Q_r)$ after recursively generating $Q_l$ and $Q_r$. The resulting proof term is $P_B$. + +Operationally, $T'$ and $P_B$ are produced together by merging the sorted batch into $T$. Preserved subtrees are emitted at their roots without traversal, so the merge performs constant work per emitted constructor and per batch element. +\end{definition} + +\begin{lemma}[Generator invariant] +\label{lem:generator} +For every subterm $Q$ generated for a subtree $U$ of $T'$: +\begin{enumerate}[nosep,label=(\roman*)] + \item $\mathsf{ok}(Q)$; + \item $\mathsf{old}(Q)=\mathsf{dig}(\mathsf{Tree}(M[U]))$; + \item $\mathsf{new}(Q)=\mathsf{dig}(U)$; + \item either $Q=S(\mathsf{dig}(U))$ and $\mathsf{adv}(Q)=\bot$, or $\mathsf{adv}(Q)=(\mathsf{dep}(U),\mathsf{reg}(U))$; + \item the $L$ labels of $Q$, from left to right, are exactly the bindings of $B$ below $U$, in strictly increasing key order. +\end{enumerate} +Consequently, $P_B$ accepts $(\mathsf{dig}(T),\mathsf{dig}(T'),B)$ and is computable, together with $T'$, in time $O(|P_B|+|B|)$ after sorting $B$. +\end{lemma} \begin{proof} -If $B = [\,]$ then $T \oplus B = T$ and $\pi_B = [\,]$ is accepted. Assume $B \neq [\,]$, write $T' = T \oplus B$ and $M = \mathsf{map}(T)$; $T'$ is valid with $\mathsf{map}(T') = M \uplus B$ by Proposition~\ref{prop:canon}(iii). For a region $\varrho$ let $M_\varrho$ be the set of keys of $M$ extending $\varrho$. By Proposition~\ref{prop:canon}(v), a junction with region $p$ is in $T$ iff $M_{p\|0} \neq \emptyset \neq M_{p\|1}$, and a subtree of $T'$ containing no batch key equals the subtree of $T$ over the same keys. Call such subtrees of $T'$, taken maximal, \emph{preserved}; call a junction of $T'$ \emph{new} if it is not a junction of $T$. +Induction over the generator. -Define the \emph{difference term} $P_B$ over $T'$, top down: a preserved subtree becomes $S(\mathsf{dig})$ if its parent junction is a junction of $T$, and its opened root---$O$ with the true labels and child digests, or $O_L$---if its parent is new; a leaf with key in $B$ becomes $L(k, v)$; every other node $\mathsf{Node}(d,p,\cdot,\cdot)$ becomes $N(d, \cdot, \cdot)$ over the terms of its children. $P_B$ is computed by one simultaneous traversal of $T$ and $T'$. We check that $P_B$ accepts $(\mathsf{dig}(T), \mathsf{dig}(T'), B)$; Lemma~\ref{lem:parse} then concludes. +If $U$ is preserved, then $M[U]=\mathsf{map}(U)$ and Proposition~\ref{prop:unique} gives $U=\mathsf{Tree}(M[U])$. Both $S$ and the opened-root forms have equal old and new digest $\mathsf{dig}(U)$; the opened forms carry the true top-node advice, while $S$ is unadvised. There are no $L$ labels. If $U=\mathsf{Leaf}(k,v)$ comes from $B$, freshness gives $M[U]=\emptyset$; the emitted $L(k,v)$ has old digest $\varnothing=\mathsf{dig}(\mathsf{Tree}(\emptyset))$, new digest $\mathsf{dig}(U)$, true leaf advice, and the required singleton label list. Thus all five claims hold in the terminal cases. -\emph{Advice.} By construction, every subterm except an $S$ is advised, and every advised subterm carries the true depth and region of its top node in $T'$. At every $N$, some child is not an $S$: if both children were preserved, the junction and its whole subtree would be preserved, contradicting maximality. So agreement holds, the derived region is the true region $p$, and coherence holds because $T'$ is valid. +Let $U=\mathsf{Node}(d,p,U_l,U_r)$ emit $Q=N(d,Q_l,Q_r)$ and apply the induction hypothesis to its children. At least one child term is not $S$: otherwise both child subtrees would contain no batch key and the generator would have stopped at $U$. Every advised child carries its true top-node depth and region, so validity of $U$ gives coherence; all advised children yield the true prefix $p$, so agreement holds and $\mathsf{adv}(Q)=(d,p)$. -\emph{Old digests.} By induction, $\mathsf{old}$ of the subterm at a node with region $\varrho$ equals $\mathsf{dig}(\mathsf{Tree}(M_\varrho))$, with the values of $M$. For terminals: a preserved subtree is $\mathsf{Tree}(M_\varrho)$ itself; an $L$ leaf has $M_k = \emptyset$ and $\mathsf{old} = \varnothing$. For a junction at region $p$: if $M_{p\|0} = M_{p\|1} = \emptyset$ then $M_p = \emptyset$; if exactly one is empty, $\mathsf{Tree}(M_p) = \mathsf{Tree}(M_{p\|\beta})$ and the pass-through applies; if neither is empty, $T$ has this junction with the same $(d, p)$ and with the trees over $M_{p\|0}$, $M_{p\|1}$ as children, and the hashed case recomputes its digest. At the root, $\mathsf{old}(P_B) = \mathsf{dig}(T)$. +The cone identity of Lemma~\ref{lem:persist}, applied to $U$ in $T'=\mathsf{Tree}(M\uplus B)$, says that $U$ contains exactly the bindings below $p$. Key placement at $U$ then gives $M[U_l]=M_{p\|0}$ and $M[U_r]=M_{p\|1}$; these maps partition $M[U]$. If both parts are empty, so is $M[U]$ and the four-way rule returns $\varnothing$. If exactly one part is nonempty, its unique valid tree is also $\mathsf{Tree}(M[U])$, and the rule passes through its digest. If both are nonempty, the two parts contain keys on opposite sides of $p$; the construction in Proposition~\ref{prop:unique} gives +\[ + \mathsf{Tree}(M[U]) + = \mathsf{Node}(d,p,\mathsf{Tree}(M[U_l]),\mathsf{Tree}(M[U_r])), +\] +so the hashed case gives its digest. This proves (ii). -\emph{Confinement.} If $\mathsf{old} = \varnothing$ on some side of an $N$ at region $p$, then $M_{p\|0}$ or $M_{p\|1}$ is empty, so the junction is new; its preserved child, if any, was emitted opened, and every other subterm kind is advised. +If either child old digest is $\varnothing$, its old map is empty because no nonempty tree has digest $\varnothing$. Lemma~\ref{lem:persist}(i) then shows that the junction at $p$ is new. A preserved child below it was emitted opened, and every non-preserved child is advised by the induction hypothesis; hence both children are advised and confinement holds. Together with coherence and agreement this proves (i). The definition of $\mathsf{new}$ and the induction hypothesis give (iii). The preceding advice argument gives (iv). Finally, the $L$ list of $Q$ is the concatenation of its two child lists; Lemma~\ref{lem:shape}(iii) places every left key before every right key, proving (v). -\emph{New digests and batch order.} $\mathsf{new}$ agrees with $\mathsf{dig}$ on the terminals and recomputes every junction, so $\mathsf{new}(P_B) = \mathsf{dig}(T')$ by induction. The $L$ leaves, left to right, are the leaves of $T'$ with keys in $B$, in strictly increasing key order by Proposition~\ref{prop:canon}(iv). +At the root, $M[T']=M$, so Proposition~\ref{prop:unique} gives $\mathsf{Tree}(M)=T$. Claims (i)--(v) therefore say exactly that $P_B$ accepts $(\mathsf{dig}(T),\mathsf{dig}(T'),B)$. The operational merge of Definition~\ref{def:generator} visits each emitted constructor and batch element once, giving the stated time bound. \end{proof} -\begin{theorem}[History soundness] -\label{thm:history} -Every certified history (Definition~\ref{def:aoc}) is append-only consistent, and each $T_i$ is the unique valid tree representing its map---or a collision is computable from the transcript. +\begin{theorem}[Completeness] +\label{thm:complete} +Let $T$ be a valid tree and $B$ a batch whose keys are pairwise distinct and absent from $\mathsf{map}(T)$. Then a stream $\pi_B$ such that Algorithm~\ref{alg:stackverify} accepts $(\pi_B, \mathsf{dig}(T), \mathsf{dig}(T \oplus B), B)$ is computable from $T$ and $B$ in linear time after sorting $B$. \end{theorem} \begin{proof} -Induction on rounds: $T_0 = \varepsilon$ is valid with $\mathsf{dig}(T_0) = \varnothing$, and Theorem~\ref{thm:round} supplies the step. Uniqueness is Proposition~\ref{prop:canon}(iii). +For $B=[\,]$, take $\pi_B=[\,]$. Otherwise Lemma~\ref{lem:generator} shows that the generated term $P_B$ accepts the required roots and batch. Serialize $P_B$ in post-order and apply Lemma~\ref{lem:parse}; its linear-time bound and the generator bound give the claim. \end{proof} -\begin{lemma}[Query soundness] -\label{lem:query} -Let $T$ be a valid tree with $\mathsf{dig}(T) = r$. (i) If an inclusion proof for $(k, v)$ verifies against $r$, then $(k, v) \in \mathsf{map}(T)$. (ii) If a non-inclusion witness for $k$ verifies against $r$, then $k \notin \mathrm{dom}(\mathsf{map}(T))$. -\end{lemma} +\begin{theorem}[History soundness] +\label{thm:history} +Every certified history (Definition~\ref{def:aoc}) is append-only consistent, or a collision is computable from the transcript. +\end{theorem} \begin{proof} -(i) No $H$-image equals $\varnothing$, so $r \neq \varnothing$ and $T \neq \varepsilon$. The proof is an opening tree evaluating to $r$; Lemma~\ref{lem:match} places its junction chain and its terminal $\mathsf{OLeaf}(k, v)$ in $T$. Hence $\mathsf{Leaf}(k, v) \in T$. - -(ii) If $r = \varnothing$ then $T = \varepsilon$ and the claim holds. Otherwise assume no collision was found and suppose $k \in \mathrm{dom}(\mathsf{map}(T))$. Lemma~\ref{lem:match} places the witness chain in $T$. By Proposition~\ref{prop:canon}(i), every ancestor of $k$'s leaf carries a region that is a prefix of $k$, and the leaf lies on the side $k[d]$ of each. The witness starts at the root and follows the $k[d_j]$-side child of junctions whose regions are prefixes of $k$; by induction, every node it visits is an ancestor of $k$'s leaf, or the leaf itself. Its terminal is therefore a junction whose region is a prefix of $k$, or the leaf with key $k$. Both terminal conditions of Definition~\ref{def:incl} fail: a contradiction. +Induction on rounds. The base map is $M_0=\emptyset$ and $r_0=\varnothing=\mathsf{dig}(\mathsf{Tree}(M_0))$. Assume $M_{i-1}$ is defined and $r_{i-1}=\mathsf{dig}(\mathsf{Tree}(M_{i-1}))$. Apply Theorem~\ref{thm:round} to the valid tree $\mathsf{Tree}(M_{i-1})$ and the accepted round $i$. It yields a valid $T'$ with +\[ + \mathsf{dig}(T')=r_i, + \qquad + \mathsf{map}(T')=M_{i-1}\uplus B_i. +\] +Thus the disjoint union defining $M_i$ exists, and Proposition~\ref{prop:unique} gives $T'=\mathsf{Tree}(M_i)$. Hence $r_i=\mathsf{dig}(\mathsf{Tree}(M_i))$, completing the induction. \end{proof} \begin{corollary}[Unicity] \label{cor:unicity} -In a certified history, verifying inclusion proofs for $(k, v)$ against $r_i$ and for $(k, v')$ against $r_j$ imply $v = v'$. +In a certified history, verifying inclusion certificates for $(k, v)$ against $r_i$ and for $(k, v')$ against $r_j$ imply $v = v'$. \end{corollary} \begin{proof} -Take $i \le j$. By Theorem~\ref{thm:history} and Lemma~\ref{lem:query}(i), $v = \mathsf{map}(T_i)(k)$ and $v' = \mathsf{map}(T_j)(k)$. Maps grow monotonically, so $\mathsf{map}(T_i) \subseteq \mathsf{map}(T_j)$ and $v = v'$. +Apply Theorem~\ref{thm:history}; if it produces a collision, we are done. Otherwise, without loss of generality let $i\leq j$. Then $r_i=\mathsf{dig}(\mathsf{Tree}(M_i))$ and $r_j=\mathsf{dig}(\mathsf{Tree}(M_j))$. Theorem~\ref{thm:query}(i) gives $M_i(k)=v$ and $M_j(k)=v'$. Since $M_i\subseteq M_j$, the two values are equal. \end{proof} -\begin{corollary}[No phantom bindings] -\label{cor:nophantom} -In a certified history, if an inclusion proof for $(k, v)$ verifies against $r_i$, then $(k, v) \in B_1 \uplus \cdots \uplus B_i$. In particular, no inclusion proof verifies for a key that was never inserted. +\begin{corollary}[No out-of-batch bindings] +\label{cor:batchbound} +In a certified history, if an inclusion certificate for $(k,v)$ verifies against $r_i$, then +\[ + (k,v)\in B_1\uplus\cdots\uplus B_i. +\] +Here the $B_j$ are the consistency proof's witness batches. The claim does not assert that every witness binding came from an authenticated user request. \end{corollary} \begin{proof} -By Theorem~\ref{thm:history}, $\mathsf{map}(T_i) = B_1 \uplus \cdots \uplus B_i$; apply Lemma~\ref{lem:query}(i). +Apply Theorem~\ref{thm:history}. Unless it produces a collision, $M_i=B_1\uplus\cdots\uplus B_i$ and $r_i=\mathsf{dig}(\mathsf{Tree}(M_i))$; Theorem~\ref{thm:query}(i) gives the result. \end{proof} \begin{corollary}[No false non-inclusion] \label{cor:noninc} -In a certified history, a verifying inclusion proof for $(k, v)$ against $r_i$ and a verifying non-inclusion witness for $k$ against $r_j$ with $j \ge i$ together yield a collision. +In a certified history, a verifying inclusion certificate for $(k,v)$ against $r_i$ and a verifying non-inclusion certificate for $k$ against $r_j$, where $j\geq i$, together yield a collision. \end{corollary} \begin{proof} -By Lemma~\ref{lem:query}, $k \in \mathrm{dom}(\mathsf{map}(T_i)) \subseteq \mathrm{dom}(\mathsf{map}(T_j))$ and $k \notin \mathrm{dom}(\mathsf{map}(T_j))$. Both cannot hold, so one of the reductions produced a collision. +Apply Theorem~\ref{thm:history}; if it produces a collision, we are done. Otherwise the certified roots are the digests of $\mathsf{Tree}(M_i)$ and $\mathsf{Tree}(M_j)$. Theorem~\ref{thm:query} gives +\[ + k\in\mathrm{dom}(M_i)\subseteq\mathrm{dom}(M_j) + \quad\text{and}\quad + k\notin\mathrm{dom}(M_j), +\] +a contradiction. Thus one of the reductions produces a collision. \end{proof} -\begin{corollary}[Service completeness] +\begin{corollary}[Certified query service] \label{cor:service} -Let $T_i$ be the trees of Theorem~\ref{thm:history}. For every $(k, v) \in \mathsf{map}(T_i)$, the path data of $T_i$ yields a verifying inclusion proof; for every $k \notin \mathrm{dom}(\mathsf{map}(T_i))$, the key-directed descent of $T_i$ yields a verifying non-inclusion witness. Producing them requires only possession of the tree data: an availability concern, not an integrity concern. +For every root $r_i$ of a certified history, $(k,v)$ admits a verifying inclusion certificate exactly when $M_i(k)=v$, and $k$ admits a verifying non-inclusion certificate exactly when $k\notin\mathrm{dom}(M_i)$. Given $\mathsf{Tree}(M_i)$, the corresponding certificates are obtained in time linear in their path length. \end{corollary} \begin{proof} -For $(k, v) \in \mathsf{map}(T_i)$: list the junctions on the path from the root to $k$'s leaf, with their depths and the digests of the off-path children. By Proposition~\ref{prop:canon}(i)--(ii), the region of the $j$-th such junction is $k[0..d_j)$ and the leaf lies on side $k[d_j]$, so the verifier of Definition~\ref{def:incl} recomputes exactly the digests along the path, ending in $r_i$. For $k \notin \mathrm{dom}(\mathsf{map}(T_i))$: if $T_i = \varepsilon$, the empty witness verifies. Otherwise descend from the root, following bit $k[d]$ while the junction region is a prefix of $k$. Depths strictly increase, so the descent ends: at a junction whose region is not a prefix of $k$, or at a leaf, whose key is not $k$ because $k$ is absent. The recorded openings form a verifying witness. +Apply Theorem~\ref{thm:history}; unless it produces a collision, $r_i=\mathsf{dig}(\mathsf{Tree}(M_i))$. The claims are then exactly Theorem~\ref{thm:query}, including its construction and time bounds. \end{proof} \begin{remark} -Theorems~\ref{thm:round} and~\ref{thm:complete} establish soundness and completeness of each transition; Theorem~\ref{thm:history} and Corollaries~\ref{cor:unicity}--\ref{cor:service} establish the history and query properties of the accumulator interface in Definition~\ref{def:append-only-accumulator}. Every proof is a structural induction over an inductive datatype---trees, opening trees, or proof terms---with recursively defined attributes and explicit collision extraction. The verification algorithm appears only in Lemma~\ref{lem:parse}; a re-arithmetization of the verifier, such as the AIR of Section~\ref{sec:custom-air-circuit}, only needs to be proven equivalent to Algorithm~\ref{alg:stackverify}, and the rest of the argument carries over unchanged. +Theorem~\ref{thm:query} establishes soundness and completeness of authenticated queries. Theorems~\ref{thm:round} and~\ref{thm:complete} do the same for each transition, while Theorem~\ref{thm:history} and Corollaries~\ref{cor:unicity}, \ref{cor:batchbound}, \ref{cor:noninc}, and~\ref{cor:service} lift the results to certified histories. Together they establish the accumulator interface of Definition~\ref{def:append-only-accumulator}. The core arguments use structural induction over trees, opening trees, or proof terms, with recursively defined attributes and explicit collision extraction; query correctness reduces directly to Matching and canonical path construction. The consistency algorithm appears only in Lemma~\ref{lem:parse}; a re-arithmetization of that verifier, such as the AIR of Section~\ref{sec:custom-air-circuit}, only needs to be proven equivalent to Algorithm~\ref{alg:stackverify}, and the rest of the argument carries over unchanged. \end{remark} @@ -924,7 +1066,7 @@ \subsection{Data Availability} \emph{Audit plane.} The per-round artifacts consumed by the aggregation prover: for each round $i$, the tuples $(r_{i-1,\sigma}, r_{i,\sigma}, \pi_{i,\sigma})$ for every changed shard, the global root $R_i$, the issued certificates, the Trust Base entries at epoch changes, and the accepted checkpoint proofs. All of these are public by design---the consistency proofs carry no user data (the insertion batches remain private witnesses of the \emph{shard} provers and are not needed for aggregation)---and are published to a content-addressed round archive replicated by the shards and the BFT Core validators, which anyone may mirror. At $\sim$1--2\,MB per shard per round, the archive grows at an entirely manageable rate. -The aggregate proof gives the archive a bounded retention requirement: once a span of rounds has been folded into an accepted checkpoint (plus a safety margin for independent re-verification), its artifacts may be pruned, because $\Pi_n$ subsumes them. Symmetrically, the archive gives the prover role its permissionless character: a new prover bootstraps from the latest accepted checkpoint and the archive tail, with no handover, registration, or historical sync beyond the unpruned window. Anyone can jump in and start proving. +The aggregate proof gives the archive a bounded retention requirement: once a span of rounds has been folded into an accepted checkpoint (plus a safety margin for independent re-verification), its artifacts may be pruned, because $\Pi_n$ subsumes them. Symmetrically, the archive gives the prover role its permissionless character: a new prover bootstraps from the latest accepted checkpoint and the archive tail, with no handover, registration, or historical sync beyond the unpruned window. New provers can join permissionlessly. \subsection{Maximalist Validation Procedure} \label{sec:maxi-validation} From 4747c349948327b0f9829dd4b565d6ca73a56463 Mon Sep 17 00:00:00 2001 From: ristik Date: Wed, 15 Jul 2026 20:14:30 +0300 Subject: [PATCH 5/6] less pos, more sharding --- aggregation-layer.bib | 19 ++++-- aggregation-layer.tex | 144 ++++++++++++++++++++++++++---------------- 2 files changed, 104 insertions(+), 59 deletions(-) diff --git a/aggregation-layer.bib b/aggregation-layer.bib index 667897c..932cdc3 100644 --- a/aggregation-layer.bib +++ b/aggregation-layer.bib @@ -171,12 +171,19 @@ @misc{tornado } @misc{exemodel, - author = {{The Unicity Developers}}, - title = {{Unicity} Execution Model}, - year = {2025}, - publisher = {{GitHub}}, - journal = {{GitHub} repository}, - howpublished = {\url{https://github.com/unicitynetwork/execution-model-tex}} + author = {Ahto Buldas and Dirk Draheim and Mike Gault and Risto Laanoja and Vladimir Rogojin and Ahto Truu}, + title = {The {Unicity} Execution Layer}, + year = {2026}, + howpublished = {{arXiv} preprint {arXiv}:2606.02181}, + url = {https://arxiv.org/abs/2606.02181} +} + +@misc{predicates, + author = {Ahto Buldas and Dirk Draheim and Mike Gault and Risto Laanoja and Vladimir Rogojin and Ahto Truu}, + title = {{Unicity}: Predicates and Atomic Swaps}, + year = {2026}, + howpublished = {{arXiv} preprint {arXiv}:2606.02192}, + url = {https://arxiv.org/abs/2606.02192} } @misc{polygonzkevm, diff --git a/aggregation-layer.tex b/aggregation-layer.tex index a502c70..9a8b6b5 100644 --- a/aggregation-layer.tex +++ b/aggregation-layer.tex @@ -85,7 +85,7 @@ \section{Motivation} A useful scoping observation is that the consensus-relevant statement is narrower than ``the SMT was updated correctly''. The Consensus Layer needs to be convinced that \emph{no previously-recorded leaf was deleted or modified} and that \emph{every new leaf is placed coherently with its key}; Remark~\ref{rem:placement} shows, by a concrete attack, that the second half cannot be dropped. Request liveness, submitted-request accountability, and exclusion of unauthorized inserts are self-policed by the protocol layer around the public root commitment: their violation only damages the dishonest aggregator's own ability to serve users, a denial of service by an operationally replaceable component. Section~\ref{sec:scope} details this scoping argument, and Section~\ref{sec:consistency-formal} proves that the resulting statement is sufficient. The narrowness of the in-circuit statement is what makes the AIR small and the proving cheap. -In this paper, we show how to scale the Aggregation Layer to $10\,000$ tx/s \emph{per shard} and beyond. This figure was the original design target; the measured proving throughput of our reference implementation exceeds it by roughly $3\times$ on a single consumer-class CPU (Section~\ref{sec:custom-air-circuit}). Due to the small proof size and efficient verification, the Consensus Layer can support a practically unlimited number of such trustless shards. +In this paper, we show how to scale the Aggregation Layer to $10\,000$ tx/s \emph{per shard} and beyond. This figure was the original design target; the measured proving throughput of our reference implementation exceeds it by roughly $3\times$ on a single consumer-class CPU (Section~\ref{sec:custom-air-circuit}). Shards process disjoint key ranges and prove their state transitions independently, so aggregate transaction capacity is the sum of their capacities. The BFT Core receives one succinct transition proof per advancing shard rather than one item per transaction; Section~\ref{sec:sharding-architecture} makes this scaling boundary precise. \section{State of the Art and Comparison} @@ -138,7 +138,7 @@ \section{System Architecture} The rest of the processing---executing transactions, running smart contracts, etc.---can happen at the client layer, executed by users or ``agents''. Agents are themselves the interested parties in data availability and transaction validation, and they choose the ordering of incoming messages for processing. Thus, the Unicity Infrastructure is relieved of these duties, removing a major scaling bottleneck of traditional L1 blockchains. -The Unicity Infrastructure operates in a trust-minimized way by utilizing distributed authenticated data structures and cryptographic zero-knowledge tools (SNARKs) for extra succinctness of messages and tokens. The Proof of Unicity is a fresh \emph{proof of inclusion} of the token state being spent. This can be efficiently generated based on a Merkle Tree data structure. The proof size is logarithmic with respect to the tree's capacity, making it highly efficient. If the root of the tree is securely fixed, the integrity of the rest of the tree can be verified trustlessly: it is computationally infeasible to generate a valid inclusion proof for an element not present in the tree, without changing the root, or breaking underlying cryptographic assumptions. The infrastructure also supports \textit{non-inclusion proofs}, making it possible to prove to other parties that a particular token state has not yet been spent. The Unicity Infrastructure can thus be conceptualized as a large-scale, distributed Sparse Merkle Tree (SMT). Specifically, the tree is implemented as a path-compressed radix variant, the RSMT (Section~\ref{sec:stack-verifier}), which eliminates single-child internal chains while preserving the standard property that the key uniquely determines the leaf position. Furthermore, an SMT is straightforward to shard: the tree is partitionable vertically into slices. Leaves remain at their deterministically computed positions, as an SMT is an indexed data structure. Each leaf's identifier encodes its address in the tree, and the leaf's shard address is a prefix of the identifier. +The Unicity Infrastructure operates in a trust-minimized way by utilizing distributed authenticated data structures and succinct cryptographic proofs. The Proof of Unicity is a fresh \emph{proof of inclusion} of the token state being spent. This can be efficiently generated based on a Merkle Tree data structure. The proof size is logarithmic with respect to the tree's capacity, making it highly efficient. If the root of the tree is securely fixed, the integrity of the rest of the tree can be verified trustlessly: it is computationally infeasible to generate a valid inclusion proof for an element not present in the tree, without changing the root, or breaking underlying cryptographic assumptions. The infrastructure also supports \textit{non-inclusion proofs}, making it possible to prove to other parties that a particular token state has not yet been spent. The Unicity Infrastructure can thus be conceptualized as a large-scale, distributed Sparse Merkle Tree (SMT). Specifically, the tree is implemented as a path-compressed radix variant, the RSMT (Section~\ref{sec:stack-verifier}), which eliminates single-child internal chains while preserving the standard property that the key uniquely determines the leaf position. Its key-determined layout also gives a canonical horizontal partition: the prefix of an identifier selects exactly one shard, while the remaining bits locate the identifier within that shard (Section~\ref{sec:sharding-architecture}). Aggregation Layer connects to the Consensus Layer. For fully trustless operation, each request is accompanied by a cryptographic proof of SMT consistency. @@ -159,26 +159,14 @@ \section{System Architecture} \subsection{Consensus Layer} \label{sec:consensus-layer} -The Consensus Layer consists of a single logical component, the \emph{BFT Core}: a bounded-size committee of validator nodes running a leader-based Byzantine fault tolerant (BFT) consensus protocol. Its interface is narrow. Once per round, it receives the certification requests of the Aggregation Layer shards, checks that each request uniquely extends the previously certified state of its shard, verifies the accompanying consistency proof, and issues a \emph{Unicity Certificate} over the updated global state. BFT consensus provides deterministic, single-round finality and a fast, predictable round rate; the price is that liveness depends on a supermajority (more than two thirds of voting power) of the committee being online and cooperative. +The Consensus Layer consists of a single logical component, the \emph{BFT Core}: a bounded-size committee of validator nodes running a Byzantine fault tolerant (BFT) consensus protocol. During a round of execution, it receives certification requests from Aggregation Layer shards, checks that each request extends the previously certified state of its shard, verifies the accompanying consistency proof, and issues a \emph{Unicity Certificate} over the updated global state. BFT consensus provides deterministic finality; its usual quorum assumption is needed for prompt progress and for uniqueness of the most recent certified tip. -The BFT Core maintains no blockchain. Its persistent state is cumulative: the vector of most recently certified shard roots (combined into a single global root, Section~\ref{sec:data-flow}), the staking registry described below, and the \emph{Unicity Trust Base}---a chain of epoch records, one per validator-set change, each carrying the new validator identities, their stake weights and the quorum condition, and each signed by a quorum of the previous epoch's committee. There is no block content worth chaining: ordering and availability of user transactions are handled below, at the Aggregation and Execution Layers, and issued certificates are persisted by the parties who need them---embedded in tokens as proofs, and stored in the public round archive (Section~\ref{sec:data-availability}). +The BFT Core maintains no blockchain. Its persistent protocol state is cumulative: the vector of most recently certified shard roots (combined into a single global root, Section~\ref{sec:data-flow}) and the \emph{Unicity Trust Base}, an authenticated record of the validator set and quorum rule applicable to each configuration period. There are no transaction blocks: ordering and availability of user requests are handled below, at the Aggregation and Execution Layers, and issued certificates are persisted by the parties who need them and by the public round archive (Section~\ref{sec:data-availability}). -\subsubsection{Delegated Proof of Stake} -\label{sec:dpos} - -Permissionless participation in the Consensus Layer is achieved through delegated Proof of Stake (DPoS), using the native token. We specify the mechanism here; the economic parameters---emission schedule, commission bounds, minimum stakes, penalty fractions---are governance-controlled and documented separately. - -\begin{description}[nosep] - \item[Staking and delegation.] Any token holder may bond tokens, either as a \emph{validator candidate}, operating a node and publishing its consensus public key and service addresses, or as a \emph{delegator}, assigning bonded tokens to candidates of their choice. Bonded tokens are locked and earn yield (see \emph{Rewards}); unbonding is subject to a fixed delay (see below). Newly minted tokens---including validator and delegator rewards themselves---can be bonded directly, so that earned rewards compound. - \item[Validator election.] Committees serve for fixed \emph{epochs}. At each epoch boundary, candidates are ranked by total bonded stake (own plus delegated), and the top $k$ form the next committee---a stake-weighted ``beauty contest'' in which delegators continuously vote with their stake, and candidates compete on reliability, performance, and commission. The election is a deterministic function of the staking registry, which is itself part of the certified cumulative state, so anyone can recompute and verify the committee of any epoch. Voting power within the committee is proportional to bonded stake, and each epoch's validator set and quorum condition are recorded in the corresponding Trust Base entry. - \item[Rewards.] Validators and their delegators earn a protocol-defined emission per epoch, plus any protocol fees collected during the epoch, distributed pro rata to bonded stake; the validator retains a self-declared commission. Reward distribution is part of the certified state transition at the epoch boundary. - \item[Slashing and accountability.] Safety violations of a BFT protocol are \emph{attributable}: certifying two conflicting states in the same round (equivocation) requires the same key to sign two conflicting payloads, and the signature pair is self-contained cryptographic evidence, verifiable by anyone. Any party may submit such evidence; the offending validator's bonded stake---including delegations, which keeps delegators diligent in their choice of candidate---is partially destroyed, with a fraction paid to the submitter. Prolonged unavailability is handled more mildly, by withheld rewards and eviction from the committee. This is the accountable-safety approach of modern PoS finality systems~\cite{casper}. - \item[Unbonding delay.] Unbonding takes effect only after a delay covering at least one full epoch plus the evidence-submission window. The delay guarantees that misbehaving stake is still bonded when evidence against it arrives, and it bounds long-range attacks: a fully unbonded former committee cannot retroactively certify an alternative history without its equivocation being visible next to the original. The residual long-range risk is addressed by the weak-subjectivity anchor that the Trust Base chain provides and, more fundamentally, by the aggregated history proof of Section~\ref{sec:aggregation-audit}. -\end{description} - -The classical ``nothing at stake'' objection to PoS does not apply in its usual form, because there is no chain to fork: each round, the BFT Core certifies exactly one successor state or none. Its analogue---a quorum signing two conflicting successor states---is the equivocation case above: it cannot be prevented cryptographically, but it is detectable, attributable, and economically punished. Section~\ref{sec:aggregation-audit} shows that this is also the \emph{only} residual role of economic assumptions in the security argument; the correctness of all certified state transitions is verifiable from cryptographic assumptions alone. +Committee formation and its operational policy are orthogonal to the Aggregation Layer and outside the scope of this paper. For the immediate validation path we assume an authenticated Trust Base and a non-equivocating BFT quorum. Section~\ref{sec:aggregation-audit} then shows how recursive proof aggregation removes the quorum from the correctness argument for the recorded history; equivocation between otherwise valid tips remains detectable from conflicting signed artifacts. \subsection{Aggregation Layer} +\label{sec:sharding-architecture} The Aggregation Layer implements a global, append-only key-value store that immutably records every spent token state. More specifically, it provides the following services: 1) recording of key-value tuples where the key identifies a token state and value is recording some meta-data, 2) returning inclusion proofs of keys, 3) returning non-inclusion proofs of keys not present in the store. @@ -186,23 +174,73 @@ \subsection{Aggregation Layer} \begin{figure*}[!t] \centering - \includegraphics[width=.7\textwidth]{pic/layers} - \caption{Sharded architecture of the Aggregation Layer.}\label{fig:sharding} + \begin{tikzpicture}[ + font=\small, + corebox/.style={rectangle, rounded corners=2pt, draw, + align=center, minimum width=14.8cm, minimum height=1.25cm}, + shardbox/.style={rectangle, rounded corners=2pt, draw, + align=center, minimum width=3.1cm, minimum height=1.65cm}, + certflow/.style={<->, >={Latex[length=2mm]}, thick} + ] + \node[corebox] (core) at (0,2.0) {\textbf{BFT Core}\\ + certifies shard-root transitions and commits $c_i=H(\mathcal{SH}_i)$ and + $R_i=\mathsf{MerkleRoot}\bigl(\{r_{i,\sigma}\}_{\sigma\in\mathcal{SH}_i}\bigr)$}; + + \node[shardbox] (s00) at (-5.4,-0.4) {\textbf{Aggregation shard}\\ + $\sigma=00$, keys $00\ldots$\\RSMT root $r_{i,00}$}; + \node[shardbox] (s01) at (-1.8,-0.4) {\textbf{Aggregation shard}\\ + $\sigma=01$, keys $01\ldots$\\RSMT root $r_{i,01}$}; + \node[shardbox] (s10) at (1.8,-0.4) {\textbf{Aggregation shard}\\ + $\sigma=10$, keys $10\ldots$\\RSMT root $r_{i,10}$}; + \node[shardbox] (s11) at (5.4,-0.4) {\textbf{Aggregation shard}\\ + $\sigma=11$, keys $11\ldots$\\RSMT root $r_{i,11}$}; + + \draw[certflow] (s00.north) -- (s00.north |- core.south); + \draw[certflow] (s01.north) -- (s01.north |- core.south); + \draw[certflow] (s10.north) -- (s10.north |- core.south); + \draw[certflow] (s11.north) -- (s11.north |- core.south); + + \node[font=\scriptsize, align=center, fill=white, inner sep=1.5pt] + at (0,0.82) {root transition + consistency proof $\uparrow$\qquad + Unicity Certificate $\downarrow$}; + \end{tikzpicture} + \caption{Aggregation shards beneath one logical BFT Core. The four equal prefixes are illustrative.}\label{fig:sharding} \end{figure*} -The Aggregation layer is sharded based on keyspace slices and can be made hierarchical, as shown in Figure~\ref{fig:sharding}. +\paragraph{Deterministic keyspace partition.} +Let keys be $\kappa$-bit strings and let the sharding scheme $\mathcal{SH}\subseteq\{0,1\}^{*}$ be prefix-free and exhaustive: no shard identifier is a prefix of another, and every $\kappa$-bit key has a prefix in $\mathcal{SH}$. It induces the total routing function +\[ + f_{\mathcal{SH}}(k)=\text{the unique }\sigma\in\mathcal{SH} + \text{ such that }\sigma\preceq k. +\] +(where $\preceq k$ denotes that bit-string $\sigma$ is a prefix of bit-string $k$). +Shard $\sigma$ maintains an independent RSMT $T_\sigma$ containing exactly the bindings whose keys satisfy $f_{\mathcal{SH}}(k)=\sigma$. Routing therefore depends only on public key bits: it needs neither a directory lookup nor cross-shard execution, and two requests addressed to different prefixes can be batched, inserted, and proved concurrently. -\emph{Consistency proof}: Once a key is set, it has to remain there forever. Every state change of the Aggregation Layer (or a slice thereof) is accompanied by a cryptographic proof establishing that pre-existing keys have not been removed or their values altered, and that new keys were added at the positions determined by the keys themselves. (In earlier documents this artifact is also called a \emph{non-deletion proof}; we use \emph{consistency proof} throughout.) The size of this proof is logarithmic with respect to the tree's capacity and linear with respect to the size of the inclusion batch. This can be reduced to a constant size using a SNARK. Assuming correct validation of the consistency proof and chaining of the Aggregation Layer's state roots by the Consensus Layer, the Aggregation Layer can be considered trustless. +\paragraph{Authentication across shards.} +In each BFT Core round, the latest root of every shard is a leaf of a Merkle \emph{shard-root tree}; a shard that does not advance retains its previous root. The tree root $R_i$ commits to the entire Aggregation Layer state, while $c_i=H(\mathcal{SH}_i)$ binds its active prefix partition. A Unicity Certificate for shard $\sigma$ authenticates $c_i$, authenticates $r_{i,\sigma}$ to $R_i$ with the sibling hashes on the prefix path, and authenticates $R_i$ with the BFT Core's quorum certificate. Consequently, an inclusion or non-inclusion proof has two independent parts: a local RSMT path within $T_\sigma$, and a short shard-root path to $R_i$. Neither part grows with transaction throughput; the latter contains $|\sigma|$ sibling hashes. + +\paragraph{Dynamic shard splitting.} +A busy shard can be split by replacing one prefix $\sigma$ in $\mathcal{SH}$ with the two children $\sigma\|0$ and $\sigma\|1$. The children retain the parent leaves selected by the next key bit. Because RSMT leaves commit to full keys and internal nodes commit to absolute bifurcation depths and key regions (Section~\ref{sec:stack-verifier}), each child root is either the hash of an existing parent subtree or the canonical empty root; retained nodes need not be rehashed and the certified history need not be replayed. The split is activated as a configuration change, after which both children evolve and prove independently. A local RSMT certificate may lose the junction at the split depth while its shard-root certificate gains one sibling hash, moving authentication work from the shard-local tree to the common root without introducing another aggregation tier. + +\paragraph{Horizontal capacity and proof aggregation.} +If shard $\sigma$ sustains insertion rate $q_\sigma$, the Aggregation Layer sustains +\[ + Q=\sum_{\sigma\in\mathcal{SH}} q_\sigma +\] +subject to the BFT Core's capacity for shard summaries. A shard round containing thousands of insertions exports only $(r_{i-1,\sigma},r_{i,\sigma},\pi_{i,\sigma})$, where the succinct consistency proof $\pi_{i,\sigma}$ has verifier cost independent of the number of stored leaves and is verified independently of other shards. Thus, adding a shard adds storage, batching, and proving capacity without increasing any existing shard's workload; the Core's work grows with the number of advancing shards, not with $Q$. These verifications are mutually independent and can be parallelized. The off-critical-path construction of Section~\ref{sec:aggregation-audit} subsequently folds all changed-shard proofs and the corresponding $R_i$ transitions into one recursively updated proof whose public statement remains fixed-size regardless of the number of shards or elapsed rounds. + +\paragraph{Per-shard consistency.} +Once a key is set, it must remain there permanently. Every shard transition is therefore accompanied by a cryptographic proof that pre-existing keys were neither removed nor modified and that new keys were placed at the positions determined by the keys themselves. The direct hash-based witness grows with the insertion batch, whereas the STARK construction of Section~\ref{sec:custom-air-circuit} makes the public statement just the old and new shard roots and gives succinct verification independent of the batch size. Correct verification and BFT chaining of those roots make each shard an untrusted, cryptographically checked service. \subsection{Execution Layer} -The Execution Layer, also known as the Agent Layer, is responsible for executing transactions and other business logic, using the services of the Aggregation Layer and Unicity in general. +The Execution Layer is responsible for executing transactions and other business logic, using the services of the Aggregation Layer and Unicity in general. Its formal security model---including double-spending resistance, non-blocking, and service- and user-side privacy---is developed in~\cite{exemodel}. Programmable ownership predicates extend this model with off-chain smart-contract functionality~\cite{predicates}. \subsection{Data Flow} \label{sec:data-flow} -Figure~\ref{fig:dataflow} summarizes the flow of authenticated data through the system, from the shards to the auditing verifier. In each round $i$, every shard $\sigma$ submits a certification request carrying its previous root $r_{i-1,\sigma}$, its new root $r_{i,\sigma}$, and the consistency proof $\pi_{i,\sigma}$. The BFT Core verifies each proof, combines the shard roots into a global root $R_i$ (the root of a small, fixed-shape Merkle tree over the shard roots), reaches consensus, and returns Unicity Certificates to the shards. Since the BFT Core keeps no blockchain, the per-round artifacts---shard roots, consistency proofs, certificates, and Trust Base entries---are published to the public round archive (Section~\ref{sec:data-availability}). From the archive, an aggregation prover folds the history into a single constant-size proof $\Pi_n$ (Section~\ref{sec:aggregation-audit}), which any party can verify against the genesis configuration. +Figure~\ref{fig:dataflow} summarizes the flow of authenticated data through the system, from the shards to the auditing verifier. In BFT Core round $i$, each shard $\sigma$ that advances submits a certification request carrying its previous root $r_{i-1,\sigma}$, its new root $r_{i,\sigma}$, and the consistency proof $\pi_{i,\sigma}$; roots of non-advancing shards are carried forward. The BFT Core verifies the submitted proofs, combines the current shard roots into the global root $R_i$, reaches consensus, and returns Unicity Certificates to the advancing shards. Since the BFT Core keeps no blockchain, the per-round artifacts---shard roots, consistency proofs, certificates, and Trust Base entries---are published to the public round archive (Section~\ref{sec:data-availability}). From the archive, an aggregation prover folds the history into a single constant-size proof $\Pi_n$ (Section~\ref{sec:aggregation-audit}), which any party can verify against the genesis configuration. \begin{figure}[!htbp] \centering @@ -210,8 +248,8 @@ \subsection{Data Flow} dfbox/.style={rectangle, draw, align=center, minimum height=2.2em, minimum width=5.6cm}] \node[dfbox] (verifier) {Auditing user}; \node[dfbox, below=0.7cm of verifier] (prover) {Aggregation prover (permissionless)}; - \node[dfbox, below=0.7cm of prover] (arch) {Public round archive\\ {\scriptsize $\{(r_{i-1,\sigma}, r_{i,\sigma}, \pi_{i,\sigma})\}_\sigma$, $R_i$, certificates}}; - \node[dfbox, below=0.7cm of arch] (core) {BFT Core\\ {\scriptsize cumulative state, staking registry, Trust Base}}; + \node[dfbox, below=0.7cm of prover] (arch) {Public round archive\\ {\scriptsize shard transitions, $c_i$, $R_i$, certificates}}; + \node[dfbox, below=0.7cm of arch] (core) {BFT Core\\ {\scriptsize cumulative shard roots and Trust Base}}; \node[dfbox, below=1.1cm of core] (shards) {Aggregation shards $\sigma = 1, \ldots, m$}; \draw[arrow] ([xshift=-1.2cm]shards.north) -- node[left, font=\scriptsize] {$(r_{i-1,\sigma}, r_{i,\sigma}, \pi_{i,\sigma})$} ([xshift=-1.2cm]core.south); \draw[arrow] ([xshift=1.6cm]core.south) -- node[right, font=\scriptsize] {certificates} ([xshift=1.6cm]shards.north); @@ -321,7 +359,7 @@ \subsection{``Maximalist'' Security Assumptions} \subsection{Practical Security Assumptions} \label{sec:practical} -If we relax the model by assuming that a majority of BFT consensus nodes exhibit economically rational behavior and do not collude maliciously with the Aggregation Layer, the user can enjoy significantly more practical operational parameters. BFT layer forking (case 2 above) or certifying conflicting states (case 3 above) produces strong cryptographic evidence which is processed out of the critical path of serving users. +For immediate finality, we assume that a BFT quorum follows the protocol and does not collude maliciously with the Aggregation Layer. Under this standard consensus assumption, users obtain substantially better latency than the delayed full-history audit. BFT layer forking (case 2 above) or certification of conflicting states (case 3 above) produces strong cryptographic evidence that can be processed out of the critical path of serving users. In this scenario, a transaction is finalized, and an inclusion proof is returned within a few seconds, allowing the transaction to be independently verified—without consulting external data\footnote{Previously obtained Root of Trust is used to validate future transactions}—within the same timeframe. @@ -465,7 +503,7 @@ \subsection{The Region-Committing Tree and Its Verifier} \subsection{Formal Model} \label{sec:consistency-formal} -We fix the key length $\kappa = 256$, key space $\mathcal{K} = \{0,1\}^{\kappa}$, a value space $\mathcal{V} \subseteq \{0,1\}^{*}$, and a hash function $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$. For bit strings, $p \sqsubseteq q$ denotes that $p$ is a prefix of $q$, $q[j]$ is the $j$-th bit, and $q[0..d)$ is the first $d$ bits; $\langle\cdot\rangle$ are fixed-length injective encodings; $\varnothing$ is a distinguished constant outside $\{0,1\}^{\lambda}$. All statements below are unconditional reductions: each concludes either the stated property, or that two distinct strings with equal $H$-images (a \emph{collision}) are computable in time linear in the size of the objects at hand. We do not repeat this disjunction in every statement. +We fix the key length $\kappa = 256$, key space $\mathcal{K} = \{0,1\}^{\kappa}$, a value space $\mathcal{V} \subseteq \{0,1\}^{*}$, and a hash function $H \colon \{0,1\}^{*} \to \{0,1\}^{\lambda}$. For bit strings, $p \preceq q$ denotes that $p$ is a prefix of $q$, $q[j]$ is the $j$-th bit, and $q[0..d)$ is the first $d$ bits; $\langle\cdot\rangle$ are fixed-length injective encodings; $\varnothing$ is a distinguished constant outside $\{0,1\}^{\lambda}$. All statements below are unconditional reductions: each concludes either the stated property, or that two distinct strings with equal $H$-images (a \emph{collision}) are computable in time linear in the size of the objects at hand. We do not repeat this disjunction in every statement. \subsubsection{Tree commitments} @@ -478,7 +516,7 @@ \subsubsection{Tree commitments} \mathsf{dig}(\mathsf{Leaf}(k,v)) &= H(\texttt{0x00} \| k \| v),\\ \mathsf{dig}(\mathsf{Node}(d,p,l,r)) &= H(\texttt{0x01} \| \langle d\rangle \| \langle p\rangle \| \mathsf{dig}(l) \| \mathsf{dig}(r)), \end{align*} -and $\mathsf{dig}(\varepsilon) = \varnothing$. Region and depth: $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$ and $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$ and $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. A tree is \emph{valid} if every junction $\mathsf{Node}(d,p,l,r)$ in it satisfies: $l$ and $r$ are nonempty, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \sqsubseteq \mathsf{reg}(l)$, and $p\|1 \sqsubseteq \mathsf{reg}(r)$. The trees $\varepsilon$ and $\mathsf{Leaf}(k,v)$ are valid. +and $\mathsf{dig}(\varepsilon) = \varnothing$. Region and depth: $\mathsf{reg}(\mathsf{Leaf}(k,v)) = k$ and $\mathsf{reg}(\mathsf{Node}(d,p,\cdot,\cdot)) = p$; $\mathsf{dep}(\mathsf{Leaf}) = \kappa$ and $\mathsf{dep}(\mathsf{Node}(d,\ldots)) = d$. A tree is \emph{valid} if every junction $\mathsf{Node}(d,p,l,r)$ in it satisfies: $l$ and $r$ are nonempty, $\mathsf{dep}(l) > d$, $\mathsf{dep}(r) > d$, $p\|0 \preceq \mathsf{reg}(l)$, and $p\|1 \preceq \mathsf{reg}(r)$. The trees $\varepsilon$ and $\mathsf{Leaf}(k,v)$ are valid. \end{definition} The validity conditions are local: one condition per edge. The next three results separate their global consequences from the stronger persistence facts needed only for completeness. @@ -493,7 +531,7 @@ \subsubsection{Tree commitments} \end{enumerate} \end{lemma} \begin{proof} -(i) Validity gives $p\|\beta \sqsubseteq \mathsf{reg}(\text{child})$ at every edge, so by induction every node's region, and every leaf key, extends the region of each ancestor. Two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d,p,\cdot,\cdot)$, forcing both $p\|0 \sqsubseteq k$ and $p\|1 \sqsubseteq k$, which is impossible. +(i) Validity gives $p\|\beta \preceq \mathsf{reg}(\text{child})$ at every edge, so by induction every node's region, and every leaf key, extends the region of each ancestor. Two leaves with the same key $k$ would sit on opposite sides of their lowest common ancestor $\mathsf{Node}(d,p,\cdot,\cdot)$, forcing both $p\|0 \preceq k$ and $p\|1 \preceq k$, which is impossible. (ii) Every key below $\mathsf{Node}(d,p,l,r)$ extends $p$. Both children are nonempty, so some key below extends $p\|0$ and some extends $p\|1$. The common prefix therefore ends after exactly the $d$ bits of $p$. @@ -502,7 +540,7 @@ \subsubsection{Tree commitments} For a finite partial map $M$ and a bit string $q$, write \[ - M_q = \{\,k \mapsto v \in M \mid q \sqsubseteq k\,\} + M_q = \{\,k \mapsto v \in M \mid q \preceq k\,\} \] for the restriction of $M$ to the key-space cone below $q$. @@ -530,7 +568,7 @@ \subsubsection{Tree commitments} \begin{proof} First consider a subtree $U$ with region $\varrho$ in $\mathsf{Tree}(A)$. Lemma~\ref{lem:shape}(i) shows that every key below $U$ extends $\varrho$. Conversely, key-directed descent places every key of $A_\varrho$ below $U$. Hence $\mathsf{map}(U)=A_\varrho$. -(i) For the forward direction, the cone identity just proved and the two nonempty children supply keys extending $p\|0$ and $p\|1$. Conversely, suppose both restricted maps are nonempty and descend from the root of $\mathsf{Tree}(M)$. At a current junction with region $q$, the two selected key sets lie below it, so Lemma~\ref{lem:shape}(ii) gives $q \sqsubseteq p$. If $q \neq p$, all keys extending $p$ select the same child at depth $|q|$; recurse into that child. Depths increase, the two selected sets prevent termination at a leaf, and the descent therefore reaches the junction with region $p$. +(i) For the forward direction, the cone identity just proved and the two nonempty children supply keys extending $p\|0$ and $p\|1$. Conversely, suppose both restricted maps are nonempty and descend from the root of $\mathsf{Tree}(M)$. At a current junction with region $q$, the two selected key sets lie below it, so Lemma~\ref{lem:shape}(ii) gives $q \preceq p$. If $q \neq p$, all keys extending $p$ select the same child at depth $|q|$; recurse into that child. Depths increase, the two selected sets prevent termination at a leaf, and the descent therefore reaches the junction with region $p$. (ii) The condition in (i) is monotone under extension from $M$ to $M \uplus B$, and a junction's depth is the length of its region. @@ -620,7 +658,7 @@ \subsubsection{Authenticated queries} \[ q=H(\texttt{0x01}\|\langle d\rangle\|\langle p\rangle\|c^0\|c^1). \] - If $p\not\sqsubseteq k$, accept iff this is the final entry. If $p\sqsubseteq k$, require $p=k[0..d)$ and another entry, set $q=c^{k[d]}$, and continue. + If $p\not\preceq k$, accept iff this is the final entry. If $p\preceq k$, require $p=k[0..d)$ and another entry, set $q=c^{k[d]}$, and continue. \item At $E(k',v')$, accept iff this is the final entry, $q=H(\texttt{0x00}\|k'\|v')$, and $k'\neq k$. \end{enumerate} @@ -754,7 +792,7 @@ \subsection{Certified Update Security} (1)~Edges inside assigned subtrees are edges of $T$. (2)~The two edges below an $O$ graft: by the matching, the $O$ coincides with a junction of $T$ and its assigned children are the children of that junction in $T$; these are edges of $T$. (3)~An edge whose child is an $S$ graft: the parent is an $N$; the $S$ child is unadvised, so by confinement both old digests at the parent are non-$\varnothing$, and the parent appears in $P_0$ as an $\mathsf{ONode}$ with its derived region. The matching places this junction, and the $T$-subtree assigned to the $S$ hole below it, in $T$; this is an edge of $T$. -(4)~Every remaining edge has an advised child. Coherence gives $\delta > d$ and, with agreement, $p\|\beta \sqsubseteq \varrho$; by the advice claim, $(\delta, \varrho)$ is the true depth and region of the child's top node. Edges of $T$ satisfy the validity conditions because $T$ is valid; edges of kind (4) satisfy them directly. Hence $T'$ is valid. +(4)~Every remaining edge has an advised child. Coherence gives $\delta > d$ and, with agreement, $p\|\beta \preceq \varrho$; by the advice claim, $(\delta, \varrho)$ is the true depth and region of the child's top node. Edges of $T$ satisfy the validity conditions because $T$ is valid; edges of kind (4) satisfy them directly. Hence $T'$ is valid. \emph{Map.} The leaves of $T'$ are the leaves of assigned subtrees, the $O_L$ leaves, and the $L$ leaves. By clause (d) of the matching, the first two groups are exactly the leaves of $T$. The $L$ leaves carry exactly the elements of $B$. By Lemma~\ref{lem:shape}(i), all leaf keys of the valid $T'$ are distinct; hence the keys of $B$ are absent from $\mathsf{map}(T)$, and $\mathsf{map}(T') = \mathsf{map}(T) \uplus B$. \end{proof} @@ -995,32 +1033,33 @@ \subsection{Deployment} Operationally, the AIR-based consistency-proof producer is a drop-in component of the Unicity aggregator implementation. The proof's public statement is unchanged ($r_{i-1}, r_i$); only the proof bytes shipped from the Aggregation Layer to the Consensus Layer change. Speculative execution of the next round overlaps with the unicity-certificate wait of the current round, so the AIR's prover latency does not lengthen the user-visible round time. -The entire proving stack runs on a single CPU. Unlike L1 ZK-rollup proving pipelines, there is no GPU farm, no proving market, no proving service in the critical path of a round. A single Aggregator that sustains $10\,000$ insertions per second fits within the power budget of a laptop charger. The one place where heavier proving does occur---the recursive aggregation of the next section---runs off the critical path, at checkpoint cadence, and by an independently incentivized party. +The entire proving stack runs on a single CPU. Unlike L1 ZK-rollup proving pipelines, there is no GPU farm, no proving market, no proving service in the critical path of a round. A single Aggregator that sustains $10\,000$ insertions per second fits within the power budget of a laptop charger. The one place where heavier proving does occur---the recursive aggregation of the next section---runs off the critical path, at checkpoint cadence, and may be performed by any independent operator. \section{Proof Aggregation and Full-History Audit} \label{sec:aggregation-audit} -The per-round consistency proofs of Section~\ref{sec:custom-air-circuit} are verified by the BFT Core before certification; a user who relies on a Unicity Certificate therefore relies on a quorum of the committee having performed that verification honestly. This section removes that remaining reliance. All per-round proofs, from all shards, over the entire operating history of the system, are folded into a single fixed-size STARK. Verifying this one proof establishes---under cryptographic assumptions alone---that every certified state transition since genesis was consistent, reducing the role of the stake-weighted committee from ``trusted to compute correctly'' to ``accountable for not equivocating''. +The per-round consistency proofs of Section~\ref{sec:custom-air-circuit} are verified by the BFT Core before certification; a user who relies on a Unicity Certificate therefore relies on a quorum of the committee having performed that verification honestly. This section removes that remaining reliance. All per-round proofs, from all shards, over the entire operating history of the system, are folded into a single fixed-size STARK. Verifying this one proof establishes---under cryptographic assumptions alone---that every certified state transition since genesis was consistent, reducing the BFT committee's residual role from ``trusted to compute correctly'' to ``accountable for not equivocating''. \subsection{The Aggregate Statement} \label{sec:aggregate-statement} -Fix a network instance identifier $\alpha$ and its genesis configuration digest $g$, which commits to the initial (empty) shard roots and the genesis Trust Base entry. For round $i$, let $R_i$ denote the global root: the root of the small, fixed-shape Merkle tree over the shard roots $(r_{i,1}, \ldots, r_{i,m})$ that the BFT Core maintains as its cumulative state (Section~\ref{sec:data-flow}). Let $D_i$ be an append-only commitment---a Merkle Mountain Range~\cite{mmr} (MMR)---to the sequence of certified global roots $\big((1, R_1), \ldots, (i, R_i)\big)$. The MMR supports two operations relevant here: appending an element (recomputable in-circuit from $D_{i-1}$ and a logarithmic-size witness) and proving membership of any $(j, R_j)$ against $D_i$ with a logarithmic-size path. +Fix a network instance identifier $\alpha$ and its genesis configuration digest $g$, which commits to the initial sharding scheme $\mathcal{SH}_0$, its empty shard roots, and the genesis Trust Base entry. In round $i$, let $\mathcal{SH}_i$ be the active prefix scheme, let $c_i=H(\mathcal{SH}_i)$ be its canonical commitment, and let $R_i$ be the root of the prefix-shaped shard-root tree over $\{r_{i,\sigma}\}_{\sigma\in\mathcal{SH}_i}$ (Section~\ref{sec:sharding-architecture}). Let $D_i$ be an append-only commitment---a Merkle Mountain Range~\cite{mmr} (MMR)---to the certified sequence $\big((1,c_1,R_1),\ldots,(i,c_i,R_i)\big)$. The MMR supports appending an element (recomputable in-circuit from $D_{i-1}$ and a logarithmic-size witness) and proving membership of any $(j,c_j,R_j)$ against $D_i$ with a logarithmic-size path. \begin{definition}[Round correctness] \label{def:roundok} $\mathsf{RoundOK}(i)$ holds iff \begin{enumerate}[nosep] - \item for every shard $\sigma$: either $r_{i,\sigma} = r_{i-1,\sigma}$ (no change in this round), or the consistency proof $\pi_{i,\sigma}$ verifies for the transition $(r_{i-1,\sigma}, r_{i,\sigma})$ per Algorithm~\ref{alg:stackverify} (in its STARK-compressed form); - \item $R_i$ is the Merkle root of $(r_{i,1}, \ldots, r_{i,m})$; and - \item $D_i$ extends $D_{i-1}$ by exactly the element $(i, R_i)$. + \item for every shard that persists from $\mathcal{SH}_{i-1}$ to $\mathcal{SH}_i$, either its root is unchanged or its consistency proof $\pi_{i,\sigma}$ verifies the transition $(r_{i-1,\sigma},r_{i,\sigma})$ per Algorithm~\ref{alg:stackverify} (in its STARK-compressed form); + \item if $\mathcal{SH}_i\ne\mathcal{SH}_{i-1}$, every change replaces a prefix $\sigma$ by $\sigma\|0$ and $\sigma\|1$, and an authenticated split witness proves that the two child seed roots select exactly the corresponding subtrees of $r_{i-1,\sigma}$; any same-round child updates are then covered by ordinary consistency proofs from those seed roots; + \item $c_i=H(\mathcal{SH}_i)$ and $R_i$ is the root of the shard-root tree determined by $\mathcal{SH}_i$ and its current shard roots; and + \item $D_i$ extends $D_{i-1}$ by exactly the element $(i,c_i,R_i)$. \end{enumerate} \end{definition} The aggregate statement $\mathcal{A}_n$ is then: \emph{starting from the genesis configuration $g$, there exists a sequence of rounds $1, \ldots, n$ such that $\mathsf{RoundOK}(i)$ holds for every $i$}. Its public values are -\[ \mathsf{pv}_n = (\alpha,\, g,\, n,\, R_n,\, D_n). \] -Everything else---shard roots, per-round proofs, MMR witnesses---is private witness data, so the proof and its statement have constant size regardless of $n$ and of the number of shards. +\[ \mathsf{pv}_n = (\alpha,\, g,\, n,\, c_n,\, R_n,\, D_n). \] +Everything else---the intermediate sharding schemes and shard roots, per-round consistency and split proofs, and MMR witnesses---is private witness data, so the proof and its statement have constant size regardless of $n$ and of the number of shards. Note that validator signatures are absent from the statement. The aggregate proof does not verify the committee's quorum signatures, because the truth of $\mathcal{A}_n$ does not depend on \emph{who} certified the transitions; consistency is a property of the data itself. The link to the certified reality is made by the verifier, outside the proof, by checking that the roots it cares about coincide with Unicity Certificates validated against the Trust Base (Section~\ref{sec:maxi-validation}). Folding signature verification into the circuit is possible but adds cost without adding security: it still could not prevent a quorum from signing two divergent histories, which remains the only residual attack (Section~\ref{sec:residual-trust}). @@ -1041,7 +1080,8 @@ \subsection{Instantiation on the SP1 zkVM} \begin{enumerate}[nosep] \item reads $\mathsf{pv}_{i-1}$ and verifies the previous aggregate proof against the aggregation program's own verifying-key digest, which is itself bound into the public values; the top-level verifier checks this digest once, against the value it knows from the software distribution, closing the recursion; \item for each round in the span and each shard with a changed root, verifies the shard's Plonky3 consistency STARK by running the STARK verifier as guest code. The shard proofs destined for aggregation use the SHA-256 FRI configuration (Table~\ref{tab:perf-frihash}) precisely so that this step is cheap: the verifier's work is dominated by FRI Merkle-path hashing, which maps directly onto the zkVM's SHA-256 precompile; - \item recomputes each round's global root $R_i$ from the shard roots, appends $(i, R_i)$ to the MMR, and commits $\mathsf{pv}_i$ as the new public values. + \item when the sharding-scheme commitment changes, verifies the split witnesses that bind each child seed root to the last certified parent root; + \item recomputes each round's scheme commitment $c_i$ and global root $R_i$, appends $(i,c_i,R_i)$ to the MMR, and commits $\mathsf{pv}_i$ as the new public values. \end{enumerate} The native verification cost of one shard proof is $\sim$18\,ms (Table~\ref{tab:perf-frihash}); executed in the zkVM, with precompile acceleration, this translates to on the order of $10^7$--$10^8$ RISC-V cycles, i.e., seconds of proving time per shard-round on server-class hardware. This is orders of magnitude more expensive than the shard's own proving, which is exactly why aggregation is kept off the critical path: it runs behind the certified tip at checkpoint cadence and never delays a round. @@ -1051,11 +1091,9 @@ \subsection{Instantiation on the SP1 zkVM} \subsection{The Aggregation Prover} \label{sec:aggregation-prover} -Producing $\Pi_n$ is a pure computation over public data (Section~\ref{sec:data-availability}): the statement is deterministic, requires no private inputs and no authorization, and its output is universally verifiable. The role is therefore permissionless by construction; the design question is only who is incentivized to actually perform it. - -The incentive is a protocol bounty. The staking registry (part of the certified cumulative state) records the most recent accepted checkpoint $(n, \mathsf{pv}_n)$; a prover submits a candidate checkpoint $(\Pi_{n'}, \mathsf{pv}_{n'})$ with $n' > n$ to the BFT Core, which accepts it iff the proof verifies and its public values chain from the recorded ones---a purely mechanical judgment. The first accepted checkpoint past each protocol-defined target round earns a reward from the same emission that funds validator rewards (Section~\ref{sec:dpos}). The prover's reward address is committed inside the proof's public values, so a submitted proof cannot be intercepted and claimed by another party. +Producing $\Pi_n$ is a pure computation over public data (Section~\ref{sec:data-availability}): the statement is deterministic, requires no private inputs and no authorization, and its output is universally verifiable. No particular operator has a privileged role in its production. -Among candidate operators, BFT Core validators are the natural incumbents: they already retain the round artifacts, already run staked infrastructure, and can amortize hardware across roles. But they hold no privileged position---an independent prover with a mirror of the round archive competes on equal terms, and the presence of independent provers is desirable, since an aggregate proof produced by a party outside the committee is the strongest form of the audit. If no prover claims the bounty, no safety property degrades; the audit latency grows until governance raises the bounty. Like the aggregator nodes themselves, the aggregation prover is a disposable component: its unavailability is a service degradation, never a safety failure. +Any operator with a mirror of the round archive can extend the latest checkpoint and publish $(\Pi_{n'},\mathsf{pv}_{n'})$ for $n'>n$. Acceptance is mechanical: the proof must verify, its public values must extend the recorded checkpoint, and the claimed final root must match the folded shard-root transitions. BFT Core validators are natural operators because they already retain the round artifacts, but they hold no privileged proving capability; an independent archive mirror produces the same proof. How deployments arrange the operation of this optional service is outside the protocol statement analyzed here. If no prover is available, immediate certificate-based operation is unaffected and only audit latency increases. \subsection{Data Availability} \label{sec:data-availability} @@ -1064,7 +1102,7 @@ \subsection{Data Availability} \emph{Serving plane.} The contents of each shard's tree---the recorded keys and values---are needed to serve inclusion and non-inclusion proofs to users. This state is replicated within the shard's own validator cluster (Section~\ref{sec:practical}); its loss is a liveness failure of that shard, not a safety failure of the system, since the certified roots and the append-only discipline persist independently. -\emph{Audit plane.} The per-round artifacts consumed by the aggregation prover: for each round $i$, the tuples $(r_{i-1,\sigma}, r_{i,\sigma}, \pi_{i,\sigma})$ for every changed shard, the global root $R_i$, the issued certificates, the Trust Base entries at epoch changes, and the accepted checkpoint proofs. All of these are public by design---the consistency proofs carry no user data (the insertion batches remain private witnesses of the \emph{shard} provers and are not needed for aggregation)---and are published to a content-addressed round archive replicated by the shards and the BFT Core validators, which anyone may mirror. At $\sim$1--2\,MB per shard per round, the archive grows at an entirely manageable rate. +\emph{Audit plane.} The per-round artifacts consumed by the aggregation prover: for each round $i$, the tuples $(r_{i-1,\sigma}, r_{i,\sigma}, \pi_{i,\sigma})$ for every changed shard, the active sharding scheme and any split witnesses, the global root $R_i$, the issued certificates, the Trust Base entries at configuration changes, and the accepted checkpoint proofs. All of these are public by design---the consistency proofs carry no user data (the insertion batches remain private witnesses of the \emph{shard} provers and are not needed for aggregation)---and are published to a content-addressed round archive replicated by the shards and the BFT Core validators, which anyone may mirror. At $\sim$1--2\,MB per changed shard per round, archive growth is proportional to the number of shard transitions rather than transaction volume. The aggregate proof gives the archive a bounded retention requirement: once a span of rounds has been folded into an accepted checkpoint (plus a safety margin for independent re-verification), its artifacts may be pruned, because $\Pi_n$ subsumes them. Symmetrically, the archive gives the prover role its permissionless character: a new prover bootstraps from the latest accepted checkpoint and the archive tail, with no handover, registration, or historical sync beyond the unpruned window. New provers can join permissionlessly. @@ -1078,11 +1116,11 @@ \subsection{Maximalist Validation Procedure} \emph{Per audit:} \begin{enumerate}[nosep] \item Obtain the latest checkpoint $(\Pi_n, \mathsf{pv}_n)$ from any source; the source need not be trusted. Verify the STARK $\Pi_n$ against the known verifying-key digest, and check $\mathsf{pv}_n.\alpha = \alpha$ and $\mathsf{pv}_n.g = g$. This takes milliseconds to seconds on commodity hardware. - \item For each certificate in the received token's history that references a round $j \leq n$ with global root $R_j$: verify the MMR membership of $(j, R_j)$ in $\mathsf{pv}_n.D_n$ (a logarithmic-size path, obtainable from the round archive). This confirms that the roots anchoring the token's inclusion proofs lie on the proven, non-forking history. + \item For each certificate in the received token's history that references a round $j \leq n$ with sharding-scheme commitment $c_j$ and global root $R_j$: verify the MMR membership of $(j,c_j,R_j)$ in $\mathsf{pv}_n.D_n$ (a logarithmic-size path, obtainable from the round archive). This confirms both that the key was routed under the authenticated scheme and that the root anchoring its inclusion proof lies on the proven, non-forking history. \item For certificates younger than the checkpoint ($j > n$): validate them against the Trust Base as in the practical model (Section~\ref{sec:practical}), and re-audit when the next checkpoint arrives. \end{enumerate} -If the user ever encounters two verifying checkpoints, or a verifying checkpoint and a quorum-signed certificate, that assign different global roots to the same round, this pair is publishable evidence of committee equivocation: it triggers slashing (Section~\ref{sec:dpos}) and the user rejects the affected token history. +If the user ever encounters two verifying checkpoints, or a verifying checkpoint and a quorum-signed certificate, that assign different global roots to the same round, this pair is publishable evidence of committee equivocation, and the user rejects the affected token history. \subsection{Residual Trust Analysis} \label{sec:residual-trust} @@ -1094,7 +1132,7 @@ \subsection{Residual Trust Analysis} \item the proven history is linear: each round extends its predecessor, and $D_n$ commits to the unique sequence of global roots. \end{enumerate} -The honest-majority-of-stake assumption on the BFT Core is thereby reduced out of the correctness argument. What remains for the crypto-economic layer are exactly two properties: \emph{liveness} (rounds continue to be certified, proofs continue to be aggregated) and \emph{uniqueness of the tip} (a quorum could sign two divergent continuations, each internally consistent and each separately provable). The latter cannot be excluded by any proof system, since it is a statement about signing behavior, not about computation; it is instead made detectable by any observer holding two conflicting artifacts, attributable to specific keys, and punishable by slashing. In summary: safety of the recorded history rests on cryptography; uniqueness rests on accountability; only liveness rests on economics. +The honest-quorum assumption on the BFT Core is thereby removed from the correctness argument for the proven history. Two consensus-level properties remain: \emph{liveness} (rounds continue to be certified and proofs remain available for aggregation) and \emph{uniqueness of the tip} (a quorum could sign two divergent continuations, each internally consistent and each separately provable). The latter cannot be excluded by any proof system, since it is a statement about signing behavior rather than computation; however, two conflicting artifacts make it detectable and attributable to specific signing keys. In summary, correctness of the recorded history rests on cryptography, whereas immediate progress and a unique live tip retain the standard BFT quorum assumptions. \section{Summary} @@ -1102,9 +1140,9 @@ \section{Summary} Different proof systems offer different trade-offs. The relevant properties are proving effort, necessity (and generality) of trusted setup, interactivity, recursion-friendliness, and the maturity and trustworthiness of available tooling. STARKs are comparatively fast to prove but have larger proofs, and avoid undesirable properties such as trusted setup. Groth16 SNARKs produce small proofs but require more proving effort and a circuit-specific trusted setup. For more complex applications, hybrid approaches and proof recursion can be employed. Figure~\ref{fig:comp} illustrates the proof size trade-off. -A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Remark~\ref{rem:placement}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the globally unique tree shape into one with a tight, hand-built AIR. The result is the measured proving throughput reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer in a trustless manner is economically feasible today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. +A second axis of optimization is the scope of the in-circuit statement itself. Drawing that scope correctly requires care: the seemingly sufficient structure-only statement admits a concrete cross-round equivocation attack (Remark~\ref{rem:placement}). The right kernel---\emph{append-only consistency}, i.e., prior-state preservation plus coherent placement of insertions, made locally checkable by the region-committing node hash---is proved sufficient in Theorem~\ref{thm:history}, while completeness and service properties remain self-policed by the protocol around the public root. This still turns a verification problem that naively would require reconstructing the globally unique tree shape into one with a tight, hand-built AIR. The result is the measured proving throughput reported in Section~\ref{sec:measured}: a single Aggregator on a single CPU sustainably exceeds $10\,000$ insertions per second with a 1.7\,MB transparent proof and tens of milliseconds verification time. This shows that operating a very large-scale Aggregation Layer with cryptographically verified updates is practical today, with no GPU farm or trusted setup, and on a power budget compatible with commodity hardware. -Above the per-round proofs sits the aggregation mechanism of Section~\ref{sec:aggregation-audit}: the consistency proofs of all shards and the Consensus Layer's own state transitions are folded, by recursion on a zkVM, into a single fixed-size transparent proof of the correctness of the system's entire operating history. The two validation paths complement each other. The pragmatic path, anchored in the Unicity Trust Base, delivers finality within seconds under an accountable honest-majority-of-stake assumption; the audit path, available with a delay of minutes to hours, retrospectively removes that assumption, leaving stake with only the roles of liveness and tip uniqueness. The consistency-proof mechanism now carries a formal correctness proof (Theorem~\ref{thm:history} and its corollaries): append-only consistency of the entire certified history reduces to the collision resistance of the underlying hash function. A machine-checked formalization of this proof is the natural next step. +Above the per-round proofs sits the aggregation mechanism of Section~\ref{sec:aggregation-audit}: the consistency proofs of all shards and the Consensus Layer's own state transitions are folded, by recursion on a zkVM, into a single fixed-size transparent proof of the correctness of the system's entire operating history. The two validation paths complement each other. The pragmatic path, anchored in the Unicity Trust Base, delivers finality within seconds under the standard BFT quorum assumption; the audit path, available with a delay of minutes to hours, retrospectively removes that assumption from the correctness of the recorded history. The consistency-proof mechanism now carries a formal correctness proof (Theorem~\ref{thm:history} and its corollaries): append-only consistency of the entire certified history reduces to the collision resistance of the underlying hash function. A machine-checked formalization of this proof is the natural next step. \begin{figure}[!htbp] \centering From 3ccc058a798e6302c76bed3c733b0d623899f6b9 Mon Sep 17 00:00:00 2001 From: ristik Date: Thu, 16 Jul 2026 11:05:56 +0300 Subject: [PATCH 6/6] cleanup --- README.md | 25 ++----------------------- aggregation-layer.tex | 2 +- pic/layers.png | Bin 109307 -> 0 bytes pic/smt-circuit-cell.drawio.png | Bin 17145 -> 0 bytes pic/smt-circuit.drawio.png | Bin 34617 -> 0 bytes 5 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 pic/layers.png delete mode 100644 pic/smt-circuit-cell.drawio.png delete mode 100644 pic/smt-circuit.drawio.png diff --git a/README.md b/README.md index 7150d4f..ce263d4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Technical report on the Aggregation Layer of the Unicity Network: the component that records spent token-state identifiers in a sharded Sparse Merkle Tree (SMT) and produces Unicity Proofs: inclusion and non-inclusion proofs. -The paper details the security model, identifies the properties needed for +The paper details the security model, identifies the properties needed for trustless operation (*prior-state preservation*), and reports the design and measured performance of a Plonky3 AIR implementation that proves it in Zero Knowledge. @@ -19,28 +19,7 @@ This paper is also referred to as the **Unicity Bluepaper**. ## Abstract -Unicity is a novel blockchain protocol with the ambitious goal of -enabling token transactions to occur off-chain and, when necessary, -offline. This premise requires supporting infrastructure to guarantee -that there are no parallel states of assets, or more specifically, that -there is no double-spending; a property we term the *unicity*. It turns -out that the lack of globally shared state and ordering reduces the -blockchain overhead considerably. In designing this infrastructure, no -compromises were made regarding its trust assumptions. This paper -details the design of the Aggregation Layer, the component responsible -for producing Proofs of Inclusion and Non-inclusion to the users. We -analyze its design for efficiency and evaluate the robustness of its -trust and security model. We then identify a single critical property -that the Consensus Layer must verify on each round—*prior-state -preservation*—and observe that the remaining desirable properties -of the trustless key-value store (canonical tree shape, batch -incorporation, no phantom inserts, completeness) are not required by -the Unicity Aggregator's security model. This optimal statement is -implemented as an Algebraic Intermediate Representation (AIR) circuit -on top of the Plonky3 STARK toolkit. The implementation sustains a -proving throughput in excess of 10 000 insertions per second on -a single consumer-class CPU, with a succinct proof and tens of -milliseconds verification time, and no trusted setup. +Unicity is a novel blockchain protocol with the ambitious goal of enabling peer-to-peer token transactions to occur off-chain, without shared ordering and execution overhead. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the *unicity*. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model, and design optimal data structures and algorithms for this setup. We then identify the critical property that the Consensus Layer must verify on each round---*append-only consistency*, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. The structural core of this statement is implemented as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3 STARK toolkit. The implementation sustains a proving throughput in excess of 10 000 insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. ## Unicity Paper Map diff --git a/aggregation-layer.tex b/aggregation-layer.tex index 9a8b6b5..f7f28d7 100644 --- a/aggregation-layer.tex +++ b/aggregation-layer.tex @@ -71,7 +71,7 @@ \maketitle \begin{abstract} -Unicity is a novel blockchain protocol with the ambitious goal of enabling token transactions to occur off-chain and, when necessary, offline. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. Request liveness, submitted-request accountability, and exclusion of unauthorized inserts remain properties of the service surrounding that cryptographic kernel. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. +Unicity is a novel blockchain protocol with the ambitious goal of enabling peer-to-peer token transactions to occur off-chain, without shared ordering and execution overhead. This premise requires supporting infrastructure to guarantee that there are no parallel states of assets, or more specifically, that there is no double-spending; a property we term the \textit{unicity}. It turns out that the lack of globally shared state and ordering reduces the blockchain overhead considerably. In designing this infrastructure, no compromises were made regarding its trust assumptions. This paper details the design of the Aggregation Layer, the component responsible for producing Proofs of Inclusion and Non-inclusion to the users. We analyze its design for efficiency and evaluate the robustness of its trust and security model, and design optimal data structures and algorithms for this setup. We then identify the critical property that the Consensus Layer must verify on each round---\emph{append-only consistency}, combining prior-state preservation with coherent placement of insertions---give it a formal definition, and prove that the RSMT consistency proof enforces it over the entire certified history, assuming only collision resistance of the hash function. The structural core of this statement is implemented~\cite{rsmtair} as Algebraic Intermediate Representation (AIR) circuit on top of the Plonky3~\cite{plonky3} STARK toolkit. The implementation sustains a proving throughput in excess of $10\,000$ insertions per second on a single consumer-class CPU, with a succinct proof and tens of milliseconds verification time, and no trusted setup. Finally, we describe how the per-round proofs of all shards, together with the Consensus Layer's state transitions, are folded into a single recursively aggregated STARK: a fixed-size certificate of the correctness of the system's entire operating history, verifiable against the genesis configuration alone, without trusting the validator set. \end{abstract} diff --git a/pic/layers.png b/pic/layers.png deleted file mode 100644 index 3bb7284168483b3a10996e58db81c3251653f8f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109307 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 z 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 bZdRClS-InD&t6&L?-MPo#+@58Z{z;~;jLO9 diff --git a/pic/smt-circuit-cell.drawio.png b/pic/smt-circuit-cell.drawio.png deleted file mode 100644 index dac8c2e3a6c7ff0457db77e9aa29b012da00d034..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17145 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 k=&jcNuUx+