区块链开发(十四)以太坊go-ethereum客户端查询交易列表探讨

时间:2021-01-09 20:43:25

比特币是可以通过api(listtransactions)查询指定地址的历史交易的。但在eth中没有提供类似的查询api。Hyperledger fabric也有相应的查询历史交易记录的方法,利用如下函数,历史数据查询GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error),具体实现,可以看我写的HyperLedger Fabric ChainCode开发 文章。今天这篇博客就简单介绍一下如果解决这个问题。
问题
以太坊go-ethereum客户端是没有根据地址查询交易列表的API的。然而,在使用过程中我们往往会用到类似的API。针对是否要在客户端上添加此API,github已经有激励的讨论了。点击一下网址可以了解一下:
https://github.com/ethereum/go-ethereum/issues/1897
解决方案
那么既然有此需求,即使没有针对性的API也需要找到相应的解决方案。目前有效的解决方案有两种:
(1)调用第三方API接口。此类接口很多,不仅能在官网上查询区块信息,而且提供了查询的API。比如:https://etherchain.org/apidoc 。(此接口文件,目前我无法打开,也无法调试。)文档介绍:接口简单,不过有访问频次的限制,除非很大的访问量,还是可以使用此类接口。简单,方便。(具体需要打开文档伙伴验证,如果是自己建立的私有链,第三方的接口如何实现,有待验证。)
(2)自行维护数据,自行实现此功能。此方法的基本思路是,查询每个区块的具体交易,录入到自己的数据库中,然后通过sql语句查询自己的数据。此方法就需要有一定的编码基础和设备投入。现有的API是支持查询每一个区块内的交易记录的。虽然比较笨重,但一旦数据由自己维护之后,想怎么查询只是sql语句不同的事情了。(我比较建议采用这种办法。集中式系统与分布式系统结合的方式实现,我们不是纠结一种技术,而是要解决具体问题。)
但是在每笔交易完成后,一定要获取交易的Hash,将交易hash记录起来。获取如下:

result = meta.sendTranscation(receiver, amount, {from: account});
var hashTx;
for (var i = 0; i < result.logs.length; i++) {
        var log = result.logs[i];
        if( log.event =="Transfer" ) {   
          hashTx = result.tx;
          break;
        }
      }

获取到后,保存在资料库中。
可以通过geth客户端或者通过web3.js查询

>eth.getTransaction("0xf197f83993742a4e422244fe91a1175513ad11da2bd1209906443dcc391279eb")
{
  blockHash: "0xf3ac98d6db31f72a586b0239eab43d40fb568668561769c2e60d4dd7082050d8",
  blockNumber: 40164,
  from: "0x95a171d45c7551474f3479bf006e2a9a3852bbd8",
  gas: 90000,
  gasPrice: 100000000000,
  hash: "0xf197f83993742a4e422244fe91a1175513ad11da2bd1209906443dcc391279eb",
  input: "0x90b98a11000000000000000000000000964f31c1c95eac140e9f1ef1e1a22a5f3cc7a90600000000000000000000000000000000000000000000000000000000000f4240",
  nonce: 73,
  r: "0x3480b8405e47e1b402039f813b966cfb894ff61f60d2c5301f85c889638dce1d",
  s: "0x6cc87ac31c610f78f258f36551e7a74833cb361afe596fc43bc9ca3e8a6e3ceb",
  to: "0x7673af653c4ea7dee50a10c50d1d62a20c63cd5c",
  transactionIndex: 0,
  v: "0x42",
  value: 0
}

其中input中栏位就是这笔交易的详情。
函数签名:

0x90b98a11000000000000000000000000

交易的接受者地址(自己需要加上0x)

964f31c1c95eac140e9f1ef1e1a22a5f3cc7a906

交易主体(金额)【十六进制数据】

00000000000000000000000000000000000000000000000000000000000f4240

例外情况
如果要查询合约的交易历史,那么可以通过过滤(filter)合约日志来达到此目的。此种场景是有相应的API进行支撑的。但是这种数据,一定要从所有的 Block中扒数据,查询你得log数据。(Eth中,Log和Event是一回事,我们往往将要写入区块链的方法,前面加上 Event 来实现,所以我们可以通过filter日志来查询交易记录)这种情况,我们会在以后的学习中具体探讨。
2017年12月24日整理于深圳。
2018年1月30日修改。