トランザクション
トランザクションは、アカウントからの暗号学的に署名された命令です。アカウントは、イーサリアム・ネットワークの状態を更新するためにトランザクションを開始します。最も単純なトランザクションは、あるアカウントから別のアカウントへのETHの送金です。
前提条件
このページをよりよく理解するために、まずはアカウントとイーサリアムの紹介を読むことをお勧めします。
トランザクションとは?
イーサリアムのトランザクションとは、外部所有アカウント、つまりコントラクトではなく人間によって管理されるアカウントによって開始されるアクションを指します。例えば、ボブがアリスに1 ETHを送金する場合、ボブのアカウントから引き落とし、アリスのアカウントに入金する必要があります。この状態を変更するアクションは、トランザクション内で実行されます。
図はEthereum EVM illustrated (opens in a new tab)から引用・改変
EVMの状態を変更するトランザクションは、ネットワーク全体にブロードキャストされる必要があります。どのノードでも、EVM上でトランザクションを実行するリクエストをブロードキャストできます。その後、バリデータがトランザクションを実行し、その結果生じた状態の変更をネットワークの他の部分に伝播させます。
トランザクションには手数料が必要であり、検証済みのブロックに含められる必要があります。この概要をシンプルにするため、ガス代と検証については別の場所で説明します。
送信されるトランザクションには、以下の情報が含まれます。
from– トランザクションに署名する送信者のアドレス。コントラクト・アカウントはトランザクションを送信できないため、これは外部所有アカウントになります。to– 受信者のアドレス(外部所有アカウントの場合は価値を送金し、コントラクト・アカウントの場合はコントラクトのコードを実行します)。signature– 送信者の識別子。これは、送信者の秘密鍵がトランザクションに署名し、送信者がこのトランザクションを承認したことを確認する際に生成されます。nonce- アカウントからのトランザクション番号を示す、連続して増加するカウンター。value– 送信者から受信者に送金するETHの量(Wei建て。1 ETHは1e+18 Weiに等しい)。input data– 任意のデータを含めるためのオプションのフィールド。gasLimit– トランザクションによって消費されるガスの最大単位数。EVMは、各計算ステップに必要なガスの単位を指定します。maxPriorityFeePerGas- バリデータへのチップとして含められる、消費されるガスの最大価格。maxFeePerGas- トランザクションに対して支払う意思のある、ガス1単位あたりの最大手数料(baseFeePerGasとmaxPriorityFeePerGasを含む)。
ガスとは、バリデータがトランザクションを処理するために必要な計算量を指します。ユーザーはこの計算に対して手数料を支払う必要があります。gasLimitとmaxPriorityFeePerGasは、バリデータに支払われる最大トランザクション手数料を決定します。ガスの詳細。
トランザクション・オブジェクトは以下のようになります。
{
from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a",
gasLimit: "21000",
maxFeePerGas: "300",
maxPriorityFeePerGas: "10",
nonce: "0",
value: "10000000000"
}
しかし、トランザクション・オブジェクトは送信者の秘密鍵を使用して署名される必要があります。これにより、トランザクションが送信者からのみ送信されたものであり、不正に送信されたものではないことが証明されます。
Gethのようなイーサリアム・クライアントが、この署名プロセスを処理します。
JSON-RPC呼び出しの例:
{
"id": 2,
"jsonrpc": "2.0",
"method": "account_signTransaction",
"params": [
{
"from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
"gas": "0x55555",
"maxFeePerGas": "0x1234",
"maxPriorityFeePerGas": "0x1234",
"input": "0xabcd",
"nonce": "0x0",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x1234"
}
]
}
レスポンスの例:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"tx": {
"nonce": "0x0",
"maxFeePerGas": "0x1234",
"maxPriorityFeePerGas": "0x1234",
"gas": "0x55555",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x1234",
"input": "0xabcd",
"v": "0x26",
"r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
"s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
}
}
}
rawは、RLP(Recursive Length Prefix)エンコード形式の署名済みトランザクションです。txは、JSON形式の署名済みトランザクションです。
署名ハッシュにより、トランザクションが送信者から送信され、ネットワークに送信されたことを暗号学的に証明できます。
データ・フィールド
トランザクションの大部分は、外部所有アカウントからコントラクトにアクセスします。 ほとんどのコントラクトはSolidityで記述されており、に従ってデータ・フィールドを解釈します。
最初の4バイトは、関数の名前と引数のハッシュを使用して、呼び出す関数を指定します。 このデータベース (opens in a new tab)を使用して、セレクタから関数を特定できる場合があります。
コールデータの残りの部分は、ABI仕様で指定されているようにエンコードされた (opens in a new tab)引数です。
例えば、このトランザクション (opens in a new tab)を見てみましょう。 コールデータを見るには、Click to see Moreを使用してください。
関数セレクタは0xa9059cbbです。この署名を持つ既知の関数 (opens in a new tab)はいくつかあります。
この場合、コントラクトのソースコード (opens in a new tab)がEtherscanにアップロードされているため、関数がtransfer(address,uint256)であることがわかります。
残りのデータは以下の通りです。
0000000000000000000000004f6742badb049791cd9a37ea913f2bac38d01279
000000000000000000000000000000000000000000000000000000003b0559f4
ABI仕様によると、整数値(20バイトの整数であるアドレスなど)は、前方にゼロがパディングされた32バイトのワードとしてABIに表示されます。
したがって、toアドレスは4f6742badb049791cd9a37ea913f2bac38d01279 (opens in a new tab)であることがわかります。
valueは0x3b0559f4 = 990206452です。
トランザクション記述子
データ・フィールドには不透明な16進数のバイトが含まれているため、トランザクションが実際にどのようなアクションを実行するかを検証することは非常に困難な場合があります。この「ブラインド署名」の脆弱性は、トランザクション記述子 (opens in a new tab)(ERC-7730で定義)を使用した**クリア署名 (opens in a new tab)**によって対処されます。
ERC-7730仕様では、トランザクション記述子(多くの場合JSONファイルとして構造化されています)を使用して、ABIや、EVMトランザクションのコールデータ、EIP-712メッセージ、EIP-4337のUser Operationなどの構造化メッセージに含まれるデータを充実させます。開発者はこれらの記述子を使用して、特定のトランザクション変数をフォーマット・テンプレートに直接マッピングし、基盤となるデータがアプリケーションにとって機械可読な状態を維持できるようにします。
フロントエンドでは、ウォレットがこのフォーマット・コンテキストを使用して、不透明なバイトコードを明確で人間が読める情報に変換します。トークン・アドレスを認識されたティッカーに、または金額を小数に自動的に解決することで、ユーザーは署名する前にトランザクションの正確なインテントの平易な言葉による要約(例:「1000 USDCを少なくとも0.25 WETHにスワップする」)を提示されます。
トランザクションの種類
イーサリアムには、いくつかの異なる種類のトランザクションがあります。
- 通常のトランザクション:あるアカウントから別のアカウントへのトランザクション。
- コントラクトのデプロイ・トランザクション:'to'アドレスのないトランザクションで、データ・フィールドはコントラクトのコードに使用されます。
- コントラクトの実行:デプロイされたスマート・コントラクトと対話するトランザクション。この場合、'to'アドレスはスマート・コントラクトのアドレスになります。
ガスについて
前述の通り、トランザクションの実行にはガスがかかります。単純な送金トランザクションには21000単位のガスが必要です。
したがって、ボブがアリスに1 ETHを送金する際、baseFeePerGasが190 Gwei、maxPriorityFeePerGasが10 Gweiの場合、ボブは以下の手数料を支払う必要があります。
(190 + 10) * 21000 = 4,200,000 Gwei
--または--
0.0042 ETH
ボブのアカウントからは**-1.0042 ETH**(アリスへの1 ETH + ガス代の0.0042 ETH)が引き落とされます。
アリスのアカウントには**+1.0 ETH**が入金されます。
基本料金はバーン(焼却)されます:-0.00399 ETH
バリデータはチップを受け取ります:+0.000210 ETH
図はEthereum EVM illustrated (opens in a new tab)から引用・改変
トランザクションで使用されなかったガスは、ユーザーのアカウントに返金されます。
スマート・コントラクトとの対話
スマート・コントラクトが関与するすべてのトランザクションにはガスが必要です。
スマート・コントラクトには、コントラクトの状態を変更しないview (opens in a new tab)またはpure (opens in a new tab)関数と呼ばれる関数を含めることもできます。そのため、EOAからこれらの関数を呼び出す場合、ガスは必要ありません。このシナリオの基盤となるRPC呼び出しはeth_callです。
eth_callを使用してアクセスする場合とは異なり、これらのviewまたはpure関数は内部的(つまり、コントラクト自体または別のコントラクトから)に呼び出されることも一般的であり、その場合はガスがかかります。
トランザクションのライフサイクル
トランザクションが送信されると、以下のことが起こります。
- トランザクション・ハッシュが暗号学的に生成されます:
0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017 - その後、トランザクションはネットワークにブロードキャストされ、他のすべての保留中のネットワーク・トランザクションで構成されるトランザクション・プールに追加されます。
- トランザクションを検証し、「成功」と見なすためには、バリデータがトランザクションを選択してブロックに含める必要があります。
- 時間が経つにつれて、トランザクションを含むブロックは「ジャスティファイド」、そして「ファイナライズ済み」へとアップグレードされます。これらのアップグレードにより、トランザクションが成功し、決して変更されないことがより確実になります。ブロックが「ファイナライズ済み」になると、数十億ドルのコストがかかるネットワーク・レベルの攻撃によってのみ変更される可能性があります。
視覚的なデモ
オースティンがトランザクション、ガス、マイニングについて解説する動画をご覧ください。
型付きトランザクション・エンベロープ
イーサリアムには元々、トランザクションのフォーマットが1つしかありませんでした。各トランザクションには、ナンス、ガス価格、ガス・リミット、宛先アドレス、値、データ、v、r、sが含まれていました。これらのフィールドはRLPエンコードされており、以下のようになります。
RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])
イーサリアムは進化し、アクセス・リストやEIP-1559 (opens in a new tab)などの新機能を、レガシーなトランザクション・フォーマットに影響を与えることなく実装できるように、複数の種類のトランザクションをサポートするようになりました。
EIP-2718 (opens in a new tab)は、この動作を可能にするものです。トランザクションは次のように解釈されます。
TransactionType || TransactionPayload
各フィールドの定義は以下の通りです。
TransactionType- 0から0x7fまでの数値で、合計128種類のトランザクション・タイプが可能です。TransactionPayload- トランザクション・タイプによって定義される任意のバイト配列。
TransactionTypeの値に基づいて、トランザクションは次のように分類されます。
-
タイプ0(レガシー)トランザクション: イーサリアムのローンチ以来使用されている元のトランザクション・フォーマットです。動的なガス代の計算やスマート・コントラクトのアクセス・リストなど、EIP-1559 (opens in a new tab)の機能は含まれていません。レガシー・トランザクションは、シリアライズされた形式でそのタイプを示す特定のプレフィックスを持たず、RLP(Recursive Length Prefix)エンコードを使用する場合はバイト
0xf8で始まります。これらのトランザクションのTransactionType値は0x0です。 -
タイプ1トランザクション: イーサリアムのベルリン・アップグレードの一部としてEIP-2930 (opens in a new tab)で導入されたこれらのトランザクションには、
accessListパラメータが含まれています。このリストは、トランザクションがアクセスすると予想されるアドレスとストレージ・キーを指定し、スマート・コントラクトが関与する複雑なトランザクションのガスコストを削減するのに役立ちます。EIP-1559の手数料市場の変更は、タイプ1トランザクションには含まれていません。タイプ1トランザクションにはyParityパラメータも含まれており、これは0x0または0x1のいずれかであり、secp256k1署名のy値のパリティを示します。これらはバイト0x01で始まることで識別され、そのTransactionType値は0x1です。 -
タイプ2トランザクション(一般にEIP-1559トランザクションと呼ばれます)は、イーサリアムのロンドン・アップグレードにおいてEIP-1559 (opens in a new tab)で導入されたトランザクションです。これらはイーサリアム・ネットワーク上の標準的なトランザクション・タイプとなっています。これらのトランザクションは、トランザクション手数料を基本料金と優先手数料に分離することで予測可能性を向上させる、新しい手数料市場メカニズムを導入しています。これらはバイト
0x02で始まり、maxPriorityFeePerGasやmaxFeePerGasなどのフィールドを含みます。タイプ2トランザクションは、その柔軟性と効率性から現在ではデフォルトとなっており、特にネットワークの混雑時に、ユーザーがトランザクション手数料をより予測しやすく管理できるため好まれています。これらのトランザクションのTransactionType値は0x2です。 -
タイプ3(ブロブ)トランザクションは、イーサリアムのデンクン・アップグレードの一部としてEIP-4844 (opens in a new tab)で導入されました。これらのトランザクションは、「ブロブ」データ(Binary Large Objects)をより効率的に処理するように設計されており、より低コストでイーサリアム・ネットワークにデータを投稿する方法を提供することで、特にレイヤー2 (L2)のロールアップに恩恵をもたらします。ブロブ・トランザクションには、
blobVersionedHashes、maxFeePerBlobGas、blobGasPriceなどの追加フィールドが含まれています。これらはバイト0x03で始まり、そのTransactionType値は0x3です。ブロブ・トランザクションは、イーサリアムのデータ可用性とスケーリング機能における大幅な改善を表しています。 -
タイプ4トランザクションは、イーサリアムのペクトラ・アップグレードの一部としてEIP-7702 (opens in a new tab)で導入されました。これらのトランザクションは、アカウント抽象化と前方互換性を持つように設計されています。これにより、EOAは元の機能を損なうことなく、一時的にスマート・コントラクト・アカウントのように振る舞うことができます。これらには
authorization_listパラメータが含まれており、EOAが権限を委任するスマート・コントラクトを指定します。トランザクション後、EOAのコード・フィールドには委任されたスマート・コントラクトのアドレスが含まれます。
参考文献
役に立つコミュニティ・リソースをご存知ですか?このページを編集して追加してください!