Hyperledger Fabric 消息协议
Fabric中大量采用了gRPC消息在不同组件之间进行通信交互,主要包括如下几种情况:客户端访问Peer节点,客户端和Peer节点访问排序节点,链码容器与Peer节点交互,以及多个Peer节点之间的Gossip交互。
消息结构
除了Peer节点之间的Gossip通信外,大多都采用了信封(Envelope)结构来对消息进行封装.
普通信封结构并不复杂,包括一个载荷(Payload)域存放数据,以及对载荷域中内容进行签名的签名(Signature)域。载荷域中又包括头部(Header)域记录类型、版本、签名者信息等元数据,以及数据(Data)域,记录消息内容。
头部域是一个通用的结构。包括两种头部:通道头(ChannelHeader)和签名头(Signature-Header)。通道头中记录了如下与通道和交易相关的很多信息。
●Type:int32类型,代表了结构体(如Envelope)的类型。结构体消息根据类型不同,其Payload可以解码为不同的结构。类型可以为MESSAGE、CONFIG、CONFIG_UPDATE、ENDORSER_TRANSACTION、ORDERER_TRANSACTION、DELIVER_SEEK_INFO、CHAINCODE_PACKAGE、PEER_ADMIN_OPERATION等。
●Version:int32类型,版本号记录了消息协议的版本,一般为0。
●Timestamp:*google_protobuf.Timestamp类型,消息创建的时间。
●ChannelID:string类型,消息所关联的通道ID。
●TxID:string类型,交易的ID,由交易发起者创建。
●Epoch:uint64类型,所属的世代,目前指定为所属区块的高度。
●Extension:[]byte类型,扩展域。
●TlsCertHash:[]byte类型。如果启用了双向TLS认证,则此处为客户端TLS证书的Hash值。
签名头中主要记录签名者的身份信息。
客户端访问Peer节点
客户端通过SDK和Endorser Peer进行交互,执行链码相关操作(安装、实例化、升级链码以及调用),加入、列出应用通道和监听事件操作等。
除监听事件外,大部分消息都采用了SignedProposal结构(定义在fabric-protos-go项目的peer/chaincode.pb.go文件),消息中ChannelHeader.Type为ENDORSER_TRANSACTION或CONFIG,发往的gRPC服务地址为/protos.Endorser/ProcessProposal。监听事件则通过DeliverClient接口类型来实现,包括Deliver、DeliverFiltered、DeliverWithPrivateData三种方法。
SignedProposal消息结构中包括Proposal和对其的签名。Proposal消息结构中同样包括Header域、Payload域,以及扩展域。其中,Payload域和扩展域如何解码都取决于Channel-Header中的Type指定的类型。
客户端、Peer节点访问Orderer
客户端通过SDK和Orderer进行交互,执行链码实例化、调用和升级,应用通道创建和更新,以及区块结构获取等操作。Peer节点可以直接向Orderer请求获取区块结构。两者采用了同样的获取接口。
请求消息都采用了Envelope结构,并且都发往/orderer.AtomicBroadcast/Broadcast gRPC服务地址。从Orderer获取信息时,则发往/orderer.AtomicBroadcast/Deliver gRPC服务地址。
链码和Peer节点交互
对于原生链码,在链码容器启动后,会向Peer节点进行注册,gRPC地址为/protos.ChaincodeSupport/Register。对于外部链码,在其启动后,Peer节点会主动发起连接请求,gRPC地址为/protos.Chaincode/Connect。
链码和Peer之间的交互消息为ChaincodeMessage结构其中,Payload域中可以包括各种Chaincode操作消息,如GetHistoryForKey、GetQueryResult、PutStateInfo、GetStateByRange等。
注册完成后,双方建立起双工通道,通过更多消息类型实现多种交互.
Peer节点之间Gossip交互
Peer之间可以通过Gossip协议来完成邻居探测、Leader选举、区块分发、私密数据同步等过程,主要原理为通过GossipClient客户端的GossipStream双向流进行通信,发送Signed-GossipMessage消息结构,gRPC服务地址主要为/gossip.Gossip/GossipStream。
此外,Peer可通过单独的Ping服务对远端节点在线状态进行探测,gRPC服务地址为/gossip.Gossip/Ping。
Gossip交互过程
总结Gossip交互过程如图14-16所示。利用不同的消息体,完成Peer之间的信息同步。
Gossip消息结构
Gossip采用签名信封结构(SignedGossipMessage)用来封装Gossip消息(GossipMessage)和对应的信封结构(Envelope)。
Gossip消息标签
GossipMessage为核心的数据结构。其可能的标签值(GossipMessage_Tag)如下所示,这些标签默认带有GossipMessage前缀。
●UNDEFINED:标签未定义,当标签为空时返回该值。
●EMPTY:空标签,用于建立连接、心跳、请求和响应成员消息。
●ORG_ONLY:仅限组织内消息,如私密数据。
●CHAN_ONLY:仅限通道内消息。
●CHAN_AND_ORG:限通道内同一组织内,如获取区块数据。
●CHAN_OR_ORG:限通道内或限组织内,如状态信息。
Gossip消息内容结构
GossipMessage通过消息内容类型来应用到不同场景。合法的消息内容结构(isGossipMessage_Content)下面详细介绍,这些结构默认带有GossipMessage前缀。
(1)成员消息适用于邻居发现场景,定期维护存活的邻居信息,不局限在通道内,主要由gossip/discovery模块实现。
(2)拉取消息
适用于从远程节点拉取身份或区块数据,主要数据结构为:gossip/gossip/pull/pullstore.go#Mediator和gossip/gossip/algo/pull.go#PullEngine。包括如下两种消息类型:
●PullMsgType_IDENTITY_MSG,获取对方的身份信息,消息标签为EMPTY,不局限在通道内。
●PullMsgType_BLOCK_MSG,获取区块数据。消息标签为CHAN_AND_ORG,局限在通道内的同一组织内。
(3)数据消息
适用于从远程节点同步区块或私密数据。
(4)状态消息
适用于与远程节点同步账本状态。
(5)其他消息
其他消息包括连接消息、选举Leader消息和空消息。