[EIP1052] 新オペコードであるEXTCODEHASHの導入の提案について理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、コントラクトの検証のために、コントラクトのkeccak256ハッシュを返す新しいオペコード`EXTCODEHASH`を導入する提案している**EIP1052**についてまとめていきます！

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

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

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

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

# 概要

このEIP（Ethereum Improvement Proposal、イーサリアム改善提案）は、新しいオペコードに関するもので、コントラクトのコードのkeccak256ハッシュを返す機能を定めています。
keccak256は暗号学的ハッシュ関数の一種で、データの一意的な値を生成するのに使われます。
この新しいオペコードを使用することで、イーサリアム上のコントラクトのコードのハッシュ値を取得できるようになります。
これは、コントラクトのコードが変更されていないことを確認するのに有用なツールとなり得ます。

# 動機

コントラクト間での相互作用では、特定のコントラクトのコードが特定の条件を満たしているかどうかを確認する必要がある場面がしばしばあります。
これは、特にセキュリティや互換性を保証するために重要です。
例えば、あるDAppが、特定の機能を提供することが証明されたコントラクトのみと連携したい場合、そのDAppのコントラクトはパートナーコントラクトのバイトコードを検証する必要があります。

このプロセスを実現する一つの方法は`EXTCODECOPY`オペコードを使用することです。
このオペコードは、指定されたアドレスにデプロイされたコントラクトのバイトコードをコピーし、検証プロセスで使用できるようにします。
しかし、この方法はバイトコードの全文をコピーするため、データ量が多くなりがちで、特に大規模なコントラクトの場合にはガスコスト（トランザクションを実行するために必要な手数料）が高くつきます。

そこで、コントラクトのバイトコード全体をコピーして分析する代わりに、そのハッシュ値を直接取得することで、効率的に検証プロセスを行うことができる`EXTCODEHASH`オペコードの導入が提案されています。
**keccak256**ハッシュは、バイトコードの独特な値を出力し、バイトコードが`1`ビットでも異なれば、生成されるハッシュ値も大きく異なります。
このため、ハッシュ値を比較するだけで、コントラクトのコードが期待通りであるかを高速かつ低コストで確認できるのです。

# 仕様

`EXTCODEHASH`オペコードは、特定のアドレスに存在するアカウントのコードを分析する時に役立つ新機能です。
このオペコードを使用すると、イーサリアムのスマートコントラクトは、他のコントラクトの実際のバイトコードを読み込むことなく、そのコードのユニークな識別子である**keccak256**ハッシュ値を取得できます。
このプロセスは、スタックからアドレスを表す`256`ビットのデータを取り、最初の`96`ビット（アドレスの上位ビット）をゼロに設定します。
これにより、有効なイーサリアムアドレスの形式になり、残りの`160`ビットがそのアドレスを指定します。

このオペコードは、アドレスに関連付けられたアカウントが実際に存在し、コードを含んでいる場合に、そのコードのハッシュを返します。
しかし、アカウントが存在しないか、**EIP161**に基づいて「**空**」とみなされる場合（例えばイーサリアムを保持していないアドレスなど）、スタックには単に`0`がプッシュされます。
また、アカウントが存在してもコードを持たない場合（例えば通常のイーサリアムウォレットアドレスなど）、空のデータのハッシュ値がプッシュされます。
この空のデータのハッシュ値は、特定の固定値（`c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`）として予め定義されています。

`EXTCODEHASH`オペコードの使用には、ガスコストとして`400`が必要です。
ガスコストは、イーサリアムネットワーク上でトランザクションやコントラクトの実行を行う時に消費される手数料の単位です。
このコストは、ネットワークのリソースを利用するための料金として設定されており、オペコードの実行に必要な計算量とストレージの使用量に基づいています。
`EXTCODEHASH`のコストが`400`であることは、この操作が比較的リソースを少なく消費することを意味します。
このため、開発者はこのオペコードを効率的に使用し、不必要なガスの消費を避けることが重要です。

# 補足

`EXTCODEHASH`オペコードの導入は、スマートコントラクトが他のコントラクトの存在やその特性をより効率的に検証することを可能にします。
このオペコードは、特に他のコントラクトのバイトコードのハッシュ値を検証する必要がある場合に有用ですが、バイトコード自体は不要な場合に役立ちます。
これにより、無駄なガスの消費を減らすことができます。

`EXTCODEHASH`のガスコストが`BALANCE`オペコードと同じである理由は、両方のオペコードがイーサリアムのブロックチェーン上の特定のアカウントに関する情報を取得するために、同様のアカウントルックアッププロセスを必要とするためです。
このプロセスには、ステートトライを検索してアカウントの詳細を取得する作業が含まれます。

:::note info
### ステートトライ
イーサリアムでは、全てのアカウントの情報（残高、ストレージ、コントラクトのコードなど）は「**ステートトライ（state trie）**」と呼ばれるデータ構造に保存されています。
ステートトライは、キーと値のペアを効率的に格納および検索するための木構造（トライ木）です。
この木構造を使って、イーサリアムはネットワーク上のあらゆるアカウントの状態を追跡します。

プロセスの一環として、イーサリアムのスマートコントラクトやトランザクションは、特定のアカウントに関する情報を取得する必要がある場合があります。
この情報を取得するために、イーサリアムはステートトライを検索します。
具体的には、アカウントのアドレスをキーとして使用し、そのアドレスに関連付けられた値（アカウントの詳細）をトライから取得します。

たとえば、あるコントラクトが別のコントラクトの残高を確認したい場合、イーサリアムはそのコントラクトのアドレスを使ってステートトライを検索し、該当するアカウントの残高情報を取得します。
同様に、`EXTCODEHASH`オペコードを使用してアカウントのコードのハッシュを取得する場合も、そのアカウントのアドレスを使ってステートトライを検索し、コードのハッシュを取得します。

このプロセスは非常に効率的で、イーサリアムネットワークが膨大な数のアカウントとトランザクションを迅速に処理できる理由の一つです。
ステートトライの構造は、新しいアカウントの追加や既存のアカウントの更新を容易にし、イーサリアムブロックチェーンの全体的なパフォーマンスとセキュリティを向上させています。
:::

引数に関しては、`EXTCODEHASH`（および`BALANCE`、`EXTCODESIZE`、`EXTCODECOPY`）では、最初の`12`バイトは無視され、最後の`20`バイトのみがアカウントアドレスとして解釈されます。
この`20`バイトのアドレスは、イーサリアムアドレスの標準的な長さに相当します。

さらに、`EXTCODEHASH`はコードを持たないアカウントとまったく存在しないアカウントを区別することができます。
これは、イーサリアムのステートトライにおけるアカウントの表現方法と一致しており、スマートコントラクトが存在チェックを行う時の精度を高めます。
たとえば、スマートコントラクトは`EXTCODEHASH`を使用して、特定のアカウントが有効なコントラクトであるか、単にイーサリアムを保持するウォレットアドレスであるか、または全く存在しないかを確認できます。
これにより、コントラクト間の相互作用がより安全かつ効率的になります。

# 互換性

互換性の問題は特にありません。

# テスト

- コードを持たないアカウントの`EXTCODEHASH`は`c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`です。
    - これは空データの**keccak256**ハッシュに相当します。
- 存在しないアカウントの`EXTCODEHASH`は`0`です。
- プリコンパイルされたコントラクトの`EXTCODEHASH`は`c5d246...`または`0`のどちらかです。
- アカウントAの`EXTCODEHASH`がXであれば、`A + 2**160`の`EXTCODEHASH`もXです。
- 現在のトランザクションで自己破壊したアカウントの`EXTCODEHASH`。
- 自己破壊（**selfdestructed**）した後にその自己破壊（**selfdestructed**）が取り消されたアカウントの`EXTCODEHASH`。
- 現在のトランザクションで作成されたアカウントの`EXTCODEHASH`。
- 新しく作成された後にその作成が取り消されたアカウントの`EXTCODEHASH`。
- 最初は存在せず、後に空になるアカウントの`EXTCODEHASH`。
- 状態クリアルールによってクリアされる予定の空のアカウントの`EXTCODEHASH`。

上記のテストは、イーサリアムの`EXTCODEHASH`オペコードがどのように動作するか、そして特定の状況下でのアカウントの`EXTCODEHASH`値がどのように決定されるかを示しています。
特に、コードを持たないアカウントと存在しないアカウントを区別する能力は、スマートコントラクトがネットワーク上の他のコントラクトとの相互作用をより正確に管理するのに役立ちます。
また、アドレスの変更が`EXTCODEHASH`に影響を与えないこと、および特定のトランザクション内でのアカウントの変更が`EXTCODEHASH`にどのように反映されるか（または反映されないか）も重要な点です。

# 引用

Nick Johnson <arachnid@notdot.net>, Paweł Bylica <pawel@ethereum.org>, "EIP-1052: EXTCODEHASH opcode," Ethereum Improvement Proposals, no. 1052, May 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1052.

# 最後に

今回は「コントラクトの検証のために、コントラクトのkeccak256ハッシュを返す新しいオペコード`EXTCODEHASH`を導入する提案している**EIP1052**」についてまとめてきました！
いかがだったでしょうか？

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