ZIP: 227 Title: Issuance of Zcash Shielded Assets Owners: Pablo Kogan <pablo@qed-it.com> Vivek Arte <vivek@qed-it.com> Daira-Emma Hopwood <daira-emma@electriccoin.co> Jack Grigg <str4d@electriccoin.co> Credits: Daniel Benarroch Aurelien Nicolas Deirdre Connolly Teor Status: Draft Category: Consensus Created: 2022-05-01 License: MIT Discussions-To: <https://github.com/zcash/zips/issues/618> Pull-Request: <https://github.com/zcash/zips/pull/680>
The key words "MUST", "MUST NOT", "SHOULD", "RECOMMENDED", and "MAY" in this document are to be interpreted as described in BCP 14 1 when, and only when, they appear in all capitals.
The term "network upgrade" in this document is to be interpreted as described in ZIP 200 7.
The terms "Orchard" and "Action" in this document are to be interpreted as described in ZIP 224 9.
We define the following additional terms:
This ZIP (ZIP 227) proposes the Orchard Zcash Shielded Assets (OrchardZSA) protocol, in conjunction with ZIP 226 10. 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 10. This ZIP must only be implemented in conjunction with ZIP 226 10. The proposed issuance mechanism is only valid for the OrchardZSA transfer protocol, because it produces notes that can only be transferred via this protocol.
This ZIP introduces the issuance mechanism for Custom Assets on the Zcash chain. While originally part of a single ZSA ZIP, 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 10.
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.
The issuance mechanism described in this ZIP is broad enough for issuers to either create Assets on Zcash (i.e. Assets that originate on the Zcash blockchain), as well as for institutions to create bridges from other chains and import Wrapped Assets. This enables what we hope will be a useful set of applications.
The design presented in this ZIP enables issuance of shielded Assets in various modes:
See the Concrete Applications section for more details.
For every new Asset, there MUST be a new and unique Asset Identifier, denoted \(\mathsf{AssetId}\!\) . We define this to be a globally unique pair \(\mathsf{AssetId} := (\mathsf{ik}, \mathsf{asset\_desc})\!\) , where \(\mathsf{ik}\) is the issuance key and \(\mathsf{asset\_desc}\) is a byte string.
A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the OrchardZSA protocol and potentially future Zcash shielded protocols. For this Asset Identifier, we derive an Asset Digest, \(\mathsf{AssetDigest}\!\) , which is simply is a \(\textsf{BLAKE2b-512}\) hash of the Asset Identifier. From the Asset Digest, we derive a specific Asset Base within each shielded protocol using the applicable hash-to-curve algorithm. This Asset Base is included in shielded notes.
Let
Define \(\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{“ZSA-Asset-Digest”},\; \mathsf{EncodeAssetId}(\mathsf{AssetId}))\!\) , where
Define \(\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})\)
In the case of the OrchardZSA protocol, we define \(\mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest_{AssetId}})\) where \(\mathsf{GroupHash}^\mathbb{P}\) is defined as in 27.
The relations between the Asset Identifier, Asset Digest, and Asset Base are shown in the following diagram:
Note: To keep notations light and concise, we may omit \(\mathsf{AssetId}\) (resp. \(\mathsf{Protocol}\!\) ) in the subscript (resp. superscript) when the Asset Identifier (resp. Protocol) is clear from the context.
Wallets MUST NOT display just the \(\mathsf{asset\_desc}\) string to their users as the name of the Asset. Some possible alternatives include:
TODO: Fill this section.
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
\(0\)
and
\(512\!\)
.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
\(\mathsf{finalize}\)
boolean that defines whether the issuance of that specific Custom Asset is finalized or not.The \(\mathsf{finalize}\) boolean is set by the Issuer to signal that there will be no further issuance of the specific Custom Asset. As we will see in Specification: Consensus Rule Changes, transactions that attempt to issue further amounts of a Custom Asset that has previously been finalized will be rejected.
The complete encoding of these fields into an IssueAction
is defined in ZIP 230 15.
We note that the output note commitment of the recipient's notes are not included in the actual transaction, but when added to the global state of the chain, they will be added to the note commitment tree as a shielded note. This prevents future usage of the note from being linked to the issuance transaction, as the nullifier key is not known to the validators and chain observers.
An issuance bundle is the aggregate of all the issuance-related information. Specifically, contains all the issuance actions and the issuer signature on the transaction SIGHASH that validates the issuance itself. It contains the following fields:
vIssueActions
: an array of issuance actions, of type IssueAction
.The issuance bundle is added within the transaction format as a new bundle. The detailed encoding of the issuance bundle as a part of the V6 transaction format is defined in ZIP 230 16.
The issuer program performs the following operations:
For all actions IssueAction
:
IssueAction
into the vector vIssueActions
of the bundle.For the IssueBundle
:
vIssueActions
vector.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.
Issuance requires the following additions to the global state:
A map, \(\mathsf{issued\_assets} : \mathbb{P}^* \to \{0 .. \mathsf{MAX\_ISSUE}\} \times \mathbb{B}\!\) , from the Asset Base, \(\mathsf{AssetBase} : \mathbb{P}^*\!\) , to a tuple \((\mathsf{balance}, \mathsf{final})\!\) , for every Asset that has been issued. We use the notation \(\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{balance}\) and \(\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{final}\) to access, respectively, the elements of the tuple stored in the global state for a given \(\mathsf{AssetBase}\!\) . If \(\mathsf{issued\_assets}(\mathsf{AssetBase}) = \bot\!\) , it is assumed that \(\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{balance} = 0\) and \(\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{final} = 0\!\) .
For any Asset represented by \(\mathsf{AssetBase}\!\) :
The maximum total supply of any issued Custom Asset is denoted by the constant \(\mathsf{MAX\_ISSUE} := 2^{64} - 1\!\) .
The issuance state, that is, the \(\mathsf{issued\_assets}\) map, MUST be updated by a node during the processing of any transaction that contains burn information, or an issuance bundle. The issuance state is chained as follows:
We describe the consensus rule changes that govern the management of the global issuance state in the Specification: Consensus Rule Changes section. We use \(\mathsf{issued\_assets}_{\mathsf{IN}}\) and \(\mathsf{issued\_assets}_{\mathsf{OUT}}\) to denote the input issuance state and output issuance state for a transaction, respectively.
For every transaction:
IssueAction
MUST be valid encodings of the types given in Issue Note Description, and MUST encode the same
\(\mathsf{AssetBase}\!\)
.IssueAction
:
flagsIssuance
field of IssueAction
, the node MUST set
\(\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\!\mathsf{final} = 1\!\)
.The following is a list of rationale for different decisions made in the proposal:
It is necessary to ensure that the balance of any issued Custom Asset never becomes negative within a shielded pool, along the lines of ZIP 209 8. However, unlike for the shielded ZEC pools, there is no individual transaction field that directly corresponds to both the issued and burnt amounts for a given Asset. Therefore, we require that all nodes maintain a record of the current amount in circulation for every issued Custom Asset, and update this record based on the issuance and burn transactions processed. This allows for efficient detection of balance violations for any Asset, in which scenario we specify a consensus rule to reject the transaction or block.
We limit the total issuance of any Asset to a maximum of \(\mathsf{MAX\_ISSUE}\!\) . This is a practical limit that also allows an issuer to issue the complete supply of an Asset in a single transaction.
Nodes also need to reject transactions that issue Custom Assets that have been previously finalized. The \(\mathsf{issued\_assets}\) map allows nodes to store whether or not a given Asset has been finalized.
Asset Features
This section details the construction of the subtree of hashes in the transaction digest that corresponds to issuance transaction data. Details of the overall changes to the transaction digest due to the OrchardZSA protocol can be found in ZIP 226 13. As in ZIP 244 18, the digests are all personalized BLAKE2b-256 hashes, and in cases where no elements are available for hashing, a personalized hash of the empty byte array is used.
A new issuance transaction digest algorithm is defined that constructs the subtree of the transaction digest tree of hashes for the issuance portion of a transaction. Each branch of the subtree will correspond to a specific subset of issuance transaction data. The overall structure of the hash is as follows; each name referenced here will be described in detail below:
issuance_digest ├── issue_actions_digest │ ├── issue_notes_digest │ ├── assetDescription │ └── flagsIssuance └── issuanceValidatingKey
In the specification below, nodes of the tree are presented in depth-first order.
A BLAKE2b-256 hash of the following values
T.5a: issue_actions_digest (32-byte hash output) T.5b: issuanceValidatingKey (32 bytes)
The personalization field of this hash is set to:
"ZTxIdSAIssueHash"
In case the transaction has no issuance components, ''issuance_digest'' is:
BLAKE2b-256("ZTxIdSAIssueHash", [])
A BLAKE2b-256 hash of Issue Action information for all Issuance Actions belonging to the transaction. For each Action, the following elements are included in the hash:
T.5a.i : notes_digest (32-byte hash output) T.5a.ii : assetDescription (field encoding bytes) T.5a.iii: flagsIssuance (1 byte)
The personalization field of this hash is set to:
"ZTxIdIssuActHash"
A BLAKE2b-256 hash of Note information for all Notes belonging to the Issuance Action. For each Note, the following elements are included in the hash:
T.5a.i.1: recipient (field encoding bytes) T.5a.i.2: value (field encoding bytes) T.5a.i.3: assetBase (field encoding bytes) T.5a.i.4: rho (field encoding bytes) T.5a.i.5: rseed (field encoding bytes)
The personalization field of this hash is set to:
"ZTxIdIAcNoteHash"
In case the transaction has no Issue Notes, ''issue_notes_digest'' is:
BLAKE2b-256("ZTxIdIAcNoteHash", [])
This is the raw encoding of an Orchard shielded payment address as defined in the protocol specification 28.
Note value encoded as little-endian 8-byte representation of 64-bit unsigned integer (e.g. u64 in Rust) raw value.
Asset Base encoded as the 32-byte representation of a point on the Pallas curve.
Nullifier encoded as 32-byte representation of a point on the Pallas curve.
The ZIP 212 32-byte seed randomness for a note.
The Asset description byte string.
An 8-bit value representing a set of flags. Ordered from LSB to MSB:
A byte encoding of issuance validating key for the bundle as defined in the Issuance Key Derivation section.
The per-input transaction digest algorithm to generate the signature digest in ZIP 244 19 is modified so that a signature digest is produced for each transparent input, each Sapling input, each Orchard action, and additionally for each Issuance Action. For Issuance Actions, this algorithm has the exact same output as the transaction digest algorithm, thus the txid may be signed directly.
The overall structure of the hash is as follows. We highlight the changes for the OrchardZSA protocol via the [ADDED FOR ZSA]
text label, and we omit the descriptions of the sections that do not change for the OrchardZSA protocol:
signature_digest ├── header_digest ├── transparent_sig_digest ├── sapling_digest ├── orchard_digest └── issuance_digest [ADDED FOR ZSA]
A BLAKE2b-256 hash of the following values
S.1: header_digest (32-byte hash output) S.2: transparent_sig_digest (32-byte hash output) S.3: sapling_digest (32-byte hash output) S.4: orchard_digest (32-byte hash output) S.5: issuance_digest (32-byte hash output) [ADDED FOR ZSA]
The personalization field remains the same as in ZIP 244 18.
Identical to that specified for the transaction identifier.
In addition to the parameters defined in the Fee calculation section of ZIP 317 20, the OrchardZSA protocol upgrade defines the following additional parameters:
Parameter | Value |
---|---|
\(issuance\_fee\) | \(100 \cdot marginal\_fee\) per issuance action (as defined below) |
Wallets implementing this specification SHOULD use a conventional fee, viz. \(zsa\_conventional\_fee\!\) , that is calculated in zatoshis. Additional definitions that are used in the formula for the calculation are in the table below:
Input | Units | Description |
---|---|---|
\(nOrchardActions\) | number | the number of OrchardZSA transfer actions (including ZEC actions) |
\(nTotalOutputsZSAIssuance\) | number | the total number of OrchardZSA issuance outputs (added across issuance actions) |
\(nCreateActions\) | number | the number of OrchardZSA issuance actions that issue a Custom Asset that is not present in the Global Issuance State |
The other inputs to this formula are taken from transaction fields defined in the Zcash protocol specification 29 and the global state. They are defined in the Fee calculation section of ZIP 317 20. Note that \(nOrchardActions\!\) , that is used in the computation of \(logical\_actions\!\) , is redefined in the above table, and now combines the actions for native ZEC as well as OrchardZSA transfer actions for Custom Assets.
The formula for the computation of the \(zsa\_logical\_actions\) (with the updated computation of \(logical\_actions\) as described above) is:
The formula for the computation of the \(zsa\_conventional\_fee\) is:
It is not a consensus requirement that fees follow this formula; however, wallets SHOULD create transactions that pay this fee, in order to reduce information leakage, unless overridden by the user.
The OrchardZSA fee calculation accounts for the additions to the Global Issuance State that are required for the OrchardZSA protocol. Every newly created Custom Asset adds a new row to the Global Issuance State. Subsequent issuance, finalization, or burn of existing Custom Assets only changes the values in the corresponding row.
This explains the need for a higher fee for the creation of entirely new Custom Assets, in order to disincentivize the creation of "junk" assets.
We choose to maintain the native ZEC Asset as the primary token for the Zcash blockchain, similar to how ETH is needed for ERC20 transactions to the benefit of the Ethereum ecosystem.
An alternative proposal for the OrchardZSA fee mechanism that was not adopted was to adopt a new type of fee, denominated in the custom Asset being issued or transferred. In the context of transparent transactions, such a fee allows miners to “tap into” the ZSA value of the transactions, rather than the ZEC value of transactions. However when transactions are shielded, any design that lifts value from the transaction would also leak information about it.
Wallets need to communicate the names of the Assets in a non-confusing way to users, since the byte representation of the Asset Identifier would be hard to read for an end user. Possible solutions are provided in the Specification: Asset Identifier section.
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:
For bridging purposes, the secure method of off-boarding Assets is to burn an Asset with the burning mechanism in ZIP 226 10. Users should be aware of issuers that demand the Assets be sent to a specific address on the Zcash chain to be redeemed elsewhere, as this may not reflect the real reserve value of the specific Wrapped Asset.
Although not enforced in the global state, it is RECOMMENDED that Zcash full validators keep track of the total supply of Assets as a mutable mapping \(\mathsf{issuanceSupplyInfoMap}\) from \(\mathsf{AssetId}\) to \((\mathsf{totalSupply}, \mathsf{finalize})\) in order to properly keep track of the total supply for different Asset Identifiers. This is useful for wallets and other applications that need to keep track of the total supply of Assets.
The fee mechanism described in this ZIP will follow the mechanism described in ZIP 317, and is described in ZIP 230 17.
TBD
1 | Information on BCP 14 — "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels" and "RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words" |
---|
2 | ZIP 32: Shielded Hierarchical Deterministic Wallets |
---|
3 | ZIP 32: Shielded Hierarchical Deterministic Wallets - Specification: Hardened-only key derivation |
---|
4 | ZIP 32: Shielded Hierarchical Deterministic Wallets - Hardened-only child key derivation |
---|
5 | ZIP 32: Shielded Hierarchical Deterministic Wallets - Key path levels |
---|
6 | ZIP 32: Shielded Hierarchical Deterministic Wallets - Orchard key path |
---|
7 | ZIP 200: Network Upgrade Mechanism |
---|
8 | ZIP 209: Prohibit Negative Shielded Chain Value Pool Balances |
---|
9 | ZIP 224: Orchard |
---|
10 | ZIP 226: Transfer and Burn of Zcash Shielded Assets |
---|
11 | ZIP 226: Transfer and Burn of Zcash Shielded Assets - Note Structure & Commitment |
---|
12 | ZIP 226: Transfer and Burn of Zcash Shielded Assets - Additional Consensus Rules for the assetBurn set |
---|
13 | ZIP 226: Transfer and Burn of Zcash Shielded Assets - TxId Digest |
---|
14 | ZIP 226: Transfer and Burn of Zcash Shielded Assets - Authorizing Data Commitment |
---|
15 | ZIP 230: Version 6 Transaction Format: Issuance Action Description (IssueAction) |
---|
16 | ZIP 230: Version 6 Transaction Format: Transaction Format |
---|
17 | ZIP 230: Version 6 Transaction Format: OrchardZSA Fee Calculation |
---|
18 | ZIP 244: Transaction Identifier Non-Malleability |
---|
19 | ZIP 244: Transaction Identifier Non-Malleability: Signature Digest |
---|
20 | ZIP 317: Proportional Transfer Fee Mechanism, Fee calculation |
---|
21 | BIP 43: Purpose Field for Deterministic Wallets |
---|
22 | BIP 340: Schnorr Signatures for secp256k1 |
---|
23 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 2: Notation |
---|
24 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.1: Payment Addresses and Keys |
---|
25 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 4.2.3: Orchard Key Components |
---|
26 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 4.10: SIGHASH Transaction Hashing |
---|
27 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.4.9.8: Group Hash into Pallas and Vesta |
---|
28 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.4.2: Orchard Raw Payment Addresses |
---|
29 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.1: Transaction Encoding and Consensus |
---|