请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册
  兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储1,“区块链+时代无疑会是下一个风口,然而现在的区块链行业专业型人才正在遭遇瓶颈”
兄弟连教育区块链培训学院院长尹成表示,“希望能通过兄弟连教育区块链学院为社会为企业培养并输送更多优质的区块链高精尖型技术。



# Fabric 1.0源代码笔记 之 blockfile(区块文件存储)## 1、blockfile概述blockfile,即Fabric区块链区块文件存储,默认目录/var/hyperledger/production/ledgersData/chains,含index和chains两个子目录。其中index为索引目录,采用leveldb实现。而chains为各ledger的区块链文件,子目录以ledgerid为名,使用文件系统实现。区块文件以blockfile_为前缀,最大大小默认64M。blockfile,相关代码集中在common/ledger/blkstorage/fsblkstorage目录,目录结构如下:* blockfile_mgr.go,blockfileMgr和checkpointInfo结构体及方法。* block_stream.go,blockfileStream、blockStream、blockPlacementInfo结构体及方法。* blockfile_rw.go,blockfileWriter和blockfileReader结构体及方法(blockfileReader未使用)。* blockindex.go,index接口定义,index接口实现即blockIndex结构体及方法定义,以及blockIdxInfo、locPointer、fileLocPointer结构体及方法。* blockfile_helper.go,定义了4个工具函数,constructCheckpointInfoFromBlockFiles、retrieveLastFileSuffix、isBlockFileName、getFileInfoOrPanic。作用分别为:扫描最新的blockfile并重新构造检查点信息、获取最新的文件后缀、根据文件前缀判断是否为区块文件、获取文件状态信息。* block_serialization.go,block序列化相关工具函数。* blocks_itr.go,blocksItr结构体及方法。## 2、Block结构体定、以及Block序列化### 2.1、Block相关结构体Block结构体:```gotype Block struct {    Header *BlockHeader //BlockHeader    Data *BlockData //BlockData    Metadata *BlockMetadata}func (m *Block) GetHeader() *BlockHeader //获取BlockHeader,即m.Headerfunc (m *Block) GetData() *BlockData //获取BlockData,即m.Datafunc (m *Block) GetMetadata() *BlockMetadata //m.Metadata//代码在protos/common/common.pb.go

BlockHeader结构体:

type BlockHeader struct {    Number uint64 //区块编号    PreviousHash [byte //前一个区块哈希    DataHash [byte //当前区块哈希}func (m *BlockHeader) GetNumber() uint64 //获取区块编号,即m.Numberfunc (m *BlockHeader) GetPreviousHash() [byte //获取前一个区块哈希,即m.PreviousHashfunc (m *BlockHeader) GetDataHash() [byte //获取当前区块哈希,即m.DataHash//代码在protos/common/common.pb.go
BlockData结构体:

type BlockData struct {    Data [[byte //Data,存储交易信息}func (m *BlockData) GetData() [[byte //获取Data,即m.Data//代码在protos/common/common.pb.go
BlockMetadata结构体:

type BlockMetadata struct {    Metadata [[byte //K/V均为[]byte格式}func (m *BlockMetadata) GetMetadata() [[byte //m.Metadata//代码在protos/common/common.pb.go
补充BlockMetadataIndex:

type BlockMetadataIndex int32const (    BlockMetadataIndex_SIGNATURES BlockMetadataIndex = 0    BlockMetadataIndex_LAST_CONFIG BlockMetadataIndex = 1    BlockMetadataIndex_TRANSACTIONS_FILTER BlockMetadataIndex = 2    BlockMetadataIndex_ORDERER BlockMetadataIndex = 3)
2.2、Block序列化
serializedBlockInfo结构体定义及工具函数:

type serializedBlockInfo struct {    blockHeader *common.BlockHeader //BlockHeader    txOffsets [*txindexInfo //交易索引信息    metadata *common.BlockMetadata}type txindexInfo struct {    txID string //交易ID    loc *locPointer //文件指针}//序列化区块,返回序列化后字节,以及serializedBlockInfo(含BlockHeader和交易索引信息)func serializeBlock(block *common.Block) ([byte, *serializedBlockInfo, error)//反序列化区块,构建Block结构体func deserializeBlock(serializedBlockBytes [byte) (*common.Block, error)//反序列化区块,并构造serializedBlockInfofunc extractSerializedBlockInfo(serializedBlockBytes [byte) (*serializedBlockInfo, error)//序列化中添加BlockHeader,即Number、DataHash和PreviousHashfunc addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error//序列化中添加BlockData,并从BlockData中解析txid,返回交易索引信息数组func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([*txindexInfo, error)//序列化中添加Metadatafunc addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error//反序列化出BlockHeaderfunc extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error)//反序列化出BlockData,并返回交易索引信息数组func extractData(buf *ledgerutil.Buffer) (*common.BlockData, [*txindexInfo, error)//反序列化出Metadatafunc extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error)//从BlockData中解析出交易IDfunc extractTxID(txEnvelopBytes [byte) (string, error)//代码在common/ledger/blkstorage/fsblkstorage/block_serialization.go
3、checkpointInfo结构体定义及方法
checkpointInfo,即检查点信息,结构体定义如下:

type checkpointInfo struct {    latestFileChunkSuffixNum int //最新的区块文件后缀,如blockfile_000000    latestFileChunksize int //最新的区块文件大小    isChainEmpty bool //是否空链    lastBlockNumber uint64 //最新的区块编号}//代码在common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go
涉及方法如下:

func (i *checkpointInfo) marshal() ([byte, error) //checkpointInfo序列化func (i *checkpointInfo) unmarshal(b [byte) error //checkpointInfo反序列化func (i *checkpointInfo) String() string //转换为string//代码在common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go
4、blockfileStream相关结构体及方法
4.1、blockfileStream
blockfileStream定义如下:

type blockfileStream struct {    fileNum int //blockfile文件后缀    file *os.File //os.File    reader *bufio.Reader //bufio.Reader    currentOffset int64 //当前偏移量}//代码在common/ledger/blkstorage/fsblkstorage/block_stream.go
涉及方法如下:

//构造blockfileStreamfunc newBlockfileStream(rootDir string, fileNum int, startOffset int64) (*blockfileStream, error) func (s *blockfileStream) nextBlockBytes() ([byte, error) //下一个块,调取s.nextBlockBytesAndPlacementInfo()//下一个块和位置信息func (s *blockfileStream) nextBlockBytesAndPlacementInfo() ([byte, *blockPlacementInfo, error) func (s *blockfileStream) close() error //关闭blockfileStream//代码在common/ledger/blkstorage/fsblkstorage/block_stream.go
func (s *blockfileStream) nextBlockBytesAndPlacementInfo() ([]byte, *blockPlacementInfo, error) 代码如下:

var lenBytes [bytevar err errorvar fileInfo os.FileInfomoreContentAvailable := truefileInfo, err = s.file.Stat() //获取文件状态remainingBytes := fileInfo.Size() - s.currentOffset //文件读取剩余字节peekBytes := 8if remainingBytes < int64(peekBytes) { //剩余字节小于8,按实际剩余字节,否则按8    peekBytes = int(remainingBytes)    moreContentAvailable = false}//存储形式:前n位存储block长度length,之后length位为实际blocklenBytes, err = s.reader.Peek(peekBytes) //Peek 返回缓存的一个切片,该切片引用缓存中前 peekBytes 个字节的数据length, n := proto.DecodeVarint(lenBytes) //从切片中读取 varint 编码的整数,它返回整数和被消耗的字节数。    err = s.reader.Discard(n) //丢弃存储block长度length的前n位    blockBytes := make([byte, length)    _, err = io.ReadAtLeast(s.reader, blockBytes, int(length))    blockPlacementInfo := &blockPlacementInfo{        fileNum: s.fileNum,        blockStartOffset: s.currentOffset,        blockBytesOffset: s.currentOffset + int64(n)}    s.currentOffset += int64(n) + int64(length)    return blockBytes, blockPlacementInfo, nil//代码在common/ledger/blkstorage/fsblkstorage/block_stream.go
补充blockPlacementInfo:块位置信息

type blockPlacementInfo struct {    fileNum int //块文件后缀    blockStartOffset int64 //n+length,n之前    blockBytesOffset int64 //n+length,length之前}//代码在common/ledger/blkstorage/fsblkstorage/block_stream.go
5、blockfileWriter结构体定义及方法
type blockfileWriter struct {    filePath string //路径    file *os.File //os.File}func newBlockfileWriter(filePath string) (*blockfileWriter, error) //构造blockfileWriter,并调用writer.open()func (w *blockfileWriter) truncateFile(targetSize int) error //截取文件func (w *blockfileWriter) append(b [byte, sync bool) error //追加文件func (w *blockfileWriter) open() error //打开文件func (w *blockfileWriter) close() error //关闭文件//代码在common/ledger/blkstorage/fsblkstorage/blockfile_rw.go
6、blockIndex相关结构体及方法
6.1、index接口定义
type index interface {    getLastBlockIndexed() (uint64, error) //获取最后一个块索引(或编号)    indexBlock(blockIdxInfo *blockIdxInfo) error //索引区块    getBlockLocByHash(blockHash [byte) (*fileLocPointer, error) //根据区块哈希,获取文件区块指针    getBlockLocByBlockNum(blockNum uint64) (*fileLocPointer, error) //根据区块编号,获取文件区块指针    getTxLoc(txID string) (*fileLocPointer, error) //根据交易ID,获取文件交易指针    getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error) //根据区块编号和交易编号,获取文件交易指针    getBlockLocByTxID(txID string) (*fileLocPointer, error)//根据交易ID,获取文件区块指针    getTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)//根据交易ID,获取交易验证代码}//代码在common/ledger/blkstorage/fsblkstorage/blockindex.go
6.2、blockIndex结构体
blockIndex结构体定义如下:

type blockIndex struct {    indexItemsMap map[blkstorage.IndexableAttrbool //index属性映射    db *leveldbhelper.DBHandle //index leveldb操作}//代码在common/ledger/blkstorage/fsblkstorage/blockindex.go
补充IndexableAttr:

const (    IndexableAttrBlockNum = IndexableAttr("BlockNum")    IndexableAttrBlockHash = IndexableAttr("BlockHash")    IndexableAttrTxID = IndexableAttr("TxID")    IndexableAttrBlockNumTranNum = IndexableAttr("BlockNumTranNum")    IndexableAttrBlockTxID = IndexableAttr("BlockTxID")    IndexableAttrTxValidationCode = IndexableAttr("TxValidationCode"))


收藏

0 个回复

您需要登录后才可以回帖 登录 | 立即注册