日々Ethereum(geth)、web3.jsと戯れています。
web3.jsではスマートコントラクトの実行結果イベントを購読して結果を確認できます。
subscribeの引数には以下のようなJSONが渡されます。
{address: '0x000000000000000000000',
blockNumber: 143979,
transactionHash: '0xceca5c97fa39de7473ba513da9afb46099b49a79d837a43122f8eb03329615fb',
transactionIndex: 2,
blockHash:'0x616b19f869fc5f35d9811c125cd9520e62372a6e2afa2bcb1576d9648f26b3d9',
logIndex: 2,
removed: true,
id: 'log_de0ba17a',
returnValues: Result { '0': 'ok', message: 'ok' },
event: 'Result',
signature: '0xf5250111a819ab87d27490e1837d465f4bc000cfd9316fc90fde27c791d8026d',
raw:{data: '0x00',
topics:['0xf5250111a819ab87d27490e1837d465f4bc000cfd9316fc90fde27c791d8026d' ] } }
JSONにはtransactionHashがあるので、
1. スマートコントラクト実行、この時発行されるtransactionHashを保存
2. イベント受信
3. イベントのtransactionHash、returnValuesを見て、そのトランザクションが成功か失敗かを判定
4. 成功なら成功回数をインクリメント(DBに保存)
みたいな使い方をしていたのですが、まれに同じtransactionHashで複数回イベントを受信しててDB内の成功回数とスマートコントラクト上のデータが一致しないという現象に遭遇しました。
実は成功/失敗の判定は上記3で書いたものだけでは足りなくて、
イベントのJSONに含まれるremovedが重要でした。
(リファレンス↓)
removed: trueは孤立したブロックのためチェーン上から取り除かれたことを示すらしく、ここも判定条件に入れる必要がありました。
ということを小一時間調べてしまいましたのでメモとして残します。
Ethereum開発はノウハウ重要ですね。それにドキュメントちゃんと読まないと...。