BYTECODES

IPFS源码阅读(二)

使用IPFS中重要的就是要知道怎样存和获取数据,以及数据的交换。本文重点介绍下Add操作,就是IPFS添加文件时涉及到的相关代码。当前的IPFS版本是v0.13.0-rc1,我实际是看的master分支。

入口文件Add

Add函数位于core/coreapi/unixfs.go文件中

里面可以看到重要的几点

  1. Chunker默认大小是256kb,用"size-262144"表示

  2. 使用Balanced Merkle DAG

  3. 组件之间的关系:DAGService包含了BlockService组件,而BlockService组合了GCBlockstore组件,然后GCBlockstroe包含BaseBlocks和GCLocker两个组件,最后BaseBlocks组合了最原始的blockstore组件

Add执行过程大概如下:初始化settings,然后使用api.baseBlocks, api.blockstore初始化GCBlockstore,接着初始化DAGService


然后创建一个adder,调用AddAllAndPin

addFile

传入路径和文件, 调用adder.add生成Merkle DAG并返回root, 接着调用adder.addNode把root节点添加到MFS中(MFS具体内容看我前一遍文章),这又是通过调用mfs.PutNode方法来实现的。

PutNode(r *Root, path string, nd ipld.Node)

通过path查找root节点应该存放的目录,然后调用directory.AddChild,这个函数

  1. 会继续调用dagService.Add完成文件实际存储(最终调用的是flatfs的Put函数)

  2. 调用unixfsDir.AddChild吧根节点存放到Merkle DAG中

后续流程

根据需要是否pin文件

总结

在寻找存放文件的实际Put函数时,很是头疼,IPFS的部分代码设计还是不错的,比如模块化和接口抽象,但实际也没那么好,代码调用层次过深(包括参数传递)

另外GO语言也比较灵活,写不好就有比较乱的感觉。

附录

  • 实际文件存放目录: ~/.ipfs/blocks

  • 想看Merkle DAG是什么样子的,可以参考这个工具: https://dag.ipfs.io/

  • ipfs filestore

    IPFS中的filestore作用类似于Git中的LFS,主要用于存储大文件,在blockstore只存储大文件的dag root,在FileManager存放文件的metadata, 避免大文件充斥blockstore,节省blockstore的空间。

  • DAG中叶子节点的数据结构ipld.Node

  • DAG中有Link数据结构如下

// Link represents an IPFS Merkle DAG Link between Nodes.
type Link struct {
   // utf string name. should be unique per object
   Name string // utf8

   // cumulative size of target object
   Size uint64

   // multihash of the target object
   Cid cid.Cid
}