ethereum / ethereum/execution-specs

EIP-8297: state-root computation raises raw Python errors instead of protocol-level failures

Open
#3,255 0 comments 0 reactions 0 assignees View on GitHub
C-binary
Dominant language
Python
Stars
1.2k
Forks
505
Avg merge
2d 8h
Merged PRs (30d)
106

Description

Surfaced by the EIP-8297 test work in #3246. Two cases where computing a state root raises a raw Python exception rather than failing through the protocol's own error path.

### 1. Balance at or above 2^128

`ethereum.binary_trie.embedding.encode_basic_data` carries:

```python
assert balance < U256(2) ** U256(128) # U128 doesn't exist
```

BASIC_DATA gives `balance` a 16-byte field, so the bound is real — but it is enforced by a bare `assert` during root computation, and `AssertionError` is not an `EthereumException`. There is no protocol-level cap anywhere: `move_ether`, `create_ether` and `set_account_balance` all operate on unbounded `U256`. So a block that mints a balance past the cap **crashes the transition tool** instead of being rejected as invalid.

The EIP states no cap either — it only gives the field's offset and width.

This is unfillable at the EEST layer (t8n dies), so it is pinned only as a unit test.

### 2. Unknown code hash

`ethereum.state_pbt.State.get_code` is a bare dict subscript and raises `KeyError` for a hash absent from the store. `state_mpt.get_code` is identical in that respect — but MPT root computation never calls it, while the PBT embedding **must**, because code chunk leaves commit the code itself rather than just its hash. So an account whose code is missing from the store crashes root computation on PBT and not on MPT.

### The decision needed

- Should the balance bound be a protocol-level validity condition (rejecting the block) rather than an assertion? If balances past 2^128 are genuinely unreachable given the issuance schedule, saying so explicitly and keeping the assert as a defensive check would also be a fine answer — but that reasoning should be written down.
- Should `get_code` raise a typed error on the PBT path, given it is now reachable during root computation?

Neither is urgent, but both turn a would-be invalid block into a tooling crash, which is unpleasant to debug and would look like a client bug rather than a bad block.

Related: #3246.

Contributor guide

Open the contributing guide

Research direction

Start with ethereum.binary_trie.embedding.encode_basic_data and the balance mutation paths move_ether, create_ether, and set_account_balance, then inspect ethereum.state_pbt.State.get_code and state_mpt.get_code. Review the EIP-8297 tests from #3246 and add focused unit coverage for the oversized balance and missing code hash cases. Done means the protocol behavior is decided and root computation reports a typed protocol failure rather than a raw Python exception, or the defensive assertion rationale is documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.