Compare commits

...

7 Commits

Author SHA1 Message Date
Eli Ben-Sasson 252274b985 more comments 8 years ago
Eli Ben-Sasson e7208868a3 fix earlier git shit 8 years ago
Eli Ben-Sasson 554275c863 Revert "compilation fix", because it removed all my comments 8 years ago
eli.ben.sasson e8613232b0 compilation fix 8 years ago
eli.ben.sasson 91b2cda263 wip 8 years ago
Eli Ben-Sasson 9145b7e477 wip (work in progress) 8 years ago
Eli Ben-Sasson 05aa34cb4e wip, comments 8 years ago
  1. BIN
      protocol/protocol.pdf
  2. 183
      protocol/protocol.tex

BIN
protocol/protocol.pdf

Binary file not shown.

183
protocol/protocol.tex

@ -616,6 +616,19 @@
\newcommand{\pnote}[1]{\subparagraph{Note:}{#1}}
\newenvironment{pnotes}{\subparagraph{Notes:}\begin{itemize}}{\end{itemize}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Eli macros
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\eli}[2]{{\color{violet}{{\bf{#1}}}: {#2\xspace}}}
\newcommand{\typo}[1]{\eli{Typo/language improvement}{#1}}
\newcommand{\question}[1]{\eli{Question}{#1}}
\newcommand{\concern}[1]{\eli{Concern}{#1}}
\newcommand{\reorder}[1]{\eli{Suggested reordering}{#1}}
\newcommand{\improve}[1]{\eli{Suggested improvement}{#1}}
\newcommand{\general}[1]{\eli{General comment}{#1}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% end Eli macros
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
@ -631,12 +644,14 @@
\nsection{Introduction}
\general{Who is the intended reader of this document? Someone who wishes to build a node/miner/wallet?
In particular, what's the relation between this document and the existing code?}
\Zcash is an implementation of the \term{Decentralized Anonymous Payment}
scheme \Zerocash \cite{BCG+2014}, with some security fixes and adjustments
to terminology, functionality and performance. It bridges the existing
\emph{transparent} payment scheme used by \Bitcoin \cite{Naka2008} with a
\emph{protected} payment scheme protected by zero-knowledge succinct
\emph{protected} payment scheme protected \typo{repeated ``protected'', suggest leaving only second instance, and emphasizing it}
by zero-knowledge succinct
non-interactive arguments of knowledge (\zkSNARKs).
Changes from the original \Zerocash are explained in \crossref{differences},
@ -669,6 +684,11 @@ This specification is structured as follows:
\nsubsection{Caution}
\concern{Shouldn't this document, or even this section, also contain some legal boilerplate suggested by ZECC legal counsel?
This could prevent readers from claiming wrong-doing because of internal inconsistencies in the paper and/or inconsistencies
between this paper and the released code (DAO should serve as a reminder of the potential outcomes of such discrepancies).}
\Zcash security depends on consensus. Should a program interacting with the
\Zcash network diverge from consensus, its security will be weakened or destroyed.
The cause of the divergence doesn't matter: it could be a bug in your program,
@ -698,20 +718,29 @@ In \Zerocash \cite{BCG+2014}, \notes were called ``coins'', and \nullifiers
were called ``serial numbers''.},
which specify an amount and a \payingKey. The \payingKey is part of
a \paymentAddress, which is a destination to which \notes can be sent.
As in \Bitcoin, this is associated with a private key that can be used to
spend \notes sent to the address; in \Zcash this is called a \spendingKey.
As in \Bitcoin, this is associated with a private key
\typo{private key perhaps should be spending key here? This would
remove the need for last snippet in this paragraph}
that can be used to
spend \notes sent to the address; in \Zcash this
is called a \spendingKey.
To each \note there is cryptographically associated a \noteCommitment, and
a \nullifier\hairspace\cref{notesandnullifiers} (so that there is a 1:1:1 relation
between \notes, \noteCommitments, and \nullifiers). However, it is infeasible
to correlate a commitment with its \nullifier without knowledge of the \note.
\typo{this seems to imply knowledge of note (known to payer) suffices to correlate
the commitment and nullifier, which I think isn't the case.}
Computing the \nullifier requires the associated private \spendingKey. An
unspent valid \note, at a given point on the \blockchain, is one for which
the \noteCommitment has been publically revealed on the \blockchain prior to
that point, but the \nullifier has not.
\typo{Would be good to clarify that a note is never intended to be fully
revealed on the blockchain. }
A \transaction can contain \transparent inputs, outputs, and scripts,
which all work as in \Bitcoin. They also contain a sequence of zero or
which all work as in \Bitcoin. They \typo{It (transaction) is singular in previous sentence}
also contain a sequence of zero or
more \joinSplitDescriptions. Each of these describes a \joinSplitTransfer\hairspace\footnote{
\joinSplitTransfers in \Zcash generalize ``Mint'' and ``Pour'' \transactions
in \Zerocash; see \crossref{trstructure} for the differences.}
@ -723,7 +752,10 @@ future). Each \joinSplitDescription also includes a computationally sound
\zkSNARK proof, which proves all of the following:
\begin{itemize}
\item The inputs and outputs balance (individually for each \joinSplitTransfer).
\item The inputs and outputs balance \typo{its not clear, here and later, than
inputs/outputs refer to amounts of the coin. In fact, the standard interpretation would be
that inputs include keys, commitments, etc. in which case ``balancing'' these sounds strange.}
(individually for each \joinSplitTransfer).
\item For each input \note of non-zero value, some revealed \noteCommitment
exists for that \note.
\item The prover knew the private \spendingKeys of the input \notes.
@ -733,13 +765,16 @@ future). Each \joinSplitDescription also includes a computationally sound
the \transaction cannot be modified by a party who did not know these
private keys.
\item Each output \note is generated in such a way that its \nullifier will
not collide with the \nullifier of any other \note.
not collide with the \nullifier of any other \note. \typo{Not exactly true, there's some miniscule
probability they may collide. This also shows the importance of adding legal boilerplate to
the beginning of the document, to protect ZECC from claims saying this document is misleading.}
\end{itemize}
Outside the \zkSNARK, it is also checked that the \nullifiers for the input
\notes had not already been revealed (i.e.\ they had not already been spent).
A \paymentAddress includes two public keys: a \payingKey matching that of \notes
\reorder{Next paragraph better appear earlier, perhaps even before first usage of address
in the context of ``note'' explanation.} A \paymentAddress includes two public keys: a \payingKey matching that of \notes
sent to the address, and a \transmissionKey for a key-private asymmetric encryption
scheme. ``Key-private'' means that ciphertexts do not reveal information about
which key they were encrypted to, except to a holder of the corresponding
@ -782,6 +817,9 @@ Initial arguments to a function or randomized algorithm may be
written as subscripts, e.g.\ if $x \typecolon X$, $y \typecolon Y$, and
$\PRF{}{} \typecolon X \times Y \rightarrow Z$, then an invocation of
$\PRF{}{}(x, y)$ can also be written $\PRF{x}{}(y)$.
\typo{First use of $\PRF{}{}$ should be opened/explained, but maybe should be done later on, replacing
this instance by a generic function symbol like $f$}
The notation $\typeexp{T}{\ell}$, where $T$ is a type and $\ell$ is an integer,
means the type of sequences of length $\ell$ with elements in $T$. For example,
@ -878,6 +916,8 @@ from it.
\includegraphics[scale=.7]{key_components}
\end{center}
\reorder{Not sure what the following paragraph is trying to say.
It seems to talk about how one implements stuff, but this section is a very high-level one so why put it here?}
The composition of \paymentAddresses\changed{, \viewingKeys,} and \spendingKeys
is a cryptographic protocol detail that should not normally be
exposed to users. However, user-visible operations should be provided
@ -906,8 +946,14 @@ hypothetical weakness in that cryptosystem.
\nsubsection{\Notes}
\improve{It seems we're going bottom-up, by describing notes, then joinsplit, then transaction (then block and blockchain?).
So would be good to tell readers of this structure.}
A \note (denoted $\NoteTuple{}$) is a tuple $\changed{(\AuthPublic, \Value,
\NoteAddressRand, \NoteCommitRand)}$. It represents that a value $\Value$ is
\NoteAddressRand, \NoteCommitRand)}$. \improve{Suggest having a special type of symbols
for inputs that should be uniformly random strings of bits, of which $\NoteAddressRand, \NoteCommitRand$
are examples. Then one could say somewhere that you should pick them uniformly, using a source with ``good (i.e., maximal) entropy''}
It represents that a value $\Value$ is
spendable by the recipient who holds the \spendingKey $\AuthPrivate$ corresponding
to $\AuthPublic$, as described in the previous section.
@ -940,6 +986,7 @@ where $\Commit{}$ is instantiated in \crossref{concretecomm}.
A \nullifier (denoted $\nf$) is derived from the $\NoteAddressRand$ component
of a \note and the recipient's \spendingKey, as $\PRFnf{\AuthPrivate}(\NoteAddressRand)$.
\eli{typo}{First (real) use of PFR is here, so should be referenced/opened/explained (as done for commitment in prior paragraph)}
A \note is spent by proving knowledge of $\NoteAddressRand$ and $\AuthPrivate$ in
zero knowledge while publically disclosing its \nullifier $\nf$, allowing $\nf$ to
be used to prevent double-spending.
@ -952,7 +999,7 @@ a \noteCommitment $\cm$.
The \notePlaintexts in a \joinSplitDescription are encrypted to the
respective \transmissionKeys $\TransmitPublicNew{\allNew}$,
and the result forms part of a \notesCiphertext (see \crossref{inband}
for further details).
for further details). \question{Can this cyphertext be left empty? it's not clear from the description above.}
Each \notePlaintext (denoted $\NotePlaintext{}$) consists of
$(\Value, \NoteAddressRand, \NoteCommitRand\changed{, \Memo})$.
@ -974,16 +1021,35 @@ which consists of a \noteCommitmentTree (\crossref{merkletree}), \nullifierSet
(\crossref{nullifierset}), and data structures associated with \Bitcoin such as
the UTXO (Unspent Transaction Output) set.
Inputs to a \transaction insert value into a \transparentValuePool, and outputs
remove value from this pool. As in \Bitcoin, the remaining value in the pool is
available to miners as a fee.
An \anchor is a Merkle tree root of a \noteCommitmentTree. It uniquely identifies
Inputs \question{How are inputs defined? In Bitcoin they have
a very clear meaning but I'm not sure we mean the same thing in Zcash}
to a \transaction insert value into a \transparentValuePool, and outputs
remove value from this pool.
\question{Must they insert?
How do the protected inputs insert value into the transparent pool? I think more details are needed (or a reference
to where its discussed)}
As in \Bitcoin, the remaining value in the pool is
available to miners as a fee. \reorder{This last paragraph should likely go elsewhere, it stops the
discussion of trees and feels out of place here.}
An \anchor is a Merkle tree root of a \noteCommitmentTree.
\question{In \crossref{joinsplitencoding} an anchor is defined as one of two possible things, needs clarification. See suggestion next.}
\improve{Given a sequence $S=(c_1,\ldots, c_n)$ of coin commitments, let $h(S)$ be its Merkle-tree based hash.
Given a transaction containing an ordered sequence $JS_1,\ldots, JS_m$ of JoinSplit descriptions,
an \anchor is defined inductively thus: the anchor of $JS_1$ must be $h(S_1)$ for some prefix $S_1$ of the block-chain
and for $i\in \{2,\ldots, m\}$ an \anchor is $h(S_i)$ where $S_i$ must be either some prefix of the block-chain,
or a sequence $S_{i'}\circ JS_{i'}$ for some $i'<i$ where $\circ$ denotes sequence-concatenation.}
It uniquely identifies
a \noteCommitmentTree state given the assumed security properties of the Merkle tree's
hash function. Since the \nullifierSet is always updated together with the
\noteCommitmentTree, this also identifies a particular state of the \nullifierSet.
In a given node's \blockchainview, \treestates are chained as follows:
In a given node's \blockchainview, \treestates are chained \question{What does chained mean?
I think you want to say ``defined inductively'' instead. }
\improve{Since there is a unique mapping from a sequence (of blocks/transactions) to a hash,
I think it would simplify things to explain once this mapping, later talk about $HASH(sequence)$,
this can simplify, e.g., the interstitial JS reference.}
as follows:
\begin{itemize}
\item The input \treestate of the first \block is the empty \treestate.
@ -1009,13 +1075,16 @@ i.e.\ a \xprotected value transfer. This kind of value transfer is the primary
\Zcash-specific operation performed by \transactions; it uses, but should not be
confused with, the \joinSplitStatement used for the \zkSNARK proof and verification.
A \joinSplitTransfer spends $\NOld$ \notes $\nOld{\allOld}$ and \transparent input
$\vpubOld$, and creates $\NNew$ \notes $\nNew{\allNew}$ and \transparent output
$\vpubNew$.
A \joinSplitTransfer spends $\NOld$ \notes $\nOld{\allOld}$ and a single
\transparent input
$\vpubOld$ (which may equal $0$), and creates $\NNew$ \notes $\nNew{\allNew}$ and a single
\transparent output
$\vpubNew$ (which may equal $0$).
Each \transaction is associated with a \sequenceOfJoinSplitDescriptions.
The inputs and outputs of each \joinSplitTransfer{} \MUST balance exactly.
The inputs and outputs \typo{input/output undefined, not clear what is meant
by saying they must be balanced} of each \joinSplitTransfer{} \MUST balance exactly.
The \changed{total $\vpubNew$ value adds to, and the total} $\vpubOld$
value subtracts from the \transparentValuePool of the containing \transaction.
@ -1047,6 +1116,7 @@ Blocks in the \blockchain are associated (by all nodes) with the \merkleRoot of
after all of its constituent \joinSplitDescriptions' \noteCommitments have been
entered into the \noteCommitmentTree associated with the previous \block.
\todo{Make this more precise.}
\improve{Using the deterministic mapping from a sequence to a hash value can help simplify exposition here.}
Each \merkleNode in the \incrementalMerkleTree is associated with a \merkleHash of
size $\MerkleHashLength$ bytes.
@ -1069,7 +1139,10 @@ it would otherwise result in a double-spend.
\nsubsection{Block Subsidy and Founders' Reward} \label{subsidyconcepts}
Like \Bitcoin, \Zcash creates currency when \blocks are mined. The value created on
Like \Bitcoin, \Zcash creates currency when \blocks are mined.
\typo{At some point in time this
subsidy ends, right? the sentence above implies subsidy continues indefinitely}
The value created on
mining a \block is called the \blockSubsidy. It is composed of a \minerSubsidy and a
\foundersReward. As in \Bitcoin, the miner of a \block also receives \transactionFees.
@ -1087,6 +1160,8 @@ The first \transaction in a block must be a \coinbaseTransaction, which should
collect and spend any \minerSubsidy and \transactionFees paid by \transactions
included in this \block. The \coinbaseTransaction must also pay the \foundersReward
as described in \crossref{coinbases}.
\question{what's a coinbase transaction? The term hasn't been defined
before, not clear if its defined later as well.}
\nsection{Abstract Protocol}
@ -1158,7 +1233,7 @@ for a given key. The security notions INT-CTXT and IND-CPA are as defined in
\nsubsubsection{\KeyAgreement} \label{abstractkeyagreement}
A \keyAgreementScheme is a cryptographic protocol in which two parties agree
A \keyAgreementScheme is a cryptographic protocol in which two parties agree on
a shared secret, each using their private key and the other party's public key.
A \keyAgreementScheme $\KA$ defines a type of public keys $\KAPublic$, a type
@ -1314,7 +1389,8 @@ A \zeroKnowledgeProvingSystem is a cryptographic protocol that allows
proving a particular \statement, dependent on \primary and \auxiliaryInputs,
in zero knowledge --- that is, without revealing information about the
\auxiliaryInputs other than that implied by the \statement. The type of
\zeroKnowledgeProvingSystem needed by \Zcash is a \ppzkSNARK.
\zeroKnowledgeProvingSystem needed \typo{not sure needed is the right word, rather used is better.
One could conceivably use other types of ZK proofs as well.} by \Zcash is a \ppzkSNARK.
A \ppzkSNARK instance $\ZK$ defines:
@ -1331,7 +1407,10 @@ the \statement;
\item a verifying algorithm $\ZKVerify{} \typecolon \ZKVerifyingKey \times \ZKPrimary \times \ZKProof \rightarrow \bit$;
\end{itemize}
The security requirements below are supposed to hold with overwhelming
The security requirements \typo{Suggest calling them security assumptions. Because
these requirements are likely formally false (as all instantiated concrete protocols are)
but its OK to say we assume these properties (even if they cannot formally hold)}
below are supposed to hold with overwhelming
probability for $(\pk, \vk) \leftarrow \ZKGen()$.
\begin{securityrequirements}
@ -1416,11 +1495,15 @@ where
a key agreement public key, used to derive the key for encryption
of the \notesCiphertext (\crossref{inband})};
\item \changed{$\RandomSeed \typecolon \RandomSeedType$ is
a seed that must be chosen independently at random for each
a seed that must
\typo{its not clear how to enforce
this, so perhaps must $\to$ should}
be chosen independently at random for each
\joinSplitDescription};
\item $\h{\allOld} \typecolon \typeexp{\PRFOutput}{\NOld}$ is
a sequence of tags that bind $\hSig$ to each
$\AuthPrivate$ of the input \notes;
\question{what's a tag?}
\item $\JoinSplitProof \typecolon \ZKJoinSplitProof$ is
the \zeroKnowledgeProof for the \joinSplitStatement;
\item $\TransmitCiphertext{\allNew} \typecolon \typeexp{\Ciphertext}{\NNew}$ is
@ -1429,6 +1512,10 @@ where
The $\ephemeralKey$ and $\encCiphertexts$ fields together form the \notesCiphertext.
\improve{The discussion of non-malleability is very confusing,
it's very hard to decypher how the various signatures and are
composed, what are their inputs, and what part of the whole transaction they cover}
The value $\hSig$ is also computed from $\RandomSeed$, $\nfOld{\allOld}$, and the
$\joinSplitPubKey$ of the containing \transaction:
@ -1512,6 +1599,7 @@ sent to a random \paymentAddress.
The depth of the \noteCommitmentTree is $\MerkleDepth$ (defined in \crossref{constants}).
\typo{Following paragraph appears, nearly verbatim, earlier on}
Each \merkleNode in the \incrementalMerkleTree is associated with a \merkleHash,
which is a byte sequence. The \merkleLayer numbered $h$, counting from
\merkleLayer $0$ at the \merkleRoot, has $2^h$ \merkleNodes with \merkleIndices
@ -1548,6 +1636,17 @@ Given such a \merklePath, it is possible to verify that \merkleLeafNode
$\MerkleNode{\MerkleDepth}{i}$ is in a tree with a given \merkleRoot $\rt = \MerkleNode{0}{0}$.
\nsubsection{Non-malleability} \label{nonmalleability}
\improve{This section was one of the hardest to read.
What makes it hard is that it's not clear at this point
what data is contained in a full transaction, and how
the various signatures are applied to parts of it. Concretely, how
about explaining somewhere (earlier) the full content of a transaction
(as done in great detail later on). Another suggestion is
to describe the attack which this non-malleability prevents:
that a payer outpus in the first JS a transparent value that it wishes
to consume (and hide) in the second JS, but the miner
will mall the second JS and replace it with something that goes
to the malling miner.}
\Bitcoin defines several \sighashTypes that cover various parts of a transaction.
\changed{In \Zcash, all of these \sighashTypes are extended to cover the \Zcash-specific
@ -1592,7 +1691,9 @@ A \joinSplitTransfer can be seen, from the perspective of the \transaction, as
an input \changed{and an output simultaneously}.
\changed{$\vpubOld$ takes value from the \transparentValuePool and}
$\vpubNew$ adds value to the \transparentValuePool. As a result, \changed{$\vpubOld$ is
treated like an \emph{output} value, whereas} $\vpubNew$ is treated like an
treated \question{What's this treatment? what does it mean
that it's treated like an output? (recall output is an undefined term thus
far).} like an \emph{output} value, whereas} $\vpubNew$ is treated like an
\emph{input} value.
\changed{
@ -1601,7 +1702,7 @@ Unlike original \Zerocash \cite{BCG+2014}, \Zcash does not have
a distinction between Mint and Pour operations. The addition of $\vpubOld$ to a
\joinSplitDescription subsumes the functionality of both Mint and Pour. Also,
\joinSplitDescriptions are indistinguishable regardless of the number of real input
\notes.
\notes. \question{what's a real input? what's an input?}
}
As stated in \crossref{joinsplitdesc}, either $\vpubOld$ or $\vpubNew$ \MUST be zero.
@ -1617,14 +1718,18 @@ according to client implementation.
A \transaction that contains one or more \joinSplitDescriptions, when entered into the
blockchain, appends to the \noteCommitmentTree with all constituent
\noteCommitments. All of the constituent \nullifiers are also entered into the
\nullifierSet of the \blockchainview \emph{and} \mempool. A \transaction is not
\nullifierSet of the \blockchainview \emph{and} \mempool.
\question{what's \mempool? hasn't been defined anywhere yet}
A \transaction is not
valid if it attempts to add a \nullifier to the \nullifierSet that already
exists in the set.
\nsubsection{\JoinSplitStatement} \label{jsstatement}
A valid instance of $\JoinSplitProof$ assures that given a \term{primary input}:
\typo{The constant $2^{64}-1$ (appears 3 times below)
should likely be replaced by $MAX_MONEY$
as appearing elsewhere}
\begin{itemize}
\item[] $(\rt \typecolon \MerkleHash,
\nfOld{\allOld} \typecolon \typeexp{\PRFOutput}{\NOld},
@ -1708,6 +1813,8 @@ For details of the form and encoding of proofs, see \crossref{proofs}.
\nsubsection{In-band secret distribution} \label{inband}
\question{It's not clear if the protocol dictates that users
\emph{must} transmit secrets this way (and I think it should be optional).}
In order to transmit the secret $\Value$, $\NoteAddressRand$, and $\NoteCommitRand$
(necessary for the recipient to later spend) \changed{and also a \memo} to the
recipient \emph{without} requiring an out-of-band communication channel, the
@ -1889,6 +1996,8 @@ Define:
\begin{itemize}
\item[] $\MerkleDepth \typecolon \Nat := \changed{29}$
\question{What about the maximal number of JS in a tx?
and the max number of coins (new and old) per JS?}
\item[] $\NOld \typecolon \Nat := 2$
\item[] $\NNew \typecolon \Nat := 2$
\item[] $\MerkleHashLength \typecolon \Nat := 256$
@ -1932,6 +2041,9 @@ sequences.
}
\securityrequirement{
\typo{It sounds strange to require something that is formally
false ($\SHA$ is a fixed function so cannot be
formally collision resistant). How about requirement $\to$ assumption?}
$\SHA$ must be collision-resistant, and it must be infeasible to find a preimage $x$
such that $\SHA(x) = \zeros{256}$.
}
@ -2982,13 +3094,20 @@ $\MaxBlockSubsidy$, and $\FoundersFraction$ are instantiated in \crossref{consta
\todo{Any tx with a coinbase input must have no \transparent outputs (vout).}
The \foundersReward is paid by a \transparent output in the \coinbaseTransaction, to
one of $\NumFounderAddresses$ \transparent addresses, depending on the \blockHeight.
one
\typo{any one? presumably there will be some deterministic schedule according to which payments are rotated?}
of $\NumFounderAddresses$ \transparent addresses, depending on the \blockHeight.
\question{what about miner subsidy? How is it paid?}
\concern{This is one section that the legal team should look at. What happens if things change
in the code, what's the correct version --- this paper or the code (recall DAO)?}
Let $\SlowStartShift$ be defined as in the previous section.
\renewcommand{\arraystretch}{0.95}
For mainnet, $\FounderAddressList_{\mathrm{1}..\NumFounderAddresses}$ is \todo{}.
\question{This description refers to a static list that is not updated with time.
How will changes in ownership among stakeholders going to be reflected in this process?}
For testnet, $\FounderAddressList_{\mathrm{1}..\NumFounderAddresses}$ is:
@ -3032,7 +3151,9 @@ transaction type of the cryptocurrency on which it is based
In \Zcash, there is only the original \Bitcoin transaction type,
which is extended to contain a sequence of zero or more
\Zcash-specific operations.
\Zcash-specific operations. \typo{In many places (like the paragraph above) it would be
better to talk about \emph{Basecoin} instead of \Bitcoin because the latter refers also to a particular
payment system that is currently separated from \Zcash.}
This allows for the possibility of chaining transfers of \xprotected
value in a single \Zcash \transaction, e.g.\ to spend a \protectedNote

Loading…
Cancel
Save