[EIP5003] AUTHUSURPオペコードを追加しEOAアドレスの秘密鍵を作り替える仕組みを理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、新しいオペコードである`AUTHUSURP`を導入し、EOAの秘密鍵の作り替え仕組みを提案している**EIP5003**についてまとめていきます！

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

https://eips.ethereum.org/EIPS/eip-5003

他にも様々なEIPについてまとめています。

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

# 概要

EIP (Ethereum Improvement Proposal)とは、イーサリアムネットワークのプロトコルに変更や追加を提案する公式文書のことです。
それぞれのEIPは、ネットワークの機能を拡張したり、セキュリティの問題を解決するための提案が含まれています。
この規格で提案されている内容の中心は、新しいオペコード `AUTHUSURP` と関連する他のEIP（**EIP3074**および**EIP3607**）についてです。

### EIP-3074
**EIP3074**は「`AUTH`」と「`AUTHCALL`」という2つのオペコードを導入することを提案しています。
これにより、ウォレットやコントラクトが、ユーザーのアカウントを代わりに操作できる新しい方法を提供します。
このEIPの主な目的は、トランザクションの承認機能を改善することにあります。
これにより、ユーザーは自分の秘密鍵を使わずに、信頼できるコントラクトにトランザクションの実行を委託できるようになります。

:::note info
**ERC3074**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/f55a6d2df6d13030e20e

### EIP-3607
**EIP3607**は、コードが存在するEOAアドレスをEOAアドレスとして使用することを防ぐ仕組みを提案しています。
一度スマートコントラクトがそのアドレスにデプロイされると、そのアドレスをEOAとして使うことができなくなり、資金の不正な抜き出しなどが起きなくなります。

:::note info
**EIP3607**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/b7a12a2848d2b2022761

### 新しいオペコード：AUTHUSURP
`AUTHUSURP`という新しいオペコードは、特定の認可されたアドレスにコードをデプロイする機能を提供します。
これは、**EIP3074**により許可されたアドレスで使用されることを想定しています。
EOAにとって、**EIP3607**と組み合わせることで、元の署名鍵の権限を事実上取り消すことができます。
つまり、外部所有アカウントの管理者は、`AUTHUSURP`を使って新しいコードをデプロイすることにより、そのアカウントの制御を更新または変更することが可能になります。

この提案の意義は、イーサリアムのセキュリティと柔軟性を同時に向上させることにあります。
ユーザーはより安全にアカウントを管理できるようになり、また、新たなアプリケーションやケースに対応するためにアカウントの挙動をカスタマイズすることが容易になります。

ただし、このような変更が実装される時には、ネットワークの安全性や互換性に関する詳細な検討が必要です。
新しいオペコードや機能が導入されると、既存のシステムやプロトコルに予期せぬ影響を及ぼす可能性があります。
そのため、EIPが承認され実装されるまでには、広範なテストとコミュニティからのフィードバックが必要になります。

# 動機

イーサリアム上の外部所有アカウント（EOA）に関するセキュリティ上の問題と、新しい改善提案（EIP）がこれをどのように解決しようとしているかについて説明しています。
EOAは多くのユーザーが管理する価値を保持していますが、キーのローテーション（作り替え）、ガス代節約のためのバッチ処理、またはイーサを保持する必要を減らすためのスポンサーされたトランザクションなど、いくつかの重要な制限があります。

:::note info
キーのローテーションとは、定期的にデジタル認証や暗号化に使用される秘密鍵や公開鍵を新しいものに更新するセキュリティプラクティスです。
この手法は、潜在的な長期的な攻撃や秘密鍵が漏洩した場合のリスクを軽減するために使われます。
キーのローテーションにはいくつかの主要な理由があります：

### **セキュリティの強化**
長期間同じ秘密鍵を使用し続けると、その鍵が破られるリスクが高まります。
定期的にキーを更新することで、鍵が漏洩した場合の損害を最小限に抑え、安全性を維持できます。

### **コンプライアンス要件の満たし**
多くの規制や基準では、データ保護のために定期的なキーの回転を義務付けています。
これにより、企業は規制要件を満たし、データを安全に保つことができます。

### **リスクの分散**
もし鍵が漏洩しても、その鍵で暗号化されたデータやシステムへのアクセスは、鍵が更新されるまでの限定的な期間に制限されます。
これにより、攻撃者が損害を与える窓口を狭めることができます。

### キーのローテーションの方法
キーのローテーションプロセスは以下のステップで行われます。

1. **新しいキーの生成**
    - 新しい秘密鍵と公開鍵のペアを生成します。
    - このステップは、高いセキュリティ基準に基づいて行われる必要があります。

2. **新しいキーのデプロイ**
    - 新しいキーをシステムやアプリケーションに導入し、古いキーと置き換えます。
    - この過程で、新しいキーを使用するようにシステムを更新する必要があります。

3. **古いキーの無効化と廃棄**
    - 新しいキーが機能し始めたら、古いキーを無効化し、安全に廃棄します。
    - これにより、古いキーが悪用されるリスクを避けられます。

4. **監査とログの維持**
    - キーのローテーションプロセスを記録し、適切な監査が行えるようにします。
    - これにより、セキュリティインシデントが発生した際に追跡や原因調査が可能になります。

キーのローテーションは、セキュリティ意識の高い組織や、センシティブなデータを扱うシステムにとって、必要不可欠なプロセスとなっています。
定期的にキーを更新することで、セキュリティの保持とリスクの最小化が可能になります。
:::

### EOAの制限
EOAの大きな制約として、セキュリティのキーをローテーション（作り替え）させる機能がないことが挙げられます。
一度リークしたプライベートキーは取り消すことができず、これによりセキュリティの脅威が常に存在します。
ユーザーが新しいシークレットリカバリーフレーズに移行することは可能ですが、これはすべての資産についてトランザクションを行う必要があり、コストが非常に高くなります。
さらに、一部の権限は移行ができない可能性もあります。

### スマートコントラクトウォレットとアカウント抽象化
新しいユーザーはスマートコントラクトウォレットを使用することで、認証アルゴリズムを自由に選択し、支出限度を設定し、ソーシャルリカバリーを有効にするなど、さまざまな利点を享受することができます。
これらのウォレットは、キーのローテーション（作り替え）や権限の委譲も可能にします。
最近の標準である**EIP4337**はアプリレイヤーでのアカウント抽象化を提供しますが、これは既存の多くのユーザーのアカウントを考慮に入れていません。

:::note info
**EIP4337**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/8c97ca7c93c4557ebfc2

### 新提案の必要性
この規格で提案されている新しいEIPは、EOAの原始的な問題に対処し、EOAからの最終的な移行パスを提供することを目的としています。
これは**EIP3074**とは異なり、**EIP3074**はEOAがその署名権限を任意のスマートコントラクトに委譲できるようにするオペコードを提供しますが、元の署名キーの権限を取り消すことはできません。
新提案は、EOAの原始的な署名キーから完全に移行するための道を提供し、将来的にはコントラクトベースのアカウントへの移行を促進します。

:::note info
「**原始的な署名キー**」という用語は、主にイーサリアムの外部所有アカウント（EOA）に関連して使用されます。
この文脈での「**原始的**」という形容詞は、アカウントが持つ最初の、または基本的な署名権限を持つ秘密鍵を指しています。
これは、アカウントが最初に生成されたときに割り当てられるキーであり、アカウントのトランザクションを署名するために使われます。

### 原始的な署名キーの重要性
EOAの原始的な署名キーは、以下の点で重要です。

- **アカウントアクセス**
    - このキーはアカウントの所有権とアクセス権をコントロールします。
    - キーを持つ者は、そのアカウントを通じてトランザクションを発行し、資金を移動させることができます。

- **セキュリティリスク**
    - キーが漏洩すると、アカウントの資産が盗まれるリスクが生じます。
    - そのため、このキーの安全性は極めて重要です。

### 署名キーの問題点
- **キーのローテーション不足**
    - 従来のEOAでは、一度割り当てられた署名キーは基本的には変更が困難です。
    - これがセキュリティの弱点となり、キーが漏洩した場合のリスクが永続します。
- **機能の限定**
    - EOAは、複雑なロジックやセキュリティ機能を自身で持つことができません。
    - 例えば、複数の条件や認証が必要なトランザクションの処理ができません。

### 移行の提案
新提案は、この原始的な署名キーから完全に移行するパスを提供することで、より安全で柔軟なコントラクトベースのアカウントへの移行を促進します。
コントラクトベースのアカウントでは、キーのローテーションや複数の認証方法を設定することが可能であり、これによりセキュリティが強化され、よりダイナミックなアカウント管理が実現します。
このような移行によって、ユーザーは古い署名キーのリスクを解消し、新たなセキュリティ機能を活用できるようになります。
:::

このアプローチは、既存の多数派であるEOAユーザーを考慮に入れつつ、より安全で柔軟なアカウント管理を実現するために必要です。
提案は、EOAを維持するのではなく、EOAから抜け出すための方法として提案されており、コミュニティ全体がより安全で使いやすいプラットフォームへと進化できるように設計されています。

# 仕様

提案されている新しいオペコード `AUTHUSURP` (`0xf8`) は、Ethereum仮想マシン（EVM）において新たに導入される機能です。
このオペコードは `CREATE` (`0xf0`) オペコードに似ていますがある点で異なります。
これはスマートコントラクトのコードデプロイメントに関連していますが、特定の条件下で動作します。

### スタックの値 (top - N)
EVMはスタックベースのマシンです。
すなわち、計算中に使用されるデータはスタックという形式で一時的に格納されます。
スタック内のデータは、「**最後に入れたものが最初に出る**」（LIFO: Last In, First Out）の原則に従って管理されます。

- **top - N**
    - これはスタック内のデータ参照の方法です。
    - 「`top - 0`」はスタックの最上位にあるデータ（最も最近にプッシュされたデータ）を指します。
    - また、「`top - 1`」はその一つ下のデータを指し、以降同様に参照します。
    - この表記法は、EVMのオペコードがデータをどのように操作するかを明確にするために使用されます。

### 無効な実行 (invalid execution)
EVMでは、特定の条件下で実行が「**無効**」とみなされることがあります。
これには、スタックアンダーフロー、無効なジャンプ、データの型不一致などが含まれます。実行が無効になると、次のような処理が行われます。

- **即座に現在の実行フレームを終了**
    - 無効な実行が検出された場合、EVMはそのコントラクトの実行をすぐに停止します。
- **残りのガスをすべて消費**
    - この時、そのトランザクションに割り当てられていた残りのガスはすべて消費されます。
    - これは、エラー発生時のペナルティとして機能します。

### 空のアカウント (empty account)
イーサリアムには、スマートコントラクトアカウントと外部所有アカウント（EOA）の二種類がありますが、いずれのアカウントも「**空**」となる状態が存在します。

- **バランスが0**
    - アカウントのイーサリアムの残高が0です。
- **nonceが0**
    - アカウントのトランザクションカウントが0です。
    - EOAの場合は送信したトランザクションの数、コントラクトアカウントの場合は作成したコントラクトの数です。
- **コードがない**
    - コントラクトアカウントの場合、デプロイされたコードが存在しない状態を指します。

これらの基準を理解することは、スマートコントラクトの開発や、トランザクションの解析において非常に重要です。
それぞれの状態がどのようにEVM上で処理されるかを把握することで、より効果的なコントラクト設計やデバッグが可能になります。

## オペコードの動作

#### 入力

| Stack   | Value  |
|---------|--------|
| top - 0 | offset |
| top - 1 | length |

#### 出力

| Stack   | Value   |
|---------|---------|
| top - 0 | address |

## 動作の詳細

### 権限の確認
オペコードの実行は、**EIP3074**で定義される「`authorized`」が設定されている場合にのみ有効です。
この「`authorized`」が未設定の場合、実行は無効とされ、すべての残ガスを消費して現在の実行フレームから即座に退出します。

### ガスの計算
`authorized`が空のアカウントを指している場合（残高0、`nonce` 0、コードなし）、静的ガス料金は`32,000`とされます。
それ以外の場合は`7,000`です。

:::note info
イーサリアムのトランザクションやスマートコントラクトの実行において、「**静的ガス料金**」と「**動的ガス料金**」という二つの概念があります。
これらはトランザクションやオペコードの実行にかかるコストを計算する際に重要です。それぞれについて説明します。

### 静的ガス料金（Static Gas Fee）
静的ガス料金は、あらかじめ定められた固定のガス料金です。
この料金は、特定の操作やトランザクションに必ずかかる最低限のコストとして設定されています。
例えば、トランザクションを送信するための基本料金や、特定のオペコードを実行する際の固定料金などがこれに該当します。

静的ガス料金は、操作が実行される環境や実行時の状態に依存せず、あらかじめEVM（Ethereum Virtual Machine）の規則によって決定されています。
これにより、開発者やユーザーはトランザクションのコストをある程度予測しやすくなります。

### 動的ガス料金（Dynamic Gas Fee）
動的ガス料金は、トランザクションの実行状況やネットワークの状態によって変動するガス料金です。
この料金は、トランザクションの複雑さ、データのサイズ、またはネットワークの混雑状況などに基づいて計算されます。

例として、スマートコントラクトで複雑な計算を行う場合や、大量のデータを保存する場合に必要なガス量は、その操作のリソース使用量に比例して増加します。
また、イーサリアムネットワークが混雑している時には、トランザクションを優先的に処理させるためにより高いガス料金を設定する必要があるかもしれません。

### 例：`AUTHUSURP` のガス料金
`AUTHUSURP` オペコードにおける静的ガス料金の適用例として、`authorized`が空のアカウントを指す場合、静的ガス料金は`32,000`とされます。
これは、新しいコントラクトをデプロイする基本的なコストを反映しています。
一方で、`authorized`が空でないアカウントを指す場合の静的ガス料金は`7,000`と設定されています。
これは、既存のアカウントへの操作が新規デプロイメントよりもガスの消費が少ないためです。

静的ガス料金と動的ガス料金の違いを理解することは、イーサリアムのトランザクションコストを効率的に管理し、予測するために重要です。
:::

### nonceの無視
`AUTHUSURP` は、`authorized` アカウントの`nonce`をチェックしません。

### initcodeの実行
`initcode` は `authorized` のアドレスで実行されます。
もし `initcode` がバイトを返さない場合、その実行フレームはリバート（巻き戻し）され、`AUTHUSURP` はゼロを返します。

### コードのデプロイ
`initcode` の実行後、返されるコードがデプロイされる前に、もしアカウントのコードが空でない場合、`initcode` の実行フレームはリバートされ、`AUTHUSURP` はゼロを返します。
コードは `authorized` のアドレスにデプロイされます。

### 意義と利用シナリオ
`AUTHUSURP` は、**EIP3074**の「`authorized`」機能を使って、特定のアカウントに対して新たなコントラクトコードを安全にデプロイする手段を提供します。
これにより、特定の条件下でのみ、よりセキュアなコードの更新や変更が可能になります。
このオペコードは、イーサリアムのセキュリティと柔軟性を高めるためのさらなるステップと見ることができます。

# 補足

提案されている `AUTHUSURP` オペコードは、特定の挙動と制約を持っており、これがイーサリアムの他のコントラクトデプロイメントメソッドとは異なる動作をする理由になっています。

### Nonceのチェックが不要な理由
通常、イーサリアムのアカウント（特に外部所有アカウント、EOA）は、トランザクションごとに「`nonce`」と呼ばれるカウンターを持っています。
この`nonce`は、トランザクションが二重に実行されるのを防ぐために使われ、トランザクションが送信されるたびにインクリメントされます。
しかし、`AUTHUSURP` オペコードでは、この`nonce`をチェックしません。
これは、`AUTHUSURP` が既にトランザクションを送信したことがあるアカウント（つまり`nonce`が`0`ではないアカウント）とも動作する必要があるためです。
`AUTHUSURP` は主に認証済みのアドレスで動作し、そのアドレスの過去のトランザクション履歴は関係ないため、nonceの値は関係なく動作します。

### ゼロ長コントラクトのデプロイメント
`AUTHUSURP` を使用して初期化コード（`initcode`）がゼロ長のコントラクトをデプロイする場合、そのアドレスに何もデプロイされないため、そのアドレスを再び `AUTHUSURP` で使用することが可能です。
これは、他のデプロイメント手順（例えば `CREATE` オペコード）とは異なり、これらの命令ではデプロイメントが成功しなかった場合でも、アカウントの`nonce`はインクリメントされ、再利用を防ぐことができます。

### コードのチェックとデプロイメントのタイミング
`AUTHUSURP` の使用においては、`initcode`が同じアドレスに `AUTHUSURP` を使って何かをデプロイしようと試みる状況を捕捉するために、実際にコードをデプロイする直前にそのアカウントのコードをチェックする必要があります。
もし既にそのアドレスにコードが存在する場合、`AUTHUSURP` によるデプロイはキャンセルされ、`initcode`の実行フレームは`revert`されます。
これは、他のデプロイメント命令では通常必要ないチェックですが、`AUTHUSURP` ではnonceのインクリメントがないため、デプロイ前にアカウントの状態を確認することが重要です。

これらの特性により、`AUTHUSURP` は特定のケースに非常に有効なツールとなりますが、その挙動を正しく理解し適用することがセキュリティと効率の面で非常に重要です。

# 互換性

`AUTHUSURP` オペコードが **EIP3607** と組み合わさることにより、イーサリアムのアカウントに関連するセキュリティダイナミクスが大きく変わることになります。
ここで言及されている特定の機能は、既存の ECDSA 署名鍵の権限を無効化し、そのアカウントからのトランザクション送信能力を剥奪するものです。
これは、特定の条件下でアカウントの制御を完全に変更する新しい挙動です。
`CREATE2` オペコードとの類似性についても含めて説明します。

### EIP3607とは何か
**EIP3607** はイーサリアムの改善提案の一つで、スマートコントラクト（特にすでにデプロイされているもの）からのトランザクション送信を禁止する内容を含んでいます。
これにより、コントラクトが偽の EOA として機能することを防ぎます。
一般的には、コントラクトアカウントは他のコントラクトやユーザーに対してトランザクションを「**発信**」する能力がないため、この提案はそれをプロトコルレベルで強化するものです。

### AUTHUSURPの挙動
`AUTHUSURP` は、特定のアカウントに新しいコードをデプロイすることで、そのアカウントの制御を変更するオペコードです。
これは **EIP3074** に基づいており、認可された操作を行うことができます。
**EIP3607** と組み合わせることで、`AUTHUSURP` は元の ECDSA 署名鍵の権限を事実上無効にすることができ、その結果、署名鍵はアカウントからのトランザクションを発行する権限を失います。

### CREATE2 との類似性
`CREATE2` オペコードは、与えられた塩（`salt`）、`initcode`、そして他のパラメーターを基にコントラクトをデプロイする機能を提供します。
これにより、デプロイされるアドレスは事前に計算可能となり、必要に応じて同じアドレスに再デプロイすることが可能です。
`AUTHUSURP` との類似点は、アカウント（またはコントラクト）の挙動を柔軟に制御する能力にありますが、`AUTHUSURP` は更に元の認証情報の無効化という強力なセキュリティ機能を持っています。

:::note info
`AUTHUSURP` と **EIP3607** の組み合わせは、イーサリアム上のアカウントセキュリティに革命をもたらす可能性があり、特定の署名鍵を使った過去のアクセス方法を完全に変更することで新しいセキュリティパラダイムを提供します。
これにより、アカウントの安全性が強化され、新たなアプリケーションの可能性が開かれます。
:::

# セキュリティ

提案された `AUTHUSURP` オペコードによるアカウント制御の変更は、アカウントの制御が従来の秘密鍵から他の機構へ移行されることを意味します。
ただし、ECDSA署名を利用している既存のコントラクトは、この制御の変更が行われたことを自動的には認識できません。
これが特に問題となるのは、トランザクション外でECDSA署名を使用している場合です。

### ECDSA署名とトランザクション外の使用

イーサリアムの多くのスマートコントラクトは、ECDSA署名をトランザクション外で使用しています。
特に、トークンコントラクトの`permit`関数のように、ユーザーがトランザクションを送信することなく、トークンの承認を他者に委任できる機能です。
この場合、ユーザーは自身の秘密鍵で署名を行い、その署名をコントラクトに渡すことで、特定の操作を許可します。

### 問題の核心

`AUTHUSURP`によりアカウントが乗っ取られ（つまり、制御が秘密鍵から別の手段に移行された場合）、元の秘密鍵による署名は依然として有効とされ、コントラクトは変更されたアカウントの所有権状況を認識できません。
これは、アカウントが新しい管理下にあるにも関わらず、古い秘密鍵が依然としてある操作に対する権限を持っている可能性があることを意味します。

### 解決策：`ecrecover`の変更

`ecrecover`は、イーサリアムにおいて署名から署名者のアドレスを復元するために使われるプリコンパイルドコントラクトです。
このコントラクトを変更して、`AUTHUSURP`によってアカウントの制御が変更されたことを認識できるようにする提案があります。
つまり、`ecrecover`が署名を正しく検証した後、そのアカウントが現在有効な制御機構によって管理されているかどうかをチェックするロジックを追加するのです。

この変更により、アカウントが`AUTHUSURP`によって乗っ取られた後も、旧来の秘密鍵による署名が不正に利用されるリスクを減らすことができます。
また、スマートコントラクトのセキュリティを高めることができ、より信頼性の高いコントラクト環境を実現します。

# 引用

Dan Finlay (@danfinlay), Sam Wilson (@SamWilsn), "EIP-5003: Insert Code into EOAs with AUTHUSURP [DRAFT]," Ethereum Improvement Proposals, no. 5003, March 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5003.

# 最後に

今回は「新しいオペコードである`AUTHUSURP`を導入し、EOAの秘密鍵の作り替え仕組みを提案している**EIP5003**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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