Consistency changes for notation and updates to issuance key derivation (#30)

This PR improves the naming of variables to make them consistent with
the broader ZIPs conventions.

It also makes changes to the issuance key derivation and the terms used
for the various keys.
This commit is contained in:
Vivek Arte 2024-02-07 14:52:32 +00:00 committed by Daira-Emma Hopwood
parent a7f5ffa0e9
commit d92ccecb48
4 changed files with 83 additions and 97 deletions

View File

@ -70,7 +70,7 @@ Most of the protocol is kept the same as the Orchard protocol released with NU5,
Asset Identifiers
-----------------
For every new Asset, there must be a new and unique Asset Identifier. Every Asset is defined by an *Asset description*, ``assetDesc``, which is a global byte string (scoped across all future versions of Zcash). From this Asset description and the issuance key of the issuer, the specific Asset Identifier, :math:`\mathsf{AssetId}`, the Asset Digest, and the Asset Base (:math:`\mathsf{AssetBase}^{\mathsf{Orchard}}` for the Orchard-based ZSA protocol) are derived as defined in ZIP 227 [#zip-0227]_.
For every new Asset, there must be a new and unique Asset Identifier. Every Asset is defined by an *Asset description*, :math:`\mathsf{asset\_desc}`, which is a global byte string (scoped across all future versions of Zcash). From this Asset description and the issuance key of the issuer, the specific Asset Identifier, :math:`\mathsf{AssetId}`, the Asset Digest, and the Asset Base (:math:`\mathsf{AssetBase}^{\mathsf{Orchard}}` for the Orchard-based ZSA protocol) are derived as defined in ZIP 227 [#zip-0227]_.
This :math:`\mathsf{AssetBase}^{\mathsf{Orchard}}` will be the base point of the value commitment for the specific Custom Asset. Note that the :math:`\mathsf{AssetBase}^{\mathsf{Orchard}}` of the ZEC Asset will be kept as the original value base point, :math:`\mathcal{V}^\mathsf{Orchard}`.
@ -109,7 +109,7 @@ where:
.. math:: \begin{align}
\mathsf{cm}_{\mathsf{ZSA}} :=&\ \mathsf{SinsemillaHashToPoint}( \texttt{"z.cash:ZSA-NoteCommit-M"}, \\
&\ \ \ \mathsf{g_{d}*}\; \| \; \mathsf{pk_{d}*}\; \| \; \mathsf{I2LEBSP_{64}(v)}\; \| \; \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\rho)\; \| \; \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\psi)\; \| \; \mathsf{repr}_{\mathbb{P}}(\mathsf{AssetBase}^{\mathsf{Orchard}})) \\
&\ \ \ \mathsf{g_{d}*}\; \| \; \mathsf{pk_{d}*}\; \| \; \mathsf{I2LEBSP_{64}(v)}\; \| \; \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\rho)\; \| \; \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\psi)\; \| \; \mathsf{asset\_base}) \\
&\ + [\mathsf{rcm}] \mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"},\texttt{""})
\end{align}
@ -165,14 +165,14 @@ Value Balance Verification
In order to verify the balance of the different Assets, the verifier MUST perform exactly the same process as for the Orchard protocol [#protocol-binding]_.
For a total of :math:`n` Actions in a transfer, the prover MUST still sign the `SIGHASH` of the transaction using the binding signature key
For a total of :math:`n` Actions in a transfer, the prover MUST still sign the SIGHASH transaction hash using the binding signature key
:math:`\mathsf{bsk} = \sum_{i=1}^{n} \mathsf{rcv}_{i}`.
Then the verifier MUST compute
The verifier MUST compute
.. math:: \mathsf{bvk} =(\sum_{i=1}^{n} \mathsf{cv^{net}}_{i}) - \mathsf{ValueCommit_0^{OrchardZSA}(v^{balanceOrchard}, \mathcal{V}^{\mathsf{Orchard}})}
After computing :math:`\mathsf{bvk}`, the verifier MUST use it to verify the `bindingSignature` on the `SIGHASH` message.
After computing :math:`\mathsf{bvk}`, the verifier MUST use it to verify the binding signature on the SIGHASH transaction hash.
Rationale for Value Balance Verification
````````````````````````````````````````
@ -195,7 +195,7 @@ Split Notes
A Split Input is a copy of a previously issued input note (that is, a note that has previously been included in the Merkle tree), with the following changes:
- A ``split_flag`` boolean is set to 1.
- A :math:`\mathsf{split\_flag}` boolean is set to 1.
- The value of the note is replaced with the value 0 during the computation of the value commitment.
Input notes are sometimes split in two (or more) output notes, as in most cases, not all the value in a single note is sent to a single output.
@ -215,7 +215,7 @@ In the Orchard protocol, since each Action represents an input and an output, th
The Orchard technique requires modification for the ZSA protocol with multiple Asset Identifiers, as the output note of the split Actions *cannot* contain *any* Asset Base. We must enforce it to be an actual output of a GroupHash computation (in fact, we want it to be of the same Asset Base as the original input note, but the binding signature takes care that the proper balancing is performed). Without this enforcement the prover could input a multiple (or linear combination) of an existing Asset Base, and thereby attack the network by overflowing the ZEC value balance and hence counterfeiting ZEC funds.
Therefore, for Custom Assets we enforce that *every* input note to an ZSA Action must be proven to exist in the set of note commitments in the note commitment tree. We then enforce this real note to be “unspendable” in the sense that its value will be zeroed in split Actions and the nullifier will be randomized, making the note not spendable in the specific Action. Then, the proof itself ensures that the output note is of the same Asset Base as the input note. In the circuit, the split note functionality will be activated by a boolean private input to the proof (aka the ``split_flag`` boolean).
Therefore, for Custom Assets we enforce that *every* input note to an ZSA Action must be proven to exist in the set of note commitments in the note commitment tree. We then enforce this real note to be “unspendable” in the sense that its value will be zeroed in split Actions and the nullifier will be randomized, making the note not spendable in the specific Action. Then, the proof itself ensures that the output note is of the same Asset Base as the input note. In the circuit, the split note functionality will be activated by a boolean private input to the proof (aka the :math:`\mathsf{split\_flag}` boolean).
This ensures that the value base points of all output notes of a transfer are actual outputs of a GroupHash, as they originate in the Issuance protocol which is publicly verified.
Note that the Orchard dummy note functionality remains in use for ZEC notes, and the Split Input technique is used in order to support Custom Assets.
@ -250,14 +250,14 @@ Senders must not be able to change the Asset Base for the output note in a Split
- The Value Commitment Integrity should be changed:
- Replace the input note value by a generic value, :math:`\mathsf{v}'`, as :math:`\mathsf{cv^{net}} = \mathsf{ValueCommit_rcv^{OrchardZSA}(v - v^new, \mathsf{AssetBase}^{\mathsf{Orchard}}_{\mathsf{AssetId}})}`
- Add a boolean ``split_flag`` variable as an auxiliary witness. This variable is to be activated ``split_flag = 1`` if the Action in question has a Split Input and ``split_flag = 0`` if the Action is actually spending an input note:
- If :math:`\texttt{split_flag} = 1` then constrain :math:`\mathsf{v}' = 0` otherwise constrain :math:`\mathsf{v}'=\mathsf{v^{old}}` from the auxiliary input.
- If :math:`\texttt{split_flag} = 1` then constrain :math:`\mathsf{v^{old}} \neq 0`.
- Add a boolean :math:`\mathsf{split\_flag}` variable as an auxiliary witness. This variable is to be activated :math:`\mathsf{split\_flag} = 1` if the Action in question has a Split Input and :math:`\mathsf{split\_flag} = 0` if the Action is actually spending an input note:
- If :math:`\mathsf{split\_flag} = 1` then constrain :math:`\mathsf{v}' = 0` otherwise constrain :math:`\mathsf{v}'=\mathsf{v^{old}}` from the auxiliary input.
- If :math:`\mathsf{split\_flag} = 1` then constrain :math:`\mathsf{v^{old}} \neq 0`.
- The Merkle Path Validity should check the existence of the note commitment as usual (and not like with dummy notes):
- Check that (path, pos) is a valid Merkle path of depth :math:`\mathsf{MerkleDepth^Orchard}`, from :math:`\mathsf{cm^{old}}` to the anchor :math:`\mathsf{rt^{Orchard}}`.
- The Nullifier Integrity will be changed to prevent the identification of notes
- Replace the :math:`\psi_{old}` value with a generic :math:`\psi'` as :math:`\mathsf{nf_{old}} = \mathsf{DeriveNullifier_{nk}}(\rho^\mathsf{old}, \psi', \mathsf{cm^{old}})`
- if :math:`\mathtt{split\_flag} = 0` then constrain :math:`\psi' = \psi^{old}`. (Otherwise :math:`\psi'` should be sampled uniformly at random on :math:`\mathbb{F}_{q_{\mathbb{P}}}`.)
- if :math:`\mathsf{split\_flag} = 0` then constrain :math:`\psi' = \psi^{old}`. (Otherwise :math:`\psi'` should be sampled uniformly at random on :math:`\mathbb{F}_{q_{\mathbb{P}}}`.)
Backwards Compatibility with ZEC Notes
``````````````````````````````````````
@ -285,7 +285,7 @@ This is done as follows:
.. math:: \mathsf{bvk} = (\sum_{i=1}^{n} \mathsf{cv^{net}}_{i}) - \mathsf{ValueCommit_0^{OrchardZSA}}(\mathsf{v^{balanceOrchard}}, \mathcal{V}^{\mathsf{Orchard}}) - \sum_{k=1}^{L} \mathsf{ValueCommit_0^{OrchardZSA}}(\mathsf{v}_{k}, \mathsf{AssetBase}_{k})
After computing :math:`\mathsf{bvk}`, the verifier MUST use it to verify the `bindingSignature` on the `SIGHASH` message.
After computing :math:`\mathsf{bvk}`, the verifier MUST use it to verify the binding signature on the SIGHASH transaction hash.
In the case that the balance of all the Action values related to a specific Asset will be zero, there will be no value added to the vector. This way, neither the number of Assets nor their Asset Identifiers will be revealed, except in the case that an Asset is burnt.
@ -307,7 +307,7 @@ The burn mechanism verification is equivalent to:
.. math:: \mathsf{bvk} = ((\sum_{i=1}^{m} \mathsf{cv^{net}}_{i}) + (\sum_{j=m+1}^{n} \mathsf{cv^{net}}_{j})) - ([\mathsf{v^{balanceOrchard}}]\mathcal{V}^{\mathsf{Orchard}} + [0]\mathcal{R}^{\mathsf{Orchard}}) - (\sum_{k=1}^{L} [\mathsf{v}_{k}]\mathsf{AssetBase}_{k} + [0]\mathcal{R}^{\mathsf{Orchard}})
The relationship between :math:`\mathsf{bvk}` and :math:`\mathsf{bsk}` will hold only if the sum of the net values of the Actions equals the sum of :math:`\mathsf{v^{balanceOrchard}}` and the :math:`\mathsf{v_k}` values, across base points (i.e. Asset Base).
The relationship between :math:`\mathsf{bvk}` and :math:`\mathsf{bsk}` will hold only if the sum of the net values of the Actions equals the sum of :math:`\mathsf{v^{balanceOrchard}}` and the :math:`\mathsf{v}_k` values, across base points (i.e. Asset Base).
ZSA Transaction Structure
=========================
@ -505,7 +505,8 @@ Backward Compatibility
----------------------
In order to have backward compatibility with the ZEC notes, we have designed the circuit to support both ZEC and ZSA notes. As we specify above, there are three main reasons we can do this:
- Note commitments for ZEC notes will remain the same, while note commitments for Custom Assets will be computed taking into account the :math:`AssetBase` value as well.
- Note commitments for ZEC notes will remain the same, while note commitments for Custom Assets will be computed taking into account the :math:`\mathsf{AssetBase}` value as well.
- The existing Orchard shielded pool will continue to be used for the new ZSA notes post the upgrade.
- The value commitment is abstracted to allow for the value base-point as a variable private input to the proof.
- The ZEC-based Actions will still include dummy input notes, whereas the ZSA-based Actions will include both dummy and split input notes.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -7,7 +7,7 @@
id="svg2"
version="1.1"
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
sodipodi:docname="key_components_zsa.svg"
sodipodi:docname="zip-0227-key-components-zsa.svg"
inkscape:export-filename="key_components_zsa.png"
inkscape:export-xdpi="179.99957"
inkscape:export-ydpi="179.99957"
@ -33,8 +33,8 @@
showgrid="false"
inkscape:window-width="1158"
inkscape:window-height="916"
inkscape:window-x="177"
inkscape:window-y="38"
inkscape:window-x="381"
inkscape:window-y="81"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
@ -179,25 +179,15 @@
id="rect2985-9-7-8"
style="fill:#fdb341;fill-opacity:1;stroke:#000000;stroke-width:1.06667;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /><text
id="text3755-4"
y="1079.853"
x="94.809486"
y="1082.3408"
x="97.56559"
style="font-style:normal;font-weight:normal;font-size:25.6px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.06667"
xml:space="preserve"><tspan
y="1079.853"
x="94.809486"
y="1082.3408"
x="97.56559"
id="tspan3757-5"
sodipodi:role="line"
style="stroke-width:1.06667">sk</tspan></text><text
id="text3759-9"
y="1082.4244"
x="123.28569"
style="font-style:normal;font-weight:normal;font-size:14.9333px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.06667"
xml:space="preserve"><tspan
y="1082.4244"
x="123.28569"
id="tspan3761-0"
sodipodi:role="line"
style="stroke-width:1.06667">iss</tspan></text><text
style="stroke-width:1.06667">idk</tspan></text><text
id="text3850"
y="857.8241"
x="184.16003"
@ -217,7 +207,7 @@
y="1077.58"
x="184.15979"
id="tspan3852-9-9"
sodipodi:role="line">Issuance master key</tspan></text><text
sodipodi:role="line">Issuance derivation key</tspan></text><text
id="text3850-7"
y="792.51001"
x="138.73125"

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -44,12 +44,12 @@ We define the following additional terms:
Abstract
========
This ZIP (ZIP 227) proposes the Zcash Shielded Assets (ZSA) protocol, in conjunction with ZIP 226 [#zip-0226]_. This protocol is an extension of the Orchard protocol that enables the creation, transfer and burn of custom Assets on the Zcash chain. The creation of such Assets is defined in this ZIP (ZIP 227), while the transfer and burn of such Assets is defined in ZIP 226 [#zip-0226]_. This ZIP must only be implemented in conjuction with ZIP 226 [#zip-0226]_. The proposed issuance mechanism is only valid for the ZSA transfer protocol, because it produces notes that can only be transferred under ZSA.
This ZIP (ZIP 227) proposes the Zcash Shielded Assets (ZSA) protocol, in conjunction with ZIP 226 [#zip-0226]_. This protocol is an extension of the Orchard protocol that enables the creation, transfer and burn of Custom Assets on the Zcash chain. The creation of such Assets is defined in this ZIP (ZIP 227), while the transfer and burn of such Assets is defined in ZIP 226 [#zip-0226]_. This ZIP must only be implemented in conjuction with ZIP 226 [#zip-0226]_. The proposed issuance mechanism is only valid for the ZSA transfer protocol, because it produces notes that can only be transferred under ZSA.
Motivation
==========
This ZIP introduces the issuance mechanism for custom Assets on the Zcash chain. While originally part of a same ZSA ZIP (ZIP 226 [#zip-0226]_) the issuance mechanism turned out to be substantial enough to stand on its own and justify the creation of this supporting ZIP for ZIP 226 [#zip-0226]_.
This ZIP introduces the issuance mechanism for Custom Assets on the Zcash chain. While originally part of a same ZSA ZIP (ZIP 226 [#zip-0226]_) the issuance mechanism turned out to be substantial enough to stand on its own and justify the creation of this supporting ZIP for ZIP 226 [#zip-0226]_.
This ZIP only enables *transparent* issuance. As a first step, transparency will allow for proper testing of the applications that will be most used in the Zcash ecosystem, and will enable the supply of Assets to be tracked.
@ -70,12 +70,12 @@ See the `Concrete Applications`_ section for more details.
Requirements
============
- Any user of the Zcash blockchain can issue custom Assets on chain.
- Any user of the Zcash blockchain can issue Custom Assets on chain.
- The issuance mechanism should enable public tracking of the supply of the Assets on the Zcash blockchain.
- Issuing or changing the attributes of a specific Asset should require cryptographic authorization.
- The Asset identification should be unique (among all shielded pools) and different issuer public keys should not be able to generate the same Asset Identifier.
- An issuer should be able to issue different Assets in the same transaction. In other words, in a single "issuance bundle", the issuer should be able publish many "issuance actions", potentially creating multiple Custom Assets.
- Every "issuance action" should contain a ``finalize`` boolean that defines whether the specific Custom Asset can have further tokens issued or not.
- Every "issuance action" should contain a :math:`\mathsf{finalize}` boolean that defines whether the specific Custom Asset can have further tokens issued or not.
Specification: Issuance Keys and Issuance Authorization Signature Scheme
@ -83,11 +83,11 @@ Specification: Issuance Keys and Issuance Authorization Signature Scheme
The ZSA Protocol adds the following three keys to the key components [#protocol-addressesandkeys]_:
1. The issuance master key, denoted as :math:`\mathsf{sk}_{\mathsf{iss}}`, as the name suggests, is the master key that is used to derive the other two keys.
1. The issuance derivation key, denoted as :math:`\mathsf{idk}`, as the name suggests, is the key that is used to derive the other two keys.
2. The issuance authorizing key is the key that is used to sign the issuance transaction, and is denoted as ``isk``. This key is used to authorize the issuance of a specific Asset Identifier, and is only used by the issuer.
2. The issuance authorizing key is the key that is used to sign the issuance transaction, and is denoted as :math:`\mathsf{isk}`. This key is used to authorize the issuance of a specific Asset Identifier, and is only used by the issuer.
3. The issuance validating key, denoted as ``ik``, is the key that is used to validate the issuance transaction. This key is used to validate the issuance of a specific Asset Identifier, and is used by all blockchain users (specifically the Asset owners and consensus validators) to associate the Asset in question with the issuer.
3. The issuance validating key, denoted as :math:`\mathsf{ik}`, is the key that is used to validate the issuance transaction. This key is used to validate the issuance of a specific Asset Identifier, and is used by all blockchain users (specifically the Asset owners and consensus validators) to associate the Asset in question with the issuer.
The relations between these keys are shown in the following diagram:
@ -108,59 +108,59 @@ Specifically, we instantiate :math:`\mathsf{IssueAuthSig}` as :math:`\mathsf{Red
Issuance Key Derivation
-----------------------
The issuance master key is generated by choosing a bit sequence uniformly at random from :math:`\mathbb{B}^{\mathbb{Y}[32]}`, like the Orchard spending key [#protocol-orchardkeycomponents]_.
The issuance derivation key is generated by choosing a bit sequence uniformly at random from :math:`\mathbb{B}^{\mathbb{Y}[32]}`, like the Orchard spending key [#protocol-orchardkeycomponents]_.
Issuance master key derivation for hierarchical deterministic wallets
`````````````````````````````````````````````````````````````````````
Issuance derivation key generation for hierarchical deterministic wallets
`````````````````````````````````````````````````````````````````````````
The issuance master key is derived using the Orchard master key derivation procedure defined in ZIP 32 [#zip-0032-orchard-master]_. We reuse the functions defined there in what follows in this section.
The issuance derivation key is generated using the Orchard master key derivation procedure defined in ZIP 32 [#zip-0032-orchard-master]_. We reuse the functions defined there in what follows in this section.
Let :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.
We define the master extended issuance key :math:`m_{\mathsf{Issuance}} := \mathsf{MasterKeyGen}(\texttt{"ZIP32ZSAIssue_V1"}, S)`.
As in ZIP 32 for Orchard [#zip-0032-orchard-child-key-derivation]_, we only use hardened child key derivation for the issuance master key.
As in ZIP 32 for Orchard [#zip-0032-orchard-child-key-derivation]_, we only use hardened child key derivation for the issuance derivation key.
We reuse the :math:`\mathsf{CDKsk}` function for Orchard child key derivation from ZIP 32.
We use the notation of ZIP 32 [#zip-0032-orchard-key-path]_ for shielded HD paths, and define the issuance master key path as :math:`m_\mathsf{Issuance} / purpose' / coin\_type' / account'`. We fix the path levels as follows:
We use the notation of ZIP 32 [#zip-0032-orchard-key-path]_ for shielded HD paths, and define the issuance derivation key path as :math:`m_\mathsf{Issuance} / purpose' / coin\_type' / account'`. We fix the path levels as follows:
- :math:`purpose`: a constant set to :math:`227` (i.e. :math:`\texttt{0xe3}`). :math:`purpose'` is thus :math:`227'` (or :math:`\texttt{0x800000e3}`) following the BIP 43 recommendation.
- :math:`coin\_type`: Defined as in ZIP 32 [#zip-0032-key-path-levels]_.
- :math:`account`: fixed to index :math:`0`.
Given the *extended issuance master key* :math:`(\mathsf{sk}, \mathsf{c})`, we set the issuance master key to be :math:`\mathsf{sk_{iss}} := \mathsf{sk}`.
From the generated :math:`(\mathsf{sk}, \mathsf{c})`, we set the issuance derivation key to be :math:`\mathsf{idk} := \mathsf{sk}`.
Derivation of issuance authorizing key and issuance validating key
``````````````````````````````````````````````````````````````````
The issuance authorizing key and issuance validating key are derived from the issuance master key in an analogous manner to the derivation of the Orchard spend authorizing key and Orchard spend validating key from the Orchard spending key [#protocol-orchardkeycomponents]_, as described below.
The issuance authorizing key and issuance validating key are derived from the issuance derivation key in an analogous manner to the derivation of the Orchard spend authorizing key and Orchard spend validating key from the Orchard spending key [#protocol-orchardkeycomponents]_, as described below.
- The issuance authorizing key is derived from the issuance master key, :math:`\mathsf{sk}_{\mathsf{iss}}`, as a private signature key:
- The issuance authorizing key is derived from the issuance derivation key, :math:`\mathsf{idk}`, as a private signature key. The function :math:`\mathsf{PRF^{expand}_{idk}}` is as defined in the Zcash protocol specification [#protocol-abstractprfs]_:
.. math:: \mathtt{isk} := \mathsf{ToScalar}^{\mathsf{Orchard}}( \mathsf{sk}_{\mathsf{iss}} )
.. math:: \mathsf{isk} := \mathsf{ToScalar}^{\mathsf{Orchard}}( \mathsf{PRF^{expand}_{idk}}([\mathtt{0x0a}]) )
- The issuance validating key is derived from the issuance authorizing key, :math:`\mathtt{isk}`, as a public verification key:
- The issuance validating key is derived from the issuance authorizing key, :math:`\mathsf{isk}`, as a public verification key:
.. math:: \mathtt{ik} := \mathsf{IssueAuthSig}.\mathsf{DerivePublic}(\mathtt{isk})
.. math:: \mathsf{ik} := \mathsf{IssueAuthSig}.\mathsf{DerivePublic}(\mathsf{isk})
This allows the issuer to use the same wallet it usually uses to transfer Assets, while keeping a disconnect from the other keys. Specifically, this method is aligned with the requirements and motivation of ZIP 32 [#zip-0032]_. It provides further anonymity and the ability to delegate issuance of an Asset (or in the future, generate a multi-signature protocol) while the rest of the keys remain in the wallet safe.
Specification: Asset Identifier
===============================
For every new Asset, there must be a new and unique Asset Identifier, denoted :math:`\mathsf{AssetId}`. We define this to be a globally unique pair :math:`\mathsf{AssetId} := (\mathtt{ik}, \mathtt{assetDesc})`, where ``ik`` is the issuance key and ``assetDesc`` is a byte string.
For every new Asset, there must be a new and unique Asset Identifier, denoted :math:`\mathsf{AssetId}`. We define this to be a globally unique pair :math:`\mathsf{AssetId} := (\mathsf{ik}, \mathsf{asset\_desc})`, where :math:`\mathsf{ik}` is the issuance key and :math:`\mathsf{asset\_desc}` is a byte string.
A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the Orchard-based ZSA protocol and potentially future Zcash shielded protocols. For this Asset Identifier, we derive an Asset Digest, :math:`\mathsf{AssetDigest}`, which is simply is a :math:`\textsf{BLAKE2b-512}` hash of the Asset Identifier.
From the Asset Digest, we derive a specific Asset Base within each such shielded protocol (for example :math:`\mathsf{AssetBase}^{\mathsf{Orchard}}_{\mathsf{AssetId}}` for the Orchard-based ZSA protocol), using the applicable hash-to-curve algorithm. This Asset Base is included in shielded notes.
Let
- ``assetDesc`` be the asset description, which includes any information pertaining to the issuance, and is a byte sequence of up to 512 bytes which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later.
- ``ik`` be the issuance validating key of the issuer, a public key used to verify the signature on the issuance transaction's SIGHASH.
- :math:`\mathsf{asset\_desc}` be the asset description, which includes any information pertaining to the issuance, and is a byte sequence of up to 512 bytes which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later.
- :math:`\mathsf{ik}` be the issuance validating key of the issuer, a public key used to verify the signature on the issuance transaction's SIGHASH.
Define :math:`\mathsf{AssetDigest_{\mathsf{AssetId}}} := \textsf{BLAKE2b-512}(\texttt{"ZSA-Asset-Digest"},\; \mathsf{EncodeAssetId}(\mathsf{AssetId}))`,
where
- :math:`\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathtt{ik}, \mathtt{assetDesc})) := \mathsf{0x00} || \mathsf{repr}_{\mathbb{P}}(\mathtt{ik}) || \mathtt{assetDesc}\!`.
- :math:`\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathsf{ik}, \mathsf{asset\_desc})) := \mathsf{0x00} || \mathsf{repr}_{\mathbb{P}}(\mathsf{ik}) || \mathsf{asset\_desc}\!`.
Define :math:`\mathsf{AssetBase^{Protocol}_{\mathsf{AssetId}}} := \mathsf{ZSAValueBase^{Protocol}}(\mathsf{AssetDigest}_{\mathsf{AssetId}})`,
where
@ -185,7 +185,7 @@ Specification: Global Issuance State
Issuance requires the following additions to the global state defined at block boundaries:
- ``finalized_assets``, a set of :math:`\mathsf{AssetDigest}` that have been finalized (i.e.: the ``finalize`` flag has been set to ``1`` in some issuance transaction preceding the block boundary).
- :math:`\mathsf{previously\_finalized}`, a set of :math:`\mathsf{AssetId}` that have been finalized (i.e.: the :math:`\mathsf{finalize}` flag has been set to :math:`1` in some issuance transaction preceding the block boundary).
Specification: Issuance Action, Issuance Bundle and Issuance Protocol
@ -194,24 +194,22 @@ Specification: Issuance Action, Issuance Bundle and Issuance Protocol
Issuance Action Description
---------------------------
An issuance action, ``IssueAction``, is the instance of issuing a specific custom Asset, and contains the following fields:
An issuance action, ``IssueAction``, is the instance of issuing a specific Custom Asset, and contains the following fields:
- ``assetDescSize``: the size of the Asset description, a number between :math:`0` and :math:`512`, stored in two bytes.
- ``assetDesc``: the Asset description, a byte string of up to 512 bytes as defined in the `Specification: Asset Identifier`_ section.
- :math:`\mathsf{assetDescSize}`: the size of the Asset description, a number between :math:`0` and :math:`512`, stored in two bytes.
- :math:`\mathsf{asset\_desc}`: the Asset description, a byte string of up to 512 bytes as defined in the `Specification: Asset Identifier`_ section.
- ``vNotes``: an array of ``Note`` containing the unencrypted output notes of the recipients of the Asset.
- ``flagsIssuance``: a byte that stores the ``finalize`` boolean that defines whether the issuance of that specific Custom Asset is finalized or not
- ``flagsIssuance``: a byte that stores the :math:`\mathsf{finalize}` boolean that defines whether the issuance of that specific Custom Asset is finalized or not.
An asset's :math:`\mathsf{AssetDigest}` is added to the ``finalized_assets`` set after a block that contains any issuance transaction for that asset with ``finalize = 1``. It then cannot be removed from this set.
For Assets with :math:`\mathsf{AssetDigest} \in \mathtt{finalized\_assets}`, no further tokens can be issued, so as seen below, the validators will reject the transaction.
For Assets with :math:`\mathsf{AssetDigest} \not\in \mathtt{finalized\_assets}`, new issuance actions can be issued in future transactions.
These must use the same Asset description, ``assetDesc``, and can either maintain ``finalize = 0`` or change it to ``finalize = 1``, denoting that this Custom Asset cannot be issued after the containing block.
An asset's :math:`\mathsf{AssetDigest}` is added to the :math:`\mathsf{previously\_finalized}` set after a block that contains any issuance transaction for that asset with :math:`\mathsf{finalize} = 1`. It then cannot be removed from this set. For Assets with :math:`\mathsf{AssetDigest} \in \mathsf{previously\_finalized}`, no further tokens can be issued, so as seen below, the validators will reject the transaction. For Assets with :math:`\mathsf{AssetDigest} \not\in \mathsf{previously\_finalized}`, new issuance actions can be issued in future transactions. These must use the same Asset description, :math:`\mathsf{asset\_desc}`, and can either maintain :math:`\mathsf{finalize} = 0` or change it to :math:`\mathsf{finalize} = 1`, denoting that this Custom Asset cannot be issued after the containing block.
+-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
| Bytes | Name | Data Type | Description |
+=============================+==========================+===========================================+=====================================================================+
|``2`` |``assetDescSize`` |``byte`` |The length of the ``assetDesc`` string in bytes. |
|``2`` |``assetDescSize`` |``byte`` |The length of the :math:`\mathsf{asset\_desc}` string in bytes. |
+-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
|``assetDescSize`` |``assetDesc`` |``byte[assetDescSize]`` |A byte sequence of length ``assetDescSize`` bytes which SHOULD be a |
|``assetDescSize`` |``asset_desc`` |``byte[assetDescSize]`` |A byte sequence of length ``assetDescSize`` bytes which SHOULD be a |
| | | |well-formed UTF-8 code unit sequence according to Unicode 15.0.0 |
| | | |or later. |
+-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
@ -221,7 +219,7 @@ These must use the same Asset description, ``assetDesc``, and can either maintai
| | | |where ``noteSize`` is the size, in bytes, of a Note. |
+-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
|``1`` |``flagsIssuance`` |``byte`` |An 8-bit value representing a set of flags. Ordered from LSB to MSB: |
| | | | * ``finalize`` |
| | | | * :math:`\mathsf{finalize}` |
| | | | * The remaining bits are set to ``0``. |
+-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
@ -235,9 +233,9 @@ An issuance bundle, ``IssueBundle``, is the aggregate of all the issuance-relate
Specifically, contains all the issuance actions and the issuer signature on the transaction SIGHASH that validates the issuance itself.
It contains the following fields:
- ``ik``: the issuance validating key, that allows the validators to verify that the :math:`\mathsf{AssetId}` is properly associated with the issuer.
- ``vIssueActions``: an array of issuance actions, of type `IssueAction`.
- ``issueAuthSig``: the signature of the transaction SIGHASH, signed by the issuance authorizing key, :math:`\mathtt{isk}`, that validates the issuance .
- :math:`\mathsf{ik}`: the issuance validating key, that allows the validators to verify that the :math:`\mathsf{AssetId}` is properly associated with the issuer.
- ``vIssueActions``: an array of issuance actions, of type ``IssueAction``.
- :math:`\mathsf{issueAuthSig}`: the signature of the transaction SIGHASH, signed by the issuance authorizing key, :math:`\mathsf{isk}`, that validates the issuance .
The issuance bundle is then added within the transaction format as a new bundle. That is, issuance requires the addition of the following information to the transaction format [#protocol-transactionstructure]_.
@ -261,10 +259,10 @@ The issuer program performs the following operations
For all actions ``IssueAction``:
- encode ``assetDesc`` as a UTF-8 byte string of size up to 512.
- compute :math:`\mathsf{AssetDigest}` from the issuance validating key ``ik`` and ``assetDesc`` as decribed in the `Specification: Asset Identifier`_ section.
- encode :math:`\mathsf{asset\_desc}` as a UTF-8 byte string of size up to 512.
- compute :math:`\mathsf{AssetDigest}` from the issuance validating key :math:`\mathsf{ik}` and :math:`\mathsf{asset\_desc}` as decribed in the `Specification: Asset Identifier`_ section.
- compute :math:`\mathsf{AssetBase^{Protocol}}` from :math:`\mathsf{AssetDigest}` as decribed in the `Specification: Asset Identifier`_ section.
- set the ``finalize`` boolean as desired (if more issuance actions are to be created for this Asset Identifier, set ``finalize = 0``, otherwise set ``finalize = 1``).
- set the :math:`\mathsf{finalize}` boolean as desired (if more issuance actions are to be created for this Asset Identifier, set :math:`\mathsf{finalize} = 0`, otherwise set :math:`\mathsf{finalize} = 1`)
- For each recipient :math:`i`:
- generate a ZSA output note that includes the Asset Base. For an Orchard-based ZSA note this is :math:`\mathsf{note}_i = (\mathsf{d}_i, \mathsf{pk}_{\mathsf{d}_i}, \mathsf{v}_i, \rho_i, \mathsf{rseed}_i, \mathsf{AssetBase^{Orchard}}, \mathsf{rcm}_i)\!`.
@ -273,9 +271,9 @@ For all actions ``IssueAction``:
For the ``IssueBundle``:
- encode the ``vIssueActions`` vector.
- encode the ``ik`` as 32 byte-string.
- sign the ``SIGHASH`` of the transaction with the issuance authorizing key, :math:`\mathtt{isk}`, using the :math:`\mathsf{IssueAuthSig}` signature scheme. The signature is then added to the issuance bundle.
- encode the ``vIssueActions`` vector
- encode the :math:`\mathsf{ik}` as 32 byte-string
- sign the SIGHASH transaction hash with the issuance authorizing key, :math:`\mathsf{isk}`, using the :math:`\mathsf{IssueAuthSig}` signature scheme. The signature is then added to the issuance bundle.
**Note:** that the commitment is not included in the ``IssuanceAction`` itself. As explained below, it is computed later by the validators and added to the note commitment tree.
@ -286,22 +284,22 @@ Specification: Consensus Rule Changes
For the ``IssueBundle``:
- Verify the RedPallas-based issuance authorization signature on ``SIGHASH``, ``issueAuthSig``, is verified by invoking :math:`\mathsf{issueAuthSig.VerifySig}(\mathtt{ik}, \mathtt{SIGHASH})`.
- Verify the RedPallas-based issuance authorization signature on the SIGHASH transaction hash, :math:`\mathsf{SigHash}`, :math:`\mathsf{issueAuthSig}`, is verified by invoking :math:`\mathsf{issueAuthSig.VerifySig(ik, SigHash)}`
For each ``IssueAction`` in ``IssueBundle``:
- check that :math:`0 < \mathtt{assetDescSize} <= 512`.
- check that :math:`\mathtt{assetDesc}` is a string of length :math:`\mathtt{assetDescSize}` bytes.
- check that :math:`\mathsf{asset\_desc}` is a string of length :math:`\mathtt{assetDescSize}` bytes.
- retrieve :math:`\mathsf{AssetBase}` from the first note in the sequence and check that :math:`\mathsf{AssetBase}` is derived from the issuance validating key ``ik`` and ``assetDesc`` as described in the `Specification: Asset Identifier`_ section.
- check that the :math:`\mathsf{AssetDigest}` does not exist in the ``finalized_assets`` set in the global state.
- retrieve :math:`\mathsf{AssetBase}` from the first note in the sequence and check that :math:`\mathsf{AssetBase}` is derived from the issuance validating key :math:`\mathsf{ik}` and :math:`\mathsf{asset\_desc}` as described in the `Specification: Asset Identifier`_ section.
- check that the :math:`\mathsf{AssetDigest}` does not exist in the :math:`\mathsf{previously\_finalized}` set in the global state.
- check that every note in the ``IssueAction`` contains the same :math:`\mathsf{AssetBase}` and is properly constructed as :math:`\mathsf{note} = (\mathsf{g_d, pk_d, v, \rho, rseed, AssetBase})`.
If all of the above checks pass, do the following:
- For each note, compute the note commitment as :math:`\mathsf{cm} = \mathsf{NoteCommit^{OrchardZSA}_{rcm}(repr_{\mathbb{P}}(g_d), repr_{\mathbb{P}}(pk_d), v, \rho, \psi, AssetBase)}` as defined in the Note Structure and Commitment section of ZIP 226 [#zip-0226-notestructure]_ and
- Add :math:`\mathsf{cm}` to the Merkle tree of note commitments.
- If ``finalize = 1``, add :math:`\mathsf{AssetDigest}` to the ``finalized_assets`` set immediately after the block in which this transaction occurs.
- If :math:`\mathsf{finalize} = 1`, add :math:`\mathsf{AssetDigest}` to the :math:`\mathsf{previously\_finalized}` set immediately after the block in which this transaction occurs.
- (Replay Protection) If issue bundle is present, the fees MUST be greater than zero.
@ -312,34 +310,34 @@ The following is a list of rationale for different decisions made in the proposa
- The issuance key structure is independent of the original key tree, but derived in an analogous manner (via ZIP 32). This is in order to keep the issuance details and the Asset Identifiers consistent across multiple shielded pools.
- The design decision is not to have a chosen name to describe the Custom Asset, but to delegate it to an off-chain mapping, as this would imply a land-grab “war”.
- The ``assetDesc`` is a general byte string in order to allow for a wide range of information type to be included that may be associated with the Assets. Some are:
- The :math:`\mathsf{asset\_desc}` is a general byte string in order to allow for a wide range of information type to be included that may be associated with the Assets. Some are:
- links for storage such as for NFTs.
- metadata for Assets, encoded in any format.
- bridging information for Wrapped Assets (chain of origin, issuer name, etc)
- information to be committed by the issuer, though not enforceable by the protocol.
- We require a check whether the ``finalize`` flag only has been set in a previous block rather than a previous transaction in the same block. In other words, we only update the ``finalized_assets`` set at the block boundary. This is in keeping with the current property which allows for a miner to reorder transactions in a block without changing the meaning, which we aim to preserve.
- We require non-zero fees in the presence of an issue bundle, in order to preclude the possibility of a transaction containing only an issue bundle. If a transaction includes only an issue bundle, the ``SIGHASH`` would be computed solely based on the issue bundle. A duplicate bundle would have the same ``SIGHASH``, potentially allowing for a replay attack.
- We require a check whether the :math:`\mathsf{finalize}` flag only has been set in a previous block rather than a previous transaction in the same block. In other words, we only update the :math:`\mathsf{previously\_finalized}`` set at the block boundary. This is in keeping with the current property which allows for a miner to reorder transactions in a block without changing the meaning, which we aim to preserve.
- We require non-zero fees in the presence of an issue bundle, in order to preclude the possibility of a transaction containing only an issue bundle. If a transaction includes only an issue bundle, the SIGHASH transaction hash would be computed solely based on the issue bundle. A duplicate bundle would have the same SIGHASH transaction hash, potentially allowing for a replay attack.
Concrete Applications
---------------------
**Asset Features**
- By using the ``finalize`` boolean and the burning mechanism defined in [#zip-0226]_, issuers can control the supply production of any Asset associated to their issuer keys. For example,
- By using the :math:`\mathsf{finalize}` boolean and the burning mechanism defined in [#zip-0226]_, issuers can control the supply production of any Asset associated to their issuer keys. For example,
- by setting ``finalize = 1`` from the first issuance action for that Asset Identifier, the issuer is in essence creating a one-time issuance transaction. This is useful when the max supply is capped from the beginning and the distribution is known in advance. All tokens are issued at once and distributed as needed.
- by setting :math:`\mathsf{finalize} = 1` from the first issuance action for that Asset Identifier, the issuer is in essence creating a one-time issuance transaction. This is useful when the max supply is capped from the beginning and the distribution is known in advance. All tokens are issued at once and distributed as needed.
- Issuers can also stop the existing supply production of any Asset associated to their issuer keys. This could be done by
- issuing a last set of tokens of that specific :math:`\mathsf{AssetId}`, for which ``finalize = 1``, or by
- issuing a last set of tokens of that specific :math:`\mathsf{AssetId}`, for which :math:`\mathsf{finalize} = 1`, or by
- issuing a transaction with a single note in the issuance action pertaining to that :math:`\mathsf{AssetId}`, where the note will contain a ``value = 0``. This can be used for application-specific purposes (NFT collections) or for security purposes to revoke the Asset issuance (see Security and Privacy Considerations).
- Note in the above cases, that the setting of the ``finalize`` flag will take effect at the block boundary, that is, after all the transactions in the block.
- Note in the above cases, that the setting of the :math:`\mathsf{finalize}` flag will take effect at the block boundary, that is, after all the transactions in the block.
- The issuance and burn mechanisms can be used in conjunction to determine the supply of Assets on the Zcash ecosystem. This allows for the bridging of Assets defined on other chains.
- Furthermore, NFT issuance is enabled by issuing in a single bundle several issuance actions, where each :math:`\mathsf{AssetId}` corresponds to ``value = 1`` at the fundamental unit level. Issuers and users should make sure that ``finalize = 1`` for each of the actions in this scenario.
- Furthermore, NFT issuance is enabled by issuing in a single bundle several issuance actions, where each :math:`\mathsf{AssetId}` corresponds to ``value = 1`` at the fundamental unit level. Issuers and users should make sure that :math:`\mathsf{finalize} = 1` for each of the actions in this scenario.
@ -430,7 +428,7 @@ T.5a.iii: flagsIssuance
'''''''''''''''''''''''
An 8-bit value representing a set of flags. Ordered from LSB to MSB:
- ``finalize``
- :math:`\mathsf{finalize}`
- The remaining bits are set to `0`.
@ -514,9 +512,9 @@ Security and Privacy Considerations
Issuance Key Compromise
-----------------------
The design of this protocol does not currently allow for a rotation of the issuance validating key that would allow for replacing the key of a specific Asset (see `Future Work`_). In case of compromise, the following actions are recommended:
The design of this protocol does not currently allow for rotation of the issuance validating key that would allow for replacing the key of a specific Asset. In case of compromise, the following actions are recommended:
- If an issuance validating key is compromised, the ``finalize`` boolean for all the Assets issued with that key should be set to :math:`1` and the issuer should change to a new issuance authorizing key, and issue new Assets, each with a new :math:`\mathsf{AssetId}`.
- If an issuance validating key is compromised, the :math:`\mathsf{finalize}` boolean for all the Assets issued with that key should be set to :math:`1` and the issuer should change to a new issuance authorizing key, and issue new Assets, each with a new :math:`\mathsf{AssetId}`.
Bridging Assets
---------------
@ -536,10 +534,6 @@ Fee Structures
The fee mechanism described in this ZIP will follow the mechanism described in ZIP 317b [#zip-0317b]_.
Future Work
-----------
In future versions of this ZIP, the protocol may also include a "key rotation" mechanism. This would allow an issuer to change the underlying ``ik`` of a given Asset, in case the original one was compromised, without having to change the Asset Identifier altogether.
Test Vectors
============
@ -578,6 +572,7 @@ References
.. [#zip-0316] `ZIP 316: Unified Addresses and Unified Viewing Keys <zip-0316.html>`_
.. [#protocol-addressesandkeys] `Zcash Protocol Specification, Version 2022.3.8. Section 3.1: Payment Addresses and Keys <protocol/protocol.pdf#addressesandkeys>`_
.. [#protocol-concretegrouphashpallasandvesta] `Zcash Protocol Specification, Version 2022.3.8. Section 5.4.9.8: Group Hash into Pallas and Vesta <protocol/protocol.pdf#concretegrouphashpallasandvesta>`_
.. [#protocol-abstractprfs] `Zcash Protocol Specification, Version 2022.3.8. Section 4.1.2: Pseudo Random Functions <protocol/protocol.pdf#abstractprfs>`_
.. [#protocol-orchardkeycomponents] `Zcash Protocol Specification, Version 2022.3.8. Section 4.2.3: Orchard Key Components <protocol/protocol.pdf#orchardkeycomponents>`_
.. [#protocol-spendauthsig] `Zcash Protocol Specification, Version 2022.3.8. Section 4.15: Spend Authorization Signature (Sapling and Orchard) <protocol/protocol.pdf#spendauthsig>`_
.. [#protocol-concretespendauthsig] `Zcash Protocol Specification, Version 2022.3.8. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard) <protocol/protocol.pdf#concretespendauthsig>`_