JPYC.transferWithAuthorization_no_replay
名称・種別
- 名称:
JPYC.transferWithAuthorization_no_replay - 種別: theorem
- モジュール:
JpycFormalVerification.SignaturesTheorems - ソース:
JpycFormalVerification/SignaturesTheorems.lean:301-315 - 概要: 一度消費された (from,nonce) は二度と transferWithAuthorization に使えない(再生不可)。
- 仕様: 対象
型シグネチャ
lean
∀ {O : JPYC.SigOracle} {s s' : JPYC.State} {ctx : JPYC.CallContext} {frm dst : JPYC.Address} {value validAfter validBefore : JPYC.U256} {nonce : JPYC.Bytes32} {v : JPYC.U8} {r sig : JPYC.Bytes32}, Eq (JPYC.transferWithAuthorization O s ctx frm dst value validAfter validBefore nonce v r sig) (Except.ok s') → ∀ {ctx' : JPYC.CallContext} {dst' : JPYC.Address} {value' validAfter' validBefore' : JPYC.U256} {v' : JPYC.U8} {r' sig' : JPYC.Bytes32} {s'' : JPYC.State}, Ne (JPYC.transferWithAuthorization O s' ctx' frm dst' value' validAfter' validBefore' nonce v' r' sig') (Except.ok s'')一度成功した transferWithAuthorization と同じ (認可者, nonce) では、その後どんな引数・文脈でも transferWithAuthorization は二度と成功しない、という リプレイ防止 の定理です。
和訳 docstring
リプレイ不可。 一度消費された (from, nonce) では、その後どんな引数・文脈でも transferWithAuthorization は成功しない。
解説
何を述べているか。 transferWithAuthorization が一度成功して状態が s' になったあと、同じ (from, nonce) を使う transferWithAuthorization(他の引数・受取人・時刻・署名は自由)は、結果状態がどうであれ .ok にはならないことを示します。背理法で、*_marks_used(成功後は 1)と再実行側の *_unused(成功には 0 が必要)が矛盾することを使います。
直感。 「同じ署名付き指示は一度しか効かない」。一度使った authorization は使用済み(1)なので、未使用ガード(0 が必要)を二度と通れません。
なぜ安全性に効くか。 EIP-3009 の 最重要保証 です。攻撃者が成立済みのトランザクションを再送(リプレイ)しても、二重に送金が実行されることはありません。署名そのものを傍受されても、認可は一回限りで使い切られます。
図解
Lean ソースコード
lean
/-- **No replay.** Once a `(from, nonce)` authorization has been consumed, no
later `transferWithAuthorization` with the same `(from, nonce)` can succeed
(whatever the other arguments or context). -/
theorem transferWithAuthorization_no_replay {O : SigOracle} {s s' : State} {ctx : CallContext}
{frm dst : Address} {value validAfter validBefore : U256} {nonce : Bytes32}
{v : U8} {r sig : Bytes32}
(h : transferWithAuthorization O s ctx frm dst value validAfter validBefore nonce v r sig = .ok s')
{ctx' : CallContext} {dst' : Address} {value' validAfter' validBefore' : U256} {v' : U8}
{r' sig' : Bytes32} {s'' : State} :
transferWithAuthorization O s' ctx' frm dst' value' validAfter' validBefore' nonce v' r' sig' ≠ .ok s'' := by
intro hreplay
have hused := transferWithAuthorization_marks_used h
have hunused := transferWithAuthorization_unused hreplay
rw [hused] at hunused
exact absurd hunused (by decide)