IPFS - 基于内容寻址的, 具有版本控制功能的, P2P文件系统(翻译)

IPFS - 基于内容寻址的, 具有版本控制功能的, P2P文件系统

(DRAFT 3)

Juan Benet

[email protected]

摘要

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

1.简介

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

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

业界已经不再使用HTTP,因为移动小文件相对便宜,即使对于拥有大量流量的小型组织也是如此。 但是,我们正在进入新的数据分发时代,并面临新的挑战:(a)托管和分发PB字节数量级的数据,(b)分布在不同组织的大数据的计算,(c)高容量高定制的按需或实时媒体数据流, (d)大量数据集的版本控制及超链接,(e)防止重要文件意外损坏等等。 其中许多可以归结为“大量数据,无处不在”。受关键特性和带宽问题的影响,我们已经放弃了使用HTTP来作为数据的分发协议。 下一步是让这些协议成为Web本身的一部分。

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

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

2.背景

本节介绍一些成功的peer-to-peer系统的重要技术,IPFS也使用了这些技术。

2.1 分布式哈希表

分布式哈希表(DHT)广泛用于协调和维护关于peer-to-peer系统的元数据。
例如,BitTorrent 主线DHT可以跟踪Torrent群组的一些peers。

2.1.1 Kademlia DHT

Kademlia 是一种流行的DHT,它具有以下特点:
1.通过大规模网络进行高效查找:平均查询联系 l o g 2 ( n ) 节点。 (例如:对于10万个节点的网络来说20个节点)。
2.低协调开销:它优化了发送给其他节点的控制消息的数量。
3.通过选择长寿命节点来抵抗各种攻击。
4.在包括Gnutella和BitTorrent在内的peer-to-peer应用中广泛使用,形成超过2000万个节点的网络。

2.1.2 Coral DSHT

虽然一些peer-to-peer文件系统直接在DHT中存储数据块,但这“浪费存储和带宽,因为数据必须存储在不需要的节点上”。Coral DSHT在三个特别重要的方面延伸Kademlia:
1. Kademlia将值存储在ID“最接近”(使用异或距离)密钥值的节点上。这不考虑应用程序数据局部性,忽略可能已有数据的“远”节点,并强制“最近”的节点存储它,无论它们是否需要它。这浪费了大量的存储空间和带宽。相反,Coral将地址存储到可以提供数据块的点。
2. Coral将DHT API从get_value(key)放到get_any_values(key)(DSHT中的“sloppy”)。这仍然有效,因为Coral用户只需要一个(工作)对等点,而不需要完整的列表。作为回报,Coral只能将值的子集分发到“最近”的节点,避免热点(当密钥变得流行时过载所有最近的节点)。
3.此外,Coral根据区域和大小组织一个称为群集的独立DSHT层次结构。这使节点能够首先查询其区域中的对等点,“查找附近的数据而不查询远处的节点”,并大大减少查找的延迟。

2.1.3 S / Kademlia DHT

S / Kademlia 以两种特别重要的方式扩展Kademlia以防止恶意攻击:
1. S / Kademlia提供安全的NodeId生成方案,并防止Sybill攻击。 它需要节点创建一个PKI密钥对,从中派生出他们的身份,并将他们的消息彼此签名。 一种方案是使用工作量证明(求解加密难题),以使生成Sybills的成本很高。
2. S / Kademlia节点在不相交的路径上查找值,以确保在网络中存在大部分对手的情况下诚实的节点仍然可以相互连接。 S / Kademlia的成功率达到了0.85,即使敌对部分达到了一半的节点。

2.2 Block Exchanges - BitTorrent

BitTorrent 是一个非常成功的点对点文件共享系统,它成功地协调了不信任的对等点(群)的网络,以便相互配合分配文件。 IPFS设计中使用了来自BitTorrent及其生态系统的重要功能包括:

  1. BitTorrent的数据交换协议使用类似 tit-for-tat 的策略来奖励互相作出贡献的节点,惩罚只汲取他人资源的节点。
  2. BitTorrent节点跟踪文件的可用性,优先发送最稀有的作品。 这使非种子节点能够彼此交换数据。
  3. BitTorrent的标准tit-for-tat 容易受到某些开发性带宽共享策略的影响。 PropShare是一种不同的节点带宽分配策略,可以更好地抵御剥削策略,提高集群的性能。

2.3 版本控制系统 - Git

版本控制系统提供工具来模拟随时间变化的文件并高效地分发不同的版本。 流行的版本控制系统Git提供了强大的Merkle DAG 对象模型,以分布式友好的方式捕获对文件系统树的更改。
1.不可变的以对象表示的文件(blob),目录(tree)和更改(commit)。
2.对象通过其内容的加密散列进行内容寻址。
3.与其他对象的链接被嵌入,形成Merkle DAG。 这提供了许多有用的完整性和工作流属性。
4.大多数版本控制元数据(分支,标签等)只是指针引用,因此创建和更新成本低廉。
5.版本更改仅更新引用或添加对象。
6.将版本更改分发给其他用户只需传输对象并更新远程引用即可。

2.4 自我认证的文件系统 - SFS

SFS 实现了(a)分布式信任链和(b)平等的全局共享命名空间。 SFS引入了一个技术来构建自我认证文件系统:使用以下方案来处理远程文件系统
/sfs/<Location>:<HostID>
其中<Location>是服务器网络地址,并且:
HostID = hash(public_key || Location)
因此,SFS文件系统的名称会证明其服务器。 用户可以验证服务器提供的公钥,协商共享密钥并保护所有流量。 所有SFS实例共享一个全局名称空间,其中名称分配是加密的,而不是由任何集中式主体进行控制。

3. IPFS设计

IPFS是一个分布式文件系统,它综合了以前peer to peer系统(包括DHT,BitTorrent,Git和SFS)的成功构想。 IPFS的贡献在于简化,发展,并将经过验证的技术连接到一个单一的内聚系统中,超过其各部分的总和。 IPFS为编写和部署应用程序提供了一个新的平台,并提供了一个用于分发和版本化大数据的新系统。 IPFS甚至可以发展网络本身。

IPFS是点对点的; 没有节点有特权。 IPFS节点将IPFS对象存储在本地存储中。 节点相互连接并传输对象。 这些对象表示文件和其他数据结构。 IPFS协议分为一系列负责不同功能的子协议:

1.身份 - 管理节点身份生成和验证。 在第3.1节中描述。
2.网络 - 管理与其他对等方的连接,使用各种底层网络协议。是可配置的。 在3.2节中描述。
3.路由 - 维护信息以查找特定的peer和对象。 响应本地和远程查询。 默认为DHT,但可交换。 在3.3节中描述。
4.交换 - 一种高效管理块分配的新型块交换协议(BitSwap)。 以市场为模型,弱化数据复制。 交易策略可交换。 在3.4节中描述。
5.对象 - 一个Merkle DAG内容处理的带有链接的不可变对象。 用于表示任意数据结构,例如 文件层次结构和通信系统。 在3.5节中描述。
6.文件 - 受Git启发的版本化文件系统层次结构。 在3.6节中描述。
7.命名 - 一个自我认证的可变名称系统。 在3.7节中描述。

这些子系统不是独立的; 他们组成一个整体。 但是,分别描述它们是有用的,从底层开始构建协议栈。

符号:下面的数据结构和函数都使用了Go语言。

3.1身份

节点由一个NodeId标识,它一个公钥的加密散列,由S / Kademlia静态加密创建。 节点存储公钥和私钥(使用密码加密)。 用户可以在每次登录时使用一个“新”的节点标识,但这会失去应有的网络优势。 我们鼓励节点保持标识不变。

type NodeId Multihash
type Multihash []byte
// self-describing cryptographic hash digest
type PublicKey []byte
type PrivateKey []byte
// self-describing keys
type 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网络

IPFS节点与网络中的数百个其他节点进行通信。 IPFS网络堆栈的特点:
•传输:IPFS可以使用任何传输协议,其最适合WebRTC DataChannels (用于浏览器连接)或uTP(LEDBAT )。
•可靠性:如果底层网络不提供,IPFS可以使用uTP(LEDBAT )或SCTP 提供可靠性。
•连接性:IPFS也使用ICE NAT穿越技术。
•完整性:可选择使用散列校验和来检查消息的完整性。
•真实性:可选地使用HMAC和发件人的公钥来检查消息的真实性。

3.2.1关于节点寻址的注意事项

IPFS可以使用任何网络; 它不依赖IP。 这允许IPFS在覆盖网络中使用。 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路由

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

type IPFSRouting interface {
FindPeer(node NodeId)
// gets a particular peers 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块交换 - BitSwap协议

在IPFS中,数据分发通过使用BitSwap(BitTorrent启发式协议)与其他的节点交换块来实现。 就像BitTorrent一样,BitSwap节点有一个需要的块的列表(want_list),有一个已拥有的块的列表(have_list)。 与BitTorrent不同,BitSwap并不局限于一个种子中的块。 BitSwap作类似一个市场持久的运行,节点可以获取所需的块,而不管这些块属于哪个文件。 这些块可能来自文件系统中完全不相关的文件。 节点聚集在一起,在市场上交换。
虽然交易系统的概念意味着可以创建虚拟货币,但这需要全球化的分类账本来追踪货币的所有权和转移。 这可以作为BitSwap的一个策略来实现,我将在未来的论文中探讨。

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

3.4.1 BitSwap信用

该协议还必须鼓励节点在他自身不需要块的时候仍继续做种,因为它们可能有其他节点想要的块。 因此,BitSwap节点向其他节点发送数据块,以期望偿还自身债务。 但是,水蛭们(永不分享的自由加载节点)也必须受到保护。 一个简单的信用系统解决了这个问题:
1.节点跟踪他们自身的余额(以字节验证)与其他节点。
2.根据随着债务增加而下降的函数,节点可以概率地向债务人发送贷款。
请注意,如果节点决定不发送给对等节点,则该节点随后会忽略此对等节点的ignore_cooldown的时间。 这可以防止此节点重复发起链接。 (默认BitSwap是10秒)。

3.4.2 BitSwap策略

BitSwap节点采用的策略不同可能对整个交易所的表现有着截然不同的影响。 在BitTorrent中,虽然规定了一种标准策略(tit-for-tat),但还有其他策略,例如BitTyrant (共享最不可能的块),BitThief (利用漏洞并且永远不会共享) ,PropShare (按比例分享)。 一系列策略(好的和恶意的)可以类似地由BitSwap节点实现。 功能的选择应该旨在:
1.最大化节点和整个交易所的交易表现
2.防止贪婪者利用和降低交换
3.对其他未知策略有效且耐受
4.对信任的节点要宽容

未来还将探索更多的策略空间。 在实际中,使用Sigmoid形,按照债务比例来衡量:
让一个节点和它的对等节点之间的负债比率r为:

r = b y t e s _ s e n t b y t e s _ r e c v + 1

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

P ( s e n d | r ) = 1 1 1 + e x p ( 6 3 r )

当节点的负债率超过既定信贷的两倍,那么此功能迅速下降。

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

3.4.3 BitSwap帐本

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

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

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

3.4.4 BitSwap规范

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

// Additional state kept
type 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.开放:对等节点发送账本,如果他们同意的话。
2.发送:对等节点交换want_lists和块。
3.关闭:对等节点关闭连接。
4.忽略:(特殊)如果节点的策略避免发送,则忽略对等节点(在超时期间)

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

在完成块的正确传输后,接收器将块从need_list移到have_list,并且接收者和发送者都更新他们的分类帐以反映传输的附加字节。
如果传输验证失败,则发送方可能发生故障或攻击接收方。 接收者可以自由拒绝进一步的交易。 请注意,BitSwap希望在可靠的传输通道上运行,因此传输错误(可能导致对诚实发件人的不正确处罚)预计会在数据传递给BitSwap之前被捕获。

Peer.close(Bool)。
关闭的最后一个参数表明拆除连接的意图是否是发送者的意图。 如果为false,则接收方可以选择重新打开连接immediatelty。 这避免了过早关闭。
对等连接应该在两种情况下关闭:
•silent_wait超时已过期,但未收到来自对等方的任何消息(默认BitSwap使用30秒)。 节点发出Peer.close(false)。
•节点正在退出,BitSwap正在关闭。 在这种情况下,节点发出Peer.close(true)。
关闭消息后,接收者和发送者都会断开连接,清除存储的任何状态。 如果这样做是有用的,则可以为将来存储分类帐。

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

3.5对象Merkle DAG

DHT和BitSwap允许IPFS形成一个庞大的对等系统,用于快速和强大地存储和分配数据块。 除此之外,IPFS还构建了一个Merkle DAG,一个有向非循环图,其中对象之间的链接是嵌入源中的目标的加密哈希。 这是Git数据结构的一个泛化。 Merkle DAG为IPFS提供了许多有用的属性,包括:
1.内容寻址:所有内容由其多重哈希校验和唯一标识,包括链接。
2.防篡改:所有内容都通过校验和进行验证。 如果数据被篡改或损坏,IPFS会检测到它。
3.重复数据删除:保存完全相同内容的所有对象都是相同的,并且只存储一次。 这对于索引对象特别有用,例如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可能不理解。 独立的inobject链接表允许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路径

可以使用字符串路径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本地对象

IPFS客户端需要一些本地存储器,一个外部系统,用于存储和检索IPFS管理的对象的本地原始数据。 存储类型取决于节点的用例。 在大多数情况下,这只是磁盘空间的一部分(由本机文件系统管理,通过诸如leveldb 的键值存储或直接由IPFS客户端管理)。 在其他情况下,例如非持久性缓存,此存储只是RAM的一部分。
最终,IPFS中可用的所有块都位于某个节点的本地存储中。 当用户请求对象时,它们至少暂时被发现,下载并存储在本地。 这为之后的一些可配置的时间量提供了快速查找。

3.5.3对象Pinning

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

3.5.4发布对象

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

3.5.5对象级加密

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文件

IPFS还定义了一组对象,用于在Merkle DAG之上对版本化文件系统进行建模。这个对象模型是类似于Git的:
1.块:一个可变大小的数据块。
2.列表:一个块或其他列表的集合。
3.树:块,列表或其他树的集合。
4.提交:树的版本历史记录中的快照。
我希望准确地使用Git对象格式,但不得不介绍在分布式文件系统中有用的特定功能,即(a)快速大小查找(聚合字节大小已添加到对象),(b)大文件重复数据删除(添加一个列表对象),和(c)将提交嵌入到树中。但是,IPFS File对象足够接近Git,两者之间的转换是可能的。此外,可以引入一组Git对象进行转换,而不会丢失任何信息(unix文件权限等)。
格式:下面的文件对象格式使用JSON。请注意,此结构实际上是使用protobufs进行二进制编码的,尽管ipfs包含导入/导出到JSON。

3.6.1文件对象:blob

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

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

3.6.2文件对象: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文件对象:tree

IPFS中的tree对象与Git类似:它表示一个目录,一个映射到哈希的名称。 散列引用blob,list,其他tree或commits。 请注意,传统路径命名已由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文件对象: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 }
    ]
}

3.6.5版本控制

提交对象表示对象版本历史记录中的特定快照。 比较两个不同提交的对象(和子对象)揭示了两个版本的文件系统之间的差异。 只要一个提交和它引用的所有子对象都可访问,所有先前的版本都可以被检索到,并且可以访问文件系统更改的完整历史记录。 这脱离了Merkle DAG对象模型。
IPFS用户可以使用Git版本控制工具的全部功能。 对象模型是兼容的,虽然不相同。 可以(a)构建修改为使用IPFS对象图的Git工具版本,(b)构建挂载的FUSE文件系统,将IPFS树挂载为Git repo,将Git文件系统读/写转换为IPFS格式

3.6.6文件系统路径

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

3.6.7将文件拆分成Lists和Blob

版本化和分发大文件的主要挑战之一是找到将它们拆分为独立块的正确方法。 IPFS不是假定它可以为每种类型的文件做出正确的决定,而是提供以下备选方案:
(a)像在LBFS中一样使用Rabin指纹来选择合适的块边界。
(b)使用rsync 滚动校验和算法来检测版本之间已更改的块。
(c)允许用户指定为特定文件高度调整的块分割功能。

3.6.8路径查找性能

基于路径的访问遍历对象图。 检索每个对象需要在DHT中查找它的关键字,连接到同级并检索其块。 这是相当大的开销,特别是在查找具有多个组件的路径时。 这可以通过以下方式来缓解:
•树缓存:由于所有对象都是散列寻址的,因此可以无限期地缓存它们。 此外,树的大小通常较小,所以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:命名和可变状态

到目前为止,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自我认证的名称

使用SFS的命名方案给了我们一种在密码指定的全局命名空间中构建可自行认证的名称的方法。 IPFS计划如下。
1.回想一下在IPFS中:

NodeId = hash(node.PubKey)
2.我们为每个用户分配一个可变名称空间:
/ IPNS/ <NodeId>
3.用户可以将对象发布到此路径,并由她的私钥签名,例如:
/ ipns / XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm /
4.其他用户检索对象时,可以检查与公钥和NodeId相匹配的签名。 这验证了用户发布的Object的真实性,实现了可变状态的回归。

请注意以下详细信息:
•ipns(InterPlanetary名称空间)单独的预先定义是为程序和读者建立一个易于识别的区分可变路径和不可变路径。
•因为这不是一个内容寻址对象,所以发布它依赖IPFS中唯一的可变状态分发系统,即路由系统。 该过程是(1)将对象发布为常规不可变的IPFS对象,(2)将其散列作为元数据值发布在路由系统上:
routing.setValue(NodeId, <ns-object-hash>)

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

/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/
/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/docs
/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/docs/ipfs

建议发布一个提交对象或其他具有版本历史记录的对象,以便客户端可以找到旧名称。 这留作用户选项,因为它并不总是需要的。
请注意,当用户发布此对象时,它不能以相同的方式发布

3.7.2人性化的名字

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

对等链接。
正如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 / <domain>是有效的域名,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.
Proquint可识别标识符。
一直以来都有将二进制编码转换为可发音单词的方案。 IPNS支持Proquint 。 从而:

# this proquint phrase
/ipns/dahih-dolij-sozuk-vosah-luvar-fuluh
# will resolve to corresponding
/ipns/KhAwNprxYVxKqpDZ

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

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

3.8使用IPFS

IPFS旨在用于许多不同的方式。 以下是我将要追求的一些用例:
1.作为挂载的全局文件系统,位于/ ipfs和/ ipns下。
2.作为个人同步文件夹,自动版本管理,发布和备份任何写入的文件。
3.作为加密文件或数据共享系统。
4.作为所有软件的版本管理软件。
5.作为虚拟机的根文件系统。
6.作为虚拟机的引导文件系统(在管理程序下)。
7.作为数据库:应用程序可以直接写入Merkle DAG数据模型,并获得IPFS提供的所有版本控制,缓存和分发。
8.作为一个链接(和加密)的通信平台。
9.作为完整性检查大文件的CDN(无SSL)。
10.作为加密的CDN。
11.在网页上,作为网络CDN。
12.作为永久网站。
IPFS的实现目标是:
(a)一个IPFS库,用于导入您自己的应用程序。
(b)直接操作对象的命令行工具。
(c)使用FUSE 或作为内核模块安装的文件系统。

4.未来

IPFS背后的理念是几十年来在学术界和开源领域成功实施的分布式系统研究的产物。 IPFS综合了迄今为止最成功系统的许多最佳创意。除了新协议BitSwap以外,IPFS的主要贡献在于系统和设计综合的耦合。
IPFS是新的分散式互联网基础设施的宏伟蓝图,可以构建各种不同的应用程序。它至少可以用作全局的,装载的,版本化的文件系统和命名空间,或者作为下一代文件共享系统。在最好的情况下,它可以将网络推向新的视野,在那里发布有价值的信息不会强加给发布商,而是让那些感兴趣的用户可以信任他们收到的内容,而不信任他们从其接收的内容,以及旧的但重要的文件不会丢失。 IPFS期待着给我们带来永远不会消失的网络。

5.致谢

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

猜你喜欢

转载自blog.csdn.net/luxtime/article/details/80502959
今日推荐