“拥有IPFS之后,你就可以开始用一种特定的方式来看待其他所有事物,然后你就会意识到你可以把它们全部替换掉。”
——IPFS创始人Juan Benet
01简单了解IPFS
本节将试图为Christian Lundkvist博士以下的深入技术摘要提供高层次的见解。
IPFS最初是由Juan Benet所提出,目的是试图建立一个能够快速移动的版本化科学数据系统,版本控制可以让您随时间变化跟踪软件状态(类似Git)。从那时起,IPFS就被认为是分布式、永久性Web。“IPFS是一个分布式文件系统,旨在将所有计算设备与同一文件系统连接。在某些方面,类似于Web的原始地址,但实际上更类似于交换Git对象的单个bittorrent(比特流)群。IPFS未来可能会成为互联网的一个新的主要子系统。如果构建成功,它将可以补充或替换HTTP,甚至能够替代更多。这听起来很疯狂,确实很疯狂。”
IPFS的核心是一个版本化的文件系统,可以获取文件并对其进行管理,还可以将它们存储在某个地址,然后随着时间的推移跟踪版本。IPFS还考虑了这些文件如何在网络中移动,因此它也是一个分布式文件系统。
IPFS对于数据和内容如何在网络上移动有着类似于bittorrent的规则。该文件系统层提供了非常有趣的属性,例如:
-完全分布的网站
-没有原始服务器的网站
-可以完全在客户端浏览器上运行的网站
-没有任何可与之对话的服务器网站
内容寻址
IPFS不是通过存储对象的服务器来引用对象(图片、文章、视频),而是通过文件上的哈希引用所有内容。这原理是,如果您要在浏览器中访问特定页面,则IPFS将询问整个网络“是否有人拥有与该哈希相对应的文件?” IPFS上的一个节点可以返回该文件,使您可以访问它。
IPFS在HTTP层使用内容寻址。这是一种惯例,我们将创建内容本身的某种表示形式,而不是创建一个按位置定位事物的标识符。这意味着内容将决定地址。其机制是获取一个文件,然后以加密方式对其进行哈希处理,这样您就可以得到该文件的非常小而安全的表示形式,从而确保了某个人不能仅仅拿出具有相同哈希值的另一个文件并将其用作地址。IPFS中文件的地址通常以标识根对象的哈希开始,然后是一个向下移动的路径。您正在与一个特定的对象交谈,而不是与服务器对话,可查看该对象内的路径。
HTTP vs IPFS 查找和检索文件
HTTP具有一个不错的属性,其中的标识符是位置,因此很容易找到托管该文件的计算机并与之对话。这很有用,通常效果很好,但在离线情况下或希望将整个网络上的负载降至最低的大型分布式方案中就无法使用了。
在IPFS中,步骤可分为两部分:用内容寻址识别文件,去找到它——当您拥有哈希值时,您会询问所连接的网络“谁拥有此内容?(hash)”,然后连接到相应的节点并下载。结果是点对点覆盖,可为您提供非常快速的路由。
02 IPFS示例
技术检查和IPFS(星际文件系统)是经过测试的互联网技术的综合,例如DHTs,Git版本系统和Bittorrent。它创建了一个P2P群,可以交换IPFS对象。IPFS对象的总数形成了一个经过加密验证的数据结构,称为Merkle DAG,该数据结构可用于对许多其他数据结构进行建模。我们将在本文中介绍IPFS对象和Merkle DAG,并提供可以使用IPFS建模的结构示例。
IPFS对象
IPFS本质上是一个用于检索和共享IPFS对象的P2P系统。IPFS对象是具有两个字段的数据结构:
数据——大小小于256 kb的非结构化二进制数据的斑点。
链接——链接结构的数组,这些是到其他IPFS对象的链接。
链接结构具有三个数据字段:
名称——链接的名称。
哈希——链接的IPFS对象的哈希。
大小——链接的IPFS对象的累积大小,包括跟随其链接的位置。
该尺寸领域主要用于优化P2P网络,这里我们将基本忽略它,因为从概念上讲,逻辑结构不需要它。
IPFS对象通常由其Base58编码的哈希引用。例如,让我们使用IPFS命令行工具查看带有哈希QmarHSr9aSNaPSR6G9KFPbuLV9aEqJfTk1y9B8pdwqK4Rq的IPFS对象(请在家尝试):
读者可能会注意到,所有哈希均以“ Qm”开头。这是因为哈希实际上是multihash,这意味着哈希本身在multihash的前两个字节中指定了哈希函数和哈希长度。在上面的示例中,十六进制的前两个字节为1220,其中12表示这是SHA256哈希函数,而20表示哈希的长度(以字节为单位),即32个字节。
数据和命名链接为IPFS对象集合提供了Merkle DAG的结构——DAG表示有向无环图,Merkle表示这是一个经过加密认证的数据结构,使用加密哈希来处理内容。这是留给读者的一个练习来思考为什么在这个图表中不可能有循环。
为了可视化图形结构,我们将通过一个图形来可视化IPFS对象,该图中包含节点中的数据,链接被定向到其他IPFS对象的图边,其中链接的名称是图边上的一个标签。上面的示例如下所示:
现在我们将举例说明可以由IPFS对象表示的各种数据结构。
文件系统
IPFS可以轻松表示由文件和目录组成的文件系统。
小文件
一个小文件(<256 kB)由IPFS对象表示,数据是文件内容(加上小页眉和页脚),没有链接,即链接数组为空。请注意,文件名不是IPFS对象的一部分,因此两个名称不同且内容相同的文件将具有相同的IPFS对象表示形式,因此具有相同的哈希值。
我们可以使用命令ipfs向IPFS添加一个小文件:
我们可以使用ipfs cat查看上述IPFS对象的文件内容:
使用ipfs对象查看基础结构可获得收益:
我们将该文件可视化如下:
大文件
大型文件(> 256 kB)由小于256 kB的文件块的链接列表表示,并且只有最小数据指定此对象表示大文件。指向文件块的链接的名称为空字符串。
目录结构
目录由指向代表文件或其他目录的IPFS对象的链接列表表示。链接的名称是文件和目录的名称。例如,考虑目录test_dir的以下目录结构:
文件hello.txt和my_file.txt都包含字符串Hello World!\ n。文件testing.txt包含字符串Testing 123 \ n。
当将此目录结构表示为IPFS对象时,它看起来像这样:
注意,对包含Hello World!\ n的文件进行了自动重复数据删除,\ n,该文件中的数据仅存储在IPFS中的一个逻辑位置(由其哈希地址寻址)。
IPFS命令行工具可以无缝地跟随目录链接名称来遍历文件系统:
版本文件系统
IPFS可以代表Git用于版本化文件系统的数据结构。Git提交对象在Git Book中进行了描述。在撰写本文时,尚未完全指定IPFS提交对象的结构,讨论仍在进行中。
提交对象的主要属性是它具有一个或多个链接,其名称为parent0,parent1等,指向先前的提交,并且具有名称对象的链接(在Git中称为tree),该链接指向该对象引用的文件系统结构。
我们以前面的文件系统目录结构以及两次提交为例:第一次提交是原来的结构,并在第二次提交,我们已经更新了文件my_file.txt,表示另一个世界,而不是原始的“Hello World!”。
这里还要注意,我们具有自动重复数据删除功能,因此第二个提交中的新对象只是主目录,新目录my_dir和更新后的文件my_file.txt。
03 区块链
这是IPFS最令人兴奋的用例之一。区块链具有自然的DAG结构,因为过去的区块始终通过其后继区块的哈希值进行链接。以太坊区块链等更高级的区块链也有一个关联的状态数据库,该数据库具有Merkle-Patricia树结构,也可以使用IPFS对象进行仿真。
我们假设一个简单的区块链模型,其中每个块包含以下数据:
交易对象列表;
到上一个块的链接;
状态树/数据库的哈希。
然后可以在IPFS中按以下方式对该区块链进行建模:
当将状态数据库放在IPFS上时,我们看到了重复数据删除的好处——在两个块之间,只有已更改的状态项需要显式存储。
这里有趣的一点是,将数据存储在区块链上与将数据哈希存储在区块链上之间的区别。在以太坊平台上,您需要支付相当大的费用才能将数据存储在关联的状态数据库中,以最大程度地减少状态数据库的膨胀(区块链膨胀)。因此,这是一种常见的设计模式,即较大的数据不存储数据本身,而是存储状态数据库中数据的IPFS哈希。
如果在IPFS中已经表示了具有相关状态数据库的区块链,那么将哈希存储在区块链上和将数据存储在区块链上的区别就变得有些模糊了,因为无论如何所有内容都存储在IPFS中,并且只需要区块的哈希即可状态数据库的哈希。在这种情况下,如果有人在区块链中存储了IPFS链接,我们可以无缝地跟随该链接来访问数据,就像数据存储在区块链本身中一样。
但是,我们仍然可以区分链上和链下数据存储。我们通过查看矿工在创建新区块时需要处理的内容来做到这一点。在当前的以太坊网络中,矿工需要处理将更新状态数据库的交易,为此,他们需要访问完整状态数据库,以便能够在更改后的任何地方对其进行更新。
因此,在以IPFS表示的区块链状态数据库中,我们仍然需要将数据标记为“链上”或“链下”。对于矿工来说,“链上”数据对于本地挖矿是必不可少的,并且该数据将直接受到交易的影响。“链下”数据将必须由用户更新,而矿工则无需接触。