Skip to content
ZIP.tools

ZIP 227

Issuance of Zcash Shielded Assets

  • Draft
Proposal metadata
ID
227
Status
Draft
Category
Consensus
Owners
  • Pablo Kogan
  • Vivek Arte
  • Daira-Emma Hopwood
  • Jack Grigg
Created
2022-05-01
License
MIT
Contents
  1. Terminology
  2. Abstract
  3. Motivation
  4. Use Cases
  5. Requirements
  6. Specification: Issuance Keys, Issuer Identifier, and Issuance Authorization Signature Scheme
  7. Issuance Keys
  8. Issuer Identifier
  9. Issuance Authorization Signature Scheme
  10. Issuance Key Derivation
  11. Issuance Authorization Signing and Validation
  12. Specification: Asset Identifier, Asset Digest, and Asset Base
  13. Asset Identifier
  14. Asset Digests
  15. Asset Bases
  16. Specification: Issue Note, Issuance Action, Issuance Bundle and Issuance Protocol
  17. Issue Note
  18. Issuance Action
  19. Issuance Bundle
  20. Computation of ρ
  21. Issuance Protocol
  22. Specification: Reference Notes and Global Issuance State
  23. Reference Notes
  24. Global Issuance State
  25. Management of the Global Issuance State
  26. Specification: Consensus Rule Changes
  27. Addition to the Note Commitment Tree
  28. Rationale
  29. Hash of the asset description
Preamble
ZIP
227
Title
Issuance of Zcash Shielded Assets
Credits
  • Daniel Benarroch
  • Aurelien Nicolas
  • Deirdre Connolly
  • Teor
Status
Draft
Category
Consensus
Created
2022-05-01
License
MIT

Terminology

The key words "MUST", "MUST NOT", "SHOULD", "RECOMMENDED", and "MAY" in this document are to be interpreted as described in BCP 141 when, and only when, they appear in all capitals.

The term "network upgrade" in this document is to be interpreted as described in ZIP 2002.

The character § is used when referring to sections of the Zcash Protocol Specification.3

The terms "Orchard" and "Action" in this document are to be interpreted as described in ZIP 2244.

We define the following additional terms:

  • Asset: A type of note that can be transferred on the Zcash blockchain. Each Asset is identified by an Asset Identifier Specification: Asset Identifier, Asset Digest, and Asset Base.
    • ZEC is the default (and currently the only defined) Asset for the Zcash mainnet.
    • TAZ is the default (and currently the only defined) Asset for the Zcash testnet.
    • We use the term "Custom Asset" to refer to any Asset other than ZEC and TAZ.
  • Issuance Action: an instance of a single issuance of a Zcash Shielded Asset. It defines the issuance of a single Asset Identifier.
  • Issuance Bundle: the bundle in the transaction that contains all the issuance actions of that transaction.

Abstract

This ZIP (ZIP 227) proposes the Orchard Zcash Shielded Assets (OrchardZSA) protocol, in conjunction with ZIP 2265. 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 2266. This ZIP must only be implemented in conjunction with ZIP 2267. The proposed issuance mechanism is only valid for the OrchardZSA transfer protocol, because it produces notes that can only be transferred via this protocol.

Motivation

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 2268.

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 issue Assets that wrap tokens from those chains. This enables what we hope will be a useful set of applications.

Use Cases

The design presented in this ZIP enables issuance of shielded Assets in various modes:

  • The issuer may or may not know the receivers of the issued Asset in advance.
  • The Asset can be of non-fungible type, where each Asset type can be made part of a single “series”.
  • The supply of the Asset can be limited in advance or not.
  • The Asset can be a wrapped version of an Asset issued by another chain (as long as there is a bridge that supports transfer of that Asset between chains).

See the Concrete Applications section for more details.

Requirements

  • 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\mathsf{finalize} boolean that defines whether the specific Custom Asset can have further tokens issued or not.

Specification: Issuance Keys, Issuer Identifier, and Issuance Authorization Signature Scheme

Issuance Keys

The OrchardZSA Protocol adds the following keys used for issuance:

  1. The issuance authorizing key, denoted as isk\mathsf{isk}, is the key used to authorize the issuance of Asset Identifiers by a given issuer, and is only used by that issuer.
  2. The issuance validating key, denoted as ik\mathsf{ik}, is the key that is used to validate issuance transactions. This key is used to validate the issuance of Asset Identifiers by a given issuer.

The relations between these keys are shown in the following diagram:

../rendered/assets/images/zip-0227-key-components-zsa.png Diagram of Issuance Key Components for the OrchardZSA Protocol

Issuer Identifier

The identifier for a particular issuer is denoted by issuer\mathsf{issuer}. This identifier is used by all blockchain users (specifically the owners of notes for that Asset, and consensus validators) to associate the Asset in question with the issuer.

issuer\mathsf{issuer} is equal to the encoding ik_encoding\mathsf{ik\_encoding} (specified below in Derivation of issuance validating key) of the issuance validating key ik\mathsf{ik} used to validate the issuance of Asset Identifiers by that issuer.

Note: the equality of issuer\mathsf{issuer} and ik_encoding\mathsf{ik\_encoding} might not hold in future when key rotation is specified for issuance key pairs.

Issuance Authorization Signature Scheme

The issuance authorization signature, encoded in the issueAuthSig field of an issuance bundle, is used to authorize the issuance of Custom Assets by the issuer.

The issuance authorization signature scheme, IssueAuthSig\mathsf{IssueAuthSig}, comprises all the associated types and algorithms required for a signature scheme in §4.1.7 ‘Signature’9.

Batch verification MAY be used. Precomputation MAY be used if and only if it produces equivalent results.

Orchard ZSA Issuance Authorization Signature Scheme

In the OrchardZSA protocol, we instantiate the issuance authorization signature scheme IssueAuthSig\mathsf{IssueAuthSig} as a BIP-340 Schnorr signature over the secp256k1 curve. We define the constants as per the secp256k1 standard parameters, as described in BIP 340.

The associated types of the IssueAuthSig\mathsf{IssueAuthSig} signature scheme, which are identical to BIP 340, are as follows:

  • IssueAuthSig.Message=BY[N]\mathsf{IssueAuthSig.Message} = \mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}
  • IssueAuthSig.Signature=BY[64]∪{⊥}\mathsf{IssueAuthSig.Signature} = \mathbb{B}^{\mathbb{Y}^{[64]}} \cup \{\bot\}
  • IssueAuthSig.Public=BY[32]∪{⊥}\mathsf{IssueAuthSig.Public} = \mathbb{B}^{\mathbb{Y}^{[32]}} \cup \{\bot\}
  • IssueAuthSig.Private=BY[32]\mathsf{IssueAuthSig.Private} = \mathbb{B}^{\mathbb{Y}^{[32]}}

where BY[k]\mathbb{B}^{\mathbb{Y}^{[k]}} denotes the set of sequences of kk bytes, and BY[N]\mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}} denotes the type of byte sequences of arbitrary length, as defined in the Zcash protocol specification10.

The issuance authorizing key generation algorithm and the issuance validating key derivation algorithm are defined in the Issuance Key Derivation section, while the corresponding signing and validation algorithms are defined in the Issuance Authorization Signing and Validation section.

Issuance Key Derivation

Issuance authorizing key generation for hierarchical deterministic wallets

The issuance authorizing key is generated using the Hardened-only key derivation process defined in ZIP 3211. For the Issuance\mathsf{Issuance} context, we define the following constants:

  • Issuance.MKGDomain:=“ZcashSA_Issue_V1”\mathsf{Issuance.MKGDomain} := \texttt{“ZcashSA\_Issue\_V1”}
  • Issuance.CKDDomain:=0x81\mathsf{Issuance.CKDDomain} := \mathtt{0x81}

Let SS 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 mIssuance:=MKGhIssuance(S)m_{\mathsf{Issuance}} := \mathsf{MKGh}^{\mathsf{Issuance}}(S).

We use hardened-only child key derivation as defined in ZIP 3212 for the issuance authorizing key.

CKDsk((skpar,cpar),i)→(ski,ci)\mathsf{CKDsk}((\mathsf{sk}_{par},\mathsf{c}_{par}), i) \rightarrow (\mathsf{sk}_{i}, \mathsf{c}_{i}) :

  • Return CKDhIssuance((skpar,cpar),i)\mathsf{CKDh}^{\mathsf{Issuance}}((\mathsf{sk}_{par},\mathsf{c}_{par}), i)

We use the notation of ZIP 3213 for shielded HD paths, and define the issuance authorizing key path as mIssuance/purpose′/coin_type′/account′m_{\mathsf{Issuance}} / \mathit{purpose}' / \mathit{coin\_type}' / \mathit{account}'. We fix the path levels as follows:

  • purpose\mathit{purpose}: a constant set to 227227 (i.e. 0xe3\mathtt{0xe3}). purpose′\mathit{purpose}' is thus 227′227' (or 0x800000e3\mathtt{0x800000e3}) following the BIP 43 recommendation.14
  • coin_type\mathit{coin\_type}: Defined as in ZIP 3215.
  • account\mathit{account}: fixed to index 00.

From the generated (sk,c)(\mathsf{sk}, \mathsf{c}), we set the issuance authorizing key to be isk:=sk\mathsf{isk} := \mathsf{sk}.

Derivation of issuance validating key

Define IssueAuthSig.DerivePublic  ⦂  (isk  ⦂  IssueAuthSig.Private)→IssueAuthSig.Public\mathsf{IssueAuthSig.DerivePublic} \;{\small ⦂}\; (\mathsf{isk} \;{\small ⦂}\; \mathsf{IssueAuthSig.Private}) \to \mathsf{IssueAuthSig.Public} as:

  • ik:=PubKey(isk)\mathsf{ik} := \textit{PubKey}(\mathsf{isk})
  • Return ⊥\bot if the PubKey\textit{PubKey} algorithm invocation fails, otherwise return ik\mathsf{ik}.

where the PubKey\textit{PubKey} algorithm is defined in BIP 34016, and the output of the algorithm is in big-endian order as defined in BIP 340.

The encoding of this validating key, ik_encoding\mathsf{ik\_encoding}, includes an initial byte indicating the signature scheme, which MUST be 0x00\mathtt{0x00} indicating BIP 340. That is, ik_encoding=[0x00] ∣∣ ik\mathsf{ik\_encoding} = [\mathtt{0x00}] \,||\, \mathsf{ik}. This enables future ZIPs to specify alternative signature schemes. Note that this encoding currently only appears in the issuer field of an issuance bundle.

It is possible for the PubKey\textit{PubKey} algorithm to fail with very low probability, which means that IssueAuthSig.DerivePublic\mathsf{IssueAuthSig.DerivePublic} could return ⊥\bot with very low probability. If this happens, discard the keys and repeat with a different isk\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 3217. It provides further anonymity and the ability to delegate issuance of an Asset (or in the future, use a multi-signature protocol) while the rest of the keys remain safe in the wallet.

Issuance Authorization Signing and Validation

Define IssueAuthSig.Sign  ⦂  (isk  ⦂  IssueAuthSig.Private)×(M  ⦂  IssueAuthSig.Message)→IssueAuthSig.Signature\mathsf{IssueAuthSig.Sign} \;{\small ⦂}\; (\mathsf{isk} \;{\small ⦂}\; \mathsf{IssueAuthSig.Private}) \times (M \;{\small ⦂}\; \mathsf{IssueAuthSig.Message}) \to \mathsf{IssueAuthSig.Signature} as:

  • Let the auxiliary data a=[0x00]32a = [\mathtt{0x00}]^{32}.
  • Let σ=Sign(isk,M)\text{σ} = \mathsf{Sign}(\mathsf{isk}, M) with auxiliary data aa.
  • Return ⊥\bot if the Sign\mathsf{Sign} algorithm fails in the previous step, otherwise return σ\text{σ}.

where the Sign\mathsf{Sign} algorithm is defined in BIP 34018. Note that IssueAuthSig.Sign\mathsf{IssueAuthSig.Sign} could return ⊥\bot with very low probability.

Define IssueAuthSig.Validate  ⦂  (ik  ⦂  IssueAuthSig.Public)×(M  ⦂  IssueAuthSig.Message)×(σ  ⦂  IssueAuthSig.Signature)→B\mathsf{IssueAuthSig.Validate} \;{\small ⦂}\; (\mathsf{ik} \;{\small ⦂}\; \mathsf{IssueAuthSig.Public}) \times (M \;{\small ⦂}\; \mathsf{IssueAuthSig.Message}) \times (\text{σ} \;{\small ⦂}\; \mathsf{IssueAuthSig.Signature}) \to \mathbb{B} as:

  • Return 00 if σ=⊥\text{σ} = \bot.
  • Return 11 if Verify(key,M,σ)\mathsf{Verify}(\mathsf{key}, M, \text{σ}) succeeds, otherwise 00.

where the Verify\mathsf{Verify} algorithm is defined in BIP 34019.

The issueAuthSig\mathtt{issueAuthSig} field of an issuance bundle encodes the signature with an initial byte indicating the signature scheme, which MUST be 0x00\mathtt{0x00} indicating BIP 340. That is, issueAuthSig=[0x00] ∣∣ σ\mathtt{issueAuthSig} = [\mathtt{0x00}] \,||\, \text{σ}. This enables future ZIPs to specify alternative signature schemes.

Specification: Asset Identifier, Asset Digest, and Asset Base

The definition of the Asset Identifier, and that of the Asset Digest and Asset Base for a given Asset Identifier, will be described in this section. For context, the relations between the Asset Identifier, Asset Digest, and Asset Base are shown in the following diagram:

../rendered/assets/images/zip-0227-asset-identifier-relation.png Diagram relating the Asset Identifier, Asset Digest, and Asset Base.

Note: To keep notations light and concise, we may omit AssetId\mathsf{AssetId} in the subscript when the Asset Identifier is clear from the context.

Asset Identifier

Every Asset has a globally-unique Asset Identifier, denoted AssetId\mathsf{AssetId}. A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the OrchardZSA protocol and potentially future Zcash shielded protocols.

ZIP 227 Asset Identifiers

Assets issued using the protocol specified in this ZIP are scoped to the issuer\mathsf{issuer} that issued them. Within that scope, Asset Identifier uniqueness is obtained by way of an asset description, asset_desc\mathsf{asset\_desc}, which includes any information pertaining to the issuance. asset_desc\mathsf{asset\_desc} is a non-empty byte sequence which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later.

Define

assetDescHash:=BLAKE2b-256(“ZSA-AssetDescCRH”,  asset_desc),\mathsf{assetDescHash} := \textsf{BLAKE2b-256}(\texttt{“ZSA-AssetDescCRH”},\; \mathsf{asset\_desc}),

We define Asset Identifiers for Assets issued under this ZIP as

AssetId:=(issuer,assetDescHash)\mathsf{AssetId} := (\mathsf{issuer}, \mathsf{assetDescHash})

and define their canonical encoding as

EncodeAssetId(AssetId)=EncodeAssetId((issuer,assetDescHash)):=[0x00] ∣∣ issuer ∣∣ assetDescHash\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathsf{issuer}, \mathsf{assetDescHash})) := [\mathtt{0x00}] \,||\, \mathsf{issuer}\,||\,\mathsf{assetDescHash}

Note that the initial 0x00\mathtt{0x00} byte is a version byte, enabling future ZIPs to specify alternative issuance protocols and Asset Identifiers. (This should not be confused with the first byte of issuer\mathsf{issuer}, currently equal to the first byte of ik_encoding\mathsf{ik\_encoding}, that indicates the issuance signature scheme.)

Wallets MUST NOT display just the asset_desc\mathsf{asset\_desc} string to their users as the name of the Asset. Some possible alternatives include:

  • Wallets could allow clients to provide an additional configuration file that stores a one-to-one mapping of names to Asset Identifiers via a petname system20. This allows clients to rename the Assets in a way they find useful. Default versions of this file with well-known Assets listed can be made available online as a starting point for clients.
  • The Asset Digest could be used as a more compact byte sequence to uniquely determine an Asset, and wallets could support clients scanning QR codes to load Asset information into their wallets.

Asset Digests

From the Asset Identifier, we derive an Asset Digest

AssetDigestAssetId:=BLAKE2b-512(“ZSA-Asset-Digest”,  EncodeAssetId(AssetId)),\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{“ZSA-Asset-Digest”},\; \mathsf{EncodeAssetId}(\mathsf{AssetId})),

where EncodeAssetId(AssetId)\mathsf{EncodeAssetId}(\mathsf{AssetId}) is the canonical encoding scheme for the Asset Identifier.

Asset Bases

From the Asset Digest, we derive a specific Asset Base that represents the Custom Asset within each shielded protocol:

AssetBaseAssetId:=ZSAValueBase(AssetDigestAssetId)\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})

This Asset Base is included in shielded notes within the shielded protocol.

OrchardZSA Asset Bases

In the case of the OrchardZSA protocol, we define

ZSAValueBase(AssetDigest):=GroupHashP("z.cash:OrchardZSA",AssetDigest)\mathsf{ZSAValueBase}(\mathsf{AssetDigest}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest})

where GroupHashP\mathsf{GroupHash}^\mathbb{P} is defined as in21.

../rendered/assets/images/zip-0227-asset-identifier-relation-orchard-zsa.png Diagram relating the Issuer identifier, asset description, asset description hash, Asset Identifier, Asset Digest, and Asset Base for the OrchardZSA Protocol.

Specification: Issue Note, Issuance Action, Issuance Bundle and Issuance Protocol

Issue Note

Let ℓvalue\ell_{\mathsf{value}} be as defined in §5.3 ‘Constants’22. An Issue Note represents that a value v:{0..2ℓvalue−1}\mathsf{v} : \{0 .. 2^{\ell_{\mathsf{value}}} - 1\} of a specific Custom Asset is issued to a recipient. An Issue Note is a tuple (d,pkd,v,AssetBase,ρ,rseed)(\mathsf{d}, \mathsf{pk_d}, \mathsf{v}, \mathsf{AssetBase}, \text{ρ}, \mathsf{rseed}), where:

  • d:B[ℓd]\mathsf{d}: \mathbb{B}^{[\ell_{\mathsf{d}}]} is the diversifier of the recipient's shielded payment address, as in §3.2 ‘Notes’23.
  • pkd:KAOrchard.Public\mathsf{pk_d}: \mathsf{KA}^{\mathsf{Orchard}}.\mathsf{Public} is the recipient's diversified transmission key, as in §3.2 ‘Notes’24.
  • v:{0..2ℓvalue−1}\mathsf{v} : \{0 .. 2^{\ell_{\mathsf{value}}} - 1\} is the value of the note in terms of the number of Asset tokens.
  • AssetBase:P∗\mathsf{AssetBase}: \mathbb{P}^* is the Asset Base corresponding to the ZSA being issued in the Issue Note.
  • ρ:FqP\text{ρ}: \mathbb{F}_{q_{\mathbb{P}}} is used to derive the nullifier of the note, and is computed as in Computation of ρ.
  • rseed:B[Y32]\mathsf{rseed}: \mathbb{B}^{[\mathbb{Y}^{32}]} MUST be sampled uniformly at random by the issuer.

ZIP 23025 defines, in IssueNoteDescription, field encodings which together with issuer\mathsf{issuer} from the parent Issuance Bundle and AssetDescHash\mathsf{AssetDescHash} from the parent Issuance Action, specify an Issue Note.

Let NoteIssue\mathsf{Note^{Issue}} be the type of an Issue Note, i.e.

NoteIssue:=B[ℓd]×KAOrchard.Public×{0..2ℓvalue−1}×P∗×FqP×B[Y32].\mathsf{Note^{Issue}} := \mathbb{B}^{[\ell_{\mathsf{d}}]} \times \mathsf{KA}^{\mathsf{Orchard}}.\mathsf{Public} \times \{0 .. 2^{\ell_{\mathsf{value}}} - 1\} \times \mathbb{P}^* \times \mathbb{F}_{q_{\mathbb{P}}} \times \mathbb{B}^{[\mathbb{Y}^{32}]}.

The note commitments of Issue Notes are computed in the same manner as for OrchardZSA Notes. They will be added to the note commitment tree as any other shielded note when the transaction issuing the Asset is included on chain. 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.

Issuance Action

An issuance action, IssueAction, is the instance of issuing a specific Custom Asset, and contains the following fields:

  • assetDescHash: the hash of the Asset description, as defined in the ZIP 227 Asset Identifiers section.
  • vNotes: an array of Issue Notes containing the unencrypted output notes to the recipients of the Asset.
  • flagsIssuance: a byte that stores the finalize\mathsf{finalize} boolean that defines whether the issuance of that specific Custom Asset is finalized or not.

The finalize\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 23026.

Issuance Bundle

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:

  • issuer: the issuer identifier, that allows the validators to verify that the AssetId\mathsf{AssetId} is properly associated with the issuer.
  • vIssueActions: an array of issuance actions, of type IssueAction.
  • issueAuthSig: the encoding of a signature of the transaction SIGHASH, signed by the issuance authorizing key, isk\mathsf{isk}, that validates the issuance.

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 23027.

Computation of ρ

We define a function DeriveIssuedRho:FqP×{0..232−1}×{0..232−1}→FqP\mathsf{DeriveIssuedRho} : \mathbb{F}_{q_{\mathbb{P}}} \times \{0 .. 2^{32} - 1\} \times \{0 .. 2^{32} - 1\} \to \mathbb{F}_{q_{\mathbb{P}}} for Issue Notes in the OrchardZSA Protocol as follows:

DeriveIssuedRho(nf,iA,iN):=ToBaseOrchard(PRFexpand(I2LEOSP256(nf),[0x84] ∣∣ I2LEOSP32(iA) ∣∣ I2LEOSP32(iN))),\mathsf{DeriveIssuedRho}(\mathsf{nf}, \mathsf{i_{A}}, \mathsf{i_{N}}) := \mathsf{ToBase}^{\mathsf{Orchard}}\big(\mathsf{PRF}^{\mathsf{expand}}\big(\mathsf{I2LEOSP}_{256}(\mathsf{nf}), [\mathtt{0x84}] \,||\, \mathsf{I2LEOSP}_{32}(\mathsf{i_{A}}) \,||\, \mathsf{I2LEOSP}_{32}(\mathsf{i_{N}})\big)\big),

where ToBaseOrchard\mathsf{ToBase}^{\mathsf{Orchard}} is defined in §4.2.3 ‘Orchard Key Components’28, and PRFexpand\mathsf{PRF}^{\mathsf{expand}} is defined in §5.4.2 ‘Pseudo Random Functions’29.

The ρ\text{ρ} field of an Issue Note is computed as

ρ:=DeriveIssuedRho(nf0,0,indexAction,indexNote),\text{ρ} := \mathsf{DeriveIssuedRho}(\mathsf{nf}_{0,0}, \mathsf{index_{Action}}, \mathsf{index_{Note}}),

where nf0,0\mathsf{nf}_{0,0} is the nullifier for the input note in the first Action in the first Action Group of the OrchardZSA Bundle of the transaction, indexAction\mathsf{index_{Action}} is the zero-based index of the Issuance Action in the Issuance Bundle, and indexNote\mathsf{index_{Note}} is the zero-based index of the Issue Note in the Issuance Action.

NOTE: This implicitly requires that there always is an Action Group in the OrchardZSA bundle of the transaction. This is enforced by a consensus rule in the Specification: Consensus Rule Changes section.

Issuance Protocol

The issuer program performs the following operations:

For all actions IssueAction:

  • encode asset_desc\mathsf{asset\_desc} as a UTF-8 byte string.

  • compute assetDescHash\mathsf{assetDescHash}

  • compute AssetDigest\mathsf{AssetDigest} from the issuer identifier issuer\mathsf{issuer} and assetDescHash\mathsf{assetDescHash} as decribed in the Specification: Asset Identifier, Asset Digest, and Asset Base section.

  • compute AssetBase\mathsf{AssetBase} from AssetDigest\mathsf{AssetDigest} as decribed in the Specification: Asset Identifier, Asset Digest, and Asset Base section.

  • set the finalize\mathsf{finalize} boolean as desired (if more issuance actions are to be created for this AssetBase\mathsf{AssetBase}, set finalize=0\mathsf{finalize} = 0, otherwise set finalize=1\mathsf{finalize} = 1).

  • for each recipient ii:

    • generate an Issue Note, notei=(di,pkdi,vi,AssetBase,ρi,rseedi)\mathsf{note}_i = (\mathsf{d}_i, \mathsf{pk}_{\mathsf{d}_i}, \mathsf{v}_i, \mathsf{AssetBase}, \text{ρ}_i, \mathsf{rseed}_i).
    • encode the notei\mathsf{note}_i into the vector vNotes of the IssueAction.
  • encode the IssueAction into the vector vIssueActions of the bundle.

For the IssueBundle (see “ZSA Issuance Bundle Fields” in30):

  • encode the vIssueActions vector.
  • fill the issuerLength and issuer fields using issuer\mathsf{issuer}.
  • sign the SIGHASH transaction hash with the issuance authorizing key, isk\mathsf{isk}, using the IssueAuthSig\mathsf{IssueAuthSig} signature scheme. The signature is then added to the issuance bundle.

Note: The note 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.

Specification: Reference Notes and Global Issuance State

Reference Notes

A reference note for a Custom Asset MUST be included by the issuer as the first Note in the Action of the Issuance Bundle where that Custom Asset is being issued for the first time.

A reference note for a Custom Asset is an Issue Note where the value v\mathsf{v} is set to 00, the Asset Base (AssetBase\mathsf{AssetBase}) corresponds to that of the Custom Asset, and the recipient address (d,pkd)(\mathsf{d}, \mathsf{pk}_{\mathsf{d}}) is set to the default diversified payment address (i.e. the diversified payment address with diversifier index 00) derived from the all-zero Orchard spending key using the algorithm specified in §4.2.3 ‘Orchard Key Components’31. This corresponds to a 43-byte u8 array with the following entries:

[
  204, 54, 96, 25, 89, 33, 59, 107, 12, 219, 150, 167, 92, 23, 195, 166, 104, 169, 127, 13, 106,
  140, 92, 225, 100, 165, 24, 234, 155, 169, 165, 14, 167, 81, 145, 253, 134, 27, 15, 241, 14,
  98, 176,
]

Global Issuance State

The maximum total supply of any issued Custom Asset is denoted by the constant MAX_ISSUE:=264−1\mathsf{MAX\_ISSUE} := 2^{64} - 1.

Issuance requires the following additions to the global state:

A map, issued_assets:P∗→{0..MAX_ISSUE}×B×NoteIssue\mathsf{issued\_assets} : \mathbb{P}^* \to \{0 .. \mathsf{MAX\_ISSUE}\} \times \mathbb{B} \times \mathsf{Note^{Issue}}, from the Asset Base, AssetBase:P∗\mathsf{AssetBase} : \mathbb{P}^*, to a tuple (balance,final,noteref)(\mathsf{balance}, \mathsf{final}, \mathsf{note_{ref}}), for every Asset that has been issued. We use the notation issued_assets(AssetBase).balance\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{balance}, issued_assets(AssetBase).final\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{final}, and issued_assets(AssetBase).noteref\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{note_{ref}} to access, respectively, the elements of the tuple stored in the global state for a given AssetBase\mathsf{AssetBase}. If issued_assets(AssetBase)=⊥\mathsf{issued\_assets}(\mathsf{AssetBase}) = \bot, it is assumed that issued_assets(AssetBase).balance=0\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{balance} = 0, issued_assets(AssetBase).final=0\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{final} = 0, and issued_assets(AssetBase).noteref=⊥\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{note_{ref}} = \bot.

For any Asset represented by AssetBase\mathsf{AssetBase}:

  • issued_assets(AssetBase).balance∈{0..MAX_ISSUE}\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{balance} \in \{0 .. \mathsf{MAX\_ISSUE}\} stores the amount of the Asset in circulation, computed as the amount of the Asset that has been issued less the amount of the Asset that has been burnt.
  • issued_assets(AssetBase).final:B\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{final} : \mathbb{B} is a Boolean that stores the finalization status of the Asset (i.e.: whether the finalize\mathsf{finalize} flag has been set to 11 in any preceding issuance transaction for the Asset). The value of issued_assets(AssetBase).final\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{final} for any AssetBase\mathsf{AssetBase} cannot be changed from 11 to 00.
  • issued_assets(AssetBase).noteref:NoteIssue\mathsf{issued\_assets}(\mathsf{AssetBase}).\mathsf{note_{ref}} : \mathsf{Note^{Issue}} stores the reference note for the Asset, as defined in the Reference Notes section.

Management of the Global Issuance State

The issuance state, that is, the issued_assets\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:

  • The input issuance state for the activation block of the OrchardZSA protocol is the empty map.
  • The input issuance state for the first transaction of a block is the final issuance state of the immediately preceding block.
  • The input issuance state of each subsequent transaction in the block is the output issuance state of the immediately preceding transaction.
  • The final issuance state of a block is the output issuance state of the last transaction in the block.

We describe the consensus rule changes that govern the management of the global issuance state in the Specification: Consensus Rule Changes section. We use issued_assetsIN\mathsf{issued\_assets}_{\mathsf{IN}} and issued_assetsOUT\mathsf{issued\_assets}_{\mathsf{OUT}} to denote the input issuance state and output issuance state for a transaction, respectively.

Specification: Consensus Rule Changes

Let SigHash\mathsf{SigHash} be the SIGHASH transaction hash of this transaction, as defined in §4.10 ‘SIGHASH Transaction Hashing’32 with the modifications described in ZIP 22633, using SIGHASH_ALL\mathsf{SIGHASH\_ALL}.

For every transaction:

  • The nActionGroupsOrchard field MUST have a value of either 0 or 1 and the nAGExpiryHeight field MUST have a value of 0.
  • The output issuance state of the transaction MUST be initialized to be the same as the input issuance state, issued_assetsOUT=issued_assetsIN\mathsf{issued\_assets}_{\mathsf{OUT}} = \mathsf{issued\_assets}_{\mathsf{IN}}.
  • The assetBurn\mathsf{assetBurn} set MUST satisfy the consensus rules specified in ZIP 22634.
  • It MUST be the case that for all (AssetBase,v)∈assetBurn(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}, issued_assetsOUT(AssetBase).balance≥v\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{balance} \geq \mathsf{v}. The node then MUST update issued_assetsOUT(AssetBase)\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}) prior to processing the issuance bundle in the following manner. For every (AssetBase,v)∈AssetBurn(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{AssetBurn}, issued_assetsOUT(AssetBase).balance=issued_assetsOUT(AssetBase).balance−v\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{balance} = \mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{balance} - \mathsf{v}.

If the transaction contains an issuance bundle:

  • It MUST also contain at least one OrchardZSA Action Group.
  • The encoding ik_encoding\mathsf{ik\_encoding} of the issuance key ik\mathsf{ik} used to validate the issuance authorization signature MUST be taken from the issuer field, and MUST start with the byte value 0x00\mathtt{0x00} indicating a BIP 340 public key.
  • The issuance authorization signature, issueAuthSig\mathsf{issueAuthSig}, MUST be a valid IssueAuthSig\mathsf{IssueAuthSig} signature over SigHash\mathsf{SigHash}, i.e. IssueAuthSig. ⁣Validate(ik,SigHash,issueAuthSig)=1\mathsf{IssueAuthSig}.\!\mathsf{Validate}(\mathsf{ik}, \mathsf{SigHash}, \mathsf{issueAuthSig}) = 1.
  • For every issuance action description (IssueActioni, 1≤i≤nIssueActions\mathsf{IssueAction}_\mathsf{i},\ 1 \leq i \leq \mathtt{nIssueActions}) in the issuance bundle:
    • Every IssueNoteDescription in the IssueAction MUST be a valid field encoding as defined in ZIP 23035.

    • Let an Issue Note (with type NoteIssue\mathsf{Note^{Issue}}) be constructed from the fields of each IssueNoteDescription, with the AssetBase\mathsf{AssetBase} derived from the assetDescHash field of the IssueAction and the issuer field of the issuance bundle, as described in the Specification: Asset Identifier, Asset Digest, and Asset Base section.

    • It MUST be the case that issued_assetsOUT(AssetBase).final≠1\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{final} \neq 1.

    • If issued_assetsOUT(AssetBase).noteref=⊥\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{note_{ref}} = \bot, then let new_noteref\mathsf{new\_note_{ref}} be the first Issue Note in the Issuance Action.

      • The recipient address (d,pkd)(\mathsf{d}, \mathsf{pk}_{\mathsf{d}}) of new_noteref\mathsf{new\_note_{ref}} MUST be the default diversified payment address derived from the all-zero Orchard spending key, as described in the Reference Notes section.
      • The value of new_noteref\mathsf{new\_note_{ref}} MUST be 00.
      • The node MUST update issued_assetsOUT(AssetBase).noteref=new_noteref\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{note_{ref}} = \mathsf{new\_note_{ref}}.
    • For every Issue Note, notej\mathsf{note}_j for 1≤j≤nNotes1 \leq j \leq \mathtt{nNotes} in IssueAction:

      • The ρ\text{ρ} field of the issue note MUST have been computed as described in the Computation of ρ section.
      • It MUST be the case that issued_assetsOUT.balance+vj≤MAX_ISSUE\mathsf{issued\_assets}_{\mathsf{OUT}}.\mathsf{balance} + \mathsf{v}_j \leq \mathsf{MAX\_ISSUE}, where vj\mathsf{v}_j is the value of notej\mathsf{note}_j. The node then MUST update issued_assetsOUT.balance=issued_assetsOUT.balance+vj\mathsf{issued\_assets}_{\mathsf{OUT}}.\mathsf{balance} = \mathsf{issued\_assets}_{\mathsf{OUT}}.\mathsf{balance} + \mathsf{v}_j.
      • The node MUST compute the note commitment, cmi,j\mathsf{cm}_{\mathsf{i,j}}, as defined in the Note Structure and Commitment section of ZIP 22636.
    • If finalize=1\mathsf{finalize} = 1 within the flagsIssuance field of IssueAction, the node MUST set issued_assetsOUT(AssetBase).final=1\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{final} = 1.

Addition to the Note Commitment Tree

If the transaction is added to the block chain, the note commitments of all the OrchardZSA Notes and the Issue Notes in the transaction are added to the note commitment tree of the associated treestate. The order of addition to the tree is as specified below:

  • For each Action Group in the OrchardZSA Bundle:
    • For every Action in the Action Group, append the note commitment of every new OrchardZSA note in the Action to the note commitment tree.
  • For each Issue Action in the Issue Bundle:
    • For every Issue Note in the Issue Action, append the note commitment of the Issue Note to the note commitment tree.

Rationale

The following is a list of rationale for different decisions made in the proposal:

  • The issuance key structure is independent of the original key tree, but derived in an analogous manner (via ZIP 32). This keeps the issuance details and the Asset Identifiers consistent across multiple shielded pools. It also separates the issuance authority from the spend authority, allowing for the potential transfer of issuance authority without compromising the spend authority.
  • The Custom Asset is described via a combination of the issuer identifier and an asset description string, to preclude the possibility of two different issuers creating colliding Custom Assets.
  • The requirement of at least one OrchardZSA Action Group in the presence of an issue bundle is both to allow for the computation of the ρ\text{ρ} field of the issue notes, as well as to prevent replay attacks. 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.

Hash of the asset description

In an earlier version of this ZIP, the asset description was a direct component of the Asset Identifier, and was stored on-chain in each issuance transaction. The Asset Identifier and issuance transactions now instead include a collision-resistant hash of the asset description, for the following reasons:

Citation graph

Hover or tap a node to see its title and citations.
Loading citation graph…