深入剖析IPFS:内容寻址

煤油灯科技2022-06-22 10:22


内容寻址

要深入了解内容标识符 (CID) 的构建方式,请阅读关于CID剖析的文章

内容标识符或CID,是一个用于指向IPFS中内容的标签。它并不表明内容被储存在哪里,而是根据内容本身形成一种地址。CID长度很短,并且与其底层内容的大小无关。

CID是基于内容的加密哈希值,这意味着:

内容的任何差异都会产生不同的CID

使用相同的设置添加到两个不同的IPFS节点的相同内容将产生相同的CID。

IPFS默认使用sha-256散列算法,但也支持许多其他算法。Multihash项目代表了这方面的工作,目的是为应用程序使用哈希值并允许多种哈希函数共存。(如果对IPFS中的哈希类型是如何决定的有兴趣,可以去关注这个论坛的讨论)。

标识符格式

CID可以采用不同的编码基础或CID版本的几种不同形式。许多现有的IPFS工具仍然生成CIDv0,尽管文件(可变文件系统)和对象操作现在默认使用CIDv1。

Version 0(v0)

首次设计IPFS时,使用Base58编码的多重散列作为内容标识符。这比新的CID简单,但灵活性低很多。许多IPFS操作仍然默认使用CIDv0,所以通常应该支持v0。

如果CID是以“Qm”开头的46个字符,则为CIDv0(更多详细信息,请查看CID规范中的解码算法)。

Version 1(v1)

CIDv1包含一些前导标识符,这些标识符明确地说明了使用的表示形式,以及内容散列本身。这些包括:

multibase前缀,指定用于CID其余部分使用的编码

CID版本标识符,表明这是哪个版本的CID

多编码标识符,表明目标内容的格式——它可以帮助人们和软件知道如何解释获取的内容。

这些领先的标识符还提供了前瞻性的兼容性,支持在未来的CID版本中使用不同格式。

可以使用CID的前几个字节来解释内容地址的其余部分,并知道在从IPFS获取内容后如何对内容解码。(有关更多详细信息,请查看CID规范。它包括一个解码算法和现有软件实现的链接,用于解码CID。)

如果你无法在CIDv0和CIDv1之间做出决定,请考虑为你的新项目选择CIDv1并通过传递一个版本标志(ipfs add --cid-version 1)选择加入。这对未来更有保障,而且在浏览器环境中使用也更安全。

IPFS项目将在不久的将来切换到CIDv1作为新的默认值。

CID检查器

自己探索CID很容易。如果想要了解特定的CID的multibase、multicodec或multihash内容,可以使用CID检查器或IPLD Explorer中的CID信息面板,来对不同格式的CID进行交互式分解。

查看CID剖析教程,了解如何在多个CID版本中表示单个文件。

CID转换

将CID从v0转换到v1,可以使CID支持multibase编码。

CIDv1的默认值是不区分大小写的base32,但建议IPNS名称使用较短的base36以确保在子域上的文本表示相同。

v0 to v1

可以从命令行使用内置的ipfs cid格式命令:

JavaScript 用户还可以利用cids库提供的 toV1() 方法:

文本到二进制

CID既可以表示为文本,也可以表示为字节流。当考虑到速度和存储效率时,后者可能是更好的选择。

要将一个CIDv1从文本转换为二进制形式,只需读取第一个字符,然后用多库表中指定的编码对其余部分进行解码。

JS用户可以利用cids库来获得Uint8Array的二进制版本。

要注意正确解析CIDs。

除非是向IPFS导入数据的人,否则CID的长度是不确定的,而是取决于其中的多重哈希值的长度。

举例说明,传递一个自定义的哈希函数将产生不同长度的CID:

CID转为十六进制

有时,出于调试的目的,原始字节的十六进制表示更受欢迎。

为了获取整个CID的原始.字节的十六进制,可以使用内置的base16编码的支持并跳过f(multibase前缀):

要转换回CIDv1,在十六进制值前加上f(小写base16的multibase前缀)。按原样使用它(它是一个有效的CID),或者通过将它作为参数传递给toString来转换为不同的multibase :

提示:

子域网关将具有自定义基础(如base16)的路径转换为base32 或base36,以使CID适合DNS标签:

dweb.link/ipfs/f01701220c3c4733ec8affd06cf9e9ff50ffc6bcd2ec85a6170004bb709669c31de94391a

返回HTTP 301重定向:

→ bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi.ipfs.dweb.link


散列

加密哈希是接受任意输入,并返回一个固定长度的值的函数。特定值取决于所使用的哈希算法,如SHA-1(git使用)、SHA-256或BLAKE2。但是给定的哈系算法总是为给定的输入返回相同的值。查看维基百科的哈希函数的完整列表,了解更多信息。

例如,输入:

Hello world

将由SHA-1表示为:

0x7B502C3A1F48C8609AE212CDFB639DEE39673F5E

然而,完全相同的输入在使用SHA-256时产生了以下输出:

0x64EC88CA00B268E5BA1A35678A1B5316D212F4F366B2477232534A8AECA37F3C

请注意,第二个哈希值比第一个哈希值要长。这是因为SHA-1创建了一个160位的哈希值,而SHA-256创建了一个256位的哈希值。前面的0x表示后面的哈希值是以十六进制数字表示的。哈希值可以用不同的基数表示(base2 , base16 , base32等等)。事实上,IPFS使用它作为其内容标识符的一部分,并使用Multibase协议同时支持多个基本表示。

例如,上面的“Hello world”的SHA-256哈希值可以用base32表示为:

mtwirsqawjuoloq2gvtyug2tc3jbf5htm2zeo4rsknfiv3fdp46a

重要的哈希值特征

加密哈希值有几个重要特征:

  • 确定性:相同的输入信息总是返回完全相同的输出哈希值
  • 不相关:信息的微小变化都会产生一个完全不同的哈希值
  • 唯一性:从两个不同的信息中产生相同的哈希值是不可行的
  • 单向的:猜测或计算输入信息的哈希值是不可能的。

这些特征还意味着可以使用加密哈希值来识别任何数据:计算出来的数据的哈希值是唯一的,而且它不会太长,所以在网络上发送它不会占用大量的资源。哈希是一个固定的长度,所以一个1G的视频文件的SHA-256散列值仍然只有32字节。

这对于像IPFS这样的分布式系统来说是至关重要的,因为我们希望能够从许多地方存储和检索数据。一台运行IPFS的计算机可以询问它所连接的所有对等体是否拥有具有特定哈希值的文件,如果其中一个有,他们就把整个文件发送回来。如果没有像加密哈希这样简短的、唯一的标识符,内容寻址就不可能实现。

内容标识符不是文件哈希值

哈希函数被广泛用于检查文件的完整性。由于IPFS将内容分割成块,并通过有向无环图(DAG)进行验证,因此SHA文件散列值不会与CID相匹配。下面是一个示例,说明如果尝试这样做会发生什么的。

下载供应商可能会公布文件的散列函数的输出,通常称为校验和。该校验和使用户能够验证一个文件在发布后没有被修改过。该检查是通过对下载的文件执行相同的散列函数来完成的。如果用户从下载的文件中收到的校验和与网站上的校验和完全匹配,那么用户就知道该文件没有被更改并且可以信任。

例如,当你下载Ubuntu Linux的图像文件时,可能会看到Ubuntu网站上列出的以下SHA256校验和用于验证目的:

0xB45165ED3CD437B9FFAD02A2AAD22A4DDC69162470E2622982889CE5826F6E3D ubuntu-20.04.1-desktop-amd64.iso

下载Ubuntu镜像后,可以通过散列文件来验证文件的完整性。以确保校验和的匹配:

echo "b45165ed3cd437b9ffad02a2aad22a4ddc69162470e2622982889ce5826f6e3d *ubuntu-20.04.1-desktop-amd64.iso" | shasum -a 256 --check

ubuntu-20.04.1-desktop-amd64.iso: OK

如果将ubuntu-20.04.1-desktop-amd64.iso文件添加到IPFS,会收到一个哈希值作为输出:

ipfs add ubuntu-20.04.1-desktop-amd64.iso

added QmPK1s3pNYLi9ERiq3BDxKa4XosgWwFRQUydHUtz4YgpqB ubuntu-20.04.1-desktop-amd64.iso
 2.59 GiB / 2.59 GiB [==========================================================================================] 100.00%

ipfs add命令返回的字符串QmPK1s3pNYLi9ERiq3BDxKa4XosgWwFRQUydHUtz4YgpqB 是文件 ubuntu-20.04.1-desktop-amd64.iso 的内容标识符(CID)。可以使用CID检查器来查看CID包括什么。实际的哈希值被列在DIGEST(HEX)下:

NAME: sha2-256
BITS: 256
DIGEST (HEX): 0E7071C59DF3B9454D1D18A15270AA36D54F89606A576DC621757AFD44AD1D2E

小贴士

哈希函数的名称使用不一致。SHA-2, SHA-256 或 SHA-256位都是指同一个哈希函数。

现在可以检查CID中包含的哈希值是否等于文件的校验和:

echo "0E7071C59DF3B9454D1D18A15270AA36D54F89606A576DC621757AFD44AD1D2E *ubuntu-20.04.1-desktop-amd64.iso" | shasum -a 256 --check

ubuntu-20.04.1-desktop-amd64.iso: FAILED
shasum: WARNING: 1 computed checksum did NOT match

正如所看到的,CID中包含的哈希值与输入文件ubuntu20.04.1-desktop-amd64.iso的哈希值不一致。


不变性

不变对象是一个一旦创建就不能改变或修改其状态的对象。将文件添加到IPFS网络后,如果不更改文件的内容标识符(CID),这一功能非常适合存储不需要改变的数据。然而,当涉及到需要改变或更新的内容时,不变性就成为一个问题。本页讨论了如何保持由不可变的构建块构建的可变状态。

CID是指向内容的绝对指针。无论什么时候请求一个CID,CID的值始终相同。这是内容架构的一部分,无法更改。为了在一个易变的系统中管理不可变的文件,需要在CID的基础上再增加一层。

作为一个基本的例子,将其中的字符串hello和world两个内容块散列在具有CIDA和B的两个叶节点中。如果把这两个节点连接起来,那么就得到了CID。在这个根CID之上,分配了一个指针Pointer 。

   +-----------+
   |  Pointer  |
   +-----------+
         ↓
      +-----+
   +--|  C  |-+
   |  +-----+ |
   |          |
+-----+    +-----+
|  A  |    |  B  |
+-----+    +-----+
"hello"    "world"

如果把B的内容改为IPFS,所有的上游路径也会改变。在这个简单的例子中,唯一的上游路径是C。如果向指针请求内容,返回的是新内容,因为指针现在指向的是一个完全不同的节点。节点B没有被编辑、更新或以其他方式改变。相反,正在创建一个新的DAG,其中指针指向连接了节点A和新的节点D 的CID E。

 +-----------+
   |  Pointer  | --------------+
   +-----------+               |
                               ↓
      +-----+               +-----+
   +--|  C  |-+         +-- |  E  | --+
   |  +-----+ |         |   +-----+   |
   |          |         |             |
+-----+    +-----+     +-----+    +-----+
|  A  |    |  B  |     |  A  |    |  D  |
+-----+    +-----+     +-----+    +-----+
"hello"    "world"     "hello"    "IPFS!"

同样,节点B不会改变。它将始终指代相同的内容—world。节点A也出现在新的DAG中。这并不一定意味着我们将包含hello字符串的内存/缓冲区复制到了新消息中;这意味着位置寻址范式侧重于哪里而不是什么。在内容寻址的系统中,任何时候有人写下的字符串“hello”都会有CID A,不管是把这个字符串从以前的位置复制过来还是从头开始写。

网站解释

在这里, 有一个显示两个标题的网站,称为header_1和header_2。标题的内容是由变量string_1和string_2提供的。

<body>
  <h1 id="header_1"></h1>
  <h1 id="header_2"></h1>
</body>
<script>
  let string_1 = 'hello'
  let string_2 = 'world'
  document.getElementById('header_1').textContent = string_1
  document.getElementById('header_2').textContent = string_2
</script>

本网站的CID是QmWLdyFMUugMtKZs1xeJCSUKerWd9M627gxjAtp6TLrAgP 。用户可以到example.com/QmWLdyFMUugMtKZs1xeJCSUKerWd9M627gxjAtp6TLrAgP来查看该网站。如果我们把string_2改为IPFS,那么该网站的CID就会变成Qme1A6ofTweQ1JSfLLdkoehHhpbAAk4Z2hWjyNC7YJF9m5。现在用户可以去到example.com/Qme1A6ofTweQ1JSfLLdkoehHhpbAAk4Z2hWjyNC7YJF9m5 。

让用户使用CID访问网站是很麻烦的,因为CID会在每次变量更新时改变。变量被更新时,CID都会改变。因此,我们可以使用一个指针来维护最新的页面的CID。这样,用户可以去example.com,并且总是被引导到最新的内容。这个指针是可变的;它可以更新以反映下游的变化。

+--------+      +---------+      +----------+
|  User  | ---> | Pointer | ---> | QmWLd... |
+--------+      +---------+      +----------+

在网站的例子中,当改变一个变量时,网页的CID是不同的。必须更新指针以将用户重定向到最新的网页上。重要的是旧的CID仍然存在。没有任何内容会被覆盖原来的CID。

QmWLdyFMUugMtKZs1xeJCSUKerWd9M627gxjAtp6TLrAgP将总是指一个带有headers hello和world。我们正在做的是构建一个新的DAG。

+--------+      +---------+      +----------+
|  User  | ---> | Pointer |      | QmWLd... |
+--------+      +---------+      +----------+
                     |
                     |           +----------+
                     + --------> | Qme1A... |
                                 +----------+

这个过程本质上就是InterPlantery命名服务(IPNS)所做的!CID可能难以处理,且难以记忆,因此IPNS使用户免于直接处理CID的繁琐任务。更重要的是,CID随着内容的变化而变化,因为它们就是内容。而URLs/pointers的入站引用保持不变,而出站引用则发生变化:

+--------+      +--------------+      +-------------------------------------------------------------+
|  User  | ---> | docs.ipfs.io | ---> | bafybeigsddxhokzs3swgx6mss5i3gm6jqzv5b45e2xybqg7dr3jmsykrku |
+--------+      +--------------+      +-------------------------------------------------------------+


持久性

了解IPFS固定性(Pinning)背后的概念,以及持久性、永久性和固定性(Pinning)之间的区别。

持久性与永久性

IPFS的一个目标是保存历史,让用户在存储数据的同时最大限度地降低数据丢失或被意外删除的风险。这通常被称为永久性。但是,什么是永久性的真正含义?它为什么重要?

2011年的一项研究发现,网页的平均寿命是100天,然后才会永远消失。这对于这个时代的主要媒介来说,如此脆弱是不够的。IPFS可以存储文件的每一个版本,并使设置弹性的网络以镜像数据变得简单。

IPFS网络上的节点可以自动缓存他们下载的资源,并保持这些资源可供其他节点使用。这个系统取决于各节点是否愿意并能够与网络缓存和共享资源。存储是有限的,所以节点需要清除之前缓存的一些资源,以便为新资源腾出空间。这个过程被称为垃圾收集。

为了确保数据在IPFS上持续存在,并且在垃圾收集期间不被删除,可以将数据固定在一个或多个IPFS节点上。固定能够控制磁盘空间和数据保留。因此,应该使用这种控制来固定任何希望无限期保留在IPFS上的内容。

垃圾收集

垃圾收集是一种广泛用于软件开发的自动资源管理形式。垃圾收集器试图回收那些不再使用的对象所占用的内存。IPFS使用垃圾收集通过删除它认为不再需要的数据来释放你的IPFS节点上的磁盘空间。

IPFS的垃圾收集器是在go-ipfs配置文件的Datastore部分配置的。与垃圾收集器有关的重要设置是:

  • StorageGCWatermark:如果守护程序在启用自动垃圾收集的情况下运行,则自动触发垃圾收集的StorageMax值的百分比,默认值是90`。
  • GCPeriod : 指定垃圾收集的运行频率。只在启用自动垃圾收集时使用。默认值是1小时。

要手动启动垃圾收集,运行ipfs repo gc :

ipfs repo gc

> removed QmPZhyTu8D7NqR5NvgkgNYsSYD4CNjnyuFejB8i23itJvA
> removed QmSYQFVAZgEnpa6NxiW5agyj3XU9VR4CbERShXiLhuPPPE
> removed QmS6SJXApoi59hqD8Naktgakc6UNHK1XDhqhtMg9sBhY8g

要启用自动垃圾收集,请在启动IPFS守护进程时使用—enable-gc:

pfs daemon --enable-gc

> Initializing daemon...
> go-ipfs version: 0.9.0
> Repo version: 10
> ...

小贴士

如果使用IPFS Desktop,可以通过点击IPFS Desktop应用程序的任务栏图标来并选择高级→运行垃圾收集器来触发垃圾收集。

Pinning in context

IPFS节点可以根据不同类型的用户事件来保护数据免受垃圾收集。

通用的方法是通过添加一个低级别的本地引脚,这适用于所有的数据类型,可以手动完成。但如果使用CLI命令ipfs add添加一个文件,IPFS节点会自动固定该文件。

处理文件和目录时,更好的方法是把它们添加到本地可变文件系统(MFS)。这与本地固定的方式一样,可以保护数据免受垃圾收集的影响,在某种程度上更容易管理。

小贴士

如果想了解更多关于在IPFS中固定数据的整个生命周期的情况,请查看IPFS训练营的课程《DWeb中的数据生命周期》。

Pinning服务

为了确保重要数据被保留下来,可能需要使用Pinning服务。这些服务运行大量IPFS节点,并允许用户付费将数据固定在这些节点上。有些服务为新用户提供免费的存储空间。在以下情况下,Pinning服务是很方便的:

  • 没有大量的磁盘空间,但想确保数据能够保留。
  • 你的电脑是笔记本电脑、手机或平板电脑,与网络的连接时断时续。尽管如此,希望能够随时随地访问在IPFS上的数据,即使添加数据的设备处于离线状态。
  • 如果在自己的电脑上不小心删除了或垃圾收集了数据,需要一个备份,以确保数据始终可以从网络上的另一台电脑上获得。

一些可用的Pinning服务提供商:

  • Axel
  • Eternum
  • Infura
  • Pinata
  • Temporal
  • Crust Network

了解如何与远程固定服务。

长期存储

使用个人IPFS节点存储数据是很容易的,但由于必须管理自己的硬件,因此可能会很不方便。这个问题催生了固定服务,这种付费服务允许将数据上传到远程托管的IPFS节点,并随时检索它。然而,虽然支付固定服务来存储数据是一个方便的解决办法,但它仍然需要有人承担存储数据的成本。如果这该赞助商停止为该固定付费,则内容可能会完全丢失。虽然IPFS保证网络上的任何内容都可以被发现,但它并不保证任何内容是持续可用的。这就是Filecoin的用武之地。

使用Filecoin存储数据

Filecoin是一个去中心化的存储网络,存储供应商将其存储空间出租给客户。客户端和存储提供商就将存储多少数据,存储多长时间,以及支付多少费用和以成本达成一致。这种协议被称为交易,一旦双方达成协议,客户就会将数据发送给存储提供商,后者会定期验证他们是否正确存储了数据。当客户端想要回数据时,他们会向存储提供商发送请求,后者会启动数据传输回客户端。了解更多关于Filecoin如何工作的信息,请访问官方的Filecoin文件→。

Filecoin为用户提供了一个可靠的、长期的存储解决方案。然而,有一些限制要考虑。检索过程并不总是像IPFS固定服务那样快,Filecoin存储供应商接受的最小文件大小可能是几个GiB。此外,对于不熟悉区块链或者不习惯在命令行工作的新用户来说,创建存储交易的过程可能看起来很复杂。

IPFS + Filecoin解决方案

幸运的是,越来越多的工具和服务提供商社区帮助简化了通过IPFS提供内容的过程,同时也通过Filecoin持久化数据。这些解决方案通过充当IPFS固定服务内容,同时通过Filecoin持续保存数据。这些解决方案通过作为IPFS固定服务和Filecoin存储平台,使用去中心化协议存储数据变得简单。将两者结合起来意味着,当上传一个文件时,该文件就立即可供下载。此外,IPFS + Filecoin的组合解决方案将定期捆绑数据,并与知名的Filecoin存储供应商建立交易,确保数据在长期存储中可用。许多解决方案包括API客户端库,供开发人员集成到他们的应用程序和服务中,以及用于快速管理和检查文件的Web界面。

这一类的选项包括:

  • Web3.Storage
  • Estuary
  • Powergate
  • ChainSafe Storage
  • Fleek Storage


原文链接:https://docs.ipfs.io/concepts/


---煤油灯科技victorlamp.com翻译整理---

你可能也喜欢这些文章

科技互联网,科技,资讯,动态,洞察,量子,计算,AI,人工智能,机器人,区块链,Web3,分布式,操作系统,OS,芯片,视频,深度,论文