Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIP-0014: User-facing Asset Fingerprint #64

Merged
merged 5 commits into from
Mar 26, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions CIP-0014/CIP-0014.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# CIP-0014 User-Facing Asset Id

# Preamble

---
CIP: 0014
Title: User-Facing Asset Id
Authors: Matthias Benkort <matthias.benkort@iohk.io>, Rodney Lorrimar <rodney.lorrimar@iohk.io>
Comments-Summary: A common format for displaying a unique identifier for assets.
Comments-URI: https://github.com/cardano-foundation/CIPs/wiki/Comments:CIP-0014
Status: Draft
Type: Standards
Created: 2020-02-01
License: CC-BY-4.0
---

# Abstract

This specification defines a unique user-facing asset id as a bech32-encoded blake2b-256 digest of the concatenation of the policy id and the asset name.

# Motivation

The Mary era of Cardano introduces the support for native assets. On the blockchain, native assets are uniquely identified by both their so-called policy id and asset name. Neither the
policy id nor the asset name are intended to be human-readable data.

On the one hand, the policy id is a hash digest of either a monetary script or a Plutus script. On the other hand, the asset name is an arbitrary bytestring of up to 32 bytes (which does not necessarily decode to a valid UTF-8 sequence). In addition, it is possible for an asset to have an empty asset name, or, for assets to have identical asset names under different policy ids.

Because assets are manipulated in several user-facing features, and also via hardware devices, it is useful to come up with a short(er) and human-readable identifier for assets that user can recognize and refer to when talking about assets.

# Specification

We define a unique identifier for assets in pseudo-code as:

```
assetId := encodeBech32
( datapart = hash
( algorithm = 'blake2b'
, digest-length = 32
, message = policyId | assetName
)
, humanReadablePart = 'token'
)
```

where `|` designates the concatenation of two bytestrings and the `digest-length` is given in `bytes`.

# Rationale

- The asset id needs to be unique and must therefore include both the policy id and the asset name.
- Using a hash gives us asset id of a same deterministic length which is short enough to display reasonably well on small screens.
- The hash digest is short but long enough to still allow ~2^256 possible different asset ids, which is _plenty_.
- We use bech32 as a user-facing encoding since it is both user-friendly and quite common within the Cardano eco-system (e.g. addresses, pool ids, keys).

# Backwards Compatibility

N/A

# Reference Implementation

<details>
<summary>Haskell</summary>

```hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeApplications #-}

-- package: base >= 4.0.0
import Prelude
import Data.Function
( (&) )

-- package: bech32 >= 1.0.2
import qualified Codec.Binary.Bech32 as Bech32

-- package: bech32-th >= 1.0.2
import Codec.Binary.Bech32.TH
( humanReadablePart )

-- package: bytestring >= 0.10.0.0
import Data.ByteString
( ByteString )

-- package: cryptonite >= 0.22
import Crypto.Hash
( hash )
import Crypto.Hash.Algorithms
( Blake2b_256 )

-- package: memory >= 0.14
import Data.ByteArray
( convert )

-- package: text >= 1.0.0.0
import Data.Text
( Text )


newtype PolicyId = PolicyId ByteString
newtype AssetName = AssetName ByteString
newtype AssetId = AssetId Text

mkAssetId :: PolicyId -> AssetName -> AssetId
mkAssetId (PolicyId pid) (AssetName name)
= (pid <> name)
& convert . hash @_ @Blake2b_256
& Bech32.encodeLenient hrp . Bech32.dataPartFromBytes
& AssetId
where
hrp = [humanReadablePart|token|]
```
</details>

# Copyright

CC-BY-4.0