From 8809ca059db6bdadc2df44e2eab9e3a5adde2a0d Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 10 Feb 2022 18:33:24 -0700 Subject: [PATCH 1/2] Add EIP for beacon state root in EVM --- EIPS/eip-4788.md | 157 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 EIPS/eip-4788.md diff --git a/EIPS/eip-4788.md b/EIPS/eip-4788.md new file mode 100644 index 00000000000000..e685e13d85e408 --- /dev/null +++ b/EIPS/eip-4788.md @@ -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 committment 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 + +## Security Considerations + +TODO + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 711f7b20de2ab3a568ec40cc42b1c81347aa88a4 Mon Sep 17 00:00:00 2001 From: lightclient <14004106+lightclient@users.noreply.github.com> Date: Thu, 17 Feb 2022 08:22:43 -0700 Subject: [PATCH 2/2] fix typo --- EIPS/eip-4788.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4788.md b/EIPS/eip-4788.md index e685e13d85e408..db6dee3c633bb4 100644 --- a/EIPS/eip-4788.md +++ b/EIPS/eip-4788.md @@ -52,7 +52,7 @@ 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 committment given the `ommers` value. +3. Add the block validation that the `ommersHash` does indeed match the expected commitment given the `ommers` value. ### EVM changes