以太坊实战【地址监控二】
在以太坊实战【地址监控一】中已经找到了一种用JsonRPC的方式可以对地址进行监控,继续细节实现。
数据解析
块数据
通过RPC接口可以取到块数据,直接返回的是json格式,具体格式如下:
- number: QUANTITY - the block number. null when its pending block.
- hash: DATA, 32 Bytes - hash of the block. null when its pending block.
- parentHash: DATA, 32 Bytes - hash of the parent block.
- nonce: DATA, 8 Bytes - hash of the generated proof-of-work. null when its pending block.
- sha3Uncles: DATA, 32 Bytes - SHA3 of the uncles data in the block.
- logsBloom: DATA, 256 Bytes - the bloom filter for the logs of the block. null when its pending block.
- transactionsRoot: DATA, 32 Bytes - the root of the transaction trie of the block.
- stateRoot: DATA, 32 Bytes - the root of the final state trie of the block.
- receiptsRoot: DATA, 32 Bytes - the root of the receipts trie of the block.
- miner: DATA, 20 Bytes - the address of the beneficiary to whom the mining rewards were given.
- difficulty: QUANTITY - integer of the difficulty for this block.
- totalDifficulty: QUANTITY - integer of the total difficulty of the chain until this block.
- extraData: DATA - the "extra data" field of this block.
- size: QUANTITY - integer the size of this block in bytes.
- gasLimit: QUANTITY - the maximum gas allowed in this block.
- gasUsed: QUANTITY - the total used gas by all transactions in this block.
- timestamp: QUANTITY - the unix timestamp for when the block was collated.
- transactions: Array - Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.
- uncles: Array - Array of uncle hashes.
地址监控可能有用的字段有:
- number:用来判断下一块,记录处理块位置
- transactions:交易列表,需要通过这个交易列表判断是否要我们要处理的交易,还有交易的变化情况
交易数据
- hash: DATA, 32 Bytes - hash of the transaction.
- nonce: QUANTITY - the number of transactions made by the sender prior to this one.
- blockHash: DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.
- blockNumber: QUANTITY - block number where this transaction was in. null when its pending.
- transactionIndex: QUANTITY - integer of the transactions index position in the block. null when its pending.
- from: DATA, 20 Bytes - address of the sender.
- to: DATA, 20 Bytes - address of the receiver. null when its a contract creation transaction.
- value: QUANTITY - value transferred in Wei.
- gasPrice: QUANTITY - gas price provided by the sender in Wei.
- gas: QUANTITY - gas provided by the sender.
- input: DATA - the data send along with the transaction.
* 测试数据中还出现了v、r、s字段,暂时不明白意义
v、r、s的内容可以参考这个贴子 2018.03.23
地址监控可能有用的字段有:
- from:用来判断是否监控地址
- to:用来判断是否监控地址
- value:如果是监控地址时,这是Wei的进出数量
实现
通过JsonRPC调用的接口取到了数据,数据结构基本都清晰了,进一步就是怎么完整解析出变化地址,并与监控地址比较,如果是监控地址则进一步处理变化信息。
class EthAddrWatcher:
def addWatchAddresses(self, setAddrWatch):
def removeWatchAddresses(self, setAddrWatch):
def onAddressChanged(self):
# 地址交易变化
def run(self, noBlockStart):
# 从指定块处理到最新块
# 监控新块变化
完整代码由于还在测试期间,先不列出来了,大体结构就这样,也可以编译成命令行形式直接执行对指定地址的监控。
为了测试代码,用监控代码从创世区块开始跑起,发现在区块高度4万多才开始有交易数据,零星的一两笔持续了很长时间,只到区块高度300多万才有几十上百笔交易,能感受到以太坊成、住、坏、空的过程也是件很有意思的事情!
onBlock number: 46147(0xb443),transactions num:1
...
onBlock number: 4000985(0x3d0cd9),transactions num:320
onBlock number: 4000986(0x3d0cda),transactions num:108
onBlock number: 4000987(0x3d0cdb),transactions num:64
onBlock number: 4000988(0x3d0cdc),transactions num:134
onBlock number: 4000989(0x3d0cdd),transactions num:60
做这个过程中找到有位区块链先行者在2016年写的文章,他还留了以太坊地址,用程序代码跑了一下这个地址:0x893608751d68d046e85802926673cdf2f57f7cb8,发现这人进帐不少啊!佩服!
问题
eth_blockNumber返回0
POST url:http://192.168.0.122:8545,data:{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}
{"jsonrpc":"2.0","id":1,"result":"0x0"}
这个调用一直返回0,查了下原因说是同步过程中状态没更新,不管什么原因,这个用不了其它就没法执行了!
既然是同步问题,刚好有个eth_syncing接口,调用这个查询同步状态,如下:
POST url:http://192.168.0.122:8545,data:{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":2}
{"jsonrpc":"2.0","id":2,"result":{"currentBlock":"0x508255","highestBlock":"0x508296","knownStates":"0xffab46","pulledStates":"0xff7352","startingBlock":"0x50821f"}}
这个地方注意rpc文档里的例子是curl -X POST --data '{"jsonrpc":"2.0","method":"eth_isSyncing","params":[],"id":1}',这个method方法不对
我们正常是会有一个全节点在同步的,因为现有线上的节点基本都不会对外开放rpc接口调用了,那就用eth_syncing这个接口取得的currentBlock来进行当前块判断,当然这个接口调用也有可能返回失败,失败则用eth_blockNumber的结果。
geth配置
开启RPC调用,为安全起见,只需要指定eth模块,可绑定IP地址和端口等,如下:
geth.exe --datadir "YOURETHDATADIR" --rpc --rpcaddr "YOURIP" --nodiscover --rpcapi "eth" console
参考
https://ethereum.gitbooks.io/frontier-guide/content/rpc.html#eth_getfilterchanges
https://github.com/ethereum/go-ethereum/issues/14338
http://www.yaozihao.cn/2017/07/07/geth%E5%91%BD%E4%BB%A4%E9%80%89%E9%A1%B9%E4%BB%8B%E7%BB%8D/
感谢您阅读 @chaimyu 的帖子,期待您能留言交流!