前言

最近打算基于fabric-sdk-go实现hyperledger fabric浏览器,其中最重要的一步就是解析fabric的上链区块。虽说fabric是Golang实现的,但直到2021年2月1号才发布了第一个稳定版fabric-sdk-go,而且官方几乎没有响应的文档介绍。对于fabric-sdk-go,基本都是参照源码中的测试用例来使用;而要实现区块链浏览器,仅靠测试用例还差好多,特别是对出块信息的解析。

通过event.Client.RegisterBlockEvent()可以监听fabric的出块事件,但返回的信息中有用的是一个BlockEvent类型的chan,定义如下:

// BlockEvent contains the data for the block event
type BlockEvent struct {
	// Block is the block that was committed
	Block *cb.Block
	// SourceURL specifies the URL of the peer that produced the event
	SourceURL string
}

区块链浏览器需要的所有信息基本都包含在Block中,其定义如下:

// This is finalized block structure to be shared among the orderer and peer
// Note that the BlockHeader chains to the previous BlockHeader, and the BlockData hash is embedded
// in the BlockHeader.  This makes it natural and obvious that the Data is included in the hash, but
// the Metadata is not.
type Block struct {
	Header               *BlockHeader   `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
	Data                 *BlockData     `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
	Metadata             *BlockMetadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"`
}

本文作为区块链浏览器系列的开篇,结构体中各字段的含义会在之后的文章中一一介绍,这里就不再过多介绍。接下来将以类图的形式来解析区块中包含的信息。

classDiagram
	class Block{
		Header *BlockHeader
		Data   *BlockData
		Metadata *BlockMetadata
	}
	class BlockHeader{
		Number uint64
		PreviousHash []byte
		DataHash []byte
	}
	class BlockData{
		Data [][]byte
	}
	class BlockMetadata{
		Metadata [][]byte
	}
	class Metadata{
		Value []byte
		Signatures []*MetadataSignature
	}
	class MetadataSignature{
		SignatureHeader []byte
		Signature []byte
		IdentifierHeader []byte
	}
	class SignatureHeader{
		Creator []byte
		Nonce []byte
	}
	class SerializedIdentity{
		Mspid string
		IdBytes []byte
	}
	class Certificate{
		crypto/x509.Certificate
	}
	class IdentifierHeader{
		Identifier uint32
		Nonce []byte
	}
	class Envelope{
		Payload []byte
		Signature []byte
	}
	class Payload{
		Header *Header
		Data []byte
	}
	class Header{
		ChannelHeader []byte
		SignatureHeader []byte
	}
	class ChannelHeader{
		Type int32
		Version int32
		Timestamp *timestamp.Timestamp
		TxId string
		Epoch uint64
		Extension []byte
		TlsCertHash          []byte
	}
	class Transaction{
		Actions              []*TransactionAction
	}
	class TransactionAction{
		Header []byte
		Payload []byte
	}
	class ChaincodeActionPayload{
		ChaincodeProposalPayload []byte
		Action               *ChaincodeEndorsedAction
	}
	class ChaincodeEndorsedAction{
		ProposalResponsePayload []byte
		Endorsements         []*Endorsement
	}
	class ProposalResponsePayload{
		ProposalHash []byte
		Extension            []byte
	}
	class Endorsement{
		Endorser []byte
		Signature []byte
	}
	class ChaincodeProposalPayload{
		Input []byte
		TransientMap map[string][]byte
	}
	class ChaincodeInvocationSpec{
		ChaincodeSpec        *ChaincodeSpec
	}
	class ChaincodeSpec{
		Type                 ChaincodeSpec_Type
		ChaincodeId          *ChaincodeID
		Input                *ChaincodeInput
		Timeout              int32
	}
	class ChaincodeID{
		Path string
		Name string
		Version string
	}
	class ChaincodeInput{
		Args        [][]byte
		Decorations map[string][]byte
		IsInit               bool
	}
	class ChaincodeAction{
		Results []byte
		Events []byte
		Response *Response
		ChaincodeId          *ChaincodeID
	}
	class TxReadWriteSet{
		DataModel  TxReadWriteSet_DataModel
		NsRwset []*NsReadWriteSet
	}
	class NsReadWriteSet{
		Namespace             string
		Rwset                 []byte
		CollectionHashedRwset []*CollectionHashedReadWriteSet
	}
	class KVRWSet{
		Reads                []*KVRead
		RangeQueriesInfo     []*RangeQueryInfo
		Writes               []*KVWrite
		MetadataWrites       []*KVMetadataWrite
	}
	
	Block --* BlockHeader
	Block --* BlockData
	Block --* BlockMetadata
	
	BlockMetadata --* Metadata
	Metadata --* MetadataSignature
	
	MetadataSignature --* SignatureHeader
	MetadataSignature --* IdentifierHeader
	
	SignatureHeader --* SerializedIdentity
	SerializedIdentity --* Certificate
	
	BlockData --* Envelope
	Envelope --* Payload
	
	Payload --* Header
	Payload --* Transaction
	Transaction --* TransactionAction
	
	TransactionAction --* ChaincodeActionPayload
	
	ChaincodeActionPayload --* ChaincodeEndorsedAction
	ChaincodeActionPayload --* ChaincodeProposalPayload
	
	ChaincodeProposalPayload --* ChaincodeInvocationSpec
	
	ChaincodeInvocationSpec --* ChaincodeSpec
	
	ChaincodeSpec --* ChaincodeID
	ChaincodeSpec --* ChaincodeInput
	
	ChaincodeEndorsedAction --* Endorsement
	ChaincodeEndorsedAction --* ProposalResponsePayload
	
	ProposalResponsePayload --* ChaincodeAction
	
	ChaincodeAction --* TxReadWriteSet
	
	TxReadWriteSet --* NsReadWriteSet
	
	NsReadWriteSet --* KVRWSet
	
	Header --* ChannelHeader
	Header --* SignatureHeader

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin92
Github: mengbin92
cnblogs: 恋水无意