半小时读懂 IPFS 白皮书

半小时读懂 IPFS 白皮书

什么是IPFS?

星际文件系统 IPFS(InterPlanetary File System)是一个 P2P(peer-to-peer)的分布式文件系统,它从 DHT(Distributed Hash Table), Git, BitTorrent 等中学习了精髓,并加以改造纳为己用。我们可以将IPFS看着一个有版本控制的P2P集群,其目标是想要干掉HTTP从而建立更好的网络。

为什么需要IPFS?

HTTP用于小型数据交换时,是相对有效且成本低廉的。但是,在新的数据分发背景下,HTTP很难满足如下的需求:

  • 分发PB级数据
  • 基于大型数据的跨组织计算
  • 高清实时媒体流
  • 重要数据文件丢失

IPFS 协议

ipfs7 IPFS协议由图中7个子系统构成,这些子系统并不是彼此独立而是相互依存作为整体。接下来我们详细介绍各个子系统。

身份(Identities)

在IPFS中,节点是通过 NodeId 进行标识的, 该 id 是通过公钥(Public key)的hash 加密产生(S/Kademlia’s static crypto puzzle)。 安装IPFS后,在终端输入 $ ipfs id 可以看到自己的id信息。 id

IPFS 中每个节点存储自己的id 、公钥、私钥,如下

eg3

在每次连接时,结点会交换彼此的公钥并验证并通过公钥验证彼此的 NodeId。如果验证不通过,连接就会终止。

网络(Network)

在IPFS中,每个结点都会与其它多个结点进行通讯, 其网络具有如下特征: * 传输性:可以使用任何传输协议 * 可靠性:使用uTP 或SCTP * 连接性:使用ICE NET * 完整性:通过哈希校验数据完整性 * 有效性: 通过HMAC和公钥来进行检查

IPFS可以使用任意的网络连接方式并且可以不依靠IP进行接入。通过字符串形式的多地址(multiaddr)来存储地址,如下图所示:

eg4

路由

IPFS 的路由是基于分布式哈希表实现的(DHT),在DHT网络中,每个结点负责一小部分路由,并存储一小部分数据。如果发生某个结点退出网络,系统整体受到的影响也不会太大。IPFS 的 DHT 在进行存储时会对数据大小进行评估:

  1. 小于等于1k的数据直接存到DHT中。
  2. 否则存储拥有该数据的结点的Ids。

IPFS也可以根据不同的实际情况来采用对应的路由系统: 1. 广域网:DHT 2. 局域网:HT

区块交换

IPFS的数据交换借鉴了 BitTorrent ,但和 BitTorrent不同的是, IPFS 的 BitSwap协议并没有将区块(blocks)限制在一个种子(torrent)中,BitSwap为结点建立一个类似以物易物(barter system)的区块交易市场。在市场中,结点可以获取他们需要的区块,而不用管这些数据来源于什么文件。交换过程大概是这个样子:

eg5

由于结点能否获取想要的块很大程度上取决于结点自己手中有没有其他结点想要的块,所以,结点们都尽可能的存储他人想要的块。对于网络中某些特别稀有的块,该交换机制也激励结点进行存储。

信用

enter image description here

当一个结点什么都不想要得时候, BitSwap 鼓励结点继续分享其他结点需要的块。分享结点并不从其他结点获取数据块,但是对分享出去的块进行记账,(乐观的)希望受益结点能够在以后还清。

BitSwap 提供的信用机制:

  1. 联合他结点一起查询该结点信用余额
  2. 随时结点债务的增加,结点获取数据块的降低(其他结点发送数据库给该结点的可能性降低)

BitSwap 策略

BitSwap的策略函数选择,考虑了以下4点: 1. 最大化结点和整个市场的交易 2. 防止吸血鬼(只接收不分享)获利或者影响市场表现 3. 对其他不利的未知策略能有效对抗 4. 对信任的结点比较包容

因此 BitSwap 选用了sigmoid 函数并加入了资产负债率(debt retio)的概念,用 r 表示,计算方式如下:

eg7 bytes_sent 是分享的数据块数量 bytes_recv 是获取的数据库数量

结点将数据块分享给其他某结点的概率和器资产负债率 r 有关, 概率函数定义为:

eg8

如果我们用程序将这个概率函数画出来,图像是这个样子:

eg9

可以看到,随着 r 的增加, 结点获取数据块的概率快速的下降。同时根据 r 的计算函数我们可以看到,对于没有交易记录的结点,通常会受到其他结点的无情的处理。而对有大量成功数据交换记录的结点,其他结点采取比较包容的态度。这样的好处有三个:

  1. 防止通过生成新的结点来进行攻击
  2. 不只是通过当前的结点价值来衡量结点间的关系
  3. 对于恶化到一定程度的关系选择扼杀

BitSwap 账本

系统中的结点和其他结点一起进行账本管理,当账本信息不能匹配时(有人篡改账本),BitSwap会重新初始化账本,并找出篡改结点并记为失信结点。

账本结构如下:

BitSwap 规范

结点间连接生命周期组成: 1. 开放:根据账本信息确定是否激活连接。 2. 发送:

  • 交换愿望清单: 愿望清单在以下的几种情况中将会被分享给连接的结点: (a)连接激活(b)随机周期超时(c)清单变更(d)收到新的数据块 当结点收到愿望清单后,根据自身策略和拥有数据块的情况来进行数据发送。

  • 交换数据: 数据块发送后将通过 Multihash 进行验证,如果验证成功,将会对 need_list 、have_list、账本进行更新。

  1. 关闭:(a)30s 内没有收到结点任何消息 (b)结点正在退出网络

Merkle DAG 对象

Merkle 是 IPFS 建立的一个有向无环图数据结构。通过 Merkle, IPFS可以做到:

  1. 内容寻址
  2. 防篡改
  3. 数据去重

IPFS中,对象是通过目标的加密哈希进行连接的, 对象的形式如下:

对象路径

IPFS 对象可以通过字符串形式的路径来进行遍历,与传统的UNIX文件系统或者Web类似,路径形式如下:

eg10

本地对象

IPFS客户端需要一些本地存储字体和一个外部系统来存储与检测IPFS 管理的本地原始数据。 理论上,最终IPFS中所有可用的数据块都在某一个结点的本地存储中。

对象固定

结点可以将某些数据块进行固定,放置在结点本地存储中以确保该数据块的可用性。 通过递归的方式,结点可以固定所有的对象后代,这种方式可以确保IPFS链接的永久性。

对象发布

任何结点都可以通过将秘钥添加到DHT来发布对象。和Git类似,所有发布对象都是不可变的,如果有新版本的对象出现,那么新版本的对象拥有的哈希是不同的。

对象级加密

IPFS可以实现对象级的加密,并且可以用指定用户的秘钥进行数据解密。

文件系统

IPFS 的对象模型和Git类似,如图所示:

eg11

文件对象:blob

Blob对象包含一个可寻址的数据单元用了存储用户数据。IPFS 可以通过列表或者blobs 的形式来表示文件。

文件对象:list

列表对象是一个大型的或者去重的文件,由多个 blobs 组成。 列表对象包含有序的blob嚯列表对象。由于列表对象可以包含其他的列表对象,所以,其拓扑结构可能包含链接列表和平衡树。有向图确保了文件去重,并通过哈希寻址确保拓扑无循环。

文件对象:树

IPFS的树对象与Git泪水,通过名称哈希映射建立的目录。IPFS 通过哈希值对 blobs, lists, trees, commits 进行引用。

文件对象:提交

提交对象在IPFS中代表某对象的历史版本快照。通过快照对比,可以得到两个不同的对象之间的差异。

文件分块

IPFS 提供以下分块方案: 1. 通过 Rabin Fingerprints 来挑选合适的区块边界 2. 通过 rsync rolling-checksum 算法来检查不同版本的区块更改 3. 允许用户指定的区块分割函数

路径访问性能

路径访问遍历需要很大的开销, IPFS采用以下的方式来降低开销:

  1. 缓存树: 由于树的具有较小的数据大小,所以IPFS可以对其进行优先缓存
  2. flattened trees: 用扁平化的树来列出可达对象。 例子如下所示:

    { data”: [“tree”, “blob”, “tree”, “list”, “blob” “blob”], “links”: [ { “hash”: ““, “size”: 1234 “name”: “ttt222-name” }, { “hash”: ““, “size”: 123, “name”: “ttt222-name/bbb111-name” }, { “hash”: ““, “size”: 3456, “name”: “ttt333-name” }, { “hash”: ““, “size”: 587, “name”: “ttt333-name/lll111-name”}, { “hash”: ““, “size”: 22, “name”: “ttt333-name/lll111-name/bbb222-name” }, { “hash”: ““, “size”: 22 “name”: “bbb222-name} ]}

命名与多状态

自我命名验证

接收数据块的结点可以通过检查公钥月发送结点NodeId的一致性,来验证对象的真实性。

  • ipns(行星内部命名空间 InterPlanetary Name Space)为程序和用户都建立路径可变与不可变的可识别机制。
  • 将对象以不可变的IPFS对象发布,将其哈希作为元数据发布在路由系统中。

友好的命名

由于哈希值对人类阅读非常不友好,所以IPFS通过以下的几种方式改善了用户体验:

  • 将其他结点的链接直接添加到自己的对象中(命名空间,home, etc),类似如下形式: eg12

  • DNS TXT IPNS 记录 如果/ ipns / 是有效的域名,IPFS会在其DNS TXT记录中查找关键IPNS并将其解释为对象哈希或者另一个IPNS路径,如下所示: eg13

  • Proquint 拼读标识

  • 缩短名称