私が「Dusk」の取引詳細で引っかかってずっと困っていたのは、取引自体が消えることなしに、コントラクト実行が取り消し(リバート)され得るという点です。
最初の直感では、それらをひとつの結果にまとめてしまおうと思いました。
callが成功 = 取引が起きた。
callがリバート = 取引は起きなかった。
でもMoonlightは、そんなふうにきれいには整理できません。
受理される前に、ネットワークは送信者が支払えることを次の範囲で確認します。値(value)、コントラクトの預け入れ、そして最大ガス(最大ガス量は gas_limit × gas_price)。
それから署名を検証し、さらにnonceがアカウントの現在のnonceの「1つ上」であることを確認します。
なるほど。
面白いのは、実行の「後」にあります。
ホワイトペーパーによれば、スマートコントラクトの実行が取り消されるなら、対応する金額が返金されます。未使用のガスも返金されます。
しかし、nonceは受理時にインクリメントされます。
つまり「コントラクト側の状態変更が取り消された」と「この取引試行がネットワークによって消費された」は、同じ状態ではありません。
リバートによってコントラクト側の効果は元に戻せても、アカウント側の順序付けメカニズムは前に進み続けます。
gasにはまた別の境界があります。
ユーザーは実行前に最大ガスを負担できる必要があります。最終的には未使用ガスが戻ってくるので、実際に支払う額は少なくなる可能性がありますが。
関わってくる金額は3つあります。
・負担できる必要がある金額
・実行が消費する金額
・その後に返ってくる金額
gas_limitが「手数料」ではなく「支出上限」に見えていると、見落としやすいです。
では、アプリがいくつかのMoonlightトランザクションを順番に準備している場面を想像してください。
トランザクションNはコントラクトを呼び出してリバートします。
コントラクトの効果は消えます。
しかしNが受理されているなら、送信者のnonceは進んでいます。
トランザクションN+1は、「前回の呼び出しが失敗したから何も起きていない」かのようには推論できません。
失敗によって、コントラクトの外側で何かが変わったのです。
ここで私が好きなのは、この区別です。
実行ロールバックはローカルです。
トランザクション履歴はそうではありません。
そして、それが統合(integration)の問いを変えます。
アプリがユーザーに「このトランザクションは失敗しました」と伝えるとき、何が正確に失敗したのでしょう?
意図した状態遷移でしょうか?
それともトランザクションそのものですか?
Duskでは、それが2つの異なる答えになり得ます。
@Dusk_Foundation #Dusk $DUSK $GPS $TUT
最初の直感では、それらをひとつの結果にまとめてしまおうと思いました。
callが成功 = 取引が起きた。
callがリバート = 取引は起きなかった。
でもMoonlightは、そんなふうにきれいには整理できません。
受理される前に、ネットワークは送信者が支払えることを次の範囲で確認します。値(value)、コントラクトの預け入れ、そして最大ガス(最大ガス量は gas_limit × gas_price)。
それから署名を検証し、さらにnonceがアカウントの現在のnonceの「1つ上」であることを確認します。
なるほど。
面白いのは、実行の「後」にあります。
ホワイトペーパーによれば、スマートコントラクトの実行が取り消されるなら、対応する金額が返金されます。未使用のガスも返金されます。
しかし、nonceは受理時にインクリメントされます。
つまり「コントラクト側の状態変更が取り消された」と「この取引試行がネットワークによって消費された」は、同じ状態ではありません。
リバートによってコントラクト側の効果は元に戻せても、アカウント側の順序付けメカニズムは前に進み続けます。
gasにはまた別の境界があります。
ユーザーは実行前に最大ガスを負担できる必要があります。最終的には未使用ガスが戻ってくるので、実際に支払う額は少なくなる可能性がありますが。
関わってくる金額は3つあります。
・負担できる必要がある金額
・実行が消費する金額
・その後に返ってくる金額
gas_limitが「手数料」ではなく「支出上限」に見えていると、見落としやすいです。
では、アプリがいくつかのMoonlightトランザクションを順番に準備している場面を想像してください。
トランザクションNはコントラクトを呼び出してリバートします。
コントラクトの効果は消えます。
しかしNが受理されているなら、送信者のnonceは進んでいます。
トランザクションN+1は、「前回の呼び出しが失敗したから何も起きていない」かのようには推論できません。
失敗によって、コントラクトの外側で何かが変わったのです。
ここで私が好きなのは、この区別です。
実行ロールバックはローカルです。
トランザクション履歴はそうではありません。
そして、それが統合(integration)の問いを変えます。
アプリがユーザーに「このトランザクションは失敗しました」と伝えるとき、何が正確に失敗したのでしょう?
意図した状態遷移でしょうか?
それともトランザクションそのものですか?
Duskでは、それが2つの異なる答えになり得ます。
@Dusk_Foundation #Dusk $DUSK $GPS $TUT