首先来介绍一下IPFS中使用的Merkle DAG的数据结构,图中1是这种图的数据结构示意图,这个图由节点和链接组成,节点存储数据及数据的下级链接关系,链接存储的是数据的Hash值,正因为链接是数据的Hash值,此数据结构才被称为Merkle DAG。
图中2给出了链接的数据结构,它由3部分组成:Name:下级数据的名称;Size:下级数据的大小;Cid:下级数据的hash索引,通过该索引可以在IPFS全网查找数据。
图中3表示节点的数据结构,它存储了所有下级的链接数据,一个节点本身的数据,一个全节点数据的封装之后的数据,封装数据的方式有多种,在IPFS的IPLD相关源码中有详细描述,这里可以简单的理解为节点所有数据的一种序列号算法。另外还有就是这个序列化之后的数据的HASH值。这个Hash值用来保证数据的有效性。以上讲的比较抽象,我们通过实例来讲解。
上图中我们创建了一个nbs目录,其然后再目录下创建一个文本文件和另一个目录,新目录下也创建了一个文本文件。此目录结构比较简单。然后我们通过以下IPFS命令将其上传到IPFS网络中。
上传成功之后的界面如上,这个界面清晰的给出了nbs目录的上传信息。
根据刚才我们的数据结构阐述,nbs目录的存储方式如上图。首先nbs整个目录会有一个hash值,因为这个目录下有一个目录和一个文件,一次气links有两个,这两个links分别描述了下一个数据节点的名称,大小和hash值。本节点的data仅仅表明此数据节点表示的是一个目录(CAE=)
接下来是1.txt文件对应的节点数据,因为它没有下一级数据结构,因此其links是空数组,其data实1.txt文本内容的一种编码之后的数据。
一次类推可以得到目录a和文本2.txt的节点数据和链接数据。接下来我们通过IPFS相关命令来验证一下数据。
上图是通过IPFS的DAG命令来查询数据和链接的信息。你可以发现,通过hash值加文件或者目录名称的方式也可以正确查询出节点的相关信息,也就是说直接通过link中hash或者通过link中name字段都可以查询出相关的节点数据。这种方式有点类似于我们访问网站时,我们可以通过IP地址访问网站,也可以通过域名来访问网站。这也是为什么Merkle DAG 层被称作IPFS网络协议架构的IP层的原因。
接下来我们看一下关于Merkle DAG这一层的相关接口,我们仅以Get接口说明其实现逻辑:其部分接口如下图
上图中,当Merkle DAG层接收到Get命令之后,调用接口中的Get(cid)方法,该方法会首先根据Cid信息查找本地存储的数据中是否有相关的数据块,如果查找失败,则调用数据交换的GetBlock(Cid)方法来通过网络获取数据,该方法在前面的章节中已经介绍,不再赘述。
用来实现Merkle DAG的数据结构中已经定义了一个数据交换层的接口对象如下图
小节,本章节的内容比较容易理解,重点是数据结构的设计以及使用方式,在逻辑上并没有很难实现的地方,但是却相对重要,其作用可以媲美TCP/IP协议的IP层,可见其重要程度。