主页 > imtoken苹果版最新版 > 深入理解比特币数据存储

深入理解比特币数据存储

imtoken苹果版最新版 2023-08-20 05:09:12

当我们打开bitcoincash目录,我们会看到如下文件目录。 这些文件是什么,它们存储在什么地方? 下面我们就一一揭开它的神秘面纱。

比特现金文件夹:

比特现金.png

块文件夹:

方块.png

索引文件夹:

索引.png

链态文件夹:

链状态.png

通过观察bitcoincash目录,我们可以发现比特币一共存放了以下内容:

其中,块数据和块undo数据直接存储在磁盘上,块索引数据和utxo数据写入leveldb数据库。

水平数据库

为了便于理解leveldb的目录存储结构,下面简单介绍一下leveldb的原理。

leveldb.png

leveldb采用了LSMTree的存储结构,其存储逻辑大致如上图所示。 具体步骤如下:

将一条数据写入leveldb时,会先将数据写入日志文件,日志文件完成后,再将数据写入内存(memtable)。 当memtable中的数据已满时,.log文件会被锁定,同时会生成一个Immutable table文件。 该文件只支持读取操作比特币是怎么存储的,不支持写入和删除。 这时会重新生成.log文件和memtable文件,新的write输入一条数据时,会重写空的.log文件和memtable。 LevelDb后台调度会将Immutable Memtable的数据导出到磁盘,形成一个新的SSTable文件。 SSTable是在内存中不断导出数据并进行Compaction操作形成的,SSTable中的所有文件都是层次结构,第一层为Level 0,第二层为Level 1,依此类推,层级逐渐递增。 这也是它被称为 LevelDb 的原因。 各文件含义: 当前文件:

当前文件有什么用? 这个文件的内容只有一个信息,就是记录当前manifest文件的名称。 因为在LevleDb运行过程中,随着Compaction的进行,SSTable文件会发生变化,会产生新的文件,旧的文件会被丢弃。 清单也将反映这一变化。 这时候往往会生成一个新的Manifest文件来记录这个变化,Current用来指出哪个Manifest文件是我们关心的Manifest文件。

清单文件

Manifest文件存放的是xxx.ldb文件的元数据信息,因为我们只有xxx.ldb文件,不知道它属于哪一层。 这也是Manifest文件的作用。 每次打开 DB 时,leveldb 都会创建这样一个文件,并在其末尾附加一个后缀标识符。 该文件以附加模式写入磁盘。

日志文件

leveldb运行时的日志文件,方便用户查看。

锁定文件

它是一个使用文件实现的DB锁,它告诉用户一个leveldb的实例在一个进程内只允许被打开一次。

xxx.ldb文件

这个文件是记录leveldb的数据文件(区别于元数据文件),以KV的有序形式写入数据库。

level-0的文件大小为压缩后memtable文件的大小,level-1为10MB,level-2为100MB,level-3为1000MB,以此类推。

xxx.log文件

上面我们说了,为了保证数据不丢失,在写入数据之前会写入.log文件。 .log文件存储了最近的一系列更新,每一次更新都以append的形式追加到当前日志文件中。 当日志文件达到 4MB 时,将转换为有序文件,并创建一个新的日志文件来记录最新的更新。 这个日志文件映射到上面提到的 memtable 文件。 当memtable文件写入level-0时,对应的日志文件会被删除,并重新创建一个新的日志文件来对应新的memtable。 等等。

综上所述,我们可以看出leveldb是一种典型的数据和元数据分离存储的存储模型数据库。

链态文件夹

chainstate是一个leveldb数据库,主要存储utxo和tx的一些元数据信息。 chainstate 中存储的数据主要用于验证新进入的区块和 tx 是否合法。 如果没有这个操作,就意味着你需要执行全表扫描来验证每一个花出去。

chainstate_file.png

如上图所示,utxo数据主要存放在chainstate文件目录下。 由于需要存储在leveldb中,所以必须以key和value的格式准备数据。

coincoin.pngcoin_db_key.png

如上图:key一共包含三部分,1个字节的大写C,32个字节的hash,4个字节的序号。

value为coin的序列化值,如下:

图片.png

coin还包含txout结构,如下:

图片.png

对nValue和scriptPubKey分别使用不同的压缩方式进行序列化,如下:

image.png 最佳 blockimage.png

比特币在chainstate中还记录了另一部分信息,首先判断当前区块的hash是否为null,如果不为null,则以1字节的大写B为key,32字节的block hash为value,将其写入数据库中的硬币。

总结:utxo写入磁盘的数据库是:chainstate,写入的数据分为两部分。 第一部分:key为outpoint,由+组成,其中txid为32字节,tx out index用var int编码序列化,value为coin序列化后的大小。 第二部分:写入的key是1字节的DB_BEST_BLOCK标识,value是32字节的块哈希。

图片.png

在bitcoin core 0.17中,改变了chainstate目录,多写入了一些数据,如下图:

image.png注意:

在0.17的结构中,第一部分不会长期存在,只会在触发BatchWrite的第一步写入,整个coinsmap写入完成后,这部分将被删除。

索引文件夹:image.png

index文件夹主要记录block的索引信息。 区块索引是区块的元数据信息,包括区块头信息、高度、链信息; 按照utxo存储的思路,我们会在blocks key和value中寻找索引。

重新索引图像.png

写入索引的第一部分数据:key是一个1字节的DB_REINDEX_FLAG,value是一个1字节的布尔值。 用于标识是否需要重建索引操作。

txindeximage.png

index中写入的第二部分数据:key是1字节的DB_TXINDEX加上32字节的hash,value是序列化后的CDiskTxPos,它唯一的成员是int类型的nTxOffset。 这些是可选的,只有在启用“txindex”时才会出现。 每个记录存储:

交易存储在哪个块文件号中。 交易属于哪个文件,偏移量存储在哪个文件中。从块的开头到交易本身存储位置的偏移量。 块文件信息图像.png

第三部分写入索引的数据:这部分数据比较重要,

文件信息

先写入fileinfo数据,key是1字节的DB_BLOCK_FILES加上4字节的文件号,value是CBlockFileInfo序列化后的数据。

最后一个文件

接下来写入lastFile信息,key为1字节DB_LAST_BLOCK,value为4字节nLastFile。

块索引

最后写入blockindex信息,key是1字节的DB_BLOCK_INDEX加上32字节的blockhash值就是CDiskBlockIndex的序列化数据。

国旗图片.png

index中写入的第四部分数据:key是1个字节的DB_FLAG加上标志名,value是1个字节的布尔值(1为真,0为假),可以打开或关闭各种类型的标志,例如当前defined:TxIndex(是否开启交易索引)。

image.pngblock 文件夹

block文件夹下主要有两种文件,一种是blk???.dat,用来存放blocks比特币是怎么存储的,另一种是rev???.dat,用来存放undo blocks。 主要存储格式如下:

存储块序列化数据。

图片.png

存储格式如下(按顺序):

image.pngMessageStart

MessageMagic是在启动程序的时候定义的,在不同的网络中定义不同。 MessageMagic分为netMagic和diskMagic:

主网:image.pngTestNet:image.pngRegTestNet:image.png

MessageMagic是一个4字节数组,写入数据时调用FLATDATA宏定义,如下:

图片.png

FLATDATA会将vector或map数据结构中的元素按照数组的原始顺序转储到磁盘中。

图片.png

write()函数第一个参数表示要写入数据的起始位置,第二个参数表示要写入数据的大小,pbegin指向vector的起始位置,pend指向的位置结束元素+1,所以这里先写入4字节的messageStart。

image.pngBlockSize

BlockSize主要描述了Block序列化后的长度,为4字节。

image.png块序列化

区块序列化主要序列化两部分,一部分是BlockHeader结构,另一部分是交易的共享指针vtx:

图片.png

第一部分是 BlockHeader:

图片.png

第二部分是vtx:

图片.png

CTransaction主要序列化以下内容:

image.png总结:

blk????.dat文件先写入4字节的messageMagic,再写入4字节的block size,最后写入block的序列化数据。

存储 undoblock 序列化数据。

图片.png

MessageStart 和 UndoBlockSize 与 Block 中相同。

BlockUndo序列化

BlockUndo序列化只有一个vtxundo对象,vtxundo是CTxUndo的一个vector,其序列化操作如下:

图片.png

CTxUndo的序列化操作如下,其中prevout为Coin的向量:

图片.png

Coin的序列化操作如下:

图片.png

Coin由两部分组成,代码如下:

图片.png

TxOut的序列化如下,nValue和scriptPubKey的序列化采用不同的压缩方式:

image.pngBlockUndoCheckSum

具体代码如下:

图片.png

将hashBlock和blockundo的数据写入CHashWriter的接口,得到CHashWriter的hash,将32字节的hash值写入undofile文件。

blk????.dat和rev????.dat存放的数据不同,block存放的是block header和txs的序列化数据,undo block存放的是txout的序列化数据。

关于文件大小的一些问题:

blk.dat默认初始化大小为16M,最大128M,rev.dat默认初始化大小为1M。

图片.png

导入块时会检查磁盘空间,必须大于50M,否则磁盘空间不足

图片.png

关于剪枝,磁盘要求必须大于550M:

图片.png

比特币需要保留 288 个区块。 按照每个块1M的大小计算,需要288M,另外还需要15%的空间来存放UNDO数据,加上20%的孤块率,大约需要397M的空间,这是最小的,但是我们还需要加上同步块的数据blk.dat,需要128M,再加上15%左右的undo数据,大概147M。 所以整体需要147M+397M=544M,所以设置限制为550M。

如何实现比特币的热存储和冷存储?

如何实现比特币的热存储和冷存储?

要理解热存储和冷存储,我举个例子。 如果张三手里有10万元,那么张三可能会拿出5000元日常开销,剩下的95000元存入银行。 那么5000对应的是热库,95000对应的是冷库。

冷库是对比特币的再次保险,就像银行里的现金一样。 在冷存储中,可以离线生成私钥(在没有联网的机器上),然后离线保存,离线使用。 有一个叫做 Armory 的客户端可以做到这一点。 因为没有互联网,即使是最强大的黑客也无法窃取您的比特币。

比特币脚本是如何应用的?

比特币中也有一个比特币脚本。 比特币使用这个脚本来验证交易的合法性,而不是需要人工验证。

脚本相当于编写了一堆命令参数。 在发起交易时,需要将收款人的公钥以脚本的形式写入,然后脚本会验证交易的合法性,让收款人使用自己的私钥完成脚本验证。 它使用栈的数据结构。 这个结构从技术上解释了,一般来说可以push,pop,检查。 就像把书放在一个有一定高度的盒子里,盒子的宽度只能装一本书。 第一个进去的一定是最后一个出去的。 因为使用脚本,比特币实际上是通过计算机来实现所有数字货币的转账机制。

如何实现比特币的热存储和冷存储?

#欧易OKEx##比特币[超话]##数字货币#