星鉴网>IPFS常识>IPFS白皮书协议堆栈解读

IPFS白皮书协议堆栈解读

2019/1/9 18:11:56 1699人阅读

【导读】 我借用了Juan Benet(IPFS的BDFL)的演示文稿中的两张图片,在白皮书中,IPFS的设计或多或少地会使用到这些层,自下而上: IPFS协议分为一堆子协议,负责不同的功能:

IPFS堆栈可视化如下:



或者更详细的说明:



我借用了Juan Benet(IPFS的BDFL)的演示文稿中的两张图片,在白皮书中,IPFS的设计或多或少地会使用到这些层,自下而上: IPFS协议分为一堆子协议,负责不同的功能:

1. 标识 – 管理节点标识生成和验证。2. 网络 – 管理与其他对等方的连接,使用各种底层网络协议。可配置的。3. 路由 – 维护信息以定位特定的对等体和对象。响应本地和远程查询。默认为DHT,但可以交换。4. 交换 – 一种新的块交换协议(BitSwap),用于管理有效的块分发。以市场为模型,弱刺激数据复制。可切换的贸易策略。交易策略可交换。5. 对象 -一个包含了链接的不可变对象的Merkle DAG。用于表示任意数据结构,例如文件层次结构和通信系统。6. 文件 – 受Git启发的版本化文件系统层次结构。7. 命名 – 自我认证的可变名称系统。

以下是我对这些子协议的替代命名:

1. 标识:标识这些节点2. 网络:与其他节点交谈3. 路由:宣布并查找内容4. 交换:发送和接收5. 对象:组织数据6. 文件:uh?7. 命名:添加可变性 接下来,就让我们仔细分析这些,看看是否能增加我们对IPFS的理解!

标识:标识这些节点

IPFS是一个P2P网络的客户端;没有中央服务器。这些客户端是网络的节点,需要一种被其他节点识别的方法。如果你给节点1 2 3编号,那么任何人都可以添加一个具有现有ID的节点并声明为该节点。为了防止这种情况发生,需要一些加密技术。IPFS是这样做的:

1.生成PKI密钥对(公钥+私钥)2.哈希的公钥3.生成的哈希是NodeId

所有这些都是在节点的初始阶段完成的:

ipfs init > the resulting keys are stored in ~/.ipfs/configand returns the NodeId.

当两个节点开始通信时会发生以下情况:

1.交换公钥2.检查: hash(other.PublicKey) == other.NodeId3.如果是,那么我们已经确定了另一个节点,并且可以请求数据对象4.如果否,我们断开与“假”节点的连接

白皮书中未指定实际的Hash算法,请阅读此处的说明:

IPFS不将系统锁定为一组特定的函数选择,而是支持自描述值。哈希摘要值以多哈希格式存储,其中包含一个简短的头,指定使用的哈希函数,以及以字节为单位的摘要长度。 例子: \ \ \ 这使得系统可以(a)为用例选择最佳的功能(例如,更强的安全性和更快的性能),以及(b)随着功能选择的改变而演进。自描述值允许兼容地使用不同的参数选择。

这些多哈希是自描述哈希的整个系列的一部分,它非常棒,有兴趣可以看:https://github.com/multiformats/multiformats

网络:与其他节点交谈

总结如下:IPFS在任何网络之上工作(参见上图)。 这里有趣的是连接到节点的网络寻址。IPFS使用multiaddr格式。当你启动一个节点时,你可以看到它在运行:

Swarm listening on /ip4/127.0.0.1/tcp/4001Swarm listening on /ip4/172.17.0.1/tcp/4001Swarm listening on /ip4/185.24.123.123/tcp/4001Swarm listening on /ip6/2a02:1234:9:0:21a:4aff:fed4:da32/tcp/4001Swarm listening on /ip6/::1/tcp/4001API server listening on /ip4/127.0.0.1/tcp/5001Gateway (read-only) server listening on /ip4/0.0.0.0/tcp/8080

路由:宣布并查找内容

路由层基于DHT,如上一章节中所讨论的,其目的是:

1.宣布该节点有一些数据(block如下一章所述)2.找到哪些节点有一些特定的数据(通过参考块的multihash)3.如果数据足够小(= <1KB),DHT将数据存储为其值。

命令行接口和API不会像白皮书中指定的那样,公开完整的路由接口。工作内容:

# tell the DHT we have this specific content:$ ipfs dht provide QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG # ask for peers who have the content:$ ipfs dht findprovs QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdGQmYebHWdWStasXWZQiXuFacckKC33HTbicXPkdSi5Yfpz6QmczCvhy6unZEVC5ukR3BC3BPxYie4jBeRApTUKq97ZnEoQmPM3WzZ3q1SR3pzXuGPHD7e6z3eWEWCnAvrNw7Wegyc8oQmPKSqtkDmYsSxQbqNkZG1AmVnZSFyv5WF7fFE2YebNBFGQmPMJ3HLLLBtW53R2YixhVHmVb3pkR2bHni3qbqq23vBSvQmPNHJJphV1TB6Z99L6r9Y7bKaCBUQ67X17hicnEmsgWDJQmPNhiqGg81o2Perk2i7VNvvVuuLLUMKDxMNwVauP8r5YvQmPQJRgP3Vxi52Ho7HfnYdiCRJTRM1TXwgEnyjcwcLuKfbQmNNxr1ZoyPbwNe2CvYz1CVyvSNWsE8WNwDWQ9t9BDjnj5QmNT744VjtRFpDYB25EVLx7ha1zAVDKsd3qFjxfQLjPEXqQmNWwGRWTYeut6qvKDhJBuEJZnbqMPMfuF81MPvHvPBX89QmNZM5NmzZNPkvH2kPXDYNAB1cAeBNfxLyM9B1crgt3VeJQmNZRDzSJybdf4rmt972SH4U9TF6sEK8q2NSEJpEt7SkTpQmNZdBUV9QXytVcPjcYM8i9AG22G2qwjZmh4ZwpJs9KvXiQmNbSJ9okrwMphfjudiXVeE7QWkJiEe4JHHiKT8L4Pv7z5QmNdqMkVqLTsJWj7Ja3oKwLNWcAYUkRjSZPg22B7rvKFMrQmNfyHTzAetJGBFTRkXXHe5om13Qj4LLjd9SDwJ87T6vCKQmNmrRTP5sJMUkobujpVXzzjpLACBTzf9weND6prUjdstWQmNkGG9EZrq699KnjbENARLUg3HwRBC7nkojnmYY8joBXLQmP6CHbxjvu5dxdJLGNmDZATdu3TizkRZ6cD9TUQsn4oxY # Get all multiaddr’s for a peer$ ipfs dht findpeer QmYebHWdWStasXWZQiXuFacckKC33HTbicXPkdSi5Yfpz6/ip4/192.168.1.14/tcp/4001/ip6/::1/tcp/4001/ip4/127.0.0.1/tcp/4001/ip4/1.2.3.4/tcp/37665

ipfs put和ipfs只适用于API中的ipns记录。也许在DHT上存储小数据还没有实现?

交换:发送和接收

数据被分解成块,交换层负责分配这些块。它看起来像BitTorrent,但是它不同,所以协议有它自己的名字:BitSwap。

主要的不同之处在于,在BitTorrent块与寻找相同文件块(torrent swarm)的对等块进行交易时,在BitSwap块中交换交叉文件。所以有一大群的IPFS数据。

BitSwap被建模为一个激励数据复制的市场。这种方法被称为BitSwap策略,白皮书描述了一种可行的策略,并指出策略可以被另一种策略替代。这种交易系统可以建立在虚拟货币的基础上,这就是FileCoin的切入点。 当然,每个节点都可以决定自己的策略,因此通常使用的策略必须具有抵御滥用的能力。当大多数节点被设置为具有某种公平的交换方式时,它的工作原理是这样的:

1.当对等体连接时,它们会交换它们拥有的块(have_list)和要查找的块(want_list);2.要确定节点是否实际共享数据,它可以应用 BitSwap策略进行检验;3.该策略基于这两个节点之间的先前数据交换;4.当节点交换区块时,他们会跟踪他们共享的数据量(构建信用额)以及他们收到的数据量(构建债务);5.在BitSwap账目中,记录了两个节点之间的分类账目;6.如果一个节点拥有信用(共享多于接收),我们的节点会发送被要求的区块7.如果一个节点有债务,我们的节点将共享或不共享,这取决于一个确定性函数,当债务越大,共享的机会就越小;8.数据交换总是从交换分类账开始,如果不相同,我们的节点断开连接;

这是一种很酷的游戏理论!白皮书进一步描述了一些边缘情况,比如如果我没有块可以交换的块怎么办?答案很简单,就是收集你的同行正在寻找的区块,这样你就有了交易的东西。 现在让我们看看我们如何在BitSwap交换协议的内部进行搜索。 命令行界面有一个部分blocks和一个部分bitswap; 为了看到 bitswap的运行方式,我请求了一个大的视频文件:Qmdsrpg2oXZTWGjat98VgpFQb5u1Vdw5Gun2rgQ2Xhxa2t

# ask for the file$ ipfs get Qmdsrpg2oXZTWGjat98VgpFQb5u1Vdw5Gun2rgQ2Xhxa2t # in a seperate terminal, after requesting the file, I inspect the “bitswap wantlist”$ ipfs bitswap wantlistQmYEqofNsPNQEa7yNx93KgDycmrzbFkr5oc3NMKXMxx5ffQmUmDEBm9a8MYyqRdb3YQnoqPmqAo4cEWdKQErirFJdSWDQmY5VJPbsRZzFCTMrFBx2qtZiyyeLhsjBysyfC1fx2gE9SQmdbzYgyhqUNCNL8xU2HTSKwao1ck2Gmi5U1ygjQuJd92bQmbZDe5Dcv9mJr8fiqp5aJL2cbyu64tgzwCS2Vy4P3krCLQmRjzMzVeYRE5b6tDF3sTXMV1sTffno92uL3WwuFavBrWQQmPavzEJQw8atvErXQis6C6GF7DRFbb95doAaFkHe9M38uQmY9fs1Pkr3nV7RkbGdfGh3q8HuKtMMCCUp22AAbwPYnrSQmUtxZkuJuyydd124Z2cfx6jXMAMpcXZRF96QMAsXc2y6cQmbYDTJkmLqMm6ojdL6pLP7C8mMVfVPnUxn3yp8HzXDcXfQmbW9MZ7cwn8svpixosAuC7GQmUXDTZRuxJ8dJp6HyJzCSQmdCLGWsYQFhi9y3BmkhUreX2S799iWGyJqvnbK9dzB55cQmc7EvnBPf2mPCUCfvjcsaQGLEakBbUN9iycnyrLF3b2orQmd1mNnDQPf1BAjFqDHjiLe4g4ZFPAheQCniYkbQPosjDEQmPip8XzQhJFd487WWw7D8aBuGLwXtohciPtUDSnxpvMFRQmZn5NAPEDtptMb3ybaMEdcVaoxWHs7rKQ4H5UBcyHiqTZ… # find a node where we have debt$ ipfs dht findprovs Qmdsrpg2oXZTWGjat98VgpFQb5u1Vdw5Gun2rgQ2Xhxa2tQmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9zQmUh2KnjAvgEbJFSd5JZws4CNvt6LbC4C1sRpBgCbZQiqDQmc9pBLfKSwWboKHMvmKx1P7Z738CojuUXkPA1dsPrvSw2QmZFhGyS2W833nKKkbqZAU2uSvBbWUytDJkKBHimwRmhd6QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16ZicQmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6 # try one to see if we have downloaded from that node$ ipfs bitswap ledger QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3Ledger for Debt ratio: 0.000000Exchanges: 11Bytes sent: 0Bytes received: 2883738

现在,看看block命令:

# Let’s pick a block from the wantlist above$ ipfs block stat QmYEqofNsPNQEa7yNx93KgDycmrzbFkr5oc3NMKXMxx5ffKey: QmYEqofNsPNQEa7yNx93KgDycmrzbFkr5oc3NMKXMxx5ffSize: 262158 $ ipfs block get QmYEqofNsPNQEa7yNx93KgDycmrzbFkr5oc3NMKXMxx5ff > slice_of_a_movie# results in a binary file of 262 KB

我们将在下一章再看一下块如何适应。

到目前为止,我们描述的堆栈的三层结构(网络,路由,交换)在libp2p中实现。

现在,让我们看看堆栈中IPFS的核心……

对象:组织数据

现在它变得引人入胜。您可以将IPFS概括为:分布式的、经过身份验证的、哈希链接的数据结构。这些hash-linked数据结构Merkle DAG的由来(还记得我们前一章吗?)。 为了创建任何数据结构,IPFS提供了一种灵活而强大的解决方案:

1.在图表中组织数据,我们称之为图表的节点 objects2.这些对象可以包含数据(任何类型的数据,对IPFS透明)和/或指向其他对象的链接3.这些链接 – Merkle Links只是目标对象的加密哈希

这种组织数据的方式有几个有用的属性(引自白皮书):

1.内容寻址:所有内容都由其多哈希校验和(包括链接)唯一标识。2.防篡改:所有内容都通过校验和进行验证。如果数据被篡改或损坏,IPFS会检测到它。3.重复数据删除:所有保存相同内容的对象都是相等的,并且只存储一次。这对于索引对象(如git树和提交)或数据的公共部分尤其有用。

要了解IPFS对象,请查看此对象可视化示例。(https://ipfs.io/ipfs/QmNZiPk974vDsPmQii3YbrMKfi12KTSNM7XMiYyiea4VYZ/example#/ipfs/QmP8WUPq2braGQ8iZjJ6w9di6mzgoTWyRLayrMRjjDoyGr/graphmd/README.md)

另一个漂亮的功能是使用unix风格的路径,其中Merkle DAG具有以下结构:

/ipfs//

我们将在下面看到一个例子。

让我们通过重播快速入门中的一些示例来看它的实际效果:

$ mkdir foo$ mkdir foo/bar$ echo “baz” > foo/baz$ echo “baz” > foo/bar/baz$ tree foo/foo/├── bar│ └── baz└── baz$ ipfs add -r fooadded QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/bar/bazadded QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/bazadded QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN foo/baradded QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm foo# the last hash is the root-node, we can access objects through their path starting at the root, like:$ ipfs cat /ipfs/QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/bar/bazbaz# To inspect an object identified by a hash, we do$ ipfs object get /ipfs/QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm{ “Links”:[ { “Name”:”bar”, “Hash”:”QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN”, “Size”:61 }, { “Name”:”baz”, “Hash”:”QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR”, “Size”:12 } ], “Data”:”\u0008\u0001″}# The above object has no data (except the mysterious \u0008\u0001) and two links# If you’re just interested in the links, use “refs”:$ ipfs refs QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3GmQmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDNQmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR# Now a leaf object without links$ ipfs object get /ipfs/QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/bar/baz{ “Links”:[ ], “Data”:”\u0008\u0002\u0012\u0004baz\n\u0018\u0004″}# The string ‘baz’ is somewhere in there

 数据字段中出现的Unicode字符是数据序列化的结果。我认为IPFS使用的是protobuf。如果我错了请纠正我 在我写这篇文章的时候,ipfs对象命令有一个实验性的替代方法:ipfs dag:
  
  $ ipfs dag get QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm{ “data”:”CAE=”, “links”:[ { “Cid”:{ “/”:”QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN” }, “Name”:”bar”, “Size”:61 }, { “Cid”:{ “/”:”QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR” }, “Name”:”baz”, “Size”:12 } ]} $ ipfs dag get /ipfs/QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/bar/baz{ “data”:”CAISBGJhegoYBA==”, “links”:[ ]}
  
  我们看到了一些不同之处,但我们不谈这个。两个输出都遵循白皮书中的IPFS对象格式。有趣的一点是出现的“Cid”;这指的是更新的内容标识符。
  
  提到的另一个特性是pin对象的可能性,这导致将这些对象存储在本地节点的文件系统中。ipfs的当前go实现将其存储在目录下的leveldb数据库中~/.ipfs/datastore。我们已经在之前的帖子中看到了行动。 本章的最后一部分提到了对象级加密的可用性。这还没有实现:( status wip正在进行中;我也必须查找它)。项目页面在这里:ipfs keystore proposal。(https://github.com/ipfs/specs/tree/master/keystore)
  
  档案:uh?
  
  在Merkle DAG对象之上,IPFS定义了一个带版本控制的Git文件系统,其中包含以下元素:
  
  blob:blob中只有数据,它代表了IPFS中文件的概念。blob中没有链接;list:lists也是IPFS文件的表示形式,但由多个blob和/或列表组成;tree:blob,列表和/或树的集合:充当目录;commit:树中历史的快照(就像git提交一样);
  
  现在我听到你在想:这些斑点、列表和树不是和我们在归纳法中看到的一样吗?我们有带数据的对象,有或没有链接,以及类似unix的文件路径。 我听到你这么想,因为当我读到这一章的时候,我也是这么想的。在搜索了一下之后,我开始感觉到这个层被丢弃了,IPLD在“对象”层停止了,而上面的所有东西都对任何实现都是开放的。如果一位专家正在阅读这篇文章,并认为我完全搞错了:请让我知道,我将用新的见解来纠正它。
  
  那么,提交文件类型呢?白皮书的标题是“IPFS -内容寻址、版本化、P2P文件系统”,但是版本控制似乎还没有实现。 还剩下一层……
  
  命名:添加可变性
  
  由于IPFS中的链接是内容可寻址的(内容上的加密散列表示内容的块或对象),因此数据根据定义是不可变的。它只能被内容的另一个版本替换,因此它会获得一个新的“地址”。
  
  解决方案是为不可变内容创建“标签”或“指针”(就像git分支和标签一样)。这些标签可用于表示对象(或对象图)的最新版本。
  
  在IPFS中,可以使用我在上一篇文章中描述的自我认证文件系统创建此指针。它被命名为IPNS,其工作方式如下:
  
  节点的根地址是 /ipns/可以通过将IPFS对象发布到此地址来更改它指向的内容通过发布,节点的所有者(知道生成的秘密密钥的人ipfs init)以加密方式对该“指针”进行签名。这使其他用户可以验证所有者发布的对象的真实性。就像IPFS路径一样,IPNS路径也以哈希开头,然后是类似Unix的路径。IPNS记录通过DHT公布和解决。
  
  本文作者:Mark Pors

14

参与讨论

登录后参加评论......

全部评论 0

作者

返回顶部