前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Hyperledger Fabric Go SDK 事件分析

Hyperledger Fabric Go SDK 事件分析

作者头像
pseudoyu
发布2023-04-11 20:41:08
发布2023-04-11 20:41:08
96500
代码可运行
举报
文章被收录于专栏:PseudoyuPseudoyu
运行总次数:0
代码可运行

前言

最近在做跨链适配器,需要在一条本地链上利用 Go SDK 来连接 fabric 网络,并监听事件,所以对 fabric 所支持的事件与 SDK 所提供的监听方法做一下汇总。

Fabric 事件

事件是客户端与 Fabric 网络进行交互的一种方式,如上图所示,Fabric 网络中执行一个交易后,因为是异步进行的,所以客户端无法获取提交的交易状态(是否被接受),因此,Fabric 的 Peer 节点提供了事件机制,客户端可以通过 gRPC 接口来监听区块事件。从 fabric v1.1 开始,时间的注册发生在通道级别而不是 Peer 节点,因此可以进行更精细的控制

事件类型

事件主要由 Ledger 和存有链码合约的容器触发。Fabric 共支持四种事件形式:

  1. BlockEvent 监控新增到 fabric 上的块时使用
  2. ChaincodeEvent 监控链码中发布的事件时使用,也就是用户自定义事件
  3. TxStatusEvent 监控节点上的交易完成时使用
  4. FilteredBlockEvent 监控简要的区块信息

在 Fabric Go SDK 中则通过以下几种事件监听器进行操作

  1. func (c *Client) RegisterBlockEvent(filter ...fab.BlockFilter) (fab.Registration, <-chan *fab.BlockEvent, error)
  2. func (c *Client) RegisterChaincodeEvent(ccID, eventFilter string) (fab.Registration, <-chan *fab.CCEvent, error)
  3. func (c *Client) RegisterFilteredBlockEvent() (fab.Registration, <-chan *fab.FilteredBlockEvent, error)
  4. func (c *Client) RegisterTxStatusEvent(txID string) (fab.Registration, <-chan *fab.TxStatusEvent, error)

而当监听完成后需要通过 func (c *Client) Unregister(reg fab.Registration) 来取消注册并移除事件通道

gRPC 通信

SDK 与 Peer 节点通过 gRPC 进行通讯,源码见 fabric-protos/peer/events.proto

其中,定义了以下几种 message:

  1. FilteredBlock,给 FilteredBlockEvent 使用
  2. FilteredTransaction 和 FilteredTransaction,给 FilteredTransactionEvent 使用
  3. FilteredChaincodeAction,给 ChaincodeEvent 使用
  4. BlockAndPrivateData,给私有数据使用

Response 如下:

代码语言:javascript
代码运行次数:0
运行
复制
// DeliverResponse
message DeliverResponse {
    oneof Type {
        common.Status status = 1;
        common.Block block = 2;
        FilteredBlock filtered_block = 3;
        BlockAndPrivateData block_and_private_data = 4;
    }
}

以及三个 gRPC 通信接口:

代码语言:javascript
代码运行次数:0
运行
复制
service Deliver {
    // Deliver first requires an Envelope of type ab.DELIVER_SEEK_INFO with
    // Payload data as a marshaled orderer.SeekInfo message,
    // then a stream of block replies is received
    rpc Deliver (stream common.Envelope) returns (stream DeliverResponse) {
    }
    // DeliverFiltered first requires an Envelope of type ab.DELIVER_SEEK_INFO with
    // Payload data as a marshaled orderer.SeekInfo message,
    // then a stream of **filtered** block replies is received
    rpc DeliverFiltered (stream common.Envelope) returns (stream DeliverResponse) {
    }
    // DeliverWithPrivateData first requires an Envelope of type ab.DELIVER_SEEK_INFO with
    // Payload data as a marshaled orderer.SeekInfo message,
    // then a stream of block and private data replies is received
    rpc DeliverWithPrivateData (stream common.Envelope) returns (stream DeliverResponse) {
    }
}

整个流程如上图所示,Go SDK 中通过实现一个 Dispatcher 将应用中的事件注册请求转换为事件订阅请求并通过 DeliverClient 发送给 Peer 节点,Peer 节点中的 DeliverServer 接收订阅请求,调用 deliverBlocks 进入循环,从 Ledger 读取区块并生成事件,最后发送给客户端,客户端中的 Dispatcher 又将其转换为应用订阅的事件响应。

事件实现过程

实现时间过程需要两个步骤

  1. 在链码中调用 SetEvent 方法
  2. 在在客户端中通过 Go SDK 实现事件监听器
SetEvent 方法

方法定义

代码语言:javascript
代码运行次数:0
运行
复制
func (s *ChaincodeStub) SetEvent(name string, payload []byte) error

调用实例

代码语言:javascript
代码运行次数:0
运行
复制
func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response {

    err = stub.PutState(key, value)

    if err != nil {
        return shim.Error(fmt.Sprintf("unable put state (%s), error: %v", key, err))
    }

    // Payload 需要转换为字节格式
    eventPayload := "Event Information"
    payloadAsBytes := []byte(eventPayload)

    // SetEvent 方法通常位于 PutState、DelState 等与账本交互的操作之后
    err = stub.SetEvent("<事件名称>", payloadAsBytes)

    if (eventErr != nil) {
        return shim.Error(fmt.Sprintf("事件触发失败"))
    }

    return shim.Success(nil)
}
客户端事件监听器
代码语言:javascript
代码运行次数:0
运行
复制
// 实现一个链码事件监听
// 传入相应参数,这里的 eventId 必须与链码里的 <事件名称> 匹配以实现监听
reg, eventChannel, err := eventClient.RegisterChaincodeEvent(chaincodeID, eventID)

if err != nil {
    log.Fatalf("Failed to regitser block event: %v\n", err)
    return
}

// 取消注册并移除事件通道
defer eventClient.Unregister(reg)

总结

以上就是通过 Go SDK 对 fabric 网络上的事件进行监听操作的基本介绍,正在看 fabric Go SDK 源码,后续将补充一些解读。

参考资料

  1. hyperledger/fabric-sdk-go
  2. Hyperledger Fabric Packages for Go Chaincode
  3. 基于通道的 Peer 节点事件服务
  4. fabric-protos/peer/events.proto
  5. Fabric 1.4 源码解读 3:事件(Event)原理解读
  6. fabric 支持的事件
  7. 如何监听 Fabric 链码的事件
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Fabric 事件
    • 事件类型
    • gRPC 通信
    • 事件实现过程
      • SetEvent 方法
      • 客户端事件监听器
  • 总结
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档