版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010986776/article/details/84839487
1.账本存储概述
- peer节点账本存储图如下
- 左边区块链是狭义上的区块存储,底层是一个文件系统,区块并不是存储在数据库,而是直接存储为文件
- 右下角的区块索引用于查询区块,将区块属性与区块位置关联,例如根据区块哈希、高度、交易ID查询区块
- 区块索引的实现使用了levelDB,是一个内嵌的数据库
- fabric中不是一个区块单独存一个文件,所以需要区块索引去查找
- 右上角状态数据库是区块链上的最新数据
2.交易读写集
- 交易读写集(RWSet)有三个概念
- 读集
- 写集
- 版本号
- 交易验证阶段需要对交易读写集进行验证
- 交易模拟&验证过程例子,现在假设有T1,T2,T3,T4和T5共5笔交易,所有模拟基于同一个世界状态
-
世界状态:(k1,1,v1)(k2,1,v2)(k3,1,v3)(k4,1,v4)——key,version和value
-
T1通过验证,因为它并没有任何读操作,并且世界状态中k1和k2键的值分别更新为(k1,2,v1’)和(k2,2,v2’)
-
T2不能通过验证,因为它读取了k1键的值,该值在T1中被修改了
-
T3通过验证,因为它并没有任何读操作。并且世界状态中k2的值被更新为(k2,3,v2”)
-
T4不能通过验证,因为它读取了k2键的值,该值在T1中被修改了
-
T5通过验证,虽然读取了k5的值,但是k5的值之前交易并未修改过
-
3.账本存储其他概念
- 世界状态
- 交易执行后所有键的最新值
- 可以显著提升链码执行效率
- 历史数据索引
- 启用与否取决于智能合约是否有查询历史的需求
- 记录某个键在某区块的某条交易中被改变,只记录改变动作,不记录具体改变为了什么
- 区块存储
- 区块在fabric中以文件块存储,文件名是blocfile_xxxxxx(加一个6位数的编号)
- 现阶段,每个文件块大小是64M,需要更改的话,需要修改peer源码重新编译
- 区块读取
- 区块文件流
- 区块流
- 区块迭代器
- 区块索引
- 快速定位区块
- 索引键:区块高度、区块哈希、交易哈希
- 区块提交
- 保存区块文件
- 更新数据状态
4.账本存储源码
- 看core/ledger下的ledger_interface.go
- 读写集分为交易读写集生成和交易读写集验证两个部分
- 状态数据库
- core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
- 历史数据库
- core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go
- 区块文件读取
- common/ledger/blkstorage/fsblkstorage/ fs_blockstore.go
5.账本存储总结
- 账本存储的接口定义,从总体上把握
- 交易读写集校验,防止双花攻击,比特币是用最长链来防止的
- 状态数据库及历史状态数据库
- 区块文件存储及区块索引