出金タイムアウトが新しいアイデンティティを作ってはならない

出金リクエストがタイムアウトします。誘惑的な対応は単純です。取引をもう一度作り直して送信し直す。

しかしDuskでは、それによって運用上の問題がより深刻になることがあります。

Moonlightの出金では、統合ガイダンスに「取引は1回だけ構築して署名し、そのシリアライズ済みバイト列とトランザクションIDを、ブロードキャスト前に保存すべき」とあります。送信がトランスポートのタイムアウトに当たった場合、安全なリトライは、これらの“まったく同じ”署名済みバイト列を再送することです。トランザクションは、オンチェーン上での状態が調査されている間、同じアイデンティティを保ちます。

なぜそれが重要なのでしょうか? タイムアウトは、最初の試行が失敗したことを証明しないからです。たとえ 202 Accepted であっても、ルーティングされたことは分かるだけで、取り込み(inclusion)や最終性(finality)までは確認できません。その不確実性を解消する前に別のトランザクションを作成すると、出金システムが追跡すべき別のオブジェクトがさらに増えてしまいます。

Moonlightはこの違いを明確にしています。トランザクションは順次のアカウント・ノンスを使用し、同じノンスの競合トランザクションが既存のメンプール・エントリを置き換えるのは、そのガス価格が“厳密に”より高い場合に限られます。この置き換えではトランザクションIDが異なります。したがってDuskは、取引所運用者に対し、両方のIDを突合して、二重に引き落とさないよう求めています。

つまり「リトライ」と「置き換え(replacement)」は、バックエンド動作として互換ではありません。リトライは、支払い試行のアイデンティティを保持します。一方、置き換えは、同じノンスに対してあえて別のアイデンティティを作成します。

そのため、カストディ(保管)インフラにおける冪等性(idempotency)は、データベース設計の範囲を超えます。トランザクションの構築、ノンスの割り当て、署名済みバイト列、会計記録のすべてが、同一の出金を説明していなければなりません。

@Dusk $DUSK #dusk