前回は、Transaction-Ordering Dependence問題を検証するためのコントラクトをデプロイし、geth上で操作できるようにコントラクトの変数宣言を行いました。
今回はこのスマートコントラクトの動作確認を行います。
アカウントごとの役割
アカウントの役割は次の通りです。
- MAIN ACCOUNT (eth.accounts[0])
コントラクト生成者。売り手 - ACCOUNT1 (eth.accounts[1])
買い手。 - ACCOUNT2 (eth.accounts[2])
マイナー。
発行順通りに実行
動作確認は2つのトランザクを間髪入れずに連続で行う必要があるため、gethコンソール上から行います。
最初に買い手からbuy関数を呼び出し、2つ目でオーナーからupdate関数をコールしpriceを更新します。
buy関数のgasPriceを高く設定しているのがポイントとなります。
送金を行う前に各アカウントのロックを解除しています。
[コマンド]
1 | > personal.unlockAccount(eth.accounts[0]) |
実行結果を確認します。
[結果]
先にbuyを発行しているため、updatePriceでpriceが15 etherに更新される前のpriceで購入できているのは当たり前のように思えます。
しかし実際には発行順とは違う順番でトランザクションが実行されてしまうことがあります。
発行順と異なる実行
買い手はbuyトランザクションを発行する時に参照していたpriceではなくupdatePrice後のpriceで購入してしまうケースがあります。
コマンド発行順は同じですが、updatePrice関数のgasPriceを高く設定して実行してみます。
[コマンド]
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xec3b01f36b44182746ca109230567c4915512e35
Passphrase:
true
> personal.unlockAccount(eth.accounts[1])
Unlock account 0x63f25b9bbd974fdfa07477cb99c60d2073cfe560
Passphrase:
true
> mpt.buy.sendTransaction(10, {from:eth.accounts[1], gas:5000000, gasPrice:50000000000, value:web3.toWei(500, "wei")});
"0x75840755d8756c7918b925329b83ddba5d62c43caeb7c80f9144b15c5594c173"
> mpt.updatePrice.sendTransaction(20, {from:eth.accounts[0], gas:5000000, gasPrice:90000000000});
"0x4583af1ec7929ba834d493482e57f0474349dba2d09cea8d8c9376d16409708f"```
<br>
実行結果を確認します。
[結果]
<img src="/img/geth/tod3b.png" alt="" />
買い手がbuyトランザクションを発行する時に参照していたpriceは<b>15 ehter</b>でしたが、<b>20 ehter</b>での購入となってしまいました。
<br>
1回目と結果が変わったのは意図的にこの順番になるようにオーナーが<b>トランザクションの順番をコントロールした</b>からです。
Ethereumではマイニングする際に、<b>gasPriceが高いトランザクションを優先して実行</b>するようになっています。
そのため、後者のトランザクションのgasPriceを前者のgasPriceより高く設定すれば、トランザクションの発行順によらず後者が優先されてしまいます。
次回は、トランザクションのイベントを検知しこの操作を自動化してみます。