[EIP155] Ethereumネットワークでリプレイ攻撃を防ぐ仕組みを理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、Ethereumネットワークでのリプレイ攻撃を防ぐ仕組みを提案している規格である**EIP155**についてまとめていきます！

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

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

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

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

# 概要

**EIP155**は、イーサリアムのトランザクション署名の方法に関する改善提案です。
これは、イーサリアムネットワークでの「**リプレイ攻撃**」を防ぐために設計されました。リプレイ攻撃とは、あるネットワークで行われたトランザクションが、別のネットワーク上で無許可で再実行されることを指します。
**EIP155**はこの問題を解決するために、トランザクション署名のプロセスに「`CHAIN_ID`」という新しい要素を導入しました。

:::note info
リエントランシー攻撃については以下の記事を参考にしてください。
:::

https://chaldene.net/bug-bounty

# 仕様

## 主な変更点

### ブロック番号と`CHAIN_ID`の使用
特定のブロック番号（`FORK_BLKNUM`）を超えると、トランザクション署名に`CHAIN_ID`が含まれるようになります。
これにより、トランザクションが特定のイーサリアムネットワークに固有であることが保証されます。

### 署名プロセスの変更
- **以前**
    - トランザクションの署名には、6つの要素（`nonce`, `gasprice`, `startgas`, `to`, `value`, `data`）のみが使われていました。
- **新しいプロセス**
    - `CHAIN_ID`と、2つの`0`を追加して、合計9つの要素を署名に使用します。

:::note info
**2つの`0`の追加の意味**

- **バージョンの互換性**
    - トランザクションのフォーマットに`CHAIN_ID`を追加することにより、**EIP155**が有効化される前と後のトランザクションを区別する必要がありました。
    - 2つの`0`は、署名データの形式を変更することで、新しいフォーマット（**EIP155**が適用される）と古いフォーマット（**EIP155**が適用されない）のトランザクションを区別するために使われます。
- **将来の拡張性**
    - 2つの`0`は、将来のプロトコルアップデートで使用するための「**プレースホルダー（将来的に何かを入れるための予約された空間）**」として機能します。
    - これにより、将来的に新しい要素を追加する必要が生じた場合にも、既存のトランザクションフォーマットを容易に拡張することが可能になります。
- **セキュリティの強化**
    - この変更により、イーサリアムネットワーク上でのトランザクションの一意性が強化され、リプレイ攻撃を防ぐことができます。
    - `CHAIN_ID`を含めることで、署名されたトランザクションが特定のネットワークに固有であることが明確になり、他のネットワークでの無許可の再利用を防止します。


2つの`0`の追加は、トランザクションの署名プロセスにおけるフォーマットの変更を示し、**EIP155**によるリプレイ攻撃の防止策の一部として機能しています。
これにより、イーサリアムネットワークのセキュリティが向上し、将来のプロトコルアップデートへの柔軟な対応が可能になります。
:::

### 署名の`v`値の設定
- **以前**
    - `v`は`{0,1} + 27`でした。
- **新しいルール**
    - `v`は`{0,1} + CHAIN_ID * 2 + 35`になります。
    - 6つの要素のみでハッシュする場合は、従来通りの`v`値を使用します。

### 署名の回復時の変更
`CHAIN_ID`に基づく新しい`v`値（`CHAIN_ID * 2 + 35`または`CHAIN_ID * 2 + 36`）が使われている場合、トランザクションのハッシュを計算する時に9つの要素が必要です。
以前の署名スキーム（`v = 27`や`v = 28`）もそのまま有効です。

この改良により、イーサリアムのトランザクションが特定のネットワークに固有であることが確認できるようになり、異なるネットワーク間でのリプレイ攻撃を防ぐことができるようになりました。
これにより、イーサリアムのセキュリティがさらに強化されています。

# 例

イーサリアムのトランザクションがどのように署名されるかを具体的に示しています。
ここでの重要なポイントは、トランザクションのデータがどのように処理され、秘密鍵でどのように署名されるかを理解することです。

## トランザクションのパラメータの説明

- **nonce（9）**
    - トランザクションの連番。
- **gasprice（ 20 * 10^9 ）**
    - ガスの単価で、この例では`20 Gwei`。
- **startgas（21000）**
    - このトランザクションを実行するために必要なガスの量。
- **to（`0x3535353535353535353535353535353535353535`）**
    - Etherが送られるアドレス。
- **value（10^18 wei）**
    - 送られるEtherの量で、この場合は`1 Ether`。
- **data**
    - トランザクションに追加データは含まれていません。

## 署名プロセス

1. **署名データの作成**
   - これらのパラメータはRLPエンコーディングされて、特定の文字列に変換されます。
2. **署名ハッシュの計算**
   - 上記のエンコーディングされたデータから、一意のハッシュ値が生成されます。
3. **秘密鍵による署名**
   - 指定された秘密鍵を用いて、上記のハッシュ値に署名されます。
   - 署名には3つの値`(v, r, s)`が含まれます。

## 注目ポイント

- **`v`の値の変化**
   - `v`は通常`27`または`28`ですが、**EIP155**の導入により`CHAIN_ID`が考慮されるようになり、この例では`37`が使用されています。
- **署名されたトランザクションの形式**
   - 署名が完了すると、トランザクションはネットワーク上で共有するための特定の形式に変換されます。

この例は、**EIP155**によってトランザクションの署名プロセスがどのように変更されたかを示しており、特定のネットワークに固有のトランザクションを作成するための重要なステップです。
これにより、トランザクションのセキュリティが強化され、リプレイ攻撃などの問題を防ぐことができます。

# 補足

**EIP155**は、イーサリアムとその他のイーサリアムベースのブロックチェーン（例えばイーサリアムクラシックやMordenテストネットなど）間でトランザクションが重複しないようにするための改善案です。
これは、トランザクションが異なるネットワーク間で無断で再利用されるリプレイ攻撃を防ぐために重要です。

## EIP-155の要点

### ネットワークの分離
   - **EIP155**は、イーサリアム（ETH）上で行われるトランザクションがイーサリアムクラシック（ETC）やMordenテストネット上で実行されないようにする方法を提供します。
   - これにより、リプレイ攻撃を防止できます。

### `CHAIN_ID`の使用
   - この改善案では、各ネットワークが異なる`CHAIN_ID`を使うことを推奨しています。
   - ETCは異なる`CHAIN_ID`を採用すべきで、将来のテストネットやアルトイーサリアムも同様に独自の`CHAIN_ID`を設定することが奨励されています。

:::note info
**EIP155**は、イーサリアムと他の類似のネットワークを別々に運用するためのルールを設定しています。
これにより、一つのネットワークで行われたトランザクションが別のネットワークで勝手に使われることを防ぎ、各ネットワークの安全性と独立性を保ちます。
それぞれのネットワークが独自の`CHAIN_ID`を持つことで、トランザクションが特定のネットワークに属していることを確認しやすくなります。
:::

# チェインID一覧

もちろんです。以下は、イーサリアムおよびイーサリアムベースのブロックチェーンネットワークの`CHAIN_ID`（チェーンID）の一覧を表形式でわかりやすく説明したものです。

## `CHAIN_ID`の一覧表:

| `CHAIN_ID` | ネットワーク |　説明 | 
|------------|-----------------------| ----- |
| 1          | **イーサリアムメインネット** | イーサリアムブロックチェーンの主要な公開ネットワーク。 |
| 2          | **Morden（使用中止）とExpanseメインネット** | Mordenは以前使われていたテストネットで、現在は使われていません。Expanseは別のブロックチェーンプロジェクト。 |
| 3          | **Ropsten** | イーサリアムの主要なテストネットの一つ。 |
| 4          | **Rinkeby** | 別のイーサリアムテストネットで、DApp開発者に人気。 |
| 5          | **Goerli** | イーサリアムのもう一つのテストネットで、多くの開発者に使用されている。 |
| 42         | **Kovan** | イーサリアムテストネットの一つで、特に安定性が高い。 |
| 1337       | **Gethプライベートチェーン（デフォルト）**: | 個人や組織がプライベートに設定するイーサリアムベースのネットワーク。Gethクライアントを使用して構築される。 |

## 追加情報
- 他の`CHAIN_ID`については、[chainid.network](https://chainid.network)で詳細を確認できます。
- イーサリアム関連のリストへの貢献に関しては、[ethereum-lists/chains](https://github.com/ethereum-lists/chains)で行われています。

これらの`CHAIN_ID`は、それぞれのイーサリアムベースのネットワークが他のネットワークと区別され、混同されないようにするために重要です。
それぞれのネットワークが独自のIDを持つことで、セキュリティと効率が向上します。

# 引用

Vitalik Buterin (@vbuterin), "EIP-155: Simple replay attack protection," Ethereum Improvement Proposals, no. 155, October 2016. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-155.

# 最後に

今回は「Ethereumネットワークでのリプレイ攻撃を防ぐ仕組みを提案している規格である**EIP155**」についてまとめてきました！
いかがだったでしょうか？

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