ブロック
ブロックは、チェーン内の前のブロックのハッシュを持つトランザクションのバッチです。ハッシュはブロックデータから暗号学的に導出されるため、これによりブロックが(チェーン状に)リンクされます。履歴内のいずれかのブロックに1つでも変更が加えられると、それ以降のすべてのハッシュが変更され、ブロックチェーンを実行している全員がそれに気づくため、後続のすべてのブロックが無効になります。これにより、不正行為が防止されます。
前提条件
ブロックは非常に初心者向けのトピックです。しかし、このページをよりよく理解するために、まずはアカウント、トランザクション、およびイーサリアムの概要を読むことをお勧めします。
なぜブロックが必要なのか?
イーサリアムネットワークのすべての参加者が同期された状態を維持し、トランザクションの正確な履歴について合意できるようにするために、トランザクションをブロックにバッチ処理します。これは、数十(または数百)のトランザクションが一度にコミットされ、合意され、同期されることを意味します。
Ethereum EVM illustrated (opens in a new tab)から引用した図
コミットの間隔を空けることで、すべてのネットワーク参加者がコンセンサスに達するための十分な時間を与えます。トランザクションの要求は1秒間に数十回発生しますが、イーサリアムでブロックが作成およびコミットされるのは12秒に1回だけです。
ブロックの仕組み
トランザクション履歴を保持するために、ブロックは厳密に順序付けられており(作成されたすべての新しいブロックには親ブロックへの参照が含まれています)、ブロック内のトランザクションも厳密に順序付けられています。まれなケースを除き、ネットワーク上のすべての参加者は常にブロックの正確な数と履歴について合意しており、現在アクティブなトランザクション要求を次のブロックにバッチ処理するために機能しています。
ネットワーク上でランダムに選択されたバリデータによってブロックが組み立てられると、それはネットワークの残りの部分に伝播されます。すべてのノードはこのブロックを自身のブロックチェーンの最後に追加し、次のブロックを作成するために新しいバリデータが選択されます。正確なブロックの組み立てプロセスとコミットメント/コンセンサスプロセスは、現在イーサリアムの「プルーフ・オブ・ステーク (PoS)」プロトコルによって規定されています。
プルーフ・オブ・ステーク・プロトコル
プルーフ・オブ・ステーク (PoS) は以下のことを意味します。
- バリデータノードは、不正行為に対する担保として、デポジット・コントラクトに32 ETHをステークする必要があります。証明可能な不正行為はステークの一部または全部の破棄につながるため、これはネットワークの保護に役立ちます。
- 各スロット(12秒間隔)で、バリデータがランダムに選択され、ブロック・プロポーザーになります。プロポーザーはトランザクションを束ねて実行し、新しい「状態」を決定します。この情報をブロックにまとめ、他のバリデータに渡します。
- 新しいブロックについて知らされた他のバリデータは、グローバルな状態への提案された変更に同意することを確認するために、トランザクションを再実行します。ブロックが有効であると仮定して、自身のデータベースに追加します。
- バリデータが同じスロットに対して競合する2つのブロックについて知らされた場合、フォーク選択アルゴリズムを使用して、最も多くのステークされたETHによってサポートされているブロックを選択します。
ブロックには何が含まれているか?
ブロックには多くの情報が含まれています。最も高いレベルでは、ブロックには以下のフィールドが含まれます。
| フィールド | 説明 |
|---|---|
slot | ブロックが属するスロット |
proposer_index | ブロックを提案するバリデータのID |
parent_root | 前のブロックのハッシュ |
state_root | 状態オブジェクトのルートハッシュ |
body | 以下で定義される複数のフィールドを含むオブジェクト |
ブロックのbodyには、独自のフィールドがいくつか含まれています。
| フィールド | 説明 |
|---|---|
randao_reveal | 次のブロック・プロポーザーを選択するために使用される値 |
eth1_data | デポジット・コントラクトに関する情報 |
graffiti | ブロックのタグ付けに使用される任意のデータ |
proposer_slashings | スラッシングされるバリデータのリスト |
attester_slashings | スラッシングされるアテスターのリスト |
attestations | 以前のスロットに対して行われたアテステーションのリスト |
deposits | デポジット・コントラクトへの新規デポジットのリスト |
voluntary_exits | ネットワークから退出するバリデータのリスト |
sync_aggregate | ライトクライアントにサービスを提供するために使用されるバリデータのサブセット |
execution_payload | 実行クライアントから渡されたトランザクション |
attestationsフィールドには、ブロック内のすべてのアテステーションのリストが含まれています。アテステーションには、複数のデータを含む独自のデータ型があります。各アテステーションには以下が含まれます。
| フィールド | 説明 |
|---|---|
aggregation_bits | このアテステーションに参加したバリデータのリスト |
data | 複数のサブフィールドを持つコンテナ |
signature | data部分に対するバリデータセットの集約署名 |
attestation内のdataフィールドには以下が含まれます。
| フィールド | 説明 |
|---|---|
slot | アテステーションが関連するスロット |
index | アテステーションを行うバリデータのインデックス |
beacon_block_root | チェーンの先頭と見なされるビーコン・ブロックのルートハッシュ |
source | 最後にジャスティファイドされたチェックポイント |
target | 最新のエポック境界ブロック |
execution_payload内のトランザクションを実行すると、グローバルな状態が更新されます。すべてのクライアントはexecution_payload内のトランザクションを再実行し、新しい状態が新しいブロックのstate_rootフィールドと一致することを確認します。これにより、クライアントは新しいブロックが有効であり、自身のブロックチェーンに安全に追加できることを判断できます。execution payload自体は複数のフィールドを持つオブジェクトです。また、実行データに関する重要な要約情報を含むexecution_payload_headerもあります。これらのデータ構造は次のように構成されています。
execution_payload_headerには以下のフィールドが含まれます。
| フィールド | 説明 |
|---|---|
parent_hash | 親ブロックのハッシュ |
fee_recipient | トランザクション手数料を支払うアカウントのアドレス |
state_root | このブロックの変更を適用した後のグローバルな状態のルートハッシュ |
receipts_root | トランザクションレシートトライのハッシュ |
logs_bloom | イベントログを含むデータ構造 |
prev_randao | ランダムなバリデータ選択に使用される値 |
block_number | 現在のブロックの番号 |
gas_limit | このブロックで許可される最大ガス |
gas_used | このブロックで実際に使用されたガスの量 |
timestamp | ブロックタイム |
extra_data | 生バイトとしての任意の追加データ |
base_fee_per_gas | 基本料金の値 |
block_hash | 実行ブロックのハッシュ |
transactions_root | ペイロード内のトランザクションのルートハッシュ |
withdrawal_root | ペイロード内の引き出しのルートハッシュ |
execution_payload自体には以下が含まれます(トランザクションのルートハッシュの代わりに、トランザクションの実際のリストと引き出し情報が含まれている点を除き、ヘッダーと同じであることに注意してください)。
| フィールド | 説明 |
|---|---|
parent_hash | 親ブロックのハッシュ |
fee_recipient | トランザクション手数料を支払うアカウントのアドレス |
state_root | このブロックの変更を適用した後のグローバルな状態のルートハッシュ |
receipts_root | トランザクションレシートトライのハッシュ |
logs_bloom | イベントログを含むデータ構造 |
prev_randao | ランダムなバリデータ選択に使用される値 |
block_number | 現在のブロックの番号 |
gas_limit | このブロックで許可される最大ガス |
gas_used | このブロックで実際に使用されたガスの量 |
timestamp | ブロックタイム |
extra_data | 生バイトとしての任意の追加データ |
base_fee_per_gas | 基本料金の値 |
block_hash | 実行ブロックのハッシュ |
transactions | 実行されるトランザクションのリスト |
withdrawals | 引き出しオブジェクトのリスト |
withdrawalsリストには、次のように構成されたwithdrawalオブジェクトが含まれています。
| フィールド | 説明 |
|---|---|
address | 引き出しを行ったアカウントのアドレス |
amount | 引き出し額 |
index | 引き出しのインデックス値 |
validatorIndex | バリデータのインデックス値 |
ブロックタイム
ブロックタイムとは、ブロック間の時間を指します。イーサリアムでは、時間は「スロット」と呼ばれる12秒の単位に分割されます。各スロットで、ブロックを提案するために単一のバリデータが選択されます。すべてのバリデータがオンラインで完全に機能していると仮定すると、すべてのスロットにブロックが存在することになり、ブロックタイムは12秒になります。ただし、ブロックを提案するために呼び出されたときにバリデータがオフラインになっている場合があり、その場合スロットが空になることがあります。
この実装は、ブロックタイムが確率的であり、プロトコルの目標マイニング難易度によって調整されるプルーフ・オブ・ワーク (PoW) ベースのシステムとは異なります。イーサリアムの平均ブロックタイム (opens in a new tab)はこれを示す完璧な例であり、新しい12秒のブロックタイムの一貫性に基づいて、プルーフ・オブ・ワークからプルーフ・オブ・ステークへの移行を明確に推測できます。
ブロックサイズ
最後に重要な点として、ブロック自体のサイズには上限があります。各ブロックの目標サイズは3,000万ガスですが、ブロックのサイズはネットワークの需要に応じて、ブロックのガス・リミットである6,000万ガス(目標ブロックサイズの2倍)まで増減します。ブロックのガス・リミットは、前のブロックのガス・リミットから1/1024の係数で上方または下方に調整できます。その結果、バリデータはコンセンサスを通じてブロックのガス・リミットを変更できます。ブロック内のすべてのトランザクションによって消費されるガスの総量は、ブロックのガス・リミット未満でなければなりません。これは、ブロックが任意に大きくなるのを防ぐため重要です。ブロックが任意に大きくなる可能性がある場合、パフォーマンスの低いフルノードは、スペースと速度の要件により、徐々にネットワークに追いつけなくなります。ブロックが大きいほど、次のスロットに間に合うように処理するために必要な計算能力が大きくなります。これは中央集権化の力であり、ブロックサイズを制限することでこれに抵抗しています。
参考文献
役に立ったコミュニティリソースをご存知ですか?このページを編集して追加してください!