7. 使用事件订阅功能

在使用超级链的过程中,可能会遇到一些异步的情况:比如执行合约的时候,构造的交易是否合法我们可以实时获知,但具体什么时候真正的被节点打包上链就不一样了。当然还有其他类似的场景,针对这种问题,我们引入了事件订阅机制。

7.1. 事件订阅的接口

订阅的接口十分简单,只有Subscribe一个

  1. service EventService {
  2. rpc Subscribe (SubscribeRequest) returns (stream Event);
  3. }

其中订阅接口的SubscribeRequest格式如下:

  1. message SubscribeRequest {
  2. SubscribeType type = 1;
  3. bytes filter = 2;
  4. }
  5. enum SubscribeType {
  6. // 区块事件,payload为BlockFilter
  7. BLOCK = 0;
  8. }

请求里的filter用来设置事件过滤参数,是一段序列化的proto对象,因为订阅不同内容需要的参数不尽相同

BLOCK 事件的过滤参数如下:

  1. message BlockFilter {
  2. string bcname = 1;
  3. BlockRange range = 2;
  4. bool exclude_tx = 3;
  5. bool exclude_tx_event = 4;
  6. string contract = 10;
  7. string event_name = 11;
  8. string initiator = 12;
  9. string auth_require = 13;
  10. string from_addr = 14;
  11. string to_addr = 15;
  12. }
  13. message BlockRange {
  14. string start = 1;
  15. string end = 2;
  16. }

其中各个字段的说明如下:

  • bcname 链名,必填字段

  • range 指定起始订阅位置和结束位置,如果没有指定则默认从当前最新区块开始,持续订阅。

  • exclude_tx 是否去掉FilteredTransaction数据

  • exclude_tx_event 是否去掉ContractEvent数据

  • contract 匹配合约名字,为空的话匹配所有合约

  • event_name 匹配合约事件名字,为空的话匹配所有合约事件name

  • initiator 匹配交易发起者地址,为空的话匹配所有交易发起者

  • auth_require 匹配交易的auth_require中的任何一个地址,为空匹配所有

  • from_addr 匹配转账发起者地址,为空的话匹配所有转账发起者

  • to_addr 匹配转账接受者地址,为空的匹配所有转账接受者

BlockRange 字段意义:

  • 如果 start_numend_num 都为空,则表示从当前最新区块开始,持续订阅最新区块。

  • 如果 start_num 为空, end_num 不为空,则表示从当前最新区块开始,订阅到指定区块,如果``end_num``小与当前区块则什么也不做。

  • 如果 start_num 不为空, end_num 为空,则从 start_num 开始持续订阅。

  • 如果 start_numend_num 都不为空,按照指定区块范围订阅,左闭右开。

注解

需要注意的是过滤字段都是正则表达式,如果需要全匹配名字为 counter 的合约,contract 字段需要为 ^counter$ , 不能为 counter ,这么写会匹配到名为 counter1 的合约。

订阅返回的内容格式均为Event,事件的详细内容会放在payload里

  1. message Event {
  2. bytes payload = 1;
  3. }

订阅 BLOCK 事件时,填充如下内容:

  1. message ContractEvent {
  2. string contract = 1;
  3. string name = 2;
  4. bytes body = 3;
  5. }
  6. message FilteredTransaction {
  7. string txid = 1;
  8. repeated ContractEvent events = 2;
  9. }
  10. message FilteredBlock {
  11. string bcname = 1;
  12. string blockid = 2;
  13. int64 block_height = 3;
  14. repeated FilteredTransaction txs = 4;
  15. }

当然,订阅RPC接口断开的时候,订阅行为也会停止

7.2. 使用事件订阅

使用前,请检查xchain的配置conf/xchain.yaml,确保有如下配置:

  1. # 事件订阅相关配置
  2. event:
  3. enable: true
  4. # 每个ip的最大订阅连接数,为0的话不限连接数
  5. addrMaxConn: 5

7.2.1. 使用命令行订阅事件

xchain-cliwatch 指令可以用来监听事件,命令行参数的说明如下:

  • -f, --filter 过滤器字段,JSON格式的,字段解释见 message BlockFilter

  • --oneline 是否将事件打印在一行,方便命令行解析

  • --skip-empty-tx 默认watch命令会打印所有的block,即使block里面没有交易,这么做是为了方面做断点记录,--skip-empty-tx 参数可以不打印不包含交易的block

如下是一些例子

  1. 订阅所有的新块
  1. ./xchain-cli watch
  1. 订阅名字为 counter 的合约
  1. ./xchain-cli watch -f '{"contract":"^counter$"}'
  1. 订阅 counter 合约的 increase 合约事件
  1. ./xchain-cli watch -f '{"contract":"^counter$", "event_name":"^increase$"}'
  1. 订阅区块高度从100开始的事件(断点续传)
  1. ./xchain-cli watch -f '{"range":{"start":"100"}}'
  1. 订阅区块高度区间为[100, 200)的事件
  1. ./xchain-cli watch -f '{"range":{"start":"100", "end":"200"}}'