账本存储概念:
- peer节点做账本存储
- orderer是临时存储区块,peer节点是账本存储的持久化,会改变世界状态
- 文件系统,区块是存储为文件
- 区块索引,用于查询区块,是用levleDB实现的
- 状态数据库,一般存放区块链最新状态,数据不需要HA,可以从文件系统再次获取,couchDB支持模糊查询
交易读写集:
- 回忆交易流程
- 交易模拟:在背书节点执行模拟时,最终返回交易读写集(RWset),告诉区块链在交易中读写了哪些数据
- 交易排序
- 交易验证,交易验证后,更新世界状态,更新的就是读写集中的写集
- 交易读写集的3个概念
- 读集:包含键的列表,键的提交版本,读取对应的值,返回的是已提交的状态的值(读已提交),不能读取交易过程中写入的数据
- 写集:包含键的列表,写入的数据的值,如果多次写入,以最后一次为准
- 版本号:用区块高度和交易编号组成的
- 交易验证阶段是对读写集进行验证(验证读集)
- 验证读集的版本号是否等于世界状态的版本号
账本存储相关概念:
- 世界状态
- 交易执行后,所有键的最新值
- 历史数据索引(可选)
- 区块存储
- 按照文件去存 blocfile_xxxxxx
- 文件大小是64M,若修改,需要重新编译peer源码
- 账本最大容量64M*
- 区块读取
- 区块文件流
- 区块流
- 迭代器
- 区块索引
- 键:区块高度、区块哈希、交易哈希
- 值:区块文件编号、文件内的偏移量、区块数据的长度
- 区块提交
- 保存到文件
账本存储相关源码:
- 从4方面看,读写集、状态数据、历史数据、区块文件
- 可以先从core/ledger下的ledger_interface.go中看大体结构
package ledger
import (
commonledger "github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/peer"
)
//类似于前面orderer节点的manager,控制中枢
type PeerLedgerProvider interface {
//创建账本
Create(genesisBlock *common.Block) (PeerLedger, error)
//打开一个已有的账本
Open(ledgerID string) (PeerLedger, error)
//判断账本是否存在
Exists(ledgerID string) (bool, error)
//获取peer节点所有的账本
List() ([]string, error)
Close()
}
type PeerLedger interface {
//账本文件存储
commonledger.Ledger
//Get获取一些账本的区块索引相关内容
GetTransactionByID(txID string) (*peer.ProcessedTransaction, error)
GetBlockByHash(blockHash []byte) (*common.Block, error)
GetBlockByTxID(txID string) (*common.Block, error)
//获取交易的状态
//包含有效和无效
//无效有很多种,可以点进TxValidationCode去看定义
GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)