# [ACP41] ステーク期間管理の新ルールの仕組みを理解しよう！

> ACP41は、ステーカー（stakingを行う人やノード）が自分で指定するStartTime（ステーキング開始時刻）を廃止し、ステーキング取引がP-chainで「受理（accept）」された瞬間にステーキングを開始するという変更案です。

- URL: https://cardene.dev/articles/96dbb5d86eb3571b54c7
- 公開日: 2025-09-12
- 更新日: 2025-09-12
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、ステーカーが自由に指定していた開始時刻を廃止し、ステーキングした瞬間から自動的に開始されるようにする仕組みを提案している**ACP41**についてまとめていきます！

:::message
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://github.com/avalanche-foundation/ACPs/blob/main/ACPs/41-remove-pending-stakers/README.md

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

## 概要

**ACP41**は、ステーカー（stakingを行う人やノード）が自分で指定する`StartTime`（ステーキング開始時刻）を廃止し、ステーキング取引がP-chainで「**受理（accept）**」された瞬間にステーキングを開始するという変更案です。
これによりP-chain上の計算負荷が大幅に削減され、AvalancheNetworkの全バリデータ（ブロック検証者）の効率が向上します。

## 用語

| 用語 | 説明 |
| --- | ---- |
| P-chain | Avalancheのプラットフォームチェーン。バリデータの登録やステーク管理などネットワーク運用の基盤となるチェーンです。 |
| ステーカー（staker） | 自身で検証に参加するバリデータ、またはバリデータに資産を委任するデリゲータ（delegator）の総称です。 |
| バリデータ（validator） | ブロックの検証に参加するノードです。自身のステークと、他者からの委任ステークを合わせた有効ステークで検証に参加します。 |
| デリゲータ（delegator） | 自分は検証せず、資産を特定のバリデータに委任して、そのバリデータの検証に参加させる人です。 |
| `StartTime`| ステーカーが従来は任意に指定できた、ステーキングの開始時刻です。 |
| 受理（accept） | ステーキング取引が検証を終えてブロックに取り込まれ、ステートとして確定することです。 |
| 検証（verify） | 取引を受理する前に正当性をチェックする処理です。 |
| pending set | まだ開始時刻が来ておらず、将来アクティブになる予定のステーカー集合です。 |
| current set | すでに開始してアクティブ状態にあるステーカー集合です。 |
| `MaxValidatorStake` | あるバリデータが保持できる総ステーク（自己＋委任）の上限値です。 |
| `O(1)` | 計算量が入力規模に依存せず一定時間で終わることを示す表現です。 |

**ACP41**のコアは「**`StartTime`をユーザーが指定する仕組みを廃止し、ステーキング取引が受理されたら直ちにそのステーカーの期間を開始する**」ことです。
これにより、P-chain側で将来の開始時刻を待つステーカーを追跡する必要がなくなります。
具体的には、従来`pending set`として保持していた「**まだ開始していないステーカーのリスト**」を丸ごと削除でき、`current set`（現在アクティブな集合）だけを見ればよくなります。

この変更の効果として、`MaxValidatorStake`のチェックが大幅に簡素化されます。
従来は「**将来の期間が重なったときの総ステークが上限を超えないか**」を時刻付きで検査する必要がありましたが、提案後は「**いま現在の総ステーク**」を見るだけで足ります。
したがって`MaxValidatorStake`の判定は`O(1)`で済むようになります。

## 動機

これまでステーカーは自由に`StartTime`を設定できました。
この仕組みは柔軟ですが、P-chainには次のような継続的な負担を生みます。

- 検証時の将来チェック
    新しいデリゲータ取引を検証するときには、対象バリデータがすでに受理している他のステーク取引（まだ開始していないものを含む）をすべて考慮し、そのバリデータに委任された総ステーク量が`MaxValidatorStake`を超えないかを確認する必要があります。
    つまり、将来のある時点で複数のステーク期間が同時にアクティブになった場合に、合計が上限を超えていないかを見通してチェックする、ということです。

- 受理時の保留登録
    新しいステーカー取引を受理したら、その開始時刻まで`pending set`に追加・保持し続けます。

- 時刻前進時の集合移動
    P-chainの現在時刻が進むたびに、`StartTime <= 現在時刻`となったステーカーを`pending set`から`current set`へ移し替える処理が必要です。

これらはすべて、`StartTime`という将来の予定を支えるための管理コストです。
取引受理と同時に開始してしまえば、上記の管理が不要になります。
結果として、各バリデータがP-chain検証で行う計算量が下がり、ネットワーク全体の効率が上がります。

### 計算量

従来は、将来の開始・終了を跨いで`pending set`と`current set`を横断的に確認し、期間が重なる箇所での総ステークが`MaxValidatorStake`を超えないかを調べる必要がありました。
これはデータサイズや重なり状況に応じて計算量が増大します。
提案後は、「**現在アクティブな集合**」だけを見て総ステークを判定すればよく、`MaxValidatorStake`のチェックは`O(1)`で完結します。

## 処理フローのイメージ

従来（`StartTime`あり）の流れ

```mermaid
sequenceDiagram
  participant Staker as ステーカー
  participant P as P-chain
  Staker->>P: ステーキング取引を送信（StartTime付き）
  P->>P: 取引を検証（将来の重なりもチェック）
  P->>Staker: 取引を受理
  P->>P: pending setへ登録
  Note over P: 現在時刻が進む
  P->>P: StartTime到来でcurrent setへ移動
```

変更後（受理と同時開始）の流れ

```mermaid
sequenceDiagram
  participant Staker as ステーカー
  participant P as P-chain
  Staker->>P: ステーキング取引を送信（StartTimeなし）
  P->>P: 取引を検証（現在の総ステークのみ確認）
  P->>Staker: 取引を受理
  P->>P: 受理と同時にcurrent setでアクティブ化
```

## 互換性

**ACP41**は、取引タイプのステート遷移（state transition）を変更する提案です。
ステート遷移の変更は「**実行時の挙動そのもの**」を変えるため、必ずネットワーク全体でのアップグレードが必要になります。
つまり、あるノードが新しい挙動を採用し、別のノードが古い挙動を続けてしまうと検証結果に食い違いが生じ、合意が崩れてしまう可能性があるためです。
そのため、有効化前に挙動を変えることは絶対に避けなければならないと明記されています。

**ACP41**では、新しい取引形式を導入したり既存の形式を変更したりしているわけではありません。
したがって、ウォレットの実装において、署名方式やトランザクション構造を変更する必要はなく、基本的にこれまで通り動作します。

ただし注意点があります。
ウォレットが生成する取引の`EndTime`が、`CurrentChainTime + MaxStakeDuration`以上となってしまう場合、その取引は新しい仕様のもとでは拒否されます。
つまり、ウォレット側は「**取引が拒否される条件**」を理解し、適切な終了時刻を設定する必要があります。

ここで登場する`CurrentChainTime`は、P-chain上の最新ブロックのタイムスタンプ以上であることが保証されている値です。
したがって、ネットワークの共通基準時刻として信頼できます。

## 参考実装

**ACP41**で提案されているのは「**ステート管理の方法**」であり、新しい取引形式や追加フィールドの導入ではありません。
そのため、まだリファレンス実装は存在していません。
各AvalancheNetworkClient（ANC：Avalancheネットワークのクライアントソフトウェア）は、自分たちの実行ステップを提案に沿うよう修正する必要があります。

Avalanche公式のクライアント実装であるAvalancheGoについては、以下のプルリクエストで対応が進められています。
[ava-labs/avalanchego/pull/2175](https://github.com/ava-labs/avalanchego/pull/2175)

## Open Questions

この提案の中では、「**`StartTime`を指定できなくなった場合、どのようにしてステーカーは正確に`MaxStakeDuration`（最大ステーク期間）を使い切ることができるのか？**」ということについて議論されています。

### `StartTime`が指定できないことによる影響

新しい仕組みでは、ステーキング期間の開始時刻はブロックが受理されたタイムスタンプで自動的に決まります。
これにより、ユーザーが事前に「**自分はこの時間からステーキングを始めたい**」と正確に指定することができません。

その結果、以下のような制約が生まれます。

* ステーカーは、理論上の最大期間である`MaxStakeDuration`を完全に使い切ることが難しくなります。
* これは、取引が受理されるブロックのタイムスタンプを事前に正確に予測することができないためです。

つまり「**最大期間をピッタリ使う**」ことは不可能であり、数秒から数分程度の誤差が必ず生じることになります。

### 明示的なトレードオフ

この仕様変更は、単なる不具合ではなく意図的なトレードオフです。
P-chainの効率を高めるために、あえて「**`MaxStakeDuration`を完全に使えない可能性がある**」というデメリットを受け入れています。
その代わりに、以下の点は保証されています。

* ステーカーは、指定した`EndTime`において必ず元のステーク資産を返還されます。
* また、`EndTime`までに発生したステーキング報酬を確実に受け取ることができます。

この保証があることで、ユーザーは「**ステーキングが途中で失敗する**」、「**報酬が消える**」といったリスクを心配する必要はありません。

### デリゲータにとっての工夫

デリゲータ（バリデータに資産を委任する人）は、ステーキング期間をできる限り最大化するために、委任先バリデータと同じ`EndTime`を設定することが推奨されています。

この方法を取れば、デリゲータはバリデータと同じ期間アクティブでいられるため、ステーキング時間を最大限に活用できます。

## 最後に

今回は「ステーカーが自由に指定していた開始時刻を廃止し、ステーキングした瞬間から自動的に開始されるようにする仕組みを提案している**ACP41**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4
