Crypto OS
Technical Crypto OS第1段階 · ブロックチェーン開発者のメンタルモデル

T3 · 取引がコードからチェーンへ届くまで

構築から確認まで、コードは何を行う必要があるのか?

この章を 3D で体験する →
練習する能力
BuilderOnchain Literacy
実践
コードからテストネット取引を送り、意図的にガス代を低くして滞留させ、同じノンスで置き換える。
AI Lab
AI に取引失敗の 10 パターンと対応するエラーを列挙させ、そのうち 3 つをテストネットで再現する。

現実の問題

出金機能を公開しました。利用者が金額を入れて確認すると、ボタンが回ります。

最初の週に三種類の問い合わせが来ました。

  • 「引かれたのに届かない」。取引はチェーンにあり、赤い印が付いています。手数料だけが引かれ、金額は動いていません。
  • 「三十分も処理中」。ハッシュはありますが、どのブロックにもなく、エラーもありません。
  • 「二回出金した」。待ち切れず再度押し、両方が成功しました。

共通点は、コードが要求を送ったことしか知らず、その後を知らないことです。

プロセスから実際の着金まで何段階を経て、各段階はどう失敗するのでしょうか。

思考実験

取引を、厳密な郵便局へ送る、送料付きの書留と考えます。

規則は四つです。

第一に、番号は 0 から一通ずつ増え、飛ばせません。5 が未処理なら 6 は止まり、エラーなく動きません。

第二に、送料は自分で決めます。高いものから処理し、安いものは返送されず、空くまで待ちます。

第三に、同番号の新しい手紙を送れます。 十分高い送料なら古いものを置き換えます。 取消と加速の唯一の手段です。取り戻すのではなく上書きします。

第四に、配達しても受取成功とは限りません。拒否でも送料はかかり、台帳上の配達と業務の成功は別です。

問い合わせと照合します。

  • 引かれて未着は、第四の拒否です。
  • 処理中は、番号の欠落か低い送料です。
  • 二回は、新番号で独立した二通を送った結果です。

三つの bug ではなく、同じモデルの欠落です。

あなたが決める

いつ出金成功と表示できますか。

結果を観察する

四つは、同じ流れの異なる地点です。

成功を宣言する時点分かること未知のこと
署名利用者の同意送信したか
ハッシュ一ノードが受けた取込み、置換、破棄
ブロック実行した成功か巻戻しか
レシート成功と確認成功し、短期には戻りにくい極端な深い再編

一段階ではなく五段階で、各段階の失敗は独立し、例外、コード、無応答の停滞など表れ方も異なります。

最も危険なのは静かな停滞で、問い合わせまで処理していないことがあります。

モデルを作る

五段階です。

  1. 構築 Construct
  2. 署名 Sign
  3. 送信 Broadcast
  4. 実行 Execute
  5. 確認 Confirm
最初の三つはプロセス、第四はノード、第五は時間の中にあります。異なる場所の誤りへ別の対応が必要です。

各段階の役割と失敗です。

段階コードの役割典型的失敗表れ方
構築to、value、data、nonce、Gas と費用の上限、チェーン番号番号、単位、チェーンの誤り即エラーか、誤ったチェーンで成功
署名内容へ署名して送信可能なバイトを作る鍵やチェーン形式の誤り拒否か別アドレスの復元
送信バイトをノードへ渡す低費用、使用済み・飛んだ番号、基本料不足即エラーか、静かに受けて永久に停滞
実行ブロック内で実行しレシートを作るrevert、Gas 不足、状態変化失敗レシートでも手数料はかかる
確認後続ブロックを待つ再編、置換、プールから破棄見えた取引が後に見えなくなる

四つを詳しく考えます。

1.番号には二つの読み方があります。

確定分だけか、プールの待機分も含むかを選びます。連続送信は後者でなければ番号が重なりますが、先頭が永遠に入らないと後続も止まります。

2.費用不足はエラーより停滞です。

従来の成功・失敗に加え、受け入れられたが無期限の保留があります。ハッシュだけでは何も起きていないと分かりません。

3.失敗でも実行した分の費用を払います。

ノードは計算したので合理的でも、利用者には支払ったのに得られなかった状態です。正直な説明がなければ、自分が資金を取ったと思われます。

4.取消には同番号の新しい取引を使います。

撤回ではなく、高い費用で自分へゼロを送ります。先に入ったほうが有効です。新旧のハッシュは異なるため、両方を追わないと成功を失敗と扱います。

何と呼ぶか

Nonceノンス / 連番

アドレスごとの、0 から増える飛ばせない番号です。

再使用を防ぎ、同じアドレスの順序を決めます。

暗号学では一回限りの乱数(T2)、ここではカウンターで、別のものです。

Gas Limit / Fee CapGas 上限 / 費用上限

計算量の上限と、単位あたりに払う価格です。

Gas 不足は途中で失敗して課金、費用不足は実行前の停滞です。混同すると調査を誤ります。

Raw Transaction生の取引

署名済みで送信できるバイトです。

ハッシュは送信前に決まるため、取得だけでチェーンが知るとは限りません。

Mempoolメモリプール

ノードが保持する未取込み取引です。

ローカルで、チェーンの一部ではありません。全ノードにあることも、残り続けることも保証されません。T4 で扱います。

Replacement置換取引

同 nonce と高い費用で、古い取引を置き換えます。

加速と取消は同じ機構です。最低の値上げ幅があり、不足なら置換の提示額が低いと拒否されます。

Confirmation / Finality確認数 / 最終確定

確認数は上に重なったブロック数、最終確定はプロトコルの巻戻し不能の宣言です。

両者は違い、前者は確率、後者は約束です。最新と最終確定の明示的なタグを T4 で扱います。

実践

実践テストネットで停滞する取引を作り、同 nonce で置き換えるテストネット、curl、nonce を手動設定できるウォレット0、フォーセットのテスト通貨

テスト通貨に価値はなく、実資産は使いません。資金のあるウォレットでなく、専用のものを作ります。

二種類の nonce を比較します。

curl -s -X POST <テストネット-RPC-アドレス> \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount",
       "params":["<あなたのアドレス>","latest"]}'

curl -s -X POST <テストネット-RPC-アドレス> \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount",
       "params":["<あなたのアドレス>","pending"]}'

最初は等しく、後で差ができます。

現在の費用を見ます。

curl -s -X POST <テストネット-RPC-アドレス> \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_gasPrice","params":[]}'

十六進数の wei を十進数へ変え、10 の 9 乗で割って gwei にします。記録し、次は十分低い値を使います。

正常な取引で経路を確認します。

自分の別のテストアドレスへ少額を送り、ハッシュを調べます。

curl -s -X POST <テストネット-RPC-アドレス> \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":["<ハッシュ>"]}'

blockNumber が null なら未取込みです。送信と取込みの区別に使います。

意図的に止めます。

高度な設定で費用上限を第二段階の十分の一、nonce を既定にして送ります。

ハッシュがあっても、eth_getTransactionByHash の blockNumber が null のままか観測します。

正常に見えて動かない失敗です。エクスプローラーでは pending か、見つからない状態になります。

後続の停滞を観測します。

先頭を止めたまま、通常の費用で次の nonce を送ります。

費用が十分でも、先頭が未処理なら後も待ちます。第一段階の二番号の差が 2 になります。

一件で全出金が止まる、よくある事故です。

同 nonce で置換します。

第四段階の取引を加速か取消すると、同じ nonce で高い費用の取引を作ります。

手動なら、同番号と現在の二倍以上の上限を使います。値上げ不足なら拒否されます。

成功後を確認します。

  • 旧ハッシュの eth_getTransactionByHash は null となり、旧取引は存在しなくなります。
  • 新ハッシュの blockNumber は null ではありません。
  • 後続も取込みされます。

実行の成功を確認します。

curl -s -X POST <テストネット-RPC-アドレス> \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["<新しいハッシュ>"]}'

status の 0x1 は成功、0x0 は失敗で、gasUsed は実際の消費です。

コードへこの段階を入れます。状態を見ず成功とすると、問い合わせを残します。

AI Lab

AI LabAI の十種類の失敗から、三つをテストネットで再現するLevel 2 · AI Copilot

三段階で問いかけます。

第一段階:
Ethereum 取引の構築から確認までの十種類の失敗を表にしてください。
段階、ノードの典型的なエラー原文、利用者の見え方、
手数料の有無、正しい対応を示してください。

第二段階:
エラーを出さず動かないものはどれですか。
検出方法と検出間隔を示してください。

第三段階:
第二、第五、第八の失敗を、JSON-RPC と普通のウォレットだけで
テストネット上に再現する具体的な手順を示してください。
SDK は使わないでください。

例外のない失敗こそ本番事故の源泉なので、第二段階が中心です。

第三で実行すると、エラーの違いを発見できます。ノードごとの表現をモデルが混ぜているためです。

実際に使うノードを基準にエラー表を作り、モデルの記憶に頼りません。T14 で利用者の文言へ変えます。

AI の回答後、自分で必ず検証すること

  • エラー文字列を実際のノードで再現できる
  • 低い提示額と、低い置換提示額を区別している
  • 失敗なら手数料不要と言っていない
  • Gas 不足と費用上限不足を逆にしていない
  • SDK の名前と引数が公式文書に存在する
  • wei、gwei、十六進数の換算が正しい
  • ブロックの存在と成功を区別している

実例

一つの nonce が全出金を止める

急騰した費用へ追い付かない出金が、エラーなく止まりました。

後続が数千件積み上がっても、失敗要求がないので監視は通知しませんでした。

同番号の高い費用で再送すれば直りますが、気付くのが難しい問題です。

未取込みの期限、値上げ再送、pending と latest の差の警報を設けます。

手数料が送金の千倍を超える2019 年

送金より三桁大きい手数料を払った例があります。

金額と費用の欄を逆にしたと推測されています。

構築コードに単位の断言と上限検査が必要です。人の入力ミスを送信前に防ぎます。

利用者の加速で照合が崩れる

ウォレットが同番号を高い費用で再送し、成功しました。

システムは旧ハッシュだけを見て、失敗扱いで残高を解放しましたが、資金はすでに出ています。

アドレスと nonce の最終結果も監視し、T14 で置換を独立状態にします。

失敗しても成功と表示される

revert した取引のレシートは失敗で、手数料が引かれました。

取込みしか確認しないウォレットや画面は緑の成功を示しても、資金は届きません。

status は明示的に検査し、既定で成功としません。

変数を一つ変える

もし二プロセスが同じアドレスから送る

同じ番号を取得し、後が置換として拒否されるか、前を上書きします。

再現しにくい不規則な欠落になります。

単なるロックより、単一の割当者と、送信記録と同じトランザクションの保存が必要です。T15 で設計します。

もし署名後に基本料が十倍になる

費用上限は固定され、数分から数日待つ可能性があります。

監視して期限切れに同番号で値上げ再送します。そのループも冪等にし、相互に置換する取引を増やしません。

もし再試行へ新 nonce を与える

独立した二取引となり、二回支払います。

同じ出金要求には同じ番号と内容を対応させ、同じ署名済みバイトを再送します。

もしSolana に変える

連番より最近のブロックハッシュを使い、期限切れで停滞ではなく無効になります。再構築と再署名が必要です。

送信済みか不明という別問題になり、実行エラーも確認します。T6 と T14 で二方式を比べます。

持ち帰る問い

5
誰が支払っているか?

発信アドレスが失敗も含めて払います。肩代わりするなら、ホットウォレット、番号管理、悪用の防御も必要です。

9
誰がリスクを負うか?

停滞は利用者の待ちと自分のサポート、失敗は利用者の費用、照合不一致は通常自分の損失です。責任も異なる三状態を区別します。

17
AI が間違えたとき、損失を負うのは誰か?

Agent はタイムアウトで新しい取引を作り、二回払いがちです。nonce の冪等な意味を理解しないため、再試行はコードへ固定します。

章末チェック

要点

取引の構築、署名、送信、実行、承認には、それぞれ異なる失敗の形がある。

この章の実践課題を終えたらチェックしてください進捗をすべて見る

このページの内容