-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EIP-4788: Beacon state root in EVM #4788
Merged
eth-bot
merged 2 commits into
ethereum:master
from
ralexstokes:beacon-state-root-in-evm
Feb 17, 2022
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,157 @@ | ||||||||||||||||
--- | ||||||||||||||||
eip: 4788 | ||||||||||||||||
title: Beacon state root in the EVM | ||||||||||||||||
description: Expose beacon chain state roots in the EVM | ||||||||||||||||
author: Alex Stokes (@ralexstokes), Danny Ryan (@djrtwo) | ||||||||||||||||
discussions-to: https://ethereum-magicians.org/t/eip-4788-beacon-state-root-in-evm/8281 | ||||||||||||||||
status: Draft | ||||||||||||||||
type: Standards Track | ||||||||||||||||
category: Core | ||||||||||||||||
created: 2022-02-10 | ||||||||||||||||
--- | ||||||||||||||||
|
||||||||||||||||
## Abstract | ||||||||||||||||
|
||||||||||||||||
Commit to the state root of the beacon chain in the `ommers` field in the post-merge execution block. Reflect the changes in the `ommersHash` field of the execution block header. | ||||||||||||||||
|
||||||||||||||||
Store each beacon chain state root into a contract and add a new opcode that reads this contract. | ||||||||||||||||
|
||||||||||||||||
## Motivation | ||||||||||||||||
|
||||||||||||||||
Exposing the beacon chain state root allows for proofs about the beacon state to be verified inside the EVM. This functionality supports a wide variety of use cases in smart contracts involving validator status and finality produced by the consensus layer. | ||||||||||||||||
|
||||||||||||||||
In particular, this functionality is required for beacon chain validator withdrawals to the EVM. | ||||||||||||||||
|
||||||||||||||||
## Specification | ||||||||||||||||
|
||||||||||||||||
| constants | value | units | ||||||||||||||||
|--- |--- |--- | ||||||||||||||||
| `FORK_TIMESTAMP` | TBD | | ||||||||||||||||
| `FORK_EPOCH` | TBD | | ||||||||||||||||
| `HISTORY_STORAGE_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffd` | | ||||||||||||||||
| `OPCODE_VALUE` | `0x48` | | ||||||||||||||||
| `G_beacon_state_root` | 20 | gas | ||||||||||||||||
|
||||||||||||||||
### Background | ||||||||||||||||
|
||||||||||||||||
The method of injecting the beacon state root in this EIP follows the general strategy of [EIP-4399](./eip-4399.md) to make a post-merge change to the EVM integrating information from the beacon chain. This EIP along with [EIP-3675](./eip-3675.md) should be taken as relevant background to understand the particular approach of this EIP. | ||||||||||||||||
|
||||||||||||||||
The method for exposing the state root data via opcode is inspired by [EIP-2935](./eip-2935.md). | ||||||||||||||||
|
||||||||||||||||
### Block structure and validity | ||||||||||||||||
|
||||||||||||||||
Beginning at the execution timestamp `FORK_TIMESTAMP`, execution clients **MUST**: | ||||||||||||||||
|
||||||||||||||||
1. set the value of the `ommers` field in the block to an RLP list with one element: the 32 byte [hash tree root](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization) of the [beacon state](https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beaconstate) from the previous slot to this block. | ||||||||||||||||
|
||||||||||||||||
2. set the value of the `ommersHash` field in the block header to the Keccak256 hash of the `ommers` field. | ||||||||||||||||
|
||||||||||||||||
```python | ||||||||||||||||
beaconStateRoot = <32 byte value> # provided by consensus client | ||||||||||||||||
ommers = RLP([beaconStateRoot]) # in the block body | ||||||||||||||||
ommersHash = Keccak256(ommers) # in the block header | ||||||||||||||||
``` | ||||||||||||||||
|
||||||||||||||||
3. Add the block validation that the `ommersHash` does indeed match the expected commitment given the `ommers` value. | ||||||||||||||||
|
||||||||||||||||
### EVM changes | ||||||||||||||||
|
||||||||||||||||
#### Block processing | ||||||||||||||||
|
||||||||||||||||
At the start of processing any execution block where `block.timestamp >= FORK_TIMESTAMP` (i.e. before processing any transactions), write the beacon state root provided in the block into the storage of the smart contract at `HISTORY_STORAGE_ADDRESS`. This data is keyed by the block number. | ||||||||||||||||
|
||||||||||||||||
In pseudocode: | ||||||||||||||||
|
||||||||||||||||
```python | ||||||||||||||||
beacon_state_root = block.ommers[0] | ||||||||||||||||
sstore(HISTORY_STORAGE_ADDRESS, block.number, beacon_state_root) | ||||||||||||||||
``` | ||||||||||||||||
|
||||||||||||||||
#### New opcode | ||||||||||||||||
|
||||||||||||||||
Beginning at the execution timestamp `FORK_TIMESTAMP`, introduce a new opcode `BEACON_STATE_ROOT` at `OPCODE_VALUE`. This opcode consumes one word from the stack encoding the block number for the root. The opcode has a gas cost of `G_beacon_state_root`. | ||||||||||||||||
|
||||||||||||||||
The result of executing this opcode leaves one word on the stack corresponding to a read of the history contract's storage; in pseudocode: | ||||||||||||||||
|
||||||||||||||||
```python | ||||||||||||||||
block_number = evm.stack.pop() | ||||||||||||||||
sload(HISTORY_STORAGE_ADDRESS, block_number) | ||||||||||||||||
``` | ||||||||||||||||
|
||||||||||||||||
If there is no root stored at the requested block number, the opcode follows the existing EVM semantics of `sload` returning `0`. | ||||||||||||||||
|
||||||||||||||||
## Rationale | ||||||||||||||||
|
||||||||||||||||
### General strategy | ||||||||||||||||
|
||||||||||||||||
See the rationale for EIP-4399 for discussion about this general strategy of reusing execution block elements for beacon chain data. | ||||||||||||||||
|
||||||||||||||||
### Fork mechanics | ||||||||||||||||
|
||||||||||||||||
This EIP requires the consensus layer and execution layer to execute a network upgrade in lockstep. | ||||||||||||||||
To carry out this task, a `FORK_EPOCH` (of the beacon chain) will be chosen and then used to compute a timestamp `FORK_TIMESTAMP`. | ||||||||||||||||
This `FORK_TIMESTAMP` can be used in the execution layer to identify when the protocol change should be deployed. | ||||||||||||||||
|
||||||||||||||||
This technique works because the timestamps in post-merge execution blocks are aligned to beacon chain slots and thus serve as a proxy for the slot number. | ||||||||||||||||
|
||||||||||||||||
Another option for the fork definition would be to pick a beacon chain epoch and an execution payload block number. | ||||||||||||||||
This design however is not reliable due to the presence of skipped slots on the beacon chain. | ||||||||||||||||
|
||||||||||||||||
### Execution layer validations | ||||||||||||||||
|
||||||||||||||||
By including the beacon state root in the execution block in the deprecated `ommers` field, execution clients can still verify the chain in a self-contained way without relying on an available consensus client. | ||||||||||||||||
This property is important during syncing (and likely other phases of execution node operation). | ||||||||||||||||
|
||||||||||||||||
### Minimizing client code change | ||||||||||||||||
|
||||||||||||||||
By including the `ommersHash` validation, clients can use existing code with only minimal changes (supplying the actual state root) during block production and verification. | ||||||||||||||||
Having the beacon state root value in the `ommers` field means that it is fairly straightforward to provide the value from the block data to the EVM execution context for client implementations as they stand today. | ||||||||||||||||
|
||||||||||||||||
### Gas cost of opcode | ||||||||||||||||
|
||||||||||||||||
The suggested gas cost is just using the value for the `BLOCKHASH` opcode as `BEACON_STATE_ROOT` is an analogous operation. | ||||||||||||||||
|
||||||||||||||||
### Why not repurpose `BLOCKHASH`? | ||||||||||||||||
|
||||||||||||||||
The `BLOCKHASH` opcode could be repurposed to provide a beacon block root instead of the current execution block hash. | ||||||||||||||||
To minimize code change and simplify deployment to mainnet, this EIP suggests leaving `BLOCKHASH` alone and adding a new opcode with the desired semantics. | ||||||||||||||||
|
||||||||||||||||
### Why not bound history of state roots? | ||||||||||||||||
|
||||||||||||||||
Marginal state growth; adding every single root results in an additional ~84MB of state growth per year compared to ~30 GB of state overall. | ||||||||||||||||
|
||||||||||||||||
TODO: say something about statelessness | ||||||||||||||||
TODO: get latest numbers on state size, and compare against predicted growth | ||||||||||||||||
|
||||||||||||||||
### Beacon state root instead of block root | ||||||||||||||||
|
||||||||||||||||
Each slot on the beacon chain containing a block has both a block root and a state root (reflecting the state after applying said block). | ||||||||||||||||
The beacon block includes the state root so a proof about the state could also be authored against a block root at the cost of a few additional hashes. | ||||||||||||||||
Given that most use cases want to prove data encapsulated in a given state, rather than a given block, this EIP suggests exposing state roots over block roots. | ||||||||||||||||
|
||||||||||||||||
### Block number in lieu of slot | ||||||||||||||||
|
||||||||||||||||
The state roots are keyed by the `number` of the execution block. | ||||||||||||||||
Another option is to key roots by the beacon chain slot they belong to. | ||||||||||||||||
While at first pass this may seem more direct, the beacon chain can have "skipped" slots where a beacon proposer failed to produce a block that was included at a given slot. | ||||||||||||||||
Handling roots of skipped slots would complicate the EVM mechanism so this EIP suggests to use the execution block number where each distinct block number is guaranteed to have a distinct root. | ||||||||||||||||
|
||||||||||||||||
## Backwards Compatibility | ||||||||||||||||
|
||||||||||||||||
No issues. | ||||||||||||||||
|
||||||||||||||||
## Test Cases | ||||||||||||||||
|
||||||||||||||||
TODO | ||||||||||||||||
|
||||||||||||||||
## Reference Implementation | ||||||||||||||||
|
||||||||||||||||
TODO | ||||||||||||||||
|
||||||||||||||||
Comment on lines
+143
to
+150
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
These sections are optional, recommend just removing them until you have something useful to include. |
||||||||||||||||
## Security Considerations | ||||||||||||||||
|
||||||||||||||||
TODO | ||||||||||||||||
|
||||||||||||||||
## Copyright | ||||||||||||||||
|
||||||||||||||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should link to specific commit hashes rather than files in a
dev
branch. Also, are these not available in the primary consensus spec yet (hence why you are linking todev
rather thanmain
/master
)?