以太坊实战-Filter
以太坊没有提供类似比特币根据地址查询历史交易的接口,因此在某些场景下(比如,币所用户充值)必须时刻监听着新生成的区块链里面是否包含平台用户的交易记录。针对此问题,以太坊有一个可以折中的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的过程中遇到此问题的几个异常场景。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://choupangxia.com/2019/07/06/%e4%bb%a5%e5%a4%aa%e5%9d%8a%e5%ae%9e%e6%88%98-filter/