8.9 KiB
\CommitIvk
Message decomposition
\SinsemillaShortCommit
is used in the
\CommitIvk
function.
The input to \SinsemillaShortCommit
is:
\ItoLEBSP{\BaseLength{Orchard}}(\AuthSignPublic) \bconcat \ItoLEBSP{\BaseLength{Orchard}}(\NullifierKey),
where \AuthSignPublic
, \NullifierKey
are Pallas base field elements, and \BaseLength{Orchard} = 255.
Sinsemilla operates on multiples of 10 bits, so we start by decomposing the message into chunks:
\begin{align}
\ItoLEBSP{\BaseLength{Orchard}}(\AuthSignPublic) &= a \bconcat b_0 \bconcat b_1 \\
&= (\text{bits 0..=249 of } \AuthSignPublic) \bconcat
(\text{bits 250..=253 of } \AuthSignPublic) \bconcat
(\text{bit 254 of } \AuthSignPublic) \\
\ItoLEBSP{\BaseLength{Orchard}}(\NullifierKey) &= b_2 \bconcat c \bconcat d_0 \bconcat d_1 \\
&= (\text{bits 0..=4 of } \NullifierKey) \bconcat
(\text{bits 5..=244 of } \NullifierKey) \bconcat
(\text{bits 245..=253 of } \NullifierKey) \bconcat
(\text{bit 254 of } \NullifierKey) \\
\end{align}
Then we recompose the chunks into message pieces:
\begin{array}{|c|l|}
\hline
\text{Length (bits)} & \text{Piece} \\\hline
250 & a \\
10 & b = b_0 \bconcat b_1 \bconcat b_2 \\
240 & c \\
10 & d = d_0 \bconcat d_1 \\\hline
\end{array}
Each message piece is constrained by \SinsemillaHash
to its stated length. Additionally,
\AuthSignPublic
and \NullifierKey
are witnessed as field elements, so we know they are
canonical. However, we need additional constraints to enforce that:
- The chunks are the correct bit lengths (or else they could overlap in the decompositions
and allow the prover to witness an arbitrary
\SinsemillaShortCommit
message). - The chunks contain the canonical decompositions of
\AuthSignPublic
and\NullifierKey
(or else the prover could witness an input to\SinsemillaShortCommit
that is equivalent to\AuthSignPublic
and\NullifierKey
but not identical).
Some of these constraints can be implemented with reusable circuit gadgets. We define a
custom gate controlled by the selector q_\CommitIvk
to hold the remaining constraints.
Bit length constraints
Chunks a
and c
are directly constrained by Sinsemilla. For the remaining chunks, we
use the following constraints:
\begin{array}{|c|l|}
\hline
\text{Degree} & \text{Constraint} \\\hline
& \ShortLookupRangeCheck{b_0, 4} \\\hline
& \ShortLookupRangeCheck{b_2, 5} \\\hline
& \ShortLookupRangeCheck{d_0, 9} \\\hline
3 & q_\CommitIvk \cdot \BoolCheck{b_1} = 0 \\\hline
3 & q_\CommitIvk \cdot \BoolCheck{d_1} = 0 \\\hline
\end{array}
where \BoolCheck{x} = x \cdot (1 - x)
and \ShortLookupRangeCheck{}
is a
short lookup range check.
Decomposition constraints
We have now derived or witnessed every subpiece, and range-constrained every subpiece:
a
(250
bits) is witnessed and constrained outside the gate;b_0
(4
bits) is witnessed and constrained outside the gate;b_1
(1
bits) is witnessed and boolean-constrained in the gate;b_2
(5
bits) is witnessed and constrained outside the gate;c
(240
bits) is witnessed and constrained outside the gate;d_0
(9
bits) is witnessed and constrained outside the gate;d_1
(1
bits) is witnessed and boolean-constrained in the gate.
We can now use them to reconstruct both the (chunked) message pieces, and the original field element inputs:
\begin{align}
b &= b_0 + 2^4 \cdot b_1 + 2^5 \cdot b_2 \\
d &= d_0 + 2^9 \cdot d_1 \\
\AuthSignPublic &= a + 2^{250} \cdot b_0 + 2^{254} \cdot b_1 \\
\NullifierKey &= b_2 + 2^5 \cdot c + 2^{245} \cdot d_0 + 2^{254} \cdot d_1 \\
\end{align}
\begin{array}{|c|l|}
\hline
\text{Degree} & \text{Constraint} \\\hline
2 & q_\CommitIvk \cdot (b - (b_0 + b_1 \cdot 2^4 + b_2 \cdot 2^5)) = 0 \\\hline
2 & q_\CommitIvk \cdot (d - (d_0 + d_1 \cdot 2^9)) = 0 \\\hline
2 & q_\CommitIvk \cdot (a + b_0 \cdot 2^{250} + b_1 \cdot 2^{254} - \AuthSignPublic) = 0 \\\hline
2 & q_\CommitIvk \cdot (b_2 + c \cdot 2^5 + d_0 \cdot 2^{245} + d_1 \cdot 2^{254} - \NullifierKey) = 0 \\\hline
\end{array}
Canonicity checks
At this point, we have constrained \ItoLEBSP{\BaseLength{Orchard}}(\AuthSignPublic)
and
\ItoLEBSP{\BaseLength{Orchard}}(\NullifierKey)
to be 255-bit values, with top bits b_1
and d_1
respectively. We have also constrained:
\begin{align}
\ItoLEBSP{\BaseLength{Orchard}}(\AuthSignPublic) &= \AuthSignPublic \pmod{q_\mathbb{P}} \\
\ItoLEBSP{\BaseLength{Orchard}}(\NullifierKey) &= \NullifierKey \pmod{q_\mathbb{P}} \\
\end{align}
where q_\mathbb{P}
is the Pallas base field modulus. The remaining constraints will
enforce that these are indeed canonically-encoded field elements, i.e.
\begin{align}
\ItoLEBSP{\BaseLength{Orchard}}(\AuthSignPublic) &< q_\mathbb{P} \\
\ItoLEBSP{\BaseLength{Orchard}}(\NullifierKey) &< q_\mathbb{P} \\
\end{align}
The Pallas base field modulus has the form q_\mathbb{P} = 2^{254} + t_\mathbb{P}
, where
t_\mathbb{P} = \mathtt{0x224698fc094cf91b992d30ed00000001}
is 126 bits. We therefore know that if the top bit is not set, then the remaining bits
will always comprise a canonical encoding of a field element. Thus the canonicity checks
below are enforced if and only if b_1 = 1
(for \AuthSignPublic
) or d_1 = 1
(for
\NullifierKey
).
In the constraints below we use a base-
2^{10}
variant of the method used in libsnark (originally from [SVPBABW2012, Appendix C.1]) for range constraints0 \leq x < t
:
- Let
t'
be the smallest power of2^{10}
greater thant
.- Enforce
0 \leq x < t'
.- Let
x' = x + t' - t
.- Enforce
0 \leq x' < t'
.
\AuthSignPublic
with b_1 = 1 \implies \AuthSignPublic \geq 2^{254}
In these cases, we check that \textsf{ak}_{0..=253} < t_\mathbb{P}
:
-
b_1 = 1 \implies b_0 = 0.
Since
b_1 = 1 \implies \AuthSignPublic_{0..=253} < t_\mathbb{P} < 2^{126},
we know that\AuthSignPublic_{126..=253} = 0,
and in particularb_0 := \AuthSignPublic_{250..=253} = 0.
-
b_1 = 1 \implies 0 \leq a < t_\mathbb{P}.
To check that
a < t_\mathbb{P}
, we use two constraints:a)
0 \leq a < 2^{130}
. This is expressed in the custom gate as$b_1 \cdot z_{a,13} = 0,
$ wherez_{a,13}
is the index-13 running sum output by\SinsemillaHash(a).
b)
0 \leq a + 2^{130} - t_\mathbb{P} < 2^{130}
. To check this, we decomposea' = a + 2^{130} - t_\mathbb{P}
into thirteen 10-bit words (little-endian) using a running sumz_{a'}
, looking up each word in a10
-bit lookup table. We then enforce in the custom gate that$b_1 \cdot z_{a',13} = 0.
$
\begin{array}{|c|l|}
\hline
\text{Degree} & \text{Constraint} \\\hline
3 & q_\CommitIvk \cdot b_1 \cdot b_0 = 0 \\\hline
3 & q_\CommitIvk \cdot b_1 \cdot z_{a,13} = 0 \\\hline
2 & q_\CommitIvk \cdot (a + 2^{130} - t_\mathbb{P} - a') = 0 \\\hline
3 & q_\CommitIvk \cdot b_1 \cdot z_{a',13} = 0 \\\hline
\end{array}
\NullifierKey
with d_1 = 1 \implies \NullifierKey \geq 2^{254}
In these cases, we check that \textsf{nk}_{0..=253} < t_\mathbb{P}
:
-
d_1 = 1 \implies d_0 = 0.
Since
d_1 = 1 \implies \NullifierKey_{0..=253} < t_\mathbb{P} < 2^{126},
we know that\NullifierKey_{126..=253} = 0,
and in particular$d_0 := \NullifierKey_{245..=253} = 0.
$ -
d_1 = 1 \implies 0 \leq b_2 + 2^5 \cdot c < t_\mathbb{P}.
To check that
0 \leq b_2 + 2^5 \cdot c < t_\mathbb{P}
, we use two constraints:a)
0 \leq b_2 + 2^5 \cdot c < 2^{140}
.b_2
is already constrained individually to be a5
-bit value.z_{c,13}
is the index-13 running sum output by\SinsemillaHash(c).
By constraining$d_1 \cdot z_{c,13} = 0,
$ we constrainb_2 + 2^5 \cdot c < 2^{135} < 2^{140}.
b)
0 \leq b_2 + 2^5 \cdot c + 2^{140} - t_\mathbb{P} < 2^{140}
. To check this, we decompose{b_2}c' = b_2 + 2^5 \cdot c + 2^{140} - t_\mathbb{P}
into fourteen 10-bit words (little-endian) using a running sumz_{{b_2}c'}
, looking up each word in a10
-bit lookup table. We then enforce in the custom gate that$d_1 \cdot z_{{b_2}c',14} = 0.
$
\begin{array}{|c|l|}
\hline
\text{Degree} & \text{Constraint} \\\hline
3 & q_\CommitIvk \cdot d_1 \cdot d_0 = 0 \\\hline
3 & q_\CommitIvk \cdot d_1 \cdot z_{c,13} = 0 \\\hline
2 & q_\CommitIvk \cdot (b_2 + c \cdot 2^5 + 2^{140} - t_\mathbb{P} - {b_2}c') = 0 \\\hline
3 & q_\CommitIvk \cdot d_1 \cdot z_{{b_2}c',14} = 0 \\\hline
\end{array}
Region layout
The constraints controlled by the q_\CommitIvk
selector are arranged across 9
advice columns, requiring two rows.
\begin{array}{|c|c|c|c|c|c|c|c|c|c}
& & & & & & & & & q_\CommitIvk \\\hline
\AuthSignPublic & a & b & b_0 & b_1 & b_2 & z_{a,13} & a' & z_{a',13} & 0 \\\hline
\NullifierKey & c & d & d_0 & d_1 & & z_{c,13} & {b_2}c' & z_{{b_2}c',14} & 1 \\\hline
\end{array}