最新消息:

比特币源码剖析(二)之数据存储

Bitcoin justnode 231浏览

在比特币中,有四种数据被持久化存储在硬盘上:

1.block/blk*.dat:这些文件存储的是真正的区块链数据,以二进制的形式存储在磁盘上。当需要跟其他节点同步区块数据以及在钱包中搜索缺失的交易时才会用到。

2.block/index/*.ldb: 数据存储在leveldb数据库中,里面包含所有区块的区块索引。每个区块索引只有88字节,截止到2018年3月,全部区块索引的大小为80M,远小于区块的总大小。

3.block/rev*.dat: 存储未交易数据,当区块链需要回滚时会用到。

4.chainstate/*.ldb:数据存储在leveldb数据库中,里面包含当前所有的未花费的交易输出。

 

blk*.dat
每一个blk*.dat文件的大小是128M,截止到2018年3月10号,最新的区块文件是blk1168.dat,总大小是150G。

每一个区块文件(比如blk00001.dat)都有一个与之相对应的未交易文件rev*.dat(比如rev00001.dat)。区块文件的信息存储在leveldb数据库中,分为两部分:

在比特币代码中想要读取区块文件的内容,需要如下两个变量:

1.DiskBlockPos:这是指向区块文件所在位置的结构体变量,包含两个元素:filename和offset

2.vInfoBlockFiles:这是一个元素类型为BlockFileInfo的vector变量。

 

区块索引(block index)
区块索引包含所有区块的mete信息。注意这里的“所有区块”不仅仅是指最长区块链上的区块,还包括分支链上的区块。这里有个容易混淆的概念,人们通常所说的区块链实际上是区块链中的最长链,而真正的区块链是树状结构,这棵树上包含很多个分支。

区块索引存储在leveldb中,其中key以字符”b”开头,key/value格式为:’b’+32字节的区块hash值 -> 区块索引。每个区块索引存储如下内容:

* 区块头信息
* 区块的高度
* 区块中的交易数量
* 区块存储在哪个blk*.dat文件中,以及区块在该文件中的偏移量
* 未交易数据存储在哪个rev*.dat文件中,以及未交易数据在该文件中的偏移量

 

UTXO(chainstate leveldb)
UTXO(Unspent Transaction Out):即未花费交易输出,通俗的讲指的就是比特币中的“币”。在比特币中并没有采用更直观的账户余额模型(每个账号对应相应的金额),而是采用UTXO模型,每个账号所拥有的比特币数量是该账号所有未花费交易输出的总和。当需要获取某个账号拥有的比特币数量时,就需要遍历所有未花费交易输出,进行累加。

UTXO在leveldb中的key/value格式:’c’+32字节的交易的hash->value。value中存储的内容如下:

*交易的版本
*这个交易是不是coinbase
*哪个高度的区块包含这个交易
*这个交易的第几个output是未花费的
*未花费交易输出的scriptPubKey和amount

 

rev*.dat
rev*.dat文件中存储的是未交易数据,这些未交易数据是区块进行回滚时所必须的。从本质上来讲,这些未交易数据其实是一系列CTxOut对象(该对象包含amount和scriptPubKey两个变量)

举个例子:假设有个交易A,它有三个交易输出:out1,out2,out3。当out1被花费时,out1中的amount和scriptPubKey会被写入到rev*.dat文件中。out2被花费时和out1类似。只有当out3被花费时,情况会有所不同。除了out3中的scriptPubKey和amount被写入以外,交易A的高度以及交易A是不是coinbase也需要被写入。