[EIP3607] Etherumアドレスの衝突を防ぐ提案を理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、コントラクトアカウントとEOAアカウントでアドレスの衝突が起きる可能性があり、アドレスを`160`ビットから`256`ビットに変更する提案をしている**EIP3607**についてまとめていきます！

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

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

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

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

# 概要

Ethereumのアドレスは`160`ビットの長さしかなく、これはコントラクトのアカウント（スマートコントラクトのアドレス）とEOA（外部所有）アカウント（ユーザーが直接コントロールするアカウント、略してEOA）の間で衝突（同じアドレスを持つ可能性）が発生する可能性があることを意味します。
計算によると、約2の80乗の計算操作を行うことで、このような衝突を作り出すことが可能であり、これは現在の大規模な予算（およそ100億USD）があれば実現可能です。

最悪の攻撃シナリオでは、安全に見えるスマートコントラクト（例えば、トークンを包むラッパーや自動市場作成（AMM）タイプのコントラクトなど）がデプロイされ、ユーザーがそのコントラクトに資金を預けるよう誘導されます。
その後、攻撃者は同じアドレスのEOAキーを使って、これらの資金を不正に引き出すことができます。

この問題に対する修正案は、コードが既にデプロイされているアドレスをEOAアドレスとして使用することを決して許可しないというものです。
これにより、一度スマートコントラクトがそのアドレスにデプロイされると、そのアドレスをEOAとして使うことができなくなり、上述したような攻撃を防ぐことができます。

:::note info
EOAアカウントとコントラクトアカウントの違いについては以下の記事が参考になります。
:::

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58/-qoixMc413uT4FFM61uhXYUiL05Hw-wahq9hV_JtjJs

# 動機

Ethereumのアドレス衝突に関する問題と、それに対する提案された解決策（EIP、つまりEthereum Improvement Proposal）について説明しています。

## アドレス衝突の生成
Ethereumのアドレスは`160`ビットで、理論上は2の80乗のEOA（外部所有アカウント）と2の80乗のスマートコントラクトを作成することで、EOAとコントラクトアカウント間の少なくとも1つの衝突（同一アドレス）を見つけることが期待されます。
ただし、2の80乗のアドレスを保存するには`24`ヨタバイト（非常に大きな数値）のメモリが必要で、これは実用的な障壁です。
しかし、大量のストレージを必要としない衝突検索を行うアルゴリズムが存在します。
このようなアドレス衝突を見つけるためのハードウェアと電力に約100億USドルを投資すれば、約1年以内に衝突を見つけることが可能と推定されています。

## 背景
Ethereumはアドレスを256ビットに移行することを検討中であり、これにより衝突抵抗が2の128乗の複雑さに増加し、現在では予見可能な将来に解決不可能とされています。
しかし、`160`ビットアドレスでは、上述の方法で実際に衝突問題を解決できます。

## 実際の攻撃の可能性
アドレス衝突を利用した攻撃は非現実的であり、実際にはまれです。
これは、ユーザーがコントラクトをデプロイする前にアドレスへ資金を送ることを含みますが、ユーザーはコントラクトが安全にデプロイされて十分な確認が得られるまで資金を送らないことで攻撃を回避できます。
しかし、Ethereumの基本文書（Yellow Paper）では、すでにデプロイされているコントラクトアカウントからトランザクションが送信される場合のクライアントの扱い方が明示的に記述されていません。

## EIPの目的
このEIPは、すでにデプロイされているコントラクトのアカウントからのトランザクションを常に禁止するように振る舞いを明確にすることを目的としています。
これにより、アドレス衝突による現実的または深刻な攻撃のほとんどを防ぐことができます。

:::note info
この文書はEthereumのアドレス衝突問題と、それを解決するための提案された手法について説明しています。
提案された解決策は、コントラクトが既に存在するアドレスからのトランザクションを禁止することにより、潜在的な攻撃を防ぐことを目指しています。
:::

# 仕様

この仕様は、Ethereumネットワークでの特定のトランザクションの扱い方を定めています。
具体的には、以下の基準に基づいてトランザクションを無効として扱うと述べています。

- **tx.senderのCODEHASHがEMPTYCODEHASHではない場合**、そのトランザクションは無効とみなされるべきです。
    - ここで「`tx.sender`」はトランザクションを発行するアカウントを指し、「`CODEHASH`」はそのアカウントに関連付けられたコード（スマートコントラクト）のハッシュ値です。
    - もしアカウントに関連付けられたコードがなければ、`CODEHASH`は「`EMPTYCODEHASH`」と等しくなります。

- **EMPTYCODEHASH** は特定の値（`0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`）に設定されており、これはEthereumネットワーク上でコードがない、つまり普通のユーザーアカウントを示すためのハッシュ値です。

- もし`tx.sender`の`CODEHASH`がこの`EMPTYCODEHASH`と異なる場合（つまり、送信者アカウントに何らかのコードが関連付けられている場合）、そのトランザクションは無効とみなされ、クライアント（Ethereumネットワークに接続するソフトウェア）によって拒否されるべきです。
    - そして、そのようなトランザクションを含むブロックは無効とみなされるべきです。

この規定は、スマートコントラクト（コードが関連付けられたアカウント）から発行されたトランザクションを制限し、そのようなアカウントが普通のユーザーアカウント（EOA）のように振る舞うことを防ぐことを目的としています。
これにより、アドレス衝突を利用した潜在的な攻撃を防ぐことができます。

# 補足

Ethereum Improvement Proposal（EIP）に関する説明で、スマートコントラクトアカウントの挙動がそのコントラクト内のコードによって制約されるべきだという期待に基づいています。
つまり、コントラクトアカウント内の資金が突然、ある秘密鍵によって使われるべきではないということです。
過去には`160`ビットのアドレス長が衝突耐性を提供するのに十分であると暗黙的に仮定されていましたが、このEIPはそのようなケースが実際には起こり得ると認識し、プロトコルの挙動を明確化することを目的としています。

## 主なポイント

### プロトコル挙動の明確化
このEIPは、以前は定義されていなかったケースにおけるプロトコルの挙動を明確化するものであり、合意形成ルールの明示的なアップグレードというよりは、既存の期待を形式化するものです。

### 攻撃ベクトルの限定
このEIPは最も深刻な攻撃ベクトル、つまりスマートコントラクトアカウントとEOA間のアドレス衝突を利用した攻撃を排除しますが、全ての可能な攻撃ベクトルを排除するわけではありません。

## 追加の攻撃ベクトル

### 事前送金の誘導
攻撃者はユーザーに対し、コントラクトがデプロイされる前に資金を送るよう説得するかもしれません。
状態チャネルなど、一部のアプリケーションではこの挙動が必要です。

### チェーン再編成
コントラクトがデプロイされた後にチェーンの再編成が発生すると、再編成がコントラクトデプロイメントトランザクションを削除した場合、秘密鍵を使用して資金にアクセスできるようになります。

### 自己破壊コントラクト
コントラクトが自己破壊することで、コントラクト内のERC20トークン（または他のトークン）が`burn`されることを意図している場合があります。
しかし、そのアドレスの鍵を持っていれば、これらのトークンにアクセスできるようになります。

これらのシナリオは攻撃者が利用するにはより困難であり、収益性が低いため、経済的に実行可能な攻撃である可能性は低いです。

# 互換性

提案されたEIPがEthereumの過去の互換性にどのように影響するかについて説明しています。

### 攻撃の現実性
このような攻撃がEthereumメインネットで既に発生している可能性は低いとされています。
もし発生していたら、そのことは広く知られているはずです。
コントラクトアカウントとEOAを同時に使うことを「**機能**」として使用することは考えにくいです。
そのようなことを実現したい場合は、膨大な資金をかけてハードウェアを構築しハッシュ衝突を見つけ出すよりも、コントラクトにいくつかのメソッドを追加することで簡単に実現できます。

## プライベートネットワーク
プライベートネットワークでは、ジェネシス（起源）時にEOAとしても機能するコントラクトをデプロイしている場合があり、このアップグレードがワークフローに影響を与えないか確認する必要があります。
つまり、プライベートネットワークで特定の使用ケースがある場合は、この変更が問題を引き起こさないか検討する必要があります。

## クライアントの柔軟性
クライアント（Ethereumネットワークに接続するソフトウェア）は、`eth_call` や `eth_estimateGas` などのRPC呼び出しに対してこのルールを無効にすることを選択するかもしれません。
これは、一部のマルチシグ（複数署名）コントラクトが、マルチシグコントラクト自体から発信されたかのようにトランザクションを作成するためにこれらの呼び出しを使用するためです。
つまり、特定のケースでは、このルールの適用を柔軟にすることで、既存の機能やワークフローを維持することができます。

:::note info
このEIPはEthereumメインネットの過去の互換性に大きな影響を与えることはなく、攻撃が実際に発生した証拠はないとされています。
しかし、プライベートネットワークや特定のクライアント実装では、この変更が既存のワークフローに影響を与えないように注意が必要です。
:::

# テスト

このテストケースは、ある特定の条件下でEthereumトランザクションがどのように扱われるべきかを示しています。

### ジェネシス割当
- アドレス：`0x71562b71999873DB5b286dF957af199Ec94617F7`
- 残高：1 ether（`1,000,000,000,000,000,000 wei`）
- ノンス：`0`
- コード：`0xB0B0FACE`

この設定は、ジェネシス（Ethereumブロックチェーンの最初の状態）で特定のアドレスに1 etherの残高が割り当てられ、そのアドレスには「`0xB0B0FACE`」というコードが関連付けられていることを意味します。
これは、そのアドレスがスマートコントラクトを表していることを示しています。

## トランザクションの拒否
このアドレスの秘密鍵（`0x715656...`に対応する秘密鍵は`b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291`）を使って送信される全てのトランザクションは拒否されるべきです。
理由は、このアドレスには既にコードがデプロイされており、それによってこのアドレスはスマートコントラクトアカウントとして機能しているため、EOA（外部所有アカウント）としてのトランザクションを行うことはできません。

## ブロックに含まれない
これらのトランザクションはブロックチェーンに含められるべきではなく、ネットワークのクライアント（ソフトウェア）によって拒否される必要があります。
これは、スマートコントラクトアカウントからのトランザクションは、そのアカウントのコードに基づいて自動的に実行されるべきであり、秘密鍵を持つ個人が直接送金するために使用されるべきではないためです。

このテストケースは、提案されたEIPが正しく実装されているかを検証するためのものです。
それにより、スマートコントラクトアカウントとEOAアカウントの挙動が適切に区別され、システムのセキュリティが強化されます。

# 実装

トランザクションが有効かどうかを判断する過程で、送信者がEOA（外部所有アカウント）であることを確認するためのステップを追加することを提案しています。手順は以下の通りです：

- **送信者のノンスが正しいことを確認した後**、状態遷移のチェックに新しいチェックを追加します。
    - ノンスとは、アカウントがこれまでに送信したトランザクションの数を表すカウンターです。

- **送信者がEOAであることを確認**
    - トランザクションの署名から回復したアドレス（送信者）のコードハッシュ（`ch`）を取得します。
    - コードハッシュは、そのアドレスに関連付けられたスマートコントラクトのコードのハッシュ値です。

- **コードハッシュのチェック**
    - 取得したコードハッシュ`ch`が`EmptyCodeHash`（コードがないことを示す特定のハッシュ値）と等しくない場合、その送信者はEOAではないと判断され、`ErrSenderNoEOA`というエラーが返されます。
    - これは、送信者のアカウントにスマートコントラクトのコードが存在することを意味し、そのアドレスからのトランザクションは無効とみなされるべきです。

このチェックを追加することで、スマートコントラクトアカウントからの直接的なトランザクション送信を防ぎ、アドレス衝突による潜在的なセキュリティリスクを軽減します。
この実装の差分（diff）は、go-ethereum（EthereumのGo言語実装）で**EIP3607**を実装するためのものとして提供されています。
これにより、開発者は具体的なコードの変更点を確認し、Ethereumクライアントのセキュリティを向上させることができます。

https://eips.ethereum.org/assets/eip-3607/geth.diff

# セキュリティ

提案されているEthereum Improvement Proposal（EIP）がセキュリティに関する厳格なアップグレードであることを説明しています。

## セキュリティアップグレード
このEIPにより、以前は有効だった一部のトランザクションが無効になります。
これらのトランザクションには正当な使用目的がないため、セキュリティ上のデメリットは存在しないとされています。
つまり、このEIPはEthereumネットワークのセキュリティを強化することを目的としており、これによって無効となるトランザクションは本来許可されるべきではないものです。

## ソフトフォークとしての実装
このEIPはソフトフォークとして実装することが可能です。
ソフトフォークとは、ブロックチェーンのプロトコルの更新が下位互換性を保持しながら行われることを意味します。
新しい有効性ルールは、以前のルールの厳格なスーパーセット（より厳格な条件を含むセット）であるため、更新後も古いルールに従うノードは新しいルールを満たすブロックやトランザクションを引き続き認識することができます。
このアプローチにより、ネットワークの分断を避けながらセキュリティ強化が可能となります。

:::note info
このEIPはEthereumのセキュリティを向上させるためのものであり、以前に許可されていた特定の種類のトランザクションを無効にすることにより、ネットワークの安全性を高めます。
また、この変更はソフトフォークとして実装されるため、ネットワークの安定性や互換性に悪影響を与えることなく適用することができます。
:::

# 引用

Dankrad Feist (@dankrad), Dmitry Khovratovich (@khovratovich), Marius van der Wijden (@MariusVanDerWijden), "EIP-3607: Reject transactions from senders with deployed code," Ethereum Improvement Proposals, no. 3607, June 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3607.


# 最後に

今回は「コントラクトアカウントとEOAアカウントでアドレスの衝突が起きる可能性があり、アドレスを`160`ビットから`256`ビットに変更する提案をしている**EIP3607**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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