一。概述
二。读写集
(一)。交易模拟和读写集
(二)。交易验证和世界状态更新
(三)。模拟和验证示例
三。账本编号
超级账本支持多账本(详细内容参考第7章实现数据隔离的多链及多通道),每个账本的数据是分开存储的。
账本编号(LedgerID)的数据存储在LevelDB数据库中,只是记录了有哪些版本,创建新的账本会检查是否有相同的账本编号存在,
这保证了全局唯一性。账本编号库并不存储与区块相关的数据。这和区块索引不一样。
四。账本数据
账本数据(Ledger)是以二进制文件的形式存储的,每个账本数据存储在不同的目录下。
后面内容都是在已经区分了账本的情况下再对数据进行查询的。
基于文件系统的区块存储实现了如下功能接口。
【1】。账本存储管理
A。提交区块到账本(AddBlock)
B。获取区块链信息(GetBlockchainInfo)
C。获取区块数据(RetrieveBlocks)
D。关闭区块存储(Shutdown)
【2】。索引管理:跟踪区块和交易保存在哪个文件。
A。根据哈希值获取区块(RetrieveBlockByHash)
B。根据区块编号获取区块(RetrieveBlockByNumber)
C。根据交易编号获取交易(RetrieveTxByID)
D。根据区块编号和交易编号获取交易(RetrieveTxByBlockNumTranNum)
E。根据交易编号获取区块(RetrieveBlockByTxID)
F。根据交易编号获取交易验证码(RetrieveTxValidationCodeByTxID)
账本数据的所有操作都是通过区块文件管理器(blockfileMgr)实现的,定义如下:
type blockfileMgr struct{ rootDir String //区块链中区块存储的根目录 conf *Conf //配置信息 db *leveldbhelper.DBHandle //数据库指针 index index //区块索引接口 cpInfo *checkpointInfo //区块检查点信息 cpInfoCond *sync.Cond //条件变量 currentFileWriter *blockfileWriter //当前写入区块文件的指针 bcInfo atomic.Value //区块链信息 }
区块文件管理器实现的功能分为几类:
【1】账本数据存储管理
A。确定文件存储在哪个目录
B。确定区块存储在哪个文件
【2】检查点管理:跟踪最新持久化存储的文件
【3】索引管理:跟踪区块和交易保存在哪个文件
(一)。账本数据存储
(二)。账本数据读取
(三)。交易模拟执行
五。区块索引
(一)。文件位置指针
(二)。索引的同步过程
六。状态数据
(一)。LevelDB
(二)。CouchDB
"data":"$rawJSON"
}
在超级账本中:
【1】如果存储的类型是JSON,且JSONValue的data字段是状态值经过JSON序列化后的内容,则CouchDoc中的Attachments为空;
【2】如果存储的类型是字节数组,则JSONValue只保存版本信息,data字段为空,状态值放在Attachments的AttachmentBytes中,Attachments的Name为“valueBytes”,ContentType为“application/octet-stream”。在获取时根据data字段是否为空可以判断出存储的状态值类型,最后得到存储的版本和状态值。
条件查询是基于LevelDB的状态数据库所没有的功能进行的。查询前会对查询条件进行转换,增加“data.”前缀和查询记录限制等,查询结果还会默认增加“_id”"version""chaincodeid"。比如原始的查询条件为:
{
"selector":{
"owner":{
"$seq":"tom"
}
},
“fields”:[
"owner",
"asset_name",
"color",
"size"
],
"sort":[
"size",
"color"
]
}
转换后的查询条件为:
{
"selector":{
"$and":[
{
"chaincodeid":"marble"
},
{
(三)基于状态数据的区块验证
七。历史数据
历史信息记录最细的粒度就是交易,若在一个交易中多次对同一个writeKey更新数据,则会以第一次数据为准,历史信息实际存储的信息是固定的空字节数组[]byte{}。
更新区块信息的时候,会同步更新检查点信息,保存的内容是最新的区块高度和最大的交易序号,检查点信息用来判断历史信息的状态是否是最新的。
八。数据恢复
区块的提交过程分为3个步骤:
【1】。先保存区块到文件存储的账本数据中
【2】。然后更新状态数据
【3】。最后更新历史信息数据
这3个步骤是顺序执行的,在这个过程中有文件的操作,也有数据库的操作,所以在任何一个步骤都可能出现错误或者中断。恢复的过程会根据账本数据记录的区块信息和状态数据,历史信息数据的检查点进行比较,重新提交检查点之后的区块信息,保持账本数据的一致性。
本章小结:
本章介绍了Hyperledger Fabric 1.0的数据存储,包括账本数据(Ledger)、区块索引(Index)、状态数据(state Database)、历史数据(Hisotry database)等存储结构。目前的数据存储存在较大的优化空间,账本数据结构的设计带来的开销很大,最新的版本并没有实现账本载剪(Ledger Prune)功能,不能进行归档,也不能删除无效交易,所以会导致存储空间持续增长。