如何使用 IPFS 来存储和托管 NFT (教程)

可以长久保存并防止篡改,这是 NFT 核心价值之一。不幸的是,目前许多面向消费者的 NFT 由于设计上的根本性漏洞,并没有这些属性。常常看到一些 NFT 号称的“在区块链上永存”,但实际上经常因为成本和区块链存储能力的限制,存储的只有所有权记录和关联 NFT 的元数据。

很多时候,这些链接是脆弱的 (https://www.vice.com/en/article/pkdj79/peoples-expensive-nfts-keep-vanishing-this-is-why),用 HTTP 协议将用户引向特定位置,而非该资产本身。这意味着链接指向的内容可能在以后失效或者改变,造成原资产的丢失(只剩所有权记录是无价值的)。

IPFS 可以解决这个问题,使用 IPFS 的 NFT 将享有优势。但只有遵从既有规范才能较好让数据得以永久保存并可访问。随着 NFT 的迅速流行,现在是一个好时机,让我们重温下在 IPFS 上存储和链接 NFT 数据的最佳实践。在本文中,我们将探讨两个近期热度话题:内容寻址和数据完整性。在 IPFS 文档网站上,有新的章节使用 IPFS 存储 NFT 数据的最佳实践 (https://docs.ipfs.io/how-to/best-practices-for-nft-data/),可帮您了解更多细节。

内容寻址

IPFS 内容标识符 (https://docs.ipfs.io/guides/concepts/cid/)(CID) 在精准标识内容方面是极其强大和灵活的,无论该内容存于何处,以何种方式存储。为了最大限度地利用这些优点,开发者在链接 IPFS 数据时应遵循以下建议和惯例。

链接概述

本文并非对 CID 的全面解释(对此,已经有极佳的资料 (https://docs.ipfs.io/how-to/address-ipfs-on-web/#dweb-addressing-in-brief))。但本文旨在让读者了解以下几点:

CID

CID 是自描述的,是对任意内容唯一对应的标识。

例子:bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

CID 应该用在您的应用代码中,以及其他明确是在使用 IPFS 的场景下。

我们建议在磁盘上将 CID 转为 IPFS URI 存储,特别是在元数据或者区块链记录这种写入后不再更改的记录中。给 CID 加上 ipfs:// 的 URI 格式,增加了上下文信息,让用户和自动化的工具更容易找到所链接的内容。

IPFS URI

统一资源标识符 URI(https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) 用于在协议中指定某特定内容。协议是由 URI 格式决定的(作为前缀附加到 URI 上,还加上 ://)。IPFS 的 URI 格式是 ipfs。有时 URI 可以在最后附加路径。

例子:

ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

ipfs://bafybeigvafaks2bvivtv46n2z7uxszpvl25jhvzc6dbhnjjgjkbeia5jta/nft.mp4

IPFS URI 是指向文件或者目录的标准 IPFS 链接。当从智能合约链接到 IPFS 数据时,IPFS URI 表明该数据应该通过 IPFS 系统获取。

当在 NFT 的结构化元数据中对 IPFS 上的图像及其他媒体资源做链接时,也应该使用 IPFS URI。

HTTP Gateway URL

HTTP gateway(https://docs.ipfs.io/how-to/address-ipfs-on-web/#http-gateways) 帮助无法原生解析 IPFS URI 的旧版浏览器进行兼容。这种链接只应在应用程序的界面中使用,而不应该存入区块链或 NFT 的元数据中。

例子:https://dweb.link/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

需注意到,HTTP gateway_又将内容分发中心化_,是中间人攻击的可能载体并带来潜在的单点失效—— 如果 gateway 运营方下线或者失联,链接将失效。而内置 IPFS 支持的浏览器(通过 IPFS Companion(https://docs.ipfs.io/install/ipfs-companion/) 浏览器扩展,或原生支持,如 Brave(https://brave.com/ipfs-support/))可以避免这些问题,因为它们可以_自动_从此类链接中提取 CID,并根据用户设置从 IPFS 加载数据。

不同场景中的寻址

在不同场景下,开发者应根据具体情况使用合适的链接设置方式。

链上

NFT 智能合约上对一个 NFT 对应的资源和元数据应该使用 IPFS URI。

例子:ipfs://bafybeibnsoufr2renqzsh347nrx54wcubt5lgkeivez63xvivplfwhtpym/metadata.json

我们建议在生成 NFT 之前先生成 IPFS URI,并将 URI 完整存于链上。对传入一个 URI 的智能合约接口,这种方式最简单。而且 ipfs:// 的 URI 格式让应用知晓此数据位于 IPFS 上。

元数据

在 NFT 的元数据中,应使用 IPFS URI,这是在文本中链接 IPFS 资源最明确,且长期可靠的方式。

下面是一个链向 NFT 媒体资产的 IPFS URI 的例子:ipfs://bafybeigvafaks2bvivtv46n2z7uxszpvl25jhvzc6dbhnjjgjkbeia5jta/nft.mp4。

开发者可以用公共 HTTP gateway(https://docs.ipfs.io/how-to/address-ipfs-on-web/#http-gateways) 来获得兼容性。

同时应该避免其他链接到内容的方式(如非 IPFS HTTP gateway 的 URL)。普通的 HTTP 链接至多只能作为内容的临时镜像,因为链接的内容很容易被改变。在区块链上,数据是永久存储而无法篡改的,所以在链上使用 HTTP 是脆弱的,有失效风险。

相比之下,IPFS URI 是永久有效的,可被安全地作为数据的规范链接。通过使用 IPFS URI 作为“真理之源”链接,应用程序更容易使用多种不同的存储方案,或在未来切换不同的 gateway,只要生成新的 gateway 链接。这比起将特定 gateway 链接“硬编码”到区块链的永久记录中更灵活。

应用

在面向用户的应用程序中,开发者应通过以下两种方式链接 IPFS 内容。

1. IPFS URI

2. HTTP gateway URL

直到更多的浏览器原生支持 IPFS URI。请注意,这两种链接都是容易从原始 CID 或 IPFS URI 生成的。

下面是一个 HTTP gateway URL 指向公共的 dweb.link:

https://dweb.link/ipfs/bafybeigvafaks2bvivtv46n2z7uxszpvl25jhvzc6dbhnjjgjkbeia5jta/nft.mp4

也可以使用 CID 作为子域名,而不是放在 URL 路径里:

https://bafybeigvafaks2bvivtv46n2z7uxszpvl25jhvzc6dbhnjjgjkbeia5jta.ipfs.dweb.link/nft.mp4

这两个例子都对应这个标准 IPFS URI:ipfs://bafybeigvafaks2bvivtv46n2z7uxszpvl25jhvzc6dbhnjjgjkbeia5jta/nft.mp4。

数据完整性

关于 NFT 资产的一个重要的点在于其完整性 —— 包括资产本身和所有相关数据。IPFS 使用 CID 来保护 NFT 数据的完整性,确保自链接创建以来没有篡改。

开发者应遵守以下建议,让 IPFS 内置的数据验证功能发挥最大效用。

链接资产元数据

元数据是 NFT 价值构成的有机部分。因此,为保全资产的价值,在 IPFS 上存储资产时也应存储元数据,并确保两者都可获取。

实现该目标的首选方法如下:

1. 创建两个新目录(一个用于资产,一个用于元数据)

2. 将资产添加到其目录中

3. 将资产的目录添加到 IPFS 中,记录其 CID

4. 在相应目录创建元数据,使用步骤 3 中的 CID 创建 IPFS URI。该 URI 应该包含目录的 CID 和资产文件名

5. 将元数据的目录添加到 IPFS 中,记录其 CID。

6. 使用步骤 5 中的 CID 为元数据创建 IPFS URI,将该 URI 存储在链上,加入所有权记录

该流程既能让开发者将文件名加入链接中(方便用户交互),又确保元数据和资产可被独立应用。

  • 元数据将在以下位置被访问:ipfs://{元数据目录的 CID}/ 元数据文件名

  • 资产可以通过以下地址访问:ipfs://{资产目录的 CID}/ 资产文件名

下面是 JSON 元数据例子,包含链接到图像文件的 IPFS URI:

如何使用 IPFS 来存储和托管 NFT (教程)

该图片可使用 IPFS URI ipfs://bafybeidfjqmasnpu6z7gvn7l6wthdcyzxh5uystkky3xvutddbapchbopi/no-time-to-explain.jpeg` 访问。在界面上,您的应用可以创建一个 gateway URL 方便用户使用 HTTP 获取该图片,例如 https://dweb.link/ipfs/bafybeidfjqmasnpu6z7gvn7l6wthdcyzxh5uystkky3xvutddbapchbopi/no-time-to-explain.jpeg

一旦元数据创建完成,作为 JSON 文件在 IPFS 上存储后,其 CID 可用来创建如 ipfs://bafybeibnsoufr2renqzsh347nrx54wcubt5lgkeivez63xvivplfwhtpym/metadata.json 的 URI。该 URI 可存入智能合约中。

整个过程的实战案例,可在 IPFS 文档网站上如何在 IPFS 上发行 NFT(https://docs.ipfs.io/how-to/mint-nfts-with-ipfs/#a-short-introduction-to-nfts) 查看。文档使用 javascript 详细演示了整个过程。

高可用

使用如 IPFS 这样的去中心化网络来提供内容的主要原因之一是为了防范链接失效 (https://en.wikipedia.org/wiki/Link_rot)。这是通过让网络中别的节点共同运营数据镜像服务来实现的。但对数据可用性有高要求的开发者不应该依赖于别的节点的利他性。为了确保链接的内容可用,开发者应该 pinning(https://docs.ipfs.io/concepts/persistence/) 内容的 CID 在自己的存储节点上,并与愿意帮忙的节点一起存储分发该内容。如果愿意的话,开发者也可以使用 pinning 服务 (https://docs.ipfs.io/how-to/work-with-pinning-services/) 来代为运营。

如果您也对 Filecoin 感兴趣,欢迎了解更多内容:

如何使用 IPFS 来存储和托管 NFT (教程)