IPFS数据结构分析
IPFS(Inter Planetary File System)简介
IPFS是基于P2P的分布式文件系统,相当于一个分布式版本的Web系统。的最大特点是基于内容寻址(content-addressing)与分布式存储(distributed storage)。
词汇定义
- hash - 哈希函数值(如sha3)
- dag - 有向无环图(directed acyclic graph)
- merkle-link - 默克尔链接(代表DAG图的边),通常包含一个代表某个对象的哈希值,ipfs通过默克尔链接构建出一个基于内容寻址的DAG图
- merkledag - merkledag是使用merkle-link构建出的DAG图,也是一种hash树;相对于merkle-tree,merkledag并不必需是平衡树,而且树的节点可以包含数据内容。
- multihash - 兼容多种hash的数据结构
- ipfs object - ipfs的节点对象,ipfs中一个object就是一个merkledag格式的结构
- merkledag format - merkledag格式,即merkledag图的节点数据结构
- link segment - merkledag格式的其中一个组成部分,即merkle-link
- data segment - merkledag格式的其中一个组成部分,即实际节点数据
- protobuf - 一种序列化编码
- multicodec - 一种序列化编码
核心数据结构
CID (Content Identifier)
CID的主要作用是唯一标识一个IPFS网络的资源,主要包含两部分内容:
- mcodec - 编码方式
- mhash - 兼容多种hash的数据结构,见词汇表multihash
IPLD (InterPlanetary Linked Data)
IPLD即原来的merkledag结构(同一个,官方文档将原来的merkledag改名为IPLD),主要包含两部分内容:
- Link Segment
- Data Segment
具体形式定义如下(ProtoBuf格式):
// An IPFS MerkleDAG Link
message MerkleLink {
bytes Hash = 1; // multihash of the target object
string Name = 2; // utf string name
uint64 Tsize = 3; // cumulative size of target object
// user extensions start at 50
}
// An IPFS MerkleDAG Node
message MerkleNode {
repeated MerkleLink Links = 2; // refs to other objects
bytes Data = 1; // opaque user data
// user extensions start at 50
}
Merkle森林
ipfs是基于内容的寻址方式(content addressing),主要有以下几个好处:
- 唯一性
- 防止篡改
- 无需复制大量数据内容
具体形式:
https://<gateway-host>.tld/ipfs/<cid>/path/to/resource
ipfs://{cidv1b32}/path/to/resource
IPFS希望构建一个Merkle森林,将所有Internet上的兼容merkledag数据的系统都包含进入这个森林。不同的系统(如Bitcoin,Ethereum或Git)在这个森林中相当于某一棵树;在系统间交换数据时只要提交某个特定对象的merkle root,便足以代表大量的数据,大大提高了系统间进行信息交换的效率。
目前merkledag兼容的系统有(仅列举一部分):
- Bitcoin
- Ethereum
- Bit Torrent
- Git
将不同系统间的相互访问寻址变成非常简单,以下举例寻址访问Ethereum的某个区块中成员数据的示例:
ipfs://{eth block cid}/number
ipfs://{eth block cid}/parent/number
ipfs://{eth block cid}/stateRoot
部分JS代码示例(具体代码可参考以下链接):
const block302516 = 'z43AaGEywSDX5PUJcrn5GfZmb6FjisJyR7uahhWPk456f7k7LDA'
const block302517 = 'z43AaGF42R2DXsU65bNnHRCypLPr9sg6D7CUws5raiqATVaB1jj'
function errOrLog (err, result) {
if (err) {
throw err
}
console.log(result.value.toString('hex'))
}
ipfs.dag.get(block302516 + '/number', errOrLog)
ipfs.dag.get(block302517 + '/parent/number', errOrLog)
ipfs.dag.get(block302517 + '/stateRoot', errOrLog)
https://github.com/ipfs/js-ipfs/blob/master/examples/traverse-ipld-graphs/eth.js
DAG结构的重要性
IPFS为整个分布式网络提供一个基础数据结构IPLD(即merkledag),使得各个系统能在此基础上构建功能强大并能相互联通的应用程序。IPLD在整个分布式网络中的位置堪比TCP/IP协议栈中IP的重要位置: