Nervos 上的 NFT 协议规范提案来啦!
日前,Nervos 研究员 Cipher 提出了最简 NFT 草案规范征集提案,从中我们可以看到这提案中的 NFT 不但可以透过 type id 等基础设施保证 NFT 物件的唯一性,同时数字落款、发行方扩展信息等等也都能更贴切 NFT 的产品业务使用需求。和 sUDT 一样,在 Nervos 上的 NFT 资产一样是「一等公民」,在资产安全上可以得到最大的保护。同时,NFT 的许多圈层是艺术家、收藏家等非区块链领域用户,Nervos 特有的互操作性 2.0 组件,如 pw-core 还能确保这些没有区块链钱包的用户,也能够轻易地透过生物识别等系统,无缝使用 Nervos 上的 NFT 应用,从而让 Nervos 能够进一步的服务更多的圈外用户。
概述
本 S-NFT 协议具备了以下功能:
公开发行人用来作为认证的信息 属性相同的多个 NFT 的类型设置 可设置 NFT 的发行数量上限 支持套装,不同的 NFT 可以构成一个套装,方便用户收集 支持兑换功能,适用于票务等场景 支持兑换后继续流转,适用于票根流转等场景 支持转让配置,发行方可精细设置转让权限 支持可交换性、永久锁定和自毁功能等配置 支持拥有者(收藏家)进行数字落款 支持定义扩展信息
基础的 S-NFT 发行逻辑首先是创建一个 Issuer cell,该 Cell 定义了发行方的基本信息。接着用它来创建一个 NFT Class Cell,它包含了某一种 NFT 的特定信息。有了 NFT Class Cell,任何人可发行 NFT Cell 并给到用户们。
Issuer Cell
数据结构
Data:
version: uint8
class_count: uint32
set_count: uint32
info_size: uint16
info: infomation in json format
Type:
code_hash: ISSUER_TYPE
args: type_id
Lock:
--
version 字段当前的设置为 0,这表示了这个 cell 的数据结构的版本号。
class_count 字段记录着发行者创建的类别数,该数在创建时应设置为 0,并在创建新的 NFT Class Cell 时自动增加。
set_count 几乎和 class_count,但他只代表该用户创建的套装数量。
info 字段是设定来记录发行者的公开信息,例如 SNS 账户,图片等等。info_size 字段则设置来表示 info 的字节长度。
Issue Cell 的 type script 设置为 ISSUER_TYPE,其 args 等于遵循 TYPE ID 脚本规则的 type_id(注:保证了该 Cell 的独一无二性)。
这里我们为了未来的使用定义了:
IssuerID = issuer_cell_typescript_hash[:20]
为了让 info 字段能够在前端服务之间更有兼容性,我们给定了几个建议的变数:
name: 发行人名称(以 UTF-8 编码) website: 网址URL email: 邮箱 authentication: 典型的关于发行人 SNS 认证声明 image: 图片 url
NFT Class Cell
每个 NFT Class Cell 代表了一群特定且相同属性的 NFT 物件。被同样的 NFT Class Cell 发出的不同种的 NFT Cells 将会以不同的 TokenID 标注,以表明他的身份。
数据结构
Data:
// must
version: uint8
total: uint32
issued: uint32
property: uint64
configure: uint8
name: <size:uint16> + <vartext>
description: <size:uint16> + <vartext>
renderer: <size:uint16> + <vartext>
// optional data array
extinfo_data: <size:uint16> + <vartext>
extinfo_data: <size:uint16> + <vartext>
...
Type:
code_hash: NFT_CLASS_TYPE
args: <IssuerID:byte20> | <class_id:uint32>
Lock:
--
typescript.args 等于 IssuerID 加上 class_id,而且 class_id 是一个在 Issuer Cell 中根据 class_count 变数自动递增的变数。
total 代表发行数量限制,可以从零到无限。
issued 代表这个类别的物件已经发行了多少,这也能够用在 NFT Cell TokenID 的变数上,当初始被创建时他们都等于零。
property 是一个用户定义的变数,用来设置 NFT 的特性,我们可以将它视作是 NFT 物件的 DNA。
configure 是个点阵图(bitmap)的变数,用来限制被 Class 发行 NFT 物件的行为。点阵图的含义如下表(bit 0 及 bit 1 分别代表特定的功能已经启用或者故障 )。
name,description 和 renderer 对于代币而言是静态的信息字段。但前端的 dApp 可以通过一个特殊数据通往 renderer 的 URL。例如 property 获得运行时生成的丰富的媒体数据。
本 RFC 也允许用户自定义的 extinfo_data 数组来提供更多的信息。
创建交易
Issuer Cell 必须被置于交易的 input 端,NFT Class Cell 可以被批量生产。
INPUT:
Issuer_cell:
Data:
class_count: k
Type:
code_hash: ISSUER_TYPE
args: type_id
OUTPUT:
Issuer_cell:
Data:
class_count: k + m
Type:
code_hash: ISSUER_TYPE
args: type_id
NFT_class_cell:
Data:
total: N_1
issued: 0
Type:
code_hash: NFT_CLASS_TYPE
args: IssuerID | <class_id = k>
...
NFT_class_cell:
Data:
total: N_m
issued: 0
Type:
code_hash: NFT_CLASS_TYPE
args: IssuerID | <class_id = k+m-1>
NFT Cell
NFT Cell 是由 NFT Class Cell 所发行,有着相同的 configure 和不同的 TokenID 以及 state 字段。
数据结构
Data:
// must
version: uint8
configure: uint8
state: uint8
// optional
extinfo_data: <size:uint16> + <vartext>
...
Type:
code_hash: NFT_TYPE
args: IssuerID | class_id | TokenID
Lock:
--
configure 必须要和 nft_class_cell.configure 相同。而不同 NFT Cell 的 state 就是不同的,这用于指示当前 NFT 的状态。
bit index | meaning | note |
bit 0 | claim state | 0/1 => unclaimed / claimed |
bit 1 | lock state | 0/1 => free / locked |
other | reserved | – |
typescript.args.IssuerID | class_id 必须要和 nft_class_cell 相同,TokenID 必须是 nft_class_cell.issued 字段的发行索引。
发行交易
typescript 允许 NFT Cells 的批量发行。
INPUT:
NFT_class_cell:
Data:
total: N
issued: < k >
property: P
configure: C
Type:
code_hash: NFT_CLASS_TYPE
args: IssuerID | class_id
OUTPUT:
NFT_class_cell:
Data:
total: N
issued: < k + m <= N >
property: P
configure: C
Type:
code_hash: NFT_CLASS_TYPE
args: IssuerID | class_id
NFT_cell:
Data:
configure: C
state: 0
Type:
code_hash: NFT_TYPE
args: IssuerID | class_id | <TokenID = k>
...
NFT_cell:
Data:
configure: C
state: 0
...
Type:
code_hash: NFT_TYPE
args: IssuerID | class_id | <TokenID = k+m-1>
NFT Set Cell
发行人可以创建 NFT Set Cell 来自定义一个 NFT 套装集合。
数据结构
Data:
// 必选
version: uint8
set_id: uint32
set_name: <size:uint16> + <vartext>
set_description: <size:uint16 + <vartext>
item_list_size: uint16
item_list: <class_id:uint32> * item_list_size
// 可选
extinfo_data: <size:uint16> + <vartext>
...
Type:
code_hash: NFT_SET_TYPE
args: IssuerID
END