兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储一

栏目: 编程工具 · 发布时间: 6年前

内容简介:blockfile,即Fabric区块链区块文件存储,默认目录/var/hyperledger/production/ledgersData/chains,含index和chains两个子目录。其中index为索引目录,采用leveldb实现。而chains为各ledger的区块链文件,子目录以ledgerid为名,使用文件系统实现。区块文件以blockfile_为前缀,最大大小默认64M。

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结构体:

type Block struct {
    Header   *BlockHeader //BlockHeader
    Data     *BlockData //BlockData
    Metadata *BlockMetadata
}

func (m *Block) GetHeader() *BlockHeader //获取BlockHeader,即m.Header
func (m *Block) GetData() *BlockData //获取BlockData,即m.Data
func (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.Number
func (m *BlockHeader) GetPreviousHash() []byte //获取前一个区块哈希,即m.PreviousHash
func (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 int32

const (
    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)
//反序列化区块,并构造serializedBlockInfo
func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error)
//序列化中添加BlockHeader,即Number、DataHash和PreviousHash
func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error
//序列化中添加BlockData,并从BlockData中解析txid,返回交易索引信息数组
func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error)
//序列化中添加Metadata
func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error
//反序列化出BlockHeader
func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error)
//反序列化出BlockData,并返回交易索引信息数组
func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error)
//反序列化出Metadata
func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error)
//从BlockData中解析出交易ID
func 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

涉及方法如下:

//构造blockfileStream
func 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 []byte
var err error
var fileInfo os.FileInfo
moreContentAvailable := true

fileInfo, err = s.file.Stat() //获取文件状态
remainingBytes := fileInfo.Size() - s.currentOffset //文件读取剩余字节
peekBytes := 8
if remainingBytes < int64(peekBytes) { //剩余字节小于8,按实际剩余字节,否则按8
    peekBytes = int(remainingBytes)
    moreContentAvailable = false
}
//存储形式:前n位存储block长度length,之后length位为实际block
lenBytes, 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.IndexableAttr]bool //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")
)
//代码在common/ledger/blkstorage/blockstorage.go

未完待续欢迎继续关注兄弟连区块链教程分享!


以上所述就是小编给大家介绍的《兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储一》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First Design Patterns

Head First Design Patterns

Elisabeth Freeman、Eric Freeman、Bert Bates、Kathy Sierra、Elisabeth Robson / O'Reilly Media / 2004-11-1 / USD 49.99

You're not alone. At any given moment, somewhere in the world someone struggles with the same software design problems you have. You know you don't want to reinvent the wheel (or worse, a flat tire),......一起来看看 《Head First Design Patterns》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器