# [EIP2327] バイトコードの後続データを実行対象から分けるBEGINDATA命令

> コントラクトのバイトコードには、実行する命令だけでなく、定数、コンパイラのメタデータ、初期化処理で扱うランタイムコードを直接入れられます。従来のEVMは後続バイトをデータとして区別しないため、解析器は末尾まで命令列として扱います。

- URL: https://cardene.dev/articles/b1fd952ab9b6a98c8166
- 公開日: 2026-07-26
- 更新日: 2026-07-26
- トピック: Blockchain
- タグ: ethereum, evm, solidity

## はじめに

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

https://amzn.asia/d/gxvJ0Pw

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください！

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

今回は「**EIP2327**」についてまとめていきます。

EIP2327は、コントラクトのバイトコード末尾へ置いたデータを、実行する命令列から区切る`BEGINDATA`命令の提案です。
後続バイトは読み出せますが、実行もジャンプもできません。

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

## 概要

コントラクトのバイトコードには、実行する命令だけでなく、定数、コンパイラのメタデータ、初期化処理で扱うランタイムコードを直接入れられます。
従来のEVMは後続バイトをデータとして区別しないため、解析器は末尾まで命令列として扱います。

EIP2327は、バイト値`0xb6`へ`BEGINDATA`を割り当てます。
最初の`BEGINDATA`より後ろをデータ領域とし、実行と有効な`JUMPDEST`の探索から外します。

![BEGINDATAで実行コードとデータ領域を分ける](/images/qiita-c7a9f391-54ba-405f-a130-089cebb66d57.webp)

境界で変わるのは、データの保存先ではなく、EVMが後続バイトをどう解釈するかです。
データ領域はコードの一部として残り、`CODECOPY`と`EXTCODECOPY`で読み出せます。

## 動機

データ領域に`0x5b`が含まれていても、開発者がその位置をジャンプ先として使うつもりとは限りません。
しかし境界がなければ、逆アセンブラ、チェーンエクスプローラー、静的解析器は、その値を命令列の一部として最後まで読みます。

有効な`JUMPDEST`を求める処理では、実行されないデータまで解析対象になります。
そのため、表示上は意味のない命令列が並び、制御フロー検証にも不要なバイト列を含めます。

![データ領域を含める解析と境界で止める解析](/images/qiita-b859164c-a147-49b8-82e7-b7549b009616.webp)

最初の`BEGINDATA`で解析を止めると、データ領域を制御フローの候補へ混ぜません。
提案は、他チェーンのトランザクションをオンチェーンで検証する時に、不要なジャンプ先解析を減らす用途も挙げています。

## 仕様

EIP2327は、最初に現れた`BEGINDATA`だけを実行コードとデータの境界にします。
境界位置と、その後ろのすべての位置は、有効なジャンプ先になりません。

![最初のBEGINDATAでJUMPDESTの探索を止める](/images/qiita-6168fb52-eed1-43a5-b516-ad14f548fa54.webp)

### `BEGINDATA`

```js
BEGINDATA // 0xb6
```

`BEGINDATA`は、実行可能な命令列の終端を示す命令です。
有効な`JUMPDEST`を計算する処理は、最初の`BEGINDATA`に到達した位置で停止します。

1. **バイトコードを先頭から読む**

    解析器は、`BEGINDATA`に達するまで命令を読み、有効な`JUMPDEST`を記録します。

2. **最初の境界で探索を止める**

    `BEGINDATA`と同じ位置、または後ろの位置は、有効な`JUMPDEST`へ追加しません。

3. **実行時は呼び出しフレームを止める**

    実行が`BEGINDATA`へ到達すると、現在の呼び出しフレームは`STOP`と同じ意味で終了します。

- **実行条件**

- `BEGINDATA`へジャンプすると、`BAD_JUMP_DESTINATION`エラーになります。
- `BEGINDATA`のガスコストは`0`です。

![実行がBEGINDATAへ到達した時の停止位置](/images/qiita-9dc8e88d-ed8a-4d28-a3b8-d2e1e846202d.webp)

バイトコード中に`0xb6`が複数あっても、解析を止めるのは最初の位置だけです。
後続バイトは命令として解釈しないため、2個目以降の`0xb6`へ特別な意味はありません。

### データ領域に残る性質

`BEGINDATA`は後続データを消去せず、実行しない領域として区切ります。
コピー命令とコードサイズの扱いは変えません。

![読み出せるが実行できないデータ領域](/images/qiita-65f58579-f834-4bca-94ce-7f063f8e1f5d.webp)

- `CODECOPY`と`EXTCODECOPY`は、データ領域を含む後続バイトを読み出せます。
- `CODESIZE`と`EXTCODESIZE`は、データ領域を含むコード全体のサイズを返します。
- データ領域にある`0x5b`は、有効な`JUMPDEST`になりません。

## 補足

`BEGINDATA`は、サブルーチンと静的ジャンプを扱うEIP615で、ジャンプテーブルの位置を見分ける案として出ていました。
EIP2327はこの命令を単独で定義し、コードとデータを分ける規則へ絞っています。

![BEGINDATAを単独のコードとデータの境界として扱う](/images/qiita-ad22b003-68de-44e9-ba15-c54789f7ce6b.webp)

EIP2327のステータスは`Stagnant`です。
Ethereumへ採用されていないため、現行EVMの命令やSolidityの出力として`BEGINDATA`を使える前提にはしません。

## テストケース

提案は、解析段階と実行段階を別々に確認します。

![ジャンプ先の拒否と到達時の停止を分けて検証する](/images/qiita-4dcf63a1-4b17-4f83-8fe8-692e299caf2b.webp)

1. **データ領域内の`0x5b`へジャンプする**

    `BEGINDATA`より後ろにある`0x5b`へジャンプすると、`BAD_JUMP_DESTINATION`エラーになります。

2. **実行が`BEGINDATA`へ到達する**

    実行中に`BEGINDATA`へ到達すると、現在の呼び出しフレームが停止します。

コピー命令で後続データを読めることと、コードサイズが後続データを含むことも別に確認します。
ジャンプ先の拒否だけでは、読み出し規則とサイズ規則の確認になりません。

## 互換性

影響を受けるのは、未使用だった`0xb6`をデータとして置き、その位置を実行時に飛び越えて後続の命令へ進むバイトコードです。
Solidityコンパイラはその構造を生成していないため、通常のコンパイラ出力はこの変更に依存しません。

![通常の出力と0xb6を飛び越える特殊なバイトコード](/images/qiita-65e96c3a-fd9b-40f8-b2ca-fd2502444863.webp)

手書きのバイトコードや特殊な生成器を使う場合は、`0xb6`の位置とジャンプ先を確認します。
最初の`0xb6`を飛び越える構造は、`BEGINDATA`として解釈される環境では動作しません。

## 参考実装

提案には参照実装がありません。
実装する場合は、`JUMPDEST`の解析停止、到達時の`STOP`、コピー命令、コードサイズを別々に検証します。

![参照実装がない場合に確認するEVM処理](/images/qiita-80186b21-dbfd-492e-ade9-22afc1a35bd7.webp)

`CODECOPY`と`EXTCODECOPY`でデータを読み出せることと、`CODESIZE`と`EXTCODESIZE`の結果が変わらないことを、ジャンプ先解析とは別のテストにします。

## セキュリティ

データ領域に偶然含まれる`0x5b`を有効な`JUMPDEST`と誤認しないことは、制御フローを検証する前提です。
最初の`BEGINDATA`で解析を止め、境界位置そのものへのジャンプも拒否します。

![実行対象から外れてもデータは公開されたまま残る](/images/qiita-1bb26641-8248-4516-a484-1f900385088b.webp)

実行できないことは、データを秘匿することではありません。
データ領域は`CODECOPY`と`EXTCODECOPY`で読めるため、秘密鍵や非公開の入力を置く場所には使えません。

## 最後に

今回は「**EIP2327**」についてまとめてきました。

EIP2327は、後続バイトをデータとして残したまま、実行とジャンプ先解析から外す提案です。
実装する側は、最初の境界で解析を止めること、到達時に停止すること、後続データを読み出せることを別々に確認します。
提案はStagnantであり、現行Ethereumで利用できる命令ではありません。

他でも色々記事を書いているのでぜひよろしければ読んでいってください！

https://amzn.asia/d/gxvJ0Pw

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://twitter.com/cardene777

https://cardene.substack.com/
