はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
今回は、手数料で速度を調整する方式をやめ、各ブロックの間に「必ず待つ最小時間(1秒未満も可)」を設け、その値をバリデータ(ブロックを作る参加者)の希望に合わせて動的に決める仕組みを提案しているACP226についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。
概要
ACP226は、AvalancheのEVMチェーンにおけるブロック生成速度を制御する仕組みを、従来の「*ブロックガスコスト方式(*」から新しい方式に置き換える提案です。
新しい方式では、バリデータ(ブロック検証者)が協力して「ブロック間の最小時間」を動的に決定します。
これにより、ブロックが過剰に早く生成されることを防ぎつつ、システムの柔軟性や拡張性を高めることを目的としています。
動機
現在のAvalanche EVMチェーンでは、ブロック生成の頻度を制御するために「ブロックガスコスト」と呼ばれる仕組みが導入されています。
これは、設定された目標ブロック生成間隔よりも早くブロックを生成する場合に追加コストを発生させ、そのコストをブロック内のトランザクションの「優先手数料(priority fee)」の合計でBurnさせる仕組みです。
しかし、この仕組みにはいくつかの課題があります。
現行方式の課題
| 課題 | 内容 |
|---|---|
| 明確な最小遅延時間がない | バリデータは手数料を支払えば理論上いくらでも早くブロックを生成できるため、過剰なブロック生成によるネットワークの不安定化リスクがある。 |
| 変更が難しい | 目標ブロックレートを変更するにはネットワーク全体のアップグレードが必要であり、運用面で調整が困難。 |
| 秒単位でしか設定できない | 現在は1秒単位でしか目標ブロック間隔を指定できず、性能改善によってサブ秒単位のブロック生成が可能になっても対応できない。 |
新しい方式の利点
ACP194によりブロック実行がコンセンサスから切り離され、さらにACP176によるガスターゲットの動的調整が可能になる環境では、「ミリ秒単位の動的最小ブロック遅延時間」を導入する方が合理的です。
これにより以下の効果が期待されます。
ACP176については以下の記事を参考にしてください。
-
ネットワークの安定性向上
どのような状況でも、ブロックは最小遅延時間を下回って生成されない。 -
柔軟な運用
バリデータが自分の希望を提示することで、合意形成に基づき動的に遅延時間が調整される。 -
将来の性能拡張に対応
サブ秒単位のブロック生成を可能にし、ハードウェアやネットワークの進化に応じてパラメータを調整できる。
ACP-226 Dynamic Minimum Block Times for Sub-Second Blocks
変更点
ACP226は、各ブロックで追加ガスコスト(ブロック内の優先手数料の合計をBurn)を課して生成速度を間接的に抑える方式をやめ、次のブロックを受け入れるまでに必ず待つ最小時間(minimumwait)を強制する方式に切り替えます。
ブロックヘッダーにミリ秒単位の時刻と最小待機時間の新フィールドを追加することで、1秒未満も含むミリ秒精度のブロック間隔を正確に指定・検証でき、ブロック間隔の一貫性を担保します。
最小待機時間の目標値は、ACP176と同様の制御則で調整されます。
各バリデータは希望する最小遅延を設定でき、ネットワークはステーク量を重みとした中央値に段階的に収束するようにパラメータ(q)を更新します。
これにより、コンセンサス参加者の設定に基づく数値へとブロック間隔が調整されます。
なぜ現行方式を変えるのか
現在の「ガスコストチェック方式」は仕組みが複雑なうえ、優先手数料が十分にあると目標ブロックレートを越えるブロック生成が止められないことがあります。
さらに、最小待機時間の強制がないため、短時間にブロックが生成されるバーストが起こる点がネットワーク安定性のリスクでした。
ACP226は、次のブロックを作成するまでに必ず一定の待機時間を設ける仕組みを導入します。
これにより、過剰に速いブロック生成を防ぎつつ、ネットワークの安定性を保ちながら1秒未満の短い間隔でのブロック生成も可能になります。
動的な遅延はどのように動作するのか
最小待機時間は、ACP176と同じ型の制御手法で段階的に調整します。
各バリデータが希望する最小待機時間を設定し、その希望をステーク量で重み付けして集約した結果に向けて、ブロックごとに少しずつ目標値を近づけます。
最終的には、ステーク量を反映した中央値付近の値に落ち着くように動きます。
役割分担は明確です。
ACP176は「1ブロックあたりの目標ガス使用量」を調整し続けます。
ACP226は「ブロック間に必ず空ける最小時間」を下限として保証します。
両者が同時に働くことで、処理量の引き上げに備えつつ、ブロック間隔が過度に短くならないよう安全側を担保し、操作から確定までの体感をスムーズにします。
今後
ガスターゲット(処理量の目安)が上がると、ブロックは小さく軽くなり、より高い頻度で生成できるようになります。
これにより、操作から結果が反映されるまでの体感が速くなります。
同時に、StreamingAsynchronousExecution(SAE=ACP194)などの性能改善が進むことで、短い待機時間でも安全に動作させるための基盤が整います。今
旧方式と新方式の比較
| 観点 | 旧方式:ガスコストで抑制 | 新方式:最小待機時間を強制 |
|---|---|---|
| 速度の抑え方 | 早すぎる生成に追加Burnを課す間接制御 | 次ブロックまでの待機を強制する直接制御 |
| サブ秒対応 | 秒精度が前提、扱いが難しい | ミリ秒時刻フィールドで安全に対応 |
| ネットワーク安定性 | 手数料が厚いと目標超過の恐れ | バースト抑制。最低間隔は常に確保 |
| 望ましい速度への収束 | 手数料状況に影響されやすい | ステーク加重中央値へ自然収束 |
| 運用の簡潔さ | 仕組みが複雑でチューニング困難 | 直感的でチューニング容易 |
-
ACP176
バリデータが設定する希望値をもとに、1ブロックあたりの目標ガス使用量を自動調整する仕組みです。
各ブロック後に制御量を少しずつ増減し、全体の希望に近い目標値へ近づけます。 -
ACP194(SAE)
ブロックの合意(並べ方を決める処理)と実行(EVMでの実際の計算)を別の工程に分け、合意を先に確定して実行を後から進められるようにする仕組みです。
これにより、合意の処理負荷を下げてより短いブロック間隔でも運用しやすくします。 -
ステーク加重中央値
各バリデータのステーク量を重みとして希望値を並べ、累積ステークが全体の50%に達した位置の値を中央値として採用する方法です。
極端な少数意見よりも、ステークの分布の中心を反映します。
仕様
この仕組みをまとめると、AvalancheのEVMチェーンにおいて「ブロックが生成される最小間隔」を、バリデータ全体で協力しながら動的に決める仕組みです。
従来は優先手数料をBurnすることで目標より早いブロック生成も可能でしたが、それでは明確な制限がなくネットワークに負担がかかる可能性がありました。
新しい方式では、ブロックヘッダーに「ミリ秒単位のタイムスタンプ」と「minimumBlockDelay(次のブロックまでに必ず待つべき時間)」を追加します。
この minimumBlockDelay は、数式に基づいてブロックごとに更新され、バリデータが自分の希望を反映させることができます。
値の変化は制御されていて、一度に大きく変わりすぎないよう仕組み化されています。
これにより、ネットワークは常に一定以上の時間を空けてブロックを生成し、過剰な高速化を防ぎつつ、ハードウェアやネットワークの進歩に応じてサブ秒単位まで柔軟にブロック生成速度を調整できるようになります。
ブロックヘッダーの変更
ACP226が有効化されると、従来使われていたblockGasCostフィールドは必ず0に設定されます。
つまり、ブロック内のトランザクションが支払う優先手数料(priority fee)の合計がブロックガスコストを超えているかどうかを検証する必要はなくなります。
代わりに、新しく次の2つのフィールドがブロックヘッダーに追加されます。
timestampMillisecondsminimumBlockDelay
timestampMilliseconds
従来のEVMブロックヘッダーには「秒」単位のタイムスタンプしかなく、これを変更するとEVMコードベースやインデクサー、ブロックエクスプローラーなどの多くのツールに大きな影響が出ます。
そこで既存のタイムスタンプはそのまま残し、新しく「ミリ秒単位のUnixタイムスタンプ」を持つtimestampMillisecondsフィールドを追加します。
ブロック検証時には以下の整合性が確認されます。
block.timestampMilliseconds / 1000 == block.timestamp
つまり、秒単位とミリ秒単位のタイムスタンプが正しく対応している必要があります。
このフィールドはuint64型で表現されます。
既存のツールはこのフィールドを無視できるため、互換性を損なうリスクが最小限に抑えられます。
minimumBlockDelay
新しく導入されるminimumBlockDelayフィールドは、次のブロックが受け入れられるまでに最低限経過しなければならない「ミリ秒単位の時間」を表します。
例えば、あるブロックBにおいてminimumBlockDelayがdであれば、次のブロックB+1のタイムスタンプは「Bのタイムスタンプ + d」以上でなければなりません。
このフィールドもuint64型で表されます。
値の更新は、ACP176で採用されている動的ガスターゲットの仕組みに似た方法で行われます。
動的 minimumBlockDelay の仕組み
minimumBlockDelayは以下の式で定義されます。
$m = M \cdot e^{\frac{q}{D}}$
- $M$
グローバルに設定された最小値(ミリ秒) - $q$
非負整数で、ACP有効化時に初期化される - $D$
変化のスピードを制御する定数
各ブロックのトランザクション実行後、$q$は最大で±$Q$まで変化させることができます。
もしこの制限を超える変化が行われた場合、そのブロックは無効とされます。
$q$の変化量はブロックビルダー(=バリデータ)が指定します。
バリデータは、自分の希望する最小遅延時間を設定でき、その値をもとに「理想の$q$」を以下の式で計算します。
$q_{desired} = D \cdot ln\left(\frac{M_{desired}}{M}\right)$
この計算結果は各ノードの内部でのみ使われるため、近似や整数丸めが許容されます。
あるいは、corethがガスターゲットで実装しているように、二分探索を使って近い整数値を求める方法も可能です。
ブロックを構築する時には、以下のようなロジックを使って現在の$q$から理想の$q$に近づけます。
# ブロックごとに新しいqを計算する例
def calc_next_q(q_current: int, q_desired: int, max_change: int) -> int:
if q_desired > q_current:
return q_current + min(q_desired - q_current, max_change)
else:
return q_current - min(q_current - q_desired, max_change)
このように$q$が更新されるたびに$m$も更新されます。
ただし、その効果は次のブロック以降に反映され、現在のブロックの生成時間には影響しません。
C-Chainでの初期パラメータ
C-Chainにおける有効化時のパラメータは以下です。
| Parameter | 説明 | 設定値 |
|---|---|---|
| $M$ | 最小のminimumBlockDelay値 |
100ミリ秒 |
| $q$ | 初期ターゲット遅延の余剰値 | 3,141,253 |
| $D$ | 更新スピードを制御する定数 | $2^{20}$ |
| $Q$ | 更新幅の最大値 | 200 |
100ミリ秒という$M$の値は、将来的に高速化が可能になった時に追加のアップグレードをしなくても柔軟に対応できるよう選ばれています。
また、初期の$q$は現在のC-Chainの目標ブロック間隔(2秒)にできる限り近づけるよう調整されています。
$D$と$Q$は、約3600ブロック(およそ2時間分)の連続した最大変化によって、遅延時間が半減または倍増する程度の緩やかな調整幅になるよう設定されています。
ProposerVM MinBlkDelayとの関係
現在のProposerVMには「連続するブロック間の最小遅延時間」を秒単位で固定的に設定するMinBlkDelayがあります。
しかし、ACP226が導入されると動的に管理されるため、ProposerVMを利用しているEVMではMinBlkDelayを0に設定する必要があります。
ブロック構築に関する注意
ACP226によって、ブロックガスコストのBurn要件は廃止されます。
ただし、ブロックビルダーは引き続きトランザクションの優先手数料を考慮するべきです。
なぜなら、優先手数料はトランザクションの順序付けに使えるほか、ブロックに含めることでAVAXのBurnを増やすことができるからです。
ユーザー側から見ると、通常は優先手数料を支払う必要はなく、ネットワークがガスで混雑しているときだけ少額の優先手数料を設定すれば十分になります。
互換性
ACP226は、ネットワーク全体のアップグレードとEVMブロックヘッダーの形式変更を伴います。
しかし、その中でもできるだけ既存との互換性を維持するように設計されています。
現在すでに使われている「秒」単位のタイムスタンプフィールドはそのまま残るため、これを利用しているアプリケーションは従来通り動作できます。
つまり、既存のDAppsやインデクサー、ブロックエクスプローラーは、秒単位の情報を参照するだけであれば修正を必要としません。
新しく導入されるtimestampMillisecondsは、より細かい時間精度が必要な場合にのみ利用される追加フィールドです。
このため、通常の利用においては既存のアプリケーションが壊れることなく引き続き動作できます。
セキュリティ
ブロックの生成があまりに速すぎると、バリデータがコンセンサスに参加するための処理に追いつけなくなる可能性があります。
その結果、ネットワーク全体の可用性に問題が生じるリスクがあります。
この新しい仕組みは、バリデータが「どのくらいの頻度でブロックを生成するか」に影響を与えられるようにすることで、過度なブロック生成を防ぐ狙いがあります。
ただし、誤った設定や過剰に攻撃的な設定を選んでしまった場合、一部のバリデータが処理に追いつけなくなる恐れがあります。
この点は運用上の注意が必要です。
また、バリデータの希望に基づいてパラメータを動的に調整する仕組み自体は、すでにC-Chainで「ガスターゲットの動的調整」として使われています。
これまでの実績から、この仕組みをブロック生成間隔の制御に使っても有効である可能性は高いと考えられています。
一方で、この仕組みには特有の性質があります。minimumBlockDelayは各ブロックで変更可能ですが、その変更速度は現在の値によって異なります。
具体的には、最小ブロック遅延が短ければ短いほどブロックを高速で生成できるため、その分だけパラメータを調整する機会が増え、結果的に値が変化しやすくなります。
逆に、遅延が長いと生成されるブロック数が減り、変化もゆるやかになります。
このため、低い値ではシステムがより「反応的(reactive)」になり、高い値では「鈍感(less reactive)」になります。
最小値を示すグローバルパラメータ$M$は、どんなに速くてもこれ以下にはならないという下限を保証しますが、最終的にどの程度の速さでブロックを生成するかはバリデータ全体の設定や合意に委ねられます。
最後に
今回は「手数料で速度を調整する方式をやめ、各ブロックの間に「必ず待つ最小時間(1秒未満も可)」を設け、その値をバリデータ(ブロックを作る参加者)の希望に合わせて動的に決める仕組みを提案しているACP226」についてまとめてきました!
いかがだったでしょうか?
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!