61

IPFS - Content Addressed, Versioned, P2

 5 years ago
source link: http://www.10tiao.com/html/527/201806/2649968411/1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.


之前有发布过一个版本,本次根据一些细节的理解,进行了微调。IPFS的论文,可以说是一个好的综述,就好像IPFS的代码一样。给大家留下巨大空间的同时又指明了方向。


ABSTRACT(摘要)

InterPlanetary文件系统(IPFS)是一个点对点分布式文件系统,旨在将所有计算设备与相同的文件系统连接起来。 在某些方面,IPFS与Web很相似,但IPFS可以被看作是一个单一的BitTorrent群,在一个Git存储库内交换对象。 换句话说,IPFS提供了高吞吐量的内容寻址块存储模型,并提供了内容寻址超链接。 这形成了一个广义的Merkle DAG,一个数据结构,人们可以在该数据结构上构建版本化文件系统,区块链甚至永久Web。 IPFS结合了分布式散列表,激励式块交换和自我认证命名空间。 IPFS没有单点故障,节点也不需要相互信任。

1. INTRODUCTION(介绍)

在构建全球分布式文件系统方面进行了许多尝试。有些系统已经取得了显着的成功,其他系统完全失败。在学术尝试中,AFS [6]得到了广泛的成功,并且今天仍在使用。其他人[7,?]还没有取得同样的成功。在学术界之外,最成功的系统一直是主要针对大型媒体(音频和视频)的点对点文件共享应用程序。最值得注意的是,Napster,KaZaA和BitTorrent [2]部署了大型文件分发系统,为超过1亿同时用户提供支持。即使在今天,BitTorrent仍然有大量的部署,每天有数千万个节点流失[16]。这些应用程序看到的分布式用户和文件数量比文件系统的文件系统分布更多。但是,这些应用程序并不是作为基础设施来设计的。虽然有成功的重新调整1,但没有出现能够提供全球性,低延迟和分散式分布的一般文件系统。

也许这是因为大多数用例的“足够好”系统已经存在:HTTP。 到目前为止,HTTP是最成功的“分布式文件系统”。 与浏览器一起使用,HTTP具有巨大的技术和社会影响。 它已经成为通过互联网传输文件的事实上的方式。 然而,它没有利用过去15年发明的数十种辉煌的文件分发技术。 从一个角度来看,考虑到后向兼容性约束的数量以及在当前模型中投入的强大团队的数量,发展中的Web基础架构几乎不可能实现。 但是从另一个角度看,自HTTP出现以来,新的协议已经出现并得到了广泛的应用。 缺乏的是升级设计:增强当前的HTTP网页,并引入新功能而不会降低用户体验。

业界已经开始使用HTTP这种长时间的方式,因为移动小文件相对便宜,即使对于拥有大量流量的小型组织也是如此。 但是,我们正在进入一个新的数据分发时代,并面临新的挑战:(a)托管和分发PB级数据集;(b)计算跨组织的大数据;(c)高容量高清晰度按需或实时数据库; 实时媒体流,(d)编辑和链接大量数据集,(e)防止重要文件被意外丢失等等。 其中很多可以归结为“大量数据,可以随时访问”。受关键特性和带宽关系的影响,我们已经放弃了针对不同数据分布协议的HTTP。 下一步是让他们成为Web本身的一部分。

正交于高效的数据分发,版本控制系统已经设法开发重要的数据协作工作流程。 分布式源代码版本控制系统Git开发了许多有用的方法来建模和实现分布式数据操作。 Git工具链提供了大型文件分发系统严重缺乏的多功能版本控制功能。 受Git启发的新解决方案正在兴起,如Camlistore [?],个人文件存储系统,以及Dat [?]数据协作工具链和数据集包管理器。 Git已经影响了分布式文件系统设计[9],因为它的基于内容寻址的Merkle DAG数据模型使得强大的文件分发策略得以可能实现。 还有待研究的是这种数据结构如何影响高吞吐量定向文件系统的设计,以及它如何升级Web本身。

本文介绍IPFS,这是一种新型的对等版本控制文件系统,旨在协调这些问题。 IPFS综合了许多过去成功的系统的学习。 仔细的接口集成产生的系统比其部分的总和大。 IPFS中心原则将所有数据建模为同一个Merkle DAG的一部分。

2. BACKGROUND(背景)

本节讨论IPFS所组合的成功P2P系统的重要属性。

2.1 Distributed Hash Tables(分布式哈希表)

分布式哈希表(DHT)广泛用于协调和维护关于点对点系统的元数据。 例如,BitTorrent MainlineDHT可以跟踪Torrent群组的一些对等部分。

2.1.1 Kademlia DHT

Kademlia [10]是一种流行的DHT,它提供:

  1. 对海量网络进行高效查询:平均查询⌈log2(n)⌉个联系节点。 (例如对于10万个节点的网络来说20跳)。

  2. 低协调开销:它优化了发送给其他节点的控制消息的数量。

  3. 通过选择长寿命节点来抵抗各种攻击。

  4. 在包括Gnutella和BitTorrent在内的P2P应用中广泛使用,形成超过2000万个节点的网络[16]。

2.1.2 Coral DSHT

尽管一些P2P文件系统直接在DHT中存储数据块,但这“浪费存储和带宽,因为数据必须存储在不必要的节点上”[5]。 Coral DSHT以三种特别重要的方式扩展了Kademlia:

  1. Kademlia将值存储在ID为“最接近”(使用异或距离)的key所在的节点上。这不考虑应用程序数据的局部性,忽略可能已经拥有数据的“远”节点,并强制“最近的”节点存储它,无论它们是否需要。这浪费了大量的存储空间和带宽。相反,Coral将地址存储到可以提供数据块的同伴。

  2. Coral将DHT API从get_value(key)扩展到get_any_values(key)(DSHT中的“sloppy”)。由于Coral用户只需要一个(工作)对等点,而不是完整的列表,这样仍然有效。作为回报,Coral只能将值的子集分发到“最近”的节点,避免热点(当key变得热门时,分布到所有最近的节点)。

  3. 此外,Coral根据区域和大小组织一个称为群集的独立DSHT层次结构。这使得节点能够首先查询其区域中的对等点,“查找附近的数据而不查询远处的节点”[5],大大减少了查找的延迟。

2.1.3 S/Kademlia DHT

S/Kademlia [1]扩展了Kademlia以防止以下两个特别重要的方式的恶意攻击:

  1. S/Kademlia提供安全NodeId生成方案,并防止Sybill攻击。 它需要节点创建一个PKI密钥对,从中派生出他们的ID,并将他们的消息签名。 一种方案包括工作证明密码难题,以使生成的Sybills变得昂贵。

  2. S/Kademlia节点在不相交的路径上查找值,以确保在网络中存在大部分对手的情况下诚实的节点可以相互连接。 S/Kademlia的成功率达到了0.85,即使敌对部分达到了一半的节点。

2.2 Block Exchanges - BitTorrent(块交换)

BitTorrent [3]是一个非常成功的点对点文件系统,它成功地协调了不相互信任的对等体(群)的网络,以便合作将文件分发给彼此。 来自BitTorrent及其生态系统的关于IPFS设计的重要功能包括:

  1. BitTorrent的数据交换协议使用准奖励策略,奖励互相作出贡献的节点,惩罚只汲取他人资源的节点。

  2. BitTorrent对等节点跟踪文件的可用性,优先发送最稀有的作品。 这消除了种子的负担,使非种子同伴能够彼此交易。

  3. BitTorrent相对容易受到某些开发性带宽共享策略的影响。 PropShare [8]是一种不同的对等带宽分配策略,可以更好地抵御剥削策略,并提高群集的性能。

2.3 Version Control Systems - Git(版本控制系统)

版本控制系统提供工具来模拟随时间变化的文件并高效地分发不同的版本。 流行的版本控制系统Git提供了强大的Merkle DAG对象模型,以分布式友好的方式捕获对文件系统树的更改。

  1. 不可变对象表示文件(blob),目录(tree)和更改(commit)。

  2. 对象通过其内容的加密散列进行内容寻址。

  3. 与其他对象的链接被嵌入,形成Merkle DAG。 这提供了许多有用的完整性和工作流属性。

  4. 大多数版本控制元数据(分支,标签等)仅仅是指针引用,因此创建和更新成本低廉。

  5. 版本更改仅更新引用或添加对象。

  6. 将版本更改分发给其他用户只需传输对象并更新远程引用即可。

2.4 Self-Certified Filesystems - SFS(自我认证文件系统)

SFS [12,11]提出了引人注目的实现(a)分布式信任链和(b)平等共享全局命名空间。 SFS引入了构建自我认证文件系统的技术:使用以下方案来处理远程文件系统

/sfs/<Location>:<HostID>

其中Location是服务器网络地址,并且:

HostID = hash(public_key || Location)

因此,SFS文件系统的名称(name)会证明其服务器。 用户可以验证服务器提供的公钥,协商共享密钥并保护所有流量。 所有SFS实例共享一个全局名称空间,其中名称分配是加密的,而不是由任何集中式主体进行门控。

3. IPFS DESIGN(IPFS设计)

IPFS是一个分布式文件系统,它综合了以前对等系统的成功想法,包括DHT,BitTorrent,Git和SFS。 IPFS的贡献正在简化,发展,并将经过验证的技术连接到一个单一的内聚系统中,超过其各部分的总和。 IPFS为编写和部署应用程序提供了一个新的平台,并提供了一个用于分发和版本化大数据的新系统。 IPFS甚至可以发展网络本身。
IPFS是点对点的; 没有节点有特权。 IPFS节点将IPFS对象存储在本地存储中。 节点相互连接并传输对象。 这些对象表示文件和其他数据结构。 IPFS协议分为一系列负责不同功能的子协议:

  1. 身份(Identities) - 管理节点身份生成和身份验证。 在第3.1节中描述。

  2. 网络(Network) - 管理与其他对等方的连接,使用各种底层网络协议。可配置的。 在3.2节中描述。

  3. 路由(Routing) - 维护信息以查找特定的对等和对象。 回应本地和远程查询。 默认为DHT,但可切换。 在3.3节中描述。

  4. 交换(Exchange) - 一种管理高效块分配的新型块交换协议(BitSwap)。 以市场为模型,弱化激励数据复制。 交易策略可切换。 在3.4节中描述。

  5. 对象(Objects) - 一个Merkle DAG内容寻址的带链接的不可变对象。 用于表示任意数据结构,例如文件分层结构和通信系统。 在3.5节中描述。

  6. 文件(Files) - 受Git启发的版本化文件系统层次结构。 在3.6节中描述。

  7. 命名(Naming) - 一个自我认证的可变名称系统。 在3.7节中描述。

这些子系统不是独立的; 他们是整合和权衡各个的属性。 然而,分开描述它们是有用的,从底层开始构建协议栈。

注意:下面的数据结构和函数在Go语法中指定。

3.1 Identities(身份)

节点通过NodeId来识别,它是使用S/Kademlia的静态加密难题[1]创建的公钥的加密哈希。节点存储公钥和私钥(使用密码加密)。用户可以在每次发布时免费安装“新”节点标识,尽管这会失去应有的网络优势,但激励节点保持不变。注意:下面的数据结构和功能在Go语法中指定。

type NodeId Multihashtype Multihash []byte// self-describing cryptographic hash digesttype PublicKey []bytetype PrivateKey []byte// self-describing keystype Node struct {
    NodeId NodeID
    PubKey PublicKey
    PriKey PrivateKey
}

基于S/Kademlia的IPFS身份生成:

difficulty = <integer parameter>
n = Node{}
do {
    n.PubKey, n.PrivKey = PKI.genKeyPair()
    n.NodeId = hash(n.PubKey)
    p = count_preceding_zero_bits(hash(n.NodeId))
} while (p < difficulty)

在第一次连接时,对等节点交换公钥,并检查:hash(other.PublicKey)等于other.NodeId。 如果不是,则连接终止。

关于加密函数的注意事项。

IPFS不是将系统锁定在一组特定的函数选项上,而是倾向于自我描述的值。 哈希默认值以multihash格式存储,其中包含指定所使用的哈希函数的短头和以字节为单位的摘要长度。 例:

<function code><digest length><digest bytes>

关于加密函数的注意事项。
这允许系统(a)为用例选择最佳功能(例如,更强的安全性与更快的性能),并且(b)随着功能选择的改变而发展。 自描述值允许兼容地使用不同的参数选择。

3.2 Network(网络)

IPFS节点与网络中的数百个其他节点进行调节性通信,可能跨越广泛的互联网。 IPFS网络栈的特点:

  • 传输(Transport):IPFS可以使用任何传输协议,并且最适合WebRTC DataChannels [?](用于浏览器连接)或uTP(LEDBAT [14])。

  • 可靠性(Reliability):如果底层网络不提供,使用uTP(LEDBAT [14])或SCTP [15],IPFS可以提供可靠性。

  • 连接性(Connectivity):IPFS也使用ICE NAT穿越技术[13]。

  • 完整性(Integrity):可选择使用散列校验和检查消息的完整性。

  • 真实性(Authenticity):可选择使用HMAC和发件人的公钥检查消息的真实性。

3.2.1 Note on Peer Addressing(关于对等节点寻址的注意事项)

IPFS可以使用任何网络; 它不依赖或假定访问IP。 这允许IPFS在覆盖(overlay)网络中使用。 IPFS将地址存储为基础网络要使用的multiaddr格式的字节字符串。 multiaddr提供了一种表达地址及其协议的方式,包括对封装的支持。 例如:

# an SCTP/IPv4 connection
/ip4/10.20.30.40/sctp/1234/

# an SCTP/IPv4 connection proxied over TCP/IPv4
/ip4/5.6.7.8/tcp/5678/ip4/1.2.3.4/sctp/1234/

3.3 Routing(路由)

IPFS节点需要一个路由系统,可以找到(a)其他对等节点的网络地址和(b)可以服务特定对象的对等节点。 IPFS使用基于S/Kademlia和Coral的DSHT,使用2.1中讨论的属性来实现此目的。 IPFS的对象大小和使用模式与Coral [5]和Mainline [16]相似,因此IPFS DHT根据其大小对存储的值进行区分。 小值(等于或小于1KB)直接存储在DHT上。 对于较大的值,DHT存储引用,这些引用是可以为块提供服务的对等节点的NodeIds。
这个DSHT的接口如下:

 type IPFSRouting interface {
    FindPeer(node NodeId)    // gets a particular peer’s network address
    SetValue(key []bytes, value []bytes)    // stores a small metadata value in DHT
    GetValue(key []bytes)    // retrieves small metadata value from DHT
    ProvideValue(key Multihash)    // announces this node can serve a large value
    FindValuePeers(key Multihash, min int)    // gets a number of peers serving a large value
  }

注意:不同的用例需要实质上不同的路由系统(例如宽网络中的DHT,本地网络中的静态HT)。 因此IPFS路由系统可以交换为符合用户需求的路由系统。 只要满足上述接口,系统的其余部分将继续运行。

3.4 Block Exchange - BitSwap Protocol(块交换 - BitSwap协议)

在IPFS中,数据分发通过使用BitTorrent启发式协议与对等方交换块来实现:BitSwap。像BitTorrent一样,BitSwap同伴正在寻找获取一组块(want_list),并有另一组块交换(have_list)。与BitTorrent不同,BitSwap并不局限于一个种子中的块。 BitSwap可以作为一个持久的市场,让节点可以获取他们需要的数据块,而不管这些数据块属于哪个文件。这些块可能来自文件系统中完全不相关的文件。节点聚集在一起,在市场上交换。

虽然易货系统的概念意味着可以创建虚拟货币,但这需要全球收发账本来追踪货币的所有权和转移。这可以作为BitSwap策略实施,并将在未来的论文中探讨。

在基本情况下,BitSwap节点必须以块的形式为对方提供直接值。当节点之间的块分布互补时,这很好地工作,这意味着他们有其他想要的东西。通常情况并非如此。在某些情况下,节点必须为它们的块工作。如果一个节点没有其对等体想要的东西(或根本没有),它就会寻找其对等体想要的东西,其优先级低于节点本身想要的。这会激励节点缓存并散播罕见的碎片,即使它们不直接对它们感兴趣。

3.4.1 BitSwap Credit(信用)

该协议还必须鼓励节点即使在不需要任何数据块的时候播种,因为它们可能有其他人想要的块。 因此,BitSwap节点乐观地向对方发送数据块,希望偿还债务。 但是,水蛭(永不分享的自由加载节点)必须受到限制。 一个简单的信用系统解决了这个问题:

  1. 同行跟踪他们的余额(以字节验证)与其他节点。

  2. 同行按照随债务增加而下降的函数,概率地向债务人同行发送贷款。

请注意,如果一个节点决定不发送给对等节点,则该节点随后会以ignore_cooldown的超时间来忽略该对等节点。 这可以防止发件人试图通过造成更多掷骰子来博概率。 (默认BitSwap是10秒)。

3.4.2 BitSwap Strategy(策略)

BitSwap对等节点可能采用的不同策略对整个交换的表现有着截然不同的影响。 在BitTorrent中,虽然规定了一个标准策略(tit-for-tat),但是BitTyrant [8](共享最少可能)到BitThief [8](利用漏洞并且绝不会分享)到PropShare [8](按比例分享)。 一系列的策略(好的和恶意的)可以类似地由BitSwap节点实施。 功能的选择应该旨在:

  1. 最大化节点和整个交换的交换表现

  2. 防止贪婪者利用和降低交换

  3. 对其他未知战略有效且具有抵抗性

  4. 对信任的对等节点要宽大

对这些策略空间的探索是未来的工作。 在实践中起作用的一个功能选择是一个S形,按照债务比例来衡量:
让一个节点和它的同伴之间的负债比率r为:

            r = bytes_sent / (bytes_recv + 1)

给定r,让发送给债务人的概率为:

            P(send | r) = 1 - 1 / ( 1 + exp(6 - 3r))

如图1所示,由于节点的负债率超过既定信贷的两倍,因此此功能迅速下降。


图1:发送概率随着r的增加而增加

债务比率是衡量信任的标准:对先前已成功交换大量数据的节点之间的债务宽松,对未知的,不可信任的节点无情。 (a)阻止攻击者创建大量新节点(sybill攻击),(b)保护以前成功的贸易关系,即使其中一个节点暂时无法提供价值,并且(c)最终扼杀关系已经恶化直到他们改善。

3.4.3 BitSwap Ledger(账本)

BitSwap节点保持分类帐核算与其他节点的传输。 这使得节点可以跟踪历史记录并避免篡改。 激活连接时,BitSwap节点交换其账本信息。 如果它不完全匹配,则收发账本从头开始重新初始化,失去应计的信用或债务。 恶意节点有可能故意“失去”账本,希望消除债务。 节点不可能累积足够的债务来保证也会失去累积的信任; 然而,合作伙伴节点可以自由地将其视为不当行为,并拒绝交易。

type Ledger struct {
    owner      NodeId
    partner    NodeId
    bytes_sent int
    bytes_recv int
    timestamp  Timestamp
}

节点可以自由地保存分类帐的历史记录,但不需要正确的操作。 只有当前的分类帐条目很有用。 根据需要,节点也可以随意收集收发账本,从较不实用的分类帐开始:旧的(同行可能不再存在)和小的收发账本。

3.4.4 BitSwap Specification(规范)

BitSwap节点遵循一个简单的协议。

// Additional state kepttype BitSwap struct {
  ledgers map[NodeId]Ledger  // Ledgers known to this node, inc inactive
  active map[NodeId]Peer  // currently open connections to other nodes
  need_list []Multihash  // checksums of blocks this node needs
  have_list []Multihash  // checksums of blocks this node has}type Peer struct {
  nodeid NodeId
  ledger Ledger  // Ledger between the node and this peer
  last_seen Timestamp  // timestamp of last received message
  want_list []Multihash  // checksums of all blocks wanted by peer
  // includes blocks wanted by peer’s peers}// Protocol interface:interface Peer {
  open (nodeid :NodeId, ledger :Ledger);
  send_want_list (want_list :WantList);
  send_block (block :Block) -> (complete :Bool);  close (final :Bool);
}

对等连接的生命周期草图:

  1. 开放(Open):对等节点发送收发账本,直到他们同意为止。

  2. 发送(Sending):对等节点交换want_lists和块。

  3. 关闭(Close):对等关闭连接。

  4. 忽略(Ignored):(特殊)如果节点的策略避免发送,则忽略对等点(在超时期间)

Peer.open(NodeId, Ledger).

连接时,节点初始化与收发帐本的连接,或者从过去的连接存储,或者新建一个连接。 然后,将带有收发帐本的开放消息发送给对等方。
一旦接收到Open消息,对等节点选择是否激活连接。 如果——根据收款人的分类帐——发件人不是可信代理人(低于零的传输或大额未清债务),接收方可能会选择忽略该请求。这应该通过ignore_cooldown超时进行概率性完成,以便纠正错误并阻止攻击者。
如果激活连接,接收方将使用本地版本的分类帐初始化Peer对象,并设置last_seen时间戳。然后,它将收到的收发账本与自己的收发账本进行比较。 如果它们完全匹配,则连接已打开。 如果它们不匹配,则对等体会创建一个新的归零总帐并将其发送出去。

Peer.send_want_list(WantList).

当连接打开时,节点将其want_list发布给所有连接的对等节点。(a)打开连接后,(b)在随机定期超时后,(c)在want_list变更后,(d)在收到新块后完成。
在收到一个want_list后,一个节点存储它。然后,它检查它是否有任何想要的块。 如果是这样,它会根据上面的BitSwap策略发送它们。

Peer.send_block(Block).

发送块很简单。节点只是传输数据块。接收到所有数据后,接收方计算Multihash校验和以验证它是否与预期的匹配,然后返回确认。

在完成块的正确传输后,接收节点将块从need_list移到have_list,并且接收者和发送者都更新他们的分类帐以反映传输的附加字节。

如果传输验证失败,则发送方可能发生故障或攻击接收方。接收者可以自由拒绝进一步的交易。请注意,BitSwap希望在可靠的传输通道上运行,因此传输错误(可能导致对诚实发件人的不正确处罚)预计会在数据传递给BitSwap之前被捕获。

Peer.close(Bool).

关闭的最后一个参数表明拆除连接的意图是否是发送者的意图。如果为false,则接收方可以选择重新立刻打开连接。这避免了过早关闭。
对等连接应该在两种情况下关闭:

  • silent_wait超时已过,但未收到来自对方的任何消息(默认BitSwap使用30秒)。节点发出Peer.close(false)。

  • 节点正在退出,BitSwap正在关闭。在这种情况下,节点发出Peer.close(true)。

关闭消息后,接收者和发送者都会断开连接,清除存储的任何状态。 如果这样做是有用的,则可以为将来存储分类帐。

注意:

  • 非活动连接上的非打开消息应该被忽略。 在send_block消息的情况下,接收者可以检查该块是否需要并且正确,如果是,则使用它。 无论如何,所有这些无序消息都会触发来自接收器的关闭(错误)消息,以强制重新初始化连接。

3.5 Object Merkle DAG

DHT和BitSwap允许IPFS形成一个大规模的点对点系统,用于快速,稳健地存储和分发数据块。 除此之外,IPFS还构建了一个Merkle DAG,一个有向无环图,其中对象之间的链接是嵌入源中的目标的加密哈希。这是Git数据结构的一个泛化。Merkle DAG为IPFS提供了许多有用的属性,包括:

  1. 内容寻址(Content Addressing):所有内容由其多重哈希校验和(包括链接)唯一标识。

  2. 防篡改(Tamper resistance):所有内容都通过校验和进行验证。 如果数据被篡改或损坏,IPFS会检测到它。

  3. 重复数据删除(Deduplication):保存完全相同内容的所有对象都是相同的,并且只存储一次。 这对于索引对象特别有用,例如git树和提交或数据的公共部分。

IPFS对象格式是:

 type IPFSLink struct {
      Name string
      // name or alias of this link
      Hash Multihash      // cryptographic hash of target
      Size int
      // total size of target
    }  type IPFSObject struct {
      links []IPFSLink      // array of links
      data []byte
      // opaque content data
  }

IPFS Merkle DAG是一种非常灵活的数据存储方式。唯一的要求是对象引用是(a)内容寻址,和(b)以上述格式编码。IPFS授予应用程序对数据字段的完全控制权; 应用程序可以使用他们选择的任何自定义数据格式,IPFS可能不理解。 单独的对象内链接表允许IPFS:

  • 列出对象中的所有对象引用。 例如:

    > ipfs ls /XLZ1625Jjn7SubMDgEyeaynFuR84ginqvzb
       XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x 189458 less
       XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5 19441 script
       XLF4hwVHsVuZ78FZK6fozf8Jj9WEURMbCX4 5286 template
    
       <object multihash> <object size> <link name>
  • 解析字符串路径查找,如foo/bar/baz。 给定一个对象,IPFS将解析第一个路径组件对象链接表中的散列,获取第二个对象,并重复下一个组件。 因此,无论数据格式是什么,字符串路径都可以遍历Merkle DAG。

  • 解析递归引用的所有对象:

      > ipfs refs --recursive \
         /XLZ1625Jjn7SubMDgEyeaynFuR84ginqvzb
       XLLxhdgJcXzLbtsLRL1twCHA2NrURp4H38s
       XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x
       XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5
       XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z
       ...

    原始数据字段和公共链接结构是在IPFS之上构建任意数据结构的必要组件。 (a)关键值存储(b)传统关系数据库(c)关联数据三重存储(d)链接文档 发布系统(e)链接的通信平台(f)加密货币区块链。 这些都可以在IPFS Merkle DAG的基础上建模,这允许这些系统中的任何一个将IPFS用作更复杂应用的传输协议。

3.5.1 Paths

可以使用字符串路径API遍历IPFS对象。 路径与传统UNIX文件系统和Web中的路径一样。 Merkle DAG链接使遍历变得简单。 请注意,IPFS中的完整路径的形式如下:

# format
/ipfs/<hash-of-object>/<name-path-to-object>
# example
/ipfs/XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x/foo.txt

/ipfs前缀允许以标准挂载点安装到现有系统中而不会发生冲突(挂载点名称当然是可配置的)。 第二个路径组件(IPFS中的第一个路径组件)是对象的哈希。 情况总是如此,因为没有全球根源。 一个根对象在处理分布式(可能是非连接)环境中的数百万个对象的一致性方面是不可能完成的任务。 相反,我们用内容寻址来模拟根。 所有对象总是可以通过它们的散列来访问 请注意,这意味着给定路径 /bar/baz中的三个对象,所有人都可以访问最后一个对象:

/ipfs/<hash-of-foo>/bar/baz
/ipfs/<hash-of-bar>/baz
/ipfs/<hash-of-baz>

3.5.2 Local Objects(本地对象)

IPFS客户端需要一些本地存储器,一个外部系统,用于存储和检索IPFS管理的对象的本地原始数据。 存储类型取决于节点的用例。 在大多数情况下,这只是磁盘空间的一部分(由本机文件系统管理,通过诸如leveldb [4]的键值存储或直接由IPFS客户端管理)。 在其他情况下,例如非持久性缓存,此存储只是RAM的一部分。

最终,IPFS中可用的所有块都位于某个节点的本地存储中。 当用户请求对象时,它们至少暂时被发现,下载并存储在本地。 这为之后的一些可配置的时间量提供了快速查找。

3.5.3 Object Pinning(对象固定)

希望确保特定对象生存的节点可以通过固定对象来实现。 这确保对象保存在节点的本地存储中。 固定可以递归地完成,以便固定所有链接的后代对象。 所有指向的对象都存储在本地。 这对保留文件(包括引用)特别有用。 这也使IPFS成为永久链接的Web,并且对象可以确保他们指向的其他人的生存。

3.5.4 Publishing Objects(发布对象)

IPFS是全球分布式的。 它旨在允许数百万用户的文件一起共存。 带有内容哈希编址的DHT允许以公平,安全和完全分布的方式发布对象。 任何人都可以通过简单地将密钥添加到DHT中来发布对象,将它们自己添加为对等节点,并为其他用户提供对象的路径。 请注意,对象基本上是不可变的,就像在Git中一样。 新版本的散列方式不同,因此是新的对象。 跟踪版本是额外版本控制对象的工作。

3.5.5 Object-level Cryptography(对象级别加密)

IPFS能够处理对象级加密操作。 加密或签名的对象被包装在一个特殊的框架中,允许加密或验证原始字节。

type EncryptedObject struct {
      Object []bytes      // raw object data encrypted
      Tag []bytes      // optional tag for encryption groups
    }    type SignedObject struct {
      Object []bytes      // raw object data signed
      Signature []bytes      // hmac signature
      PublicKey []multihash      // multihash identifying key
    }

加密操作改变对象的散列,定义一个不同的对象。 IPFS自动验证签名,并且可以用用户指定的钥匙串解密数据。 加密对象的链接也受到保护,没有解密密钥就无法穿越。 可以在一个密钥下对父对象进行加密,并且可以在另一个密钥下对子对象进行加密,或者根本没有对象。 这保证了与共享对象的链接。

3.6 Files(文件)

IPFS还定义了一组对象,用于在Merkle DAG之上对版本化文件系统进行建模。 这个对象模型类似于Git的:

  1. 块(block):一个可变大小的数据块。

  2. 列表(list):一个块或其他列表的集合。

  3. 树(tree):块,列表或其他树的集合。

  4. 提交(commit):树的版本历史记录中的快照。

我希望准确地使用Git对象格式,但不得不区分开以介绍在分布式文件系统中有用的特定功能,即(a)快速大小查找(聚合字节大小已添加到对象),(b)大文件重复数据删除(添加 一个list对象),和(c)将commits嵌入到trees中。 但是,IPFS File对象足够接近Git,两者之间的转换是可能的。 此外,可以引入一组Git对象进行转换,而不会丢失任何信息(unix文件权限等)。

注意:下面的文件对象格式使用JSON。 请注意,此结构实际上是使用protobufs进行二进制编码的,尽管ipfs包含导入/导出到JSON。

3.6.1 File Object: blob

blob对象包含一个可寻址的数据单元,表示一个文件。 IPFS块就像Git blob或文件系统数据块。 他们存储用户的数据。 请注意,IPFS文件可以由lists和blob表示。 Blob没有链接。

{
  "data": "some data here",
  // blobs have no links
}

3.6.2 File Object: list(文件对象:列表)

list对象表示一个大的或重复数据的文件,由多个连接在一起的IPFS blob组成。 列表包含一个有序的blob或list对象序列。 从某种意义上说,IPFS列表的功能类似于带有直接块的文件系统文件。 由于列表可以包含其他列表,所以可能包括链接列表和平衡树在内的拓扑结构。 其中同一节点出现在多个位置的有向图可以实现文件内重复数据删除。 当然,循环是不可能的,如散列寻址所强制的。

{
  "data": ["blob", "list", "blob"],
    // lists have an array of object types as data
  "links": [
    { "hash": "XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x",
      "size": 189458 },
    { "hash": "XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5",
      "size": 19441 },
    { "hash": "XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z",
      "size": 5286 }
    // lists have no names in links
  ]
}

3.6.3 File Object: tree(文件对象:树)

IPFS中的树对象与Git类似:它表示一个目录,一个名称映射到哈希。 散列引用blob,列表,其他树或提交。 请注意,传统路径命名已由Merkle DAG实施。

{
  "data": ["blob", "list", "blob"],
    // trees have an array of object types as data
  "links": [
    { "hash": "XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x",
      "name": "less", "size": 189458 },
    { "hash": "XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5",
      "name": "script", "size": 19441 },
    { "hash": "XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z",
      "name": "template", "size": 5286 }
    // trees do have names
  ]
}

3.6.4 File Object: commit(文件对象:提交)

IPFS中的提交对象表示任何对象的版本历史记录中的快照。 它与Git类似,但可以引用任何类型的对象。 它也链接到作者对象。

{
"data": {    "type": "tree",    "date": "2014-09-20 12:44:06Z",    "message": "This is a commit message."}, "links": [    { "hash": "XLa1qMBKiSEEDhojb9FFZ4tEvLf7FEQdhdU",      "name": "parent", "size": 25309 },    { "hash": "XLGw74KAy9junbh28x7ccWov9inu1Vo7pnX",      "name": "object", "size": 5198 },    { "hash": "XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm",      "name": "author", "size": 109 } ] }


图2:对象图示例

> ipfs file-cat <ccc111-hash> --json
{
  "data": {
    "type": "tree",
    "date": "2014-09-20 12:44:06Z",
    "message": "This is a commit message."
}, "links": [
    { "hash": "<ccc000-hash>",
      "name": "parent", "size": 25309 },
    { "hash": "<ttt111-hash>",
      "name": "object", "size": 5198 },
    { "hash": "<aaa111-hash>",
      "name": "author", "size": 109 }
] }
> ipfs file-cat <ttt111-hash> --json
{
  "data": ["tree", "tree", "blob"],
  "links": [
    { "hash": "<ttt222-hash>",
      "name": "ttt222-name", "size": 1234 },
    { "hash": "<ttt333-hash>",
      "name": "ttt333-name", "size": 3456 },
    { "hash": "<bbb222-hash>",
      "name": "bbb222-name", "size": 22 }
] }
> ipfs file-cat <bbb222-hash> --json
{
  "data": "blob222 data",
"links": [] }

图3:对象示例

3.6.5 Version control(版本控制)

提交对象表示对象的版本历史记录中的特定快照。比较两种不同提交的对象(和子代)揭示了两个版本的文件系统之间的差异。只要一个提交和它引用的所有子对象都可访问,所有前面的版本都是可检索的,并且可以访问文件系统更改的完整历史记录。这脱离了Merkle DAG对象模型。

IPFS用户可以使用Git版本控制工具的全部功能。对象模型是兼容的,虽然不相同。可以(a)构建修改为使用IPFS对象图的Git工具版本,(b)构建挂载的FUSE文件系统,将IPFS树挂载为Git repo,将Git文件系统读/写转换为IPFS格式。

3.6.6 Filesystem Paths(文件系统路径)

正如我们在Merkle DAG部分看到的,可以使用字符串路径API遍历IPFS对象。 IPFS文件对象旨在使安装在UNIX文件系统上的IPFS更简单。它们将树限制为没有数据,以便将它们表示为目录。提交可以表示为目录,也可以完全隐藏文件系统。

3.6.7 Splitting Files into Lists and Blob(将文件拆分成List和blob)

版本控制和分发大文件的主要挑战之一是找到将它们分割成独立块的正确方法。 IPFS不是假定它可以为每种类型的文件做出正确的决定,而是提供以下备选方案:

  1. 使用类似LBFS[?]中的Rabin Fingerprints[?]来选择合适的块边界。

  2. 使用rsync[?]滚动校验和算法来检测版本之间已更改的块。

  3. 允许用户指定为特定文件高度调整的块分割功能。

3.6.8 Path Lookup Performance(路径查找性能)

基于路径的访问遍历对象图。检索每个对象需要在DHT中查找它的key,连接到对等点并检索它的块。这是相当大的开销,特别是在查找具有多个组件的路径时。 这可以通过以下方式来缓解:

  • 树缓存:由于所有对象都是散列寻址的,因此可以无限制地缓存它们。此外,树的大小通常较小,所以IPFS优先将其缓存在blob上。

  • 扁平树:对于任何给定的树,可以构造一个特殊的扁平化树来列出树中可到达的所有对象。扁平化树中的名称实际上是与原始树分离的路径,带有斜杠。
    例如,上面ttt111的扁平化树:

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

3.7 IPNS: Naming and Mutable State(IPNS:命名和可变状态)

到目前为止,IPFS栈形成了一个对等块交换,构建了一个内容寻址的对象DAG。 它用于发布和检索不可变对象。 它甚至可以跟踪这些对象的版本历史记录。 但是,缺少一个关键组件:可变命名。 没有它,新内容的所有通信都必须发生在带外,发送IPFS链接。 需要的是在同一路径上检索可变状态的方法。

值得说明的是,为什么——如果最终需要可变数据——我们努力建立一个不可变的Merkle DAG。考虑从Merkle DAG中删除的IPFS的属性:对象可以(a)通过它们的散列检索,(b)完整性检查,(c)与其他链接,以及(d)无限期地缓存。 从某种意义上说:

对象是永久的

这些是高性能分布式系统的关键属性,其中数据在网络链路上移动的成本很高。 对象内容寻址构建了一个带有(a)显著带宽优化,(b)不可信内容服务,(c)永久链接以及(d)对任何对象及其引用进行完全永久备份的能力的web。
Merkle DAG,不变的内容寻址对象,以及命名可变指向Merkle DAG的指针,实例说明了许多成功的分布式系统中存在的二分法。这些包括Git版本控制系统及其不可变对象和可变引用; 和UNIX的分布式后继者Plan9[?],其可变化的Fossil[?]和不可变的Venti[?]文件系统。LBFS[?]也使用可变索引和不可变块。

3.7.1 Self-Certified Names(自我认证的命名)

使用SFS的命名方案[12,11]给了我们一种在密码指定的全局命名空间中构建可自行认证的名称的方法。 IPFS模式如下。

  1. 回想一下在IPFS中:

     NodeId = hash(node.PubKey)
  2. 我们为每个用户分配一个可变名称空间:

     /ipns/<NodeId>
  3. 用户可以将对象发布到由他的私钥签名的此路径,例如:

     /ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/
  4. 当其他用户检索该对象时,他们可以检查与公钥和NodeId相匹配的签名。 这验证了用户发布的Object的真实性,实现了可变状态的回归。

注意如下细节:

  • ipns(InterPlanetary Name Space)单独的前缀是为程序和读者建立一个容易识别的可变路径和不可变路径的区别。

  • 因为这不是一个内容寻址对象,发布它依赖于IPFS中唯一的可变状态分发系统,即路由系统。该过程是(1)将对象发布为常规不可变的IPFS对象,(2)将其散列作为元数据值发布在路由系统上:

    routing.setValue(NodeId, )

  • 已发布对象中的任何链接都充当名称空间中的子名称:

      /IPNS/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/
     /IPNS/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/docs
     /IPNS/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/docs/ipfs
  • 建议发布一个提交对象或其他具有版本历史记录的对象,以便客户端可以找到旧名称。这留作用户选项,因为它并不总是需要的。

请注意,当用户发布此对象时,它不能以相同的方式发布

3.7.2 Human Friendly Names(人类友好的命名)

虽然IPNS确实是分配和重新分配名称的一种方式,但它并不是非常用户友好的,因为它将长哈希值作为名称公开,这很难记住。 这些适用于URL,但不适用于多种离线传输。 因此,IPFS通过以下技术提高了IPNS的用户友好性。

Peer Links.(对等链接)

正如SFS鼓励的那样,用户可以将其他用户的对象直接链接到自己的对象(命名空间,家庭等)。 这也有利于创建一个信任网络(并支持旧的证书颁发机构模型):

# Alice links to bob Bob
ipfs link /<alice-pk-hash>/friends/bob /<bob-pk-hash>
# Eve links to Alice
ipfs link /<eve-pk-hash/friends/alice /<alice-pk-hash>
# Eve also has access to Bob
/<eve-pk-hash/friends/alice/friends/bob
# access Verisign certified domains
/<verisign-pk-hash>/foo.com
DNS TXT IPNS Records.

如果/ipns/ 是有效的域名,IPFS会在其DNS TXT记录中查找关键IPNS。IPFS将该值解释为对象散列值或另一个IPNS路径:

# this DNS TXT record
ipfs.benet.ai. TXT "ipfs=XLF2ipQ4jD3U ..."
# behaves as symlink
ln -s /ipns/XLF2ipQ4jD3U /ipns/fs.benet.ai
Proquint Pronounceable Identifiers.(可识别标识符)

一直以来都有将二进制编码转换为可发音单词的方案。 IPNS支持Proquint [?]。 从而:

# this proquint phrase
/ipns/dahih-dolij-sozuk-vosah-luvar-fuluh
# will resolve to corresponding
/ipns/KhAwNprxYVxKqpDZ
Name Shortening Services.(名称缩短服务)

随着服务的兴起,服务将提供名称缩短服务,为用户提供名称空间。 这与我们今天看到的DNS和Web URL类似:

# User can get a link from
/ipns/shorten.er/foobar
# To her own namespace
/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm

3.8 Using IPFS(使用IPFS)

IPFS旨在用于许多不同的方面。 以下是我将要追求的一些用例:

  1. 作为挂载的全局文件系统,位于/ipfs和/ipns下。

  2. 作为自动版本,发布和备份任何写入的安装的个人同步文件夹。

  3. 作为加密文件或数据共享系统。

  4. 作为所有软件的版本管理软件。

  5. 作为虚拟机的根文件系统。

  6. 作为虚拟机的引导文件系统(在管理程序下)。

  7. 作为数据库:应用程序可以直接写入Merkle DAG数据模型,并获得IPFS提供的所有版本控制,缓存和分发。

  8. 作为一个链接(和加密)的通信平台。

  9. 作为完整性检查大文件的CDN(无SSL)。

  10. 作为加密的CDN。

  11. 在网页上,作为网络CDN。

  12. 作为链接不死的新的永久网站。

IPFS的实现目标是:

  • 一个IPFS库,用于导入您自己的应用程序。

  • 直接操作对象的命令行工具。

  • 使用FUSE[?]或作为内核模块安装的文件系统。

4. THE FUTURE (未来)

IPFS背后的理念是几十年来在学术界和开源领域成功实现分布式系统研究的产物。IPFS综合了迄今为止最成功系统的许多最佳创意。除了新协议BitSwap以外,IPFS的主要贡献在于系统和设计综合的耦合。

IPFS是新型分散式互联网基础设施的宏伟蓝图,可以构建各种不同的应用。它至少可以用作全局的,装载的,版本化的文件系统和命名空间,或者作为下一代文件共享系统。在最好的情况下,它可以将网络推向新领域,在这些领域发布有价值的信息并不会将其托管在发布商身上,而是让那些感兴趣的用户可以信任他们收到的内容而不信任他们从其接收的同伴,以及 旧的但重要的文件不会丢失。IPFS期待着将我们带到常设网站。

5. ACKNOWLEDGMENTS

IPFS是许多伟大的想法和系统的综合。 如果不站在这些巨人的肩膀上,就不可能敢这样雄心勃勃的目标。 感谢David Dalrymple,Joe Zimmerman和Ali Yahya对这些想法进行了长时间的讨论,特别是:Merkle DAG(David,Joe),哈希阻止(David)和s / kademlia sybill保护(David ,Ali)。 并特别感谢David Mazieres的杰出想法。

6. REFERENCES TODO

7. REFERENCES

[1] I. Baumgart and S. Mies. S/kademlia: A practicable approach towards secure key-based routing. In Parallel and Distributed Systems, 2007 International Conference on, volume 2, pages 1–8. IEEE, 2007.
[2] I. BitTorrent. Bittorrent and Aˆ ̧ttorrent software surpass 150 million user milestone, Jan. 2012.
[3] B. Cohen. Incentives build robustness in bittorrent. In Workshop on Economics of Peer-to-Peer systems, volume 6, pages 68–72, 2003.
[4] J. Dean and S. Ghemawat. leveldb–a fast and lightweight key/value database library by google, 2011.
[5] M. J. Freedman, E. Freudenthal, and D. Mazieres. Democratizing content publication with coral. In NSDI, volume 4, pages 18–18, 2004.
[6] J. H. Howard, M. L. Kazar, S. G. Menees, D. A. Nichols, M. Satyanarayanan, R. N. Sidebotham, and M. J. West. Scale and performance in a distributed file system. ACM Transactions on Computer Systems (TOCS), 6(1):51–81, 1988.
[7] J. Kubiatowicz, D. Bindel, Y. Chen, S. Czerwinski, P. Eaton, D. Geels, R. Gummadi, S. Rhea,
H. Weatherspoon, W. Weimer, et al. Oceanstore: An architecture for global-scale persistent storage. ACM Sigplan Notices, 35(11):190–201, 2000.
[8] D. Levin, K. LaCurts, N. Spring, and
B. Bhattacharjee. Bittorrent is an auction: analyzing and improving bittorrent’s incentives. In ACM SIGCOMM Computer Communication Review, volume 38, pages 243–254. ACM, 2008.
[9] A. J. Mashtizadeh, A. Bittau, Y. F. Huang, and
D. Mazieres. Replication, history, and grafting in the ori file system. In Proceedings of the Twenty-Fourth ACM Symposium on Operating Systems Principles, pages 151–166. ACM, 2013.
[10] P. Maymounkov and D. Mazieres. Kademlia: A peer-to-peer information system based on the xor metric. In Peer-to-Peer Systems, pages 53–65. Springer, 2002.
[11] D. Mazieres and F. Kaashoek. Self-certifying file system. 2000.
[12] D. Mazieres and M. F. Kaashoek. Escaping the evils of centralized control with self-certifying pathnames. In Proceedings of the 8th ACM SIGOPS European workshop on Support for composing distributed applications, pages 118–125. ACM, 1998.
[13] J. Rosenberg and A. Keranen. Interactive connectivity establishment (ice): A protocol for network address translator (nat) traversal for offer/answer protocols. 2013.
[14] S. Shalunov, G. Hazel, J. Iyengar, and M. Kuehlewind. Low extra delay background transport (ledbat). draft-ietf-ledbat-congestion-04. txt, 2010.
[15] R. R. Stewart and Q. Xie. Stream control transmission protocol (SCTP): a reference guide. Addison-Wesley Longman Publishing Co., Inc., 2001.
[16] L. Wang and J. Kangasharju. Measuring large-scale distributed systems: case of bittorrent mainline dht. In Peer-to-Peer Computing (P2P), 2013 IEEE Thirteenth International Conference on, pages 1–10. IEEE, 2013.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK