CIP-0068:動態Metadata 技術解析

摘要

該提案為原生資產定義了一個元數據標準,不僅可以將輸出數據用於 NFT,還可以用於任何資產類別。

Motivation

本提案旨在解決 CIP-0025 的缺點

  • 缺乏可編程性;
  • 元數據更新/進化困難;
  • Plutus 驗證器無法檢查的元數據…

除了上述缺點, CIP-0025 還有其他 缺點

攻擊者可以使用不同的鑄造方式或使用不同的元數據格式來欺騙不知道 CIP-0025 的人,因為鑄造交易中的元數據被大多數平台以預設的方式解析。 由於CIP-0025並未強制執行,因此無法保證每個人都會了解它或遵守規則。 如果每個人都被迫遵守 CIP-0025 的規則,那麼你就限制了去中心化的能力。

該標準解決了所有這些問題,並提供了更多優勢,不僅適用於 NFT,也適用於可能出現的任何資產類別。 此外,本次CIP將引入一種對代幣進行分類的方法,以便錢包等第三方可以輕鬆知道它是什麼類型的代幣。

規格

注意事項

基本想法是發行兩種資產,其中一種引用另一種。 我們將這兩者稱為“參考 NFT”和“用戶代幣”,其中“用戶代幣”可以是 NFT、FT 或任何其他可轉讓且代表任何價值的資產類別。 因此,“用戶代幣”是存在於用戶錢包中的實際資產。

要找到“用戶代幣”的元數據,您需要查找“參考 NFT”的輸出,其中“參考 NFT”被鎖定,具體如何完成將在下面說明。 此外,此輸出包含一個保存元數據的datum。 這種做法的好處是資產的發行者可以決定鎖定或是進一步處理“參考 NFT”的輸出。 如果發行者想要完整的不可變元數據,可以將“參考 NFT”鎖定在不可使用的合約地址。 同樣,如果發行者希望 NFTs/FTs 進化或更新元數據,則可以將“參考 NFT”鎖定在發行者決定的具有任意邏輯的合約地址。

最後,通過這種結構,元數據可以被 PlutusV2 合約來當作參考輸入CIP-0031。 這將推動代幣領域的進一步創新。

”參考 NFT“ 的標籤 (asset_name_label)

這是註冊 asset_name_label 的值

asset_name_label class
(類別)
description
(說明)
100 NFT Reference NFT locked at a script containing the datum
(參考 NFT 鎖定在包含數據的合約中)

限制和條件

為了在“用戶代幣”和“參考 NFT”之間建立正確的關係,必須滿足一些條件。

  • 用戶代幣參考 NFT 必須在同一個policy ID 下。
  • 對於特定的“用戶代幣”,必須存在一個“參考 NFT”
  • 用戶代幣 和關聯的 參考 NFT 必須遵循標準命名模式。 兩種資產的資產名稱都以其各自的“asset_name_label”跟資產類別(class)定義的模式(例如 asset_name_label 222)

補充:

  1. 用戶代幣參考 NFT不需要在同一筆交易中鑄造。 鑄造順序也不重要。
  2. 可能存在多個用戶代幣引用同一個參考 NFT

The datum in the output with the reference NFT contains the metadata at the first field of the constructor 0. The version number is at the second field of this constructor. The third field allows for arbitrary plutus data. This could be useful to forward relevant data to the plutus script:

“參考 NFT”的輸出中的 datum 建構式第一區中的元數據為0。版本號位於此建構式的第二區中。 第三個允許任意 plutus 數據。 這可能有助於將相關數據轉發到 plutus 合約:

big_int = int / big_uint / big_nint
big_uint = #6.2(bounded_bytes)
big_nint = #6.3(bounded_bytes)

metadata =
  { * metadata => metadata }
  / [ * metadata ]
  / big_int
  / bounded_bytes
  
version = int

; 自定義用戶定義的 plutus 數據。
; 設置數據是可選的,但該字段是必需的
; 並且需要至少為 Unit/Void:#6.121([])
extra = plutus_data

datum = #6.121([metadata, version, extra])

222 NFT 標準

除了“參考 NFT”的必要標準外,我們還在本 CIP 中引入了兩個特定的代幣標準。 這裡的可能性是無限的,可以在此 CIP 之上為 FT、其他 NFT、半可替代代幣等建立更多標準。第一個是帶有註冊的 asset_name_label 的 222 NFT 標準

asset_name_label class
(類別)
description
(說明)
222 NFT NFT hold by the user’s wallet making use of CIP-0025 inner structure
(NFT 由用戶錢包持有,使用CIP-0025 內部結構)

Class (類別)

“用戶代幣”代表 NFT。

Pattern (模式)

用戶代幣參考 NFT 必須具有相同的名稱,前面有 asset_name_label 前綴詞。

例子:

  • 用戶代幣: (222)Test123
  • 參考 NFT: (100)Test123

Metadata (元數據)

這是元數據的狹義表示,遵循 CIP-0025 的結構。 在鏈上創建datum時,所有 UTF-8 編碼的值都需要轉換為bytes的表示形式。

files_details = 
  {
    ? name : bounded_bytes, ; UTF-8
    mediaType : bounded_bytes, ; UTF-8
    src : bounded_bytes ; UTF-8
    ; ... Additional properties are allowed
  }

metadata = 
  {
    name : bounded_bytes, ; UTF-8
    image : bounded_bytes, ; UTF-8
    ? mediaType : bounded_bytes, ; UTF-8
    ? description : bounded_bytes, ; UTF-8
    ? files : [* files_details]
    ; ... Additional properties are allowed
  }
  
; 自定義用戶定義的 plutus 數據。
; 設置數據是可選的,但該字段是必需的
; 並且需要至少為 Unit/Void:#6.121([])
extra = plutus_data

datum = #6.121([metadata, 1, extra]) ; version 1

作為 JSON 的範例datum:

{"constructor" : 0, "fields": [{"map": [{"k": "6E616D65", "v": "5370616365427564"}, {"k": "696D616765", "v": "697066733A2F2F74657374"}]}, {"int": 1}]}

第三方檢索元數據

假設第三方想要檢索以下NFT d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken
步驟如下:

  1. 用戶代幣 構建 參考 NFTd5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken
  2. 查找 參考 NFT 並找到它被鎖定的輸出。
  3. 通過進入建構式 0 的第一個字段,從輸出和查找元數據中獲取數據。
  4. 如果可能,轉換為 JSON 並將所有字符編碼為 UTF-8,或是將它們保留為十六進制。

從 Plutus 驗證器中檢索元數據

假設我們想要把以下 NFT 放進 Plutus 驗證器的 context 中
d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken

步驟如下:

  1. 從“用戶代幣”構建“參考 NFT”: “d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken”(鏈下)
  2. 查找“參考 NFT”並找到它被鎖定的輸出。(鏈下)
  3. 引用交易中的輸出。 (鏈下)
  4. 通過“參考 NFT”和“用戶代幣”的policy ID及資產名稱是否匹配來驗證引用輸出datum的有效性。(鏈上)

333 FT 標準

第二個引入的標準是帶有註冊的 asset_name_label 前綴詞的 333 FT 標準

asset_name_label
(前綴詞)
class
(類別)
description
(說明)
333 FT FT hold by the user’s wallet making use of Cardano foundation off-chain registry inner structure
(FT 由用戶錢包持有,利用 Cardano 基金會鏈下註冊表)

Class (類別)

用戶代幣 是 FT

Pattern(模式)

用戶代幣參考 NFT 必須具有相同的名稱,前面有 asset_name_label 前綴。

例子:

  • user token: (333)Test123
  • reference NFT: (100)Test123

Metadata (元數據)

這是元數據的狹義表示,遵循 Cardano 基金會鏈下元數據註冊表的結構。 在鏈上創建數據時,所有 UTF-8 編碼的鍵和值都需要轉換為bytes的表示形式。

; Explanation here: https://developers.cardano.org/docs/native-tokens/token-registry/cardano-token-registry/

metadata = 
  {
    name : bounded_bytes, ; UTF-8
    description : bounded_bytes, ; UTF-8
    ? ticker: bounded_bytes, ; UTF-8
    ? url: bounded_bytes, ; UTF-8
    ? logo: uri,
    ? decimals: int
    ; ... Additional properties are allowed
  }

; 作為 UTF-8 btye字串編碼的 URI。
; URI 格式必須是 `https`、`ipfs` 或 `data` 之一
; 不要將純文件資料編碼為 URI。
; 'logo' 不遵循 token-registry 的解釋,它需要是一個有效的 URI 而不是一個普通的btye字串。
; 僅使用以下媒體類型:`image/png`、`image/jpeg`、`image/svg+xml`

uri = bounded_bytes

; 自定義用戶定義的 plutus 數據。
; 設置數據是可選的,但該字段是必需的
; 並且需要至少為 Unit/Void:#6.121([])

extra = plutus_data
  
datum = #6.121([metadata, 1, extra]) ; version 1

作為 JSON 的範例datum:

{"constructor" : 0, "fields": [{"map": [{"k": "6E616D65", "v": "5370616365427564"}, {"k": "6465736372697074696F6E", "v": "54686973206973206D79207465737420746F6B656E"}]}, {"int": 1}]}

第三方檢索元數據

假設第三方想要檢索以下NFT d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(333)TestToken
步驟如下:

  1. 用戶代幣 構建 參考 NFTd5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken
  2. 查找 參考 NFT 並找到它被鎖定的輸出。
  3. 通過進入建構式 0 的第一個字段,從輸出和查找元數據中獲取數據。
  4. 如果可能,轉換為 JSON 並將所有字符編碼為 UTF-8,或是將它們保留為十六進制。

從 Plutus 驗證器中檢索元數據

假設我們想要把以下 NFT 放進 Plutus 驗證器的 context 中
d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(333)TestToken

步驟如下:

  1. 從“用戶代幣”構建“參考 NFT”: “d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken”(鏈下)
  2. 查找“參考 NFT”並找到它被鎖定的輸出。(鏈下)
  3. 引用交易中的輸出。 (鏈下)
  4. 通過“參考 NFT”和“用戶代幣”的policy ID及資產名稱是否匹配來驗證引用輸出datum的有效性。(鏈上)

基本原理

如果不分離“參考 NFT”和“用戶代幣”,會失去靈活性,並且移動“用戶代幣”將非常麻煩,因為每次都需要將元數據添加到“用戶代幣”發送。 因此將元數據和“用戶代幣”分開,並將元數據鎖定在另一個 UTxO 中,這樣就可以自由移動“用戶代幣”。

為了引用包含元數據正確的 UTxO,需要對其進行身份驗證,否則可能會被元數據欺騙。 實現這一目標的一種方法是向 UTxO 添加 NFT(“參考 NFT”)。 此 NFT 需要與“用戶代幣”具有相同的 Policy ID,且遵循標準中定義的資產名稱模式。 通過這種方式,您可以在“參考 NFT”和“用戶代幣”之間創建一個安全鏈接,而無需任何額外數據,鏈下和鏈上都可以利用這個標準。

鏈接的安全性源自鑄造 Policy 本身,因此使用正確的約束和規則編寫驗證器很重要,因為此 CIP 僅定義接口以保持盡可能高的靈活性。

向後兼容性

為了保持元數據與未來變化的兼容性,我們在數據中引入了一個“version”字段。