以太坊没有提供类似比特币根据地址查询历史交易的接口,因此在某些场景下(比如,币所用户充值)必须时刻监听着新生成的区块链里面是否包含平台用户的交易记录。针对此问题,以太坊有一个可以折中的JSON-RPC接口。

eth_newFilter

eth_newFilter接口可以创建一个filter对象,用来监听区块或交易发生的变化,也就所谓的日志(logs)。

主题(topic)是订单依赖的,当一条携带日志的交易在主题[A,B]之间,会被一下主题连接器所拦截:

  • [] 匹配任何交易;
  • [A] A之后的任何交易;
  • [null,B] B之前和之后的任何交易;
  • [A,B] A和B之间以及B之后的交易;
  • [[A,B],[A][B]] AB之间作为开始和AB之间作为结束,以及以后的交易;

参数说明:

  • fromBlock:开始区块,可以是具体的区块高度也可以是“latest”,“pending”或“earliest”。
  • toBlock:使用同fromBlock。
  • address:合约地址或要监听的地址列表,也就是日志的起源。
  • topics:32字节的数组,订单依赖的。
params: [{
  "fromBlock": "0x1",
  "toBlock": "0x2",
  "address": "0x8888f1f195afa192cfee860698584c030f4c9db1",
  "topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]]
}]

返回结果为filter的id。

// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"topics":["0x12341234"]}],"id":73}'

// Result
{
  "id":1,
  "jsonrpc": "2.0",
  "result": "0x1" // 1
}

eth_getFilterChanges

上面创建了filter,如果需要获取filter的变化信息还需要调用此接口进行查询。

此接口的参数就是上面接口返回的id。

返回的结果根据名字我们大家基本上就能知道大概的意思,此处不做过多解释,看一个具体的返回结果:

// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x16"],"id":73}'

// Result
{
  "id":1,
  "jsonrpc":"2.0",
  "result": [{
    "logIndex": "0x1", // 1
    "blockNumber":"0x1b4" // 436
    "blockHash": "0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d",
    "transactionHash":  "0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf",
    "transactionIndex": "0x0", // 0
    "address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d",
    "data":"0x0000000000000000000000000000000000000000000000000000000000000000",
    "topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"]
    },{
      ...
    }]
}

组合使用这两个接口,就可以实现监听某个地址的交易变化或新生成区块或交易。特别是对智能合约的执行的监听有很好的用武之地。

使用陷阱

这也是本篇文章要引出的重点。如果说如何使用这两个接口看一下官方文档就可以轻易解决,但有些经验之谈就需要实践采坑之后才能获得。这里给大家分享几点实践中的经验。

区块间隔不易设置过程

在创建filter的时候,如果我们把fromBlock和toBlock设置的间隔特别长,比如从第一个块到最新块,那么启动程序之后要么会等待很久很久,要么直接抛出超时异常。

针对超时异常在可容忍的区块区间之中为了避免异常出现,可将超时时间设长。

针对pending交易的监听需要慎重,引入pending交易可能因为无法查到交易出现异常。

慎重重启节点

首先我们要明确一下,创建的filter其实是放在所链接的节点的内存当中,如果节点重启,那么对应的filter也就随之失效,节点重启之后需要重新创建filter,重新进行监听。

历史交易无法追溯

在使用的时候我们要明确一点,filter虽然可以设置fromBlock但是已经发生且不会变化的交易是无法通过eth_getFilterChanges获取到的。顾名思义,只有changes的交易才能获取到。比如监听在某个区块区间,这个区块区间的交易已经被打包确认,此时再创建filter,eth_getFilterChanges是无法拿到被打包确认的交易,只能获取到创建filter之后发生变化的交易。

因此,在实际使用的过程中要时刻注意filter是否存活。

下篇预告

本篇文章就介绍到这里,下篇文章将给大家讲解一下使用web3j的过程中遇到此问题的几个异常场景。



以太坊实战-Filter插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.choupangxia.com/2019/07/06/%e4%bb%a5%e5%a4%aa%e5%9d%8a%e5%ae%9e%e6%88%98-filter/