Skip to content

Commit

Permalink
Merge pull request #975 from zcash/zip227-comm-asset-desc
Browse files Browse the repository at this point in the history
ZIP 227: Replace `asset_desc` with its hash in `AssetId`
  • Loading branch information
nuttycom authored Feb 25, 2025
2 parents 0c62177 + 9c32e13 commit 0fb1511
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 104 deletions.
117 changes: 57 additions & 60 deletions rendered/zip-0227.html
Original file line number Diff line number Diff line change
Expand Up @@ -268,47 +268,17 @@
</section>
</section>
<section id="specification-asset-identifier-asset-digest-and-asset-base"><h2><span class="section-heading">Specification: Asset Identifier, Asset Digest, and Asset Base</span><span class="section-anchor"> <a rel="bookmark" href="#specification-asset-identifier-asset-digest-and-asset-base"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>For every new Asset, there MUST be a new and unique Asset Identifier, denoted
<p>Every Asset has a globally-unique Asset Identifier, denoted
<span class="math">\(\mathsf{AssetId}\!\)</span>
. We define this to be a globally unique pair
<span class="math">\(\mathsf{AssetId} := (\mathsf{ik}, \mathsf{asset\_desc})\!\)</span>
, where
<span class="math">\(\mathsf{ik}\)</span>
is the issuance key and
<span class="math">\(\mathsf{asset\_desc}\)</span>
is a byte string.</p>
<p>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,
<span class="math">\(\mathsf{AssetDigest}\!\)</span>
, which is simply is a
<span class="math">\(\textsf{BLAKE2b-512}\)</span>
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.</p>
<p>Let</p>
<ul>
<li>
<span class="math">\(\mathsf{asset\_desc}\)</span>
be the asset description, which includes any information pertaining to the issuance, and is a non-empty byte sequence of at most 512 bytes which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later.</li>
<li>
<span class="math">\(\mathsf{ik}\)</span>
be the issuance validating key of the issuer, a public key used to verify the signature on the issuance transaction's SIGHASH.</li>
</ul>
<p>Define</p>
. A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the OrchardZSA protocol and potentially future Zcash shielded protocols.</p>
<p>From the Asset Identifier, we derive an Asset Digest</p>
<div class="math">\(\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{“ZSA-Asset-Digest”},\; \mathsf{EncodeAssetId}(\mathsf{AssetId})),\)</div>
<p>where</p>
<ul>
<li>
<span class="math">\(\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathsf{ik}, \mathsf{asset\_desc})) := \mathtt{0x00} || \mathsf{ik} || \mathsf{asset\_desc}\!\!\)</span>
.</li>
<li>Note that the initial
<span class="math">\(\mathtt{0x00}\)</span>
byte is a version byte.</li>
</ul>
<p>Define</p>
<div class="math">\(\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})\)</div>
<p>In the case of the OrchardZSA protocol, we define</p>
<div class="math">\(\mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest_{AssetId}})\)</div>
<p>where
<span class="math">\(\mathsf{GroupHash}^\mathbb{P}\)</span>
is defined as in <a id="footnote-reference-21" class="footnote_reference" href="#protocol-concretegrouphashpallasandvesta">31</a>.</p>
<span class="math">\(\mathsf{EncodeAssetId}(\mathsf{AssetId})\)</span>
is a canonical encoding scheme for the Asset Identifier.</p>
<p>From the Asset Digest, we derive a specific Asset Base that represents the Custom Asset within each shielded protocol:</p>
<div class="math">\(\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})\)</div>
<p>This Asset Base is included in shielded notes within the shielded protocol.</p>
<p>The relations between the Asset Identifier, Asset Digest, and Asset Base are shown in the following diagram:</p>
<figure class="align-center" align="center">
<img width="600" src="assets/images/zip-0227-asset-identifier-relation.png" alt="" />
Expand All @@ -319,13 +289,38 @@
(resp.
<span class="math">\(\mathsf{Protocol}\!\)</span>
) in the subscript (resp. superscript) when the Asset Identifier (resp. Protocol) is clear from the context.</p>
<p>Wallets MUST NOT display just the
<span class="math">\(\mathsf{asset\_desc}\)</span>
string to their users as the name of the Asset. Some possible alternatives include:</p>
<ul>
<li>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 system. 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.</li>
<li>The Asset Digest could be used as a more compact bytestring to uniquely determine an Asset, and wallets could support clients scanning QR codes to load Asset information into their wallets.</li>
</ul>
<section id="zip-227-asset-identifiers"><h3><span class="section-heading">ZIP 227 Asset Identifiers</span><span class="section-anchor"> <a rel="bookmark" href="#zip-227-asset-identifiers"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Assets issued using the protocol specified in this ZIP are scoped to the
<span class="math">\(\mathsf{ik}\)</span>
that issued them. Within that scope, Asset Identifier uniqueness is obtained by way of an asset description,
<span class="math">\(\mathsf{asset\_desc}\!\)</span>
, which includes any information pertaining to the issuance.
<span class="math">\(\mathsf{asset\_desc}\)</span>
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.</p>
<p>Define</p>
<div class="math">\(\mathsf{AssetDescHash} := \textsf{BLAKE2b-256}(\texttt{“ZSA-AssetDescCRH”},\; \mathsf{asset\_desc}),\)</div>
<p>We define Asset Identifiers for assets issued under this ZIP as</p>
<div class="math">\(\mathsf{AssetId} := (\mathsf{ik}, \mathsf{AssetDescHash})\)</div>
<p>and define their canonical encoding as</p>
<div class="math">\(\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathsf{ik}, \mathsf{AssetDescHash})) := \mathtt{0x00} || \mathsf{ik} || \mathsf{AssetDescHash}\)</div>
<p>Note that the initial
<span class="math">\(\mathtt{0x00}\)</span>
byte is a version byte, enabling future ZIPs to specify alternative issuance protocols and Asset Identifiers.</p>
<p>Wallets MUST NOT display just the
<span class="math">\(\mathsf{asset\_desc}\)</span>
string to their users as the name of the Asset. Some possible alternatives include:</p>
<ul>
<li>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 system. 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.</li>
<li>The Asset Digest could be used as a more compact bytestring to uniquely determine an Asset, and wallets could support clients scanning QR codes to load Asset information into their wallets.</li>
</ul>
</section>
<section id="orchardzsa-custom-assets"><h3><span class="section-heading">OrchardZSA Custom Assets</span><span class="section-anchor"> <a rel="bookmark" href="#orchardzsa-custom-assets"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>In the case of the OrchardZSA protocol, we define</p>
<div class="math">\(\mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest_{AssetId}})\)</div>
<p>where
<span class="math">\(\mathsf{GroupHash}^\mathbb{P}\)</span>
is defined as in <a id="footnote-reference-21" class="footnote_reference" href="#protocol-concretegrouphashpallasandvesta">31</a>.</p>
</section>
</section>
<section id="specification-issue-note-issuance-action-issuance-bundle-and-issuance-protocol"><h2><span class="section-heading">Specification: Issue Note, Issuance Action, Issuance Bundle and Issuance Protocol</span><span class="section-anchor"> <a rel="bookmark" href="#specification-issue-note-issuance-action-issuance-bundle-and-issuance-protocol"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<section id="issue-note"><h3><span class="section-heading">Issue Note</span><span class="section-anchor"> <a rel="bookmark" href="#issue-note"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
Expand Down Expand Up @@ -426,13 +421,16 @@
<ul>
<li>encode
<span class="math">\(\mathsf{asset\_desc}\)</span>
as a UTF-8 byte string of size up to 512.</li>
as a UTF-8 byte string.</li>
<li>compute
<span class="math">\(\mathsf{AssetDescHash}\)</span>
</li>
<li>compute
<span class="math">\(\mathsf{AssetDigest}\)</span>
from the issuance validating key
<span class="math">\(\mathsf{ik}\)</span>
and
<span class="math">\(\mathsf{asset\_desc}\)</span>
<span class="math">\(\mathsf{AssetDescHash}\)</span>
as decribed in the <a href="#specification-asset-identifier-asset-digest-and-asset-base">Specification: Asset Identifier, Asset Digest, and Asset Base</a> section.</li>
<li>compute
<span class="math">\(\mathsf{AssetBase}\)</span>
Expand Down Expand Up @@ -698,21 +696,20 @@
<ul>
<li>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.</li>
<li>The Custom Asset is described via a combination of the issuance validating key and an asset description string, to preclude the possibility of two different issuers creating colliding Custom Assets.</li>
<li>The
<span class="math">\(\mathsf{asset\_desc}\)</span>
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:
<ul>
<li>links for storage such as for NFTs.</li>
<li>metadata for Assets, encoded in any format.</li>
<li>bridging information for Wrapped Assets (chain of origin, issuer name, etc)</li>
<li>information to be committed by the issuer, though not enforceable by the protocol.</li>
</ul>
</li>
<li>We limit the size of the
<span class="math">\(\mathsf{asset\_desc}\)</span>
string to 512 bytes as it is a reasonable size to store metadata about the Asset, for example in JSON format.</li>
<li>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.</li>
</ul>
<section id="hash-of-the-asset-description"><h3><span class="section-heading">Hash of the asset description</span><span class="section-anchor"> <a rel="bookmark" href="#hash-of-the-asset-description"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>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:</p>
<ul>
<li>A hash output (32 bytes per Issue Action) incurs lower average bandwidth costs in issuance transactions than the asset description (previously up to 512 bytes).</li>
<li>The asset description can be longer than 512 bytes without incurring chain costs.</li>
<li>Including an asset description byte string directly in issuance transactions does not ensure that the "user-visible" asset description is consensus-visible, because the byte string could itself be a hash of another off-chain description (even if the consensus rules had required it to be a Unicode string instead of only recommending it).</li>
<li>The lack of key rotation in this issuance protocol means that it is not sufficient to mark an
<span class="math">\(\mathsf{ik}\)</span>
as trusted and then accept whatever asset descriptions are issued by it. Each Asset Identifier needs to be independently verified, which requires some out-of-band protocol that can also convey the corresponding asset description.</li>
<li>If issuance transactions include the asset descriptions directly, wallets will discover them during scanning. This is an "attractive nuisance" because it would result in wallets being more likely to expose the asset description directly to users without any verification that the received asset has the value that a user might expect from that description. By instead using a collision-resistant hash of an asset description, wallets are forced to look up the corresponding asset description when a payment is received in an unknown asset. That lookup can be mediated by a trusted party or common trusted registry of known assets, or else will need to be approved directly by a user who can personally assert their interest in that specific asset.</li>
</ul>
</section>
<section id="rationale-for-global-issuance-state"><h3><span class="section-heading">Rationale for Global Issuance State</span><span class="section-anchor"> <a rel="bookmark" href="#rationale-for-global-issuance-state"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>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 <a id="footnote-reference-35" class="footnote_reference" href="#zip-0209">8</a>. 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 case we specify a consensus rule to reject the transaction or block.</p>
<p>We limit the total issuance of any Asset to a maximum of
Expand Down
14 changes: 4 additions & 10 deletions rendered/zip-0230.html
Original file line number Diff line number Diff line change
Expand Up @@ -560,16 +560,10 @@
</thead>
<tbody>
<tr>
<td><code>varies</code></td>
<td><code>assetDescSize</code></td>
<td><code>compactSize</code></td>
<td>The length of the asset description string in bytes.</td>
</tr>
<tr>
<td><code>assetDescSize</code></td>
<td><code>asset_desc</code></td>
<td><code>byte[assetDescSize]</code></td>
<td>A byte sequence of length <code>assetDescSize</code> bytes which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later.</td>
<td><code>32</code></td>
<td><code>assetDescHash</code></td>
<td><code>byte[32]</code></td>
<td>A hash of the description of the Custom Asset.</td>
</tr>
<tr>
<td><code>varies</code></td>
Expand Down
Loading

0 comments on commit 0fb1511

Please sign in to comment.