イーサリアムのトランザクション処理メカニズムについての深い理解
序文
最初のレベルのタイトル"序文"、"ブロックチェーンとは、"分散型"不信"によって集合的に管理される分散型台帳。"配布された"元帳
簿記にはブロックチェーンが不可欠であり、当然取引が最優先になります。 Chuangyu Blockchain Security Labは、ソースコードの観点から、そしてFangトランザクションを通じて、イーサリアムトランザクションプールのデータ構造、トランザクション手数料設定、トランザクション構築、トランザクションプーリング、トランザクション署名、トランザクション検証などの論理設計を簡単に分析することを知っています。セキュリティ メカニズムの設計: パブリック チェーンのセキュリティ メカニズムの設計を検討します。
最初のレベルのタイトル

基本的な考え方
トランザクションプロセスの概略図は次のとおりです。
フローの説明:
まず、ユーザーはネットワーク経由でトランザクション リクエストを開始し、自分の秘密キーでトランザクションに署名し、トランザクションをブロードキャストしてトランザクション プールに追加します。マイナーはトランザクション プールからトランザクション情報を取得し、それをパッケージ化して生成します。その後、コンセンサスを通じてブロックが生成され、最終的にトランザクション ブロックがネットワーク全体にブロードキャストされます。
データフロー:
トランザクション プールのデータ ソース:リモート同期では、ブロードキャスト同期の形式を通じて、他のイーサリアム ノードのトランザクション データがローカル ノードに同期されます。
トランザクション プール内のデータの所在: マイナー (マイナー) によって取得および検証され、マイニングに使用され、マイニングが成功した後にブロックに書き込まれ、ブロードキャストされます。トランザクションは正規のファイルに書き込まれた後、トランザクション プールから削除されます。チェーン、トランザクションが書き込まれた場合、フォークに入った後、トランザクション プール内のトランザクションは減らず、再パッケージ化を待ちます。
最初のレベルのタイトル

データ構造
デフォルトの構成は次のとおりです。

TxPool のデータ構造は次のとおりです。
最初のレベルのタイトル
トランザクション実行を分析する場合、まず、トランザクション手数料の上限/下限の有無、トランザクションプールの構成、トランザクション情報取得の最大数など、いくつかの基本的な構成を確認する必要があります。ここでは、次の点のみを確認します。いくつかの重要なポイント:

副題

02 トレーディングプールの構成

副題
03 トランザクション取得数量


プールを初期化する


トランザクション プールの初期化は NewTxPool を通じて実現され、具体的なコードは次のとおりです。

ここでは、不当なガス価格の設定を避けるために、サニタイズ関数が最初に呼び出されて構成パラメーターが検証されます。

次に、デフォルト構成でトランザクション プール ( txpool ) を初期化します。

次に、ローカル アカウントを初期化し、構成されたローカル アカウント アドレスをトランザクション プールに追加します。

次に、さらにガス価格で注文されたトランザクションを作成します。

具体的な実装コードは以下のとおりです。


次に、reset を呼び出してトランザクション プールを更新します。

リセットの具体的な実装は次のとおりです。


次に、ログのロード中に生成されたリクエストを処理できるように、reorg ループを開始します。

以下にscheduleReorgLoopの具体的な実装コードを示しますが、この関数は主にresetとpromoteExecutableの実行計画に使用されます。

次に、関連するトランザクション イベントをサブスクライブし、メイン ループを開始します。


メイン ループ ループの具体的な実装コードは次のとおりです。これは txPool のゴルーチンであり、メイン イベント ループでもあります。主に、外部のブロックチェーン イベント、さまざまなレポート、トランザクションのエビクション イベントを待機して応答するために使用されます。
最初のレベルのタイトル

トランザクションを構築する
トランザクションはユーザーによって開始され、資産が一方の当事者から他方の当事者に転送されます。これは、いわゆる値の転送です。最も直感的なトランザクションの構築は、ウォレットを介して送金することです。ここでは、次の RPC を直接使用します。 eth_sendTransaction を例としてトランザクションの構築プロセスを分析します。eth_sendTransaction リクエストの例は次のとおりです。
パラメータの例:
from: DATA、20 バイト - 送信トランザクションの送信元アドレス
to: DATA、20 バイト - トランザクションのターゲット アドレス。新しいコントラクトを作成する場合はオプション
Gas: QUANTITY - トランザクション実行に利用可能なガス量、オプションの整数、デフォルト値 90000、未使用のガスが返されます。
GasPrice: QUANTITY - ガス価格、オプション、デフォルト: 未定
値: QUANTITY - トランザクションによって送信された量、オプションの整数

データ: DATA - コントラクトのコンパイルまたは呼び出されたメソッドの署名およびエンコードパラメータ

nonce: QUANTITY - nonce、オプション、同じ nonce を使用して保留中のトランザクションを書き換えることができます

応答例:"RPC である eth_sendTransaction の実行プロセスを追跡しましょう。ここでは、まずアカウントが存在するかどうかを確認し、次に Nonce が空かどうかを確認し、次に SingTx を呼び出して署名操作を実行し、次に SubmitTransaction を呼び出してトランザクションを送信します。"SignTx の実装コードは次のとおりです。SignTx は署名操作のために引き続き呼び出されるため、ここでは詳細を説明しません。


トランザクション署名

詳細な分析が実行されます。"署名後、SendTransaction に戻り、SubmitTransaction を呼び出して署名を送信します。ここでは、最初にトランザクション手数料が十分であるかどうかを確認し、次に SendTx を呼び出してトランザクションを送信します。"SendTx の具体的な実装は次のとおりです。ここでは、トランザクション プールにトランザクションを追加するために AddLocal が呼び出されます。ここではこれ以上の詳細は説明しません。

この 1 つの分析ユニット モジュール:

次に、受信アドレスが空かどうかを確認し、空の場合はアドレスを作成し (通常は契約の作成時に表示されます)、その後の手動調査と分析のために完全な TX 詳細のログを出力し、そのハッシュ値を返します。取引:
最初のレベルのタイトル

プールにトレードする


トランザクションには 2 つのソースがあることがわかっています: 1 つはローカルで送信され、もう 1 つはリモートで送信されます。これら 2 つの具体的な実装コードは、それぞれ AddLocals と AddRemotes です。これら 2 つの関数は、トランザクション プールにトランザクションを追加するときに使用されます。これは次のとおりです。 addTxs を呼び出すことで実現されます。

addTxs コードは次のようになります。

まず、トランザクションがフィルタリングされて、既知のトランザクション (追加トランザクションまたはブロードキャスト) であるかどうかがチェックされ、次に send 関数を呼び出して、secp256k1 楕円曲線を介して署名 (v、r、s) から導出されたアドレスを検証します。 、派生した場合 失敗するか署名が正しくない場合は、エラーが返されます。

次に、トランザクションをトランザクション プールに追加します (注: ここにはトランザクション ロックがあります)。



addTxsLocked の具体的な実装は次のとおりです。有効なトランザクションをキューに入れ、pool.add 関数を呼び出してトランザクション キューにトランザクションを追加します。

add 関数の具体的な実装は次のとおりです。

ここでは、まず現在のトランザクションが既知である (つまり、ブロードキャストされているか、プールに追加されている) かどうかを確認し、既知の場合は直接破棄されます。

次に、トランザクションがローカルで送信されたかリモートで送信されたかを識別し、関数 validateTx を呼び出してトランザクションを検証します。検証が失敗した場合、トランザクションは直接破棄されます。

次に、トランザクション プールがいっぱいかどうかを確認し、いっぱいの場合は、トランザクション キュー内の低価格のトランザクションを破棄します。GlobalSlots と GlobalQueue は、保留中とキューの最大容量です。

次に、現在のトランザクションの保留キューに同じ nonce 値を持つトランザクションがあるかどうかを判断し、存在する場合は、現在の取引所で設定されているガス価格が、設定されている PriceBump パーセンテージを超えているかどうかを判断し、超えている場合は、既存のトランザクションを置き換えて上書きしますそれ以外の場合は、エラーが返され、置換トランザクションの Gasprice が低すぎるため、それをキュー ( enqueueTx ) にスローします。


enqueueTx を呼び出した後、トランザクション キューに追加され、同時に送信元アカウントがローカル アドレスであるかどうかを確認し、そうであればトランザクション プールのローカル アドレスに追加します。

enqueueTx コードは次のとおりです。この関数は主に新しいトランザクションをトランザクション キューに挿入します。
最後に、addTx 関数に進み、ここで requestPromoteExecutables 関数が呼び出されてトランザクション プロモーション リクエスト操作を実行します。これにより、主にトランザクションがキューから保留状態になります。


トランザクション署名

トランザクション署名は主に SignTx 関数によって実現されます。まず、ウォレットが閉じられているかどうかを確認し、次にウォレット アカウントに発情トランザクション リクエストのアカウントが含まれているかどうかを確認してから、署名処理のために SignTx を呼び出します。

SignTx の具体的な実装コードは次のとおりです。

ECDSA (楕円曲線暗号化アルゴリズム) を使用して署名し、署名された結果を返します。

取引確認
最初のレベルのタイトル
取引確認
トランザクション検証はトランザクションリンク全体の中で最も重要な部分です。ユーザーにとって、トランザクション検証はユーザーの財産の安全を確保するための重要な手段です。イーサリアム全体にとって、トランザクション検証は安定した運用と持続可能な発展を保証するための重要な手段です。イーサリアムのトランザクション検証は主に次のシナリオで発生します。
ユーザーがトランザクションの署名を完了したら、できるだけ早くトランザクションを確認できるように、トランザクションをブロックチェーン ネットワークに送信する必要があります。また、ノードはトランザクションを送信する前にトランザクションを検証して、トランザクションの正当性を確認する必要があります。トランザクション;
ノードが他のノードによってブロードキャストされたトランザクションを受信すると、そのノードはトランザクションが合法かどうかを検証する必要があり、合法なトランザクションはノードのトランザクション プールに追加されます。
ノードが他のノードによって同期されたブロックを受信した場合、そのブロックに含まれるトランザクションも検証する必要があります。


トランザクション検証は validateTx 関数によって完了し、そのロジック コードは次のとおりです. ここでは、eip2718 が有効かどうかとトランザクションの種類を確認し、トランザクションのサイズ、トランザクション転送量、ガスを確認します。取引の内容、取引署名の正確性、取引の保証 Nonce 注文に従い、トレーダーの資産が十分かどうか、取引ガス価格の保証 基本取引手数料は高額です。
最初のレベルのタイトル


トランザクションのアップグレード

トランザクションのアップグレードは主に、トランザクションを保留リストに入れることを指します。このメソッドと add メソッドの違いは、add 関数は取得した新しいトランザクションを保留リストに挿入するのに対し、PromoteExecutables は実行可能ファイルを指定されたアカウント アドレス リストに入れることです。をキューリストから保留に挿入し、無効なトランザクションをチェックした後、トランザクションプール更新イベントを送信する実装コードは以下のとおりです。

ここでは、for ループを使用してすべてのアカウントを反復し、トランザクションをアップグレードします。ここでは、まず、アカウントの現在の nonce よりも nonce が低いキュー内のすべてのトランザクションが削除されます。

次に、キュー内の消費量がアカウントの残高を超えているトランザクション、またはガスが最大ガス制限を超えているトランザクションをすべて削除します。

次に、すべての実行可能なトランザクションをキューから保留状態に追加します。ここで、promoteTx メソッドが呼び出され、キュー内のトランザクション ( Txs ) が保留状態になります。

promoteTx の実装コードは次のとおりです。この関数はまずトランザクションを保留キューに挿入します。古いトランザクションの方が優れている場合 (トランザクション Gasprice が元のトランザクション値の 110% 以上である場合)、標準はこのトランザクションは、現在のトランザクションが古いトランザクションよりも優れている場合、古いトランザクションを削除し、リストを更新します。

次に、promoteExecutables 関数に戻り、非ローカル アカウント キューが制限 ( AccountQueue ) より小さい場合は、それを削除します。
最後に、削除されたエントリを記録し、queuedGauge を更新します。キュー内のこのアカウントのトランザクションが空の場合は、このアカウントを削除します。
トランザクションのダウングレード
トランザクションのダウングレードとは、新しいブロックが出現すると、パッケージ化されたトランザクションがパディングからキューにダウングレードされるか、別のトランザクションのガス価格が高い場合に、パディングからキューにダウングレードされることを意味します。実装関数はdemoteUnexecutablesで、トランザクションのダウングレードは主に以下の3つの状況で発生します。
フォークにより、Account の Nonce 値が減少します。元の正規チェーン A のトランザクション番号 m のコストは 20 で、すでにチェーン上にありますが、新しい正規チェーンのトランザクション番号 m は、フォーク後のチェーン上にない場合です。フォークの結果、トランザクション番号 m が正規チェーンに記録されます。アカウントのナンスが減少するため、トランザクション m はトランザクション プールにロールバックしてキューに配置する必要があります。
フォークにより、保留中のトランザクションの nonce 値が状態の nonce 値とは異なります。


demoteUnexecutables のコードは以下の通りで、まず保留リストを走査して各 addr の最新の Nonce 値を取得し、次に前回のクエリで取得した Nonce 値より Nonce が小さいトランザクションを削除し、アカウント残高が取引手数料を支払うのに十分ではないため、一部の一時的に無効なトランザクションが返されます。トランザクションを実行し、一時的に無効なトランザクションをキューに入れます。この時点でギャップがある場合は、後続のトランザクションをキュー リストに移動します。ダウングレード以降、保留中の特定のアドレスのトランザクションがない場合、トランザクションは削除されます。削除するアカウント:
最初のレベルのタイトル



プールのリセット
リセットを通じてトランザクション プールをリセットできます。このメソッドの具体的なコードは次のとおりです。



古いヘッドが null でない場合、再編成が開始されますが、このとき、古いチェーンのヘッド ブロックが新しいチェーンのヘッド ブロックの高さより大きい場合、古いチェーンはロールバックされ、ロールバックされたすべてのトランザクションがリサイクルされます。新しいチェーンのヘッド ブロックが古いチェーンのヘッド ブロックより大きい場合、新しいチェーンはバックオフしてトランザクションをリサイクルします。新しいチェーンと古いチェーンが同じ高さに達すると、バックオフします。共通の親ノードが見つかるまで同時に実行し、次に、discard に格納されているが、include. value には格納されていないすべてのトランザクションを見つけて、これらのトランザクションをプールに再挿入します。

次に、最新のワールド状態を設定し、新しいチェーン ヘッド ブロックの状態を設定して、古いチェーンによってバックアップされるトランザクションをトランザクション プールに入れます。
最初のレベルのタイトル"記事の最後にまとめ"ブロックチェーンは、複数のブロックがチェーン構造でつながったもので、各ブロックはブロックヘッダーとブロックボディの2つの部分で構成され、ブロックボディには取引記録が保存されます。
この記事では、イーサリアムのトランザクションプールのデータ構造、トランザクション手数料設定、トランザクション構築、トランザクション署名、トランザクションプールエントリー、トランザクション検証、トランザクションアップグレード、トランザクションダウングレード、トランザクションプールリセットなどの機能モジュールをソースコードの観点から分析します。イーサリアムトランザクション処理のプロセスとセキュリティ設計は検討されてきましたが、パブリックチェーンセキュリティシステムの構築にはまだ長い道のりがあり、さらに検討する必要があります。
参考リンク:
https://blog.csdn.net/lj900911/article/details/84825739
https://blog.csdn.net/pulong074

