define execution engine protocol

This commit is contained in:
protolambda 2021-05-10 15:48:37 +02:00
parent e78e045847
commit f58ba8f5b2
No known key found for this signature in database
GPG Key ID: EC89FDBB2B4C7623
3 changed files with 103 additions and 16 deletions

View File

@ -22,6 +22,9 @@
- [New containers](#new-containers)
- [`ExecutionPayload`](#executionpayload)
- [`ExecutionPayloadHeader`](#executionpayloadheader)
- [Protocols](#protocols)
- [`ExecutionEngine`](#executionengine)
- [`new_block`](#new_block)
- [Helper functions](#helper-functions)
- [Misc](#misc)
- [`is_execution_enabled`](#is_execution_enabled)
@ -30,7 +33,6 @@
- [`compute_time_at_slot`](#compute_time_at_slot)
- [Block processing](#block-processing)
- [Execution payload processing](#execution-payload-processing)
- [`verify_execution_state_transition`](#verify_execution_state_transition)
- [`process_execution_payload`](#process_execution_payload)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@ -137,6 +139,30 @@ class ExecutionPayloadHeader(Container):
transactions_root: Root
```
## Protocols
### `ExecutionEngine`
The `ExecutionEngine` protocol separates the consensus and execution sub-systems.
The consensus implementation references an instance of this sub-system with `EXECUTION_ENGINE`.
The following methods are added to the `ExecutionEngine` protocol for use in the state transition:
#### `new_block`
Verifies the given `ExecutionPayload` with respect to execution state transition, and persists changes if valid.
The body of this function is implementation dependent.
The Consensus API may be used to implement this with an external execution engine.
```python
def new_block(self: ExecutionEngine, execution_payload: ExecutionPayload) -> bool:
"""
Returns True if the ``execution_payload`` was verified and processed successfully, False otherwise.
"""
...
```
## Helper functions
### Misc
@ -182,20 +208,15 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
process_operations(state, block.body)
# Pre-merge, skip execution payload processing
if is_execution_enabled(state, block):
process_execution_payload(state, block.body.execution_payload) # [New in Merge]
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [New in Merge]
```
#### Execution payload processing
##### `verify_execution_state_transition`
Let `verify_execution_state_transition(execution_payload: ExecutionPayload) -> bool` be the function that verifies given `ExecutionPayload` with respect to execution state transition.
The body of the function is implementation dependent.
##### `process_execution_payload`
```python
def process_execution_payload(state: BeaconState, execution_payload: ExecutionPayload) -> None:
def process_execution_payload(state: BeaconState, execution_payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
"""
Note: This function is designed to be able to be run in parallel with the other `process_block` sub-functions
"""
@ -205,7 +226,7 @@ def process_execution_payload(state: BeaconState, execution_payload: ExecutionPa
assert execution_payload.timestamp == compute_time_at_slot(state, state.slot)
assert verify_execution_state_transition(execution_payload)
assert execution_engine.new_block(execution_payload)
state.latest_execution_payload_header = ExecutionPayloadHeader(
block_hash=execution_payload.block_hash,

View File

@ -8,8 +8,13 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Introduction](#introduction)
- [Helpers](#helpers)
- [Protocols](#protocols)
- [`ExecutionEngine`](#executionengine)
- [`set_head`](#set_head)
- [`finalize_block`](#finalize_block)
- [Containers](#containers)
- [`PowBlock`](#powblock)
- [Helper functions](#helper-functions)
- [`get_pow_block`](#get_pow_block)
- [`is_valid_transition_block`](#is_valid_transition_block)
- [Updated fork-choice handlers](#updated-fork-choice-handlers)
@ -24,7 +29,44 @@ This is the modification of the fork choice according to the executable beacon c
*Note*: It introduces the process of transition from the last PoW block to the first PoS block.
### Helpers
## Protocols
### `ExecutionEngine`
The following methods are added to the `ExecutionEngine` protocol for use in the fork choice:
#### `set_head`
Re-organizes the execution payload chain and corresponding state to make `block_hash` the head.
The body of this function is implementation dependent.
The Consensus API may be used to implement this with an external execution engine.
```python
def set_head(self: ExecutionEngine, block_hash: Hash32) -> bool:
"""
Returns True if the ``block_hash`` was successfully set as head of the execution payload chain.
"""
...
```
#### `finalize_block`
Applies finality to the execution state: it irreversibly persists the chain of all execution payloads
and corresponding state, up to and including `block_hash`.
The body of this function is implementation dependent.
The Consensus API may be used to implement this with an external execution engine.
```python
def finalize_block(self: ExecutionEngine, block_hash: Hash32) -> bool:
"""
Returns True if the data up to and including ``block_hash`` was successfully finalized.
"""
...
```
## Containers
#### `PowBlock`
@ -36,6 +78,8 @@ class PowBlock(Container):
total_difficulty: uint256
```
## Helper functions
#### `get_pow_block`
Let `get_pow_block(block_hash: Hash32) -> PowBlock` be the function that given the hash of the PoW block returns its data.
@ -52,7 +96,7 @@ def is_valid_transition_block(block: PowBlock) -> bool:
return block.is_valid and is_total_difficulty_reached
```
### Updated fork-choice handlers
## Updated fork-choice handlers
#### `on_block`

View File

@ -12,6 +12,9 @@
- [Introduction](#introduction)
- [Prerequisites](#prerequisites)
- [Protocols](#protocols)
- [`ExecutionEngine`](#executionengine)
- [`assemble_block`](#assemble_block)
- [Beacon chain responsibilities](#beacon-chain-responsibilities)
- [Block proposal](#block-proposal)
- [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody)
@ -32,6 +35,25 @@ This document is an extension of the [Phase 0 -- Validator](../phase0/validator.
All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of [The Merge](./beacon-chain.md) are requisite for this document and used throughout. Please see related Beacon Chain doc before continuing and use them as a reference throughout.
## Protocols
### `ExecutionEngine`
The following methods are added to the `ExecutionEngine` protocol for use as a validator:
#### `assemble_block`
Produces a new instance of an execution payload, with the specified timestamp,
on top of the execution payload chain tip identified by `block_head`.
The body of this function is implementation dependent.
The Consensus API may be used to implement this with an external execution engine.
```python
def assemble_block(self: ExecutionEngine, block_hash: Hash32, timestamp: uint64) -> ExecutionPayload:
...
```
## Beacon chain responsibilities
All validator responsibilities remain unchanged other than those noted below. Namely, the transition block handling and the addition of `ExecutionPayload`.
@ -49,12 +71,12 @@ Let `get_pow_chain_head() -> PowBlock` be the function that returns the head of
###### `produce_execution_payload`
Let `produce_execution_payload(parent_hash: Hash32, timestamp: uint64) -> ExecutionPayload` be the function that produces new instance of execution payload.
The body of this function is implementation dependent.
The `ExecutionEngine` protocol is used for the implementation specific part of execution payload proposals.
* Set `block.body.execution_payload = get_execution_payload(state)` where:
```python
def get_execution_payload(state: BeaconState) -> ExecutionPayload:
def get_execution_payload(state: BeaconState, execution_engine: ExecutionEngine) -> ExecutionPayload:
if not is_transition_completed(state):
pow_block = get_pow_chain_head()
if not is_valid_transition_block(pow_block):
@ -63,7 +85,7 @@ def get_execution_payload(state: BeaconState) -> ExecutionPayload:
else:
# Signify merge via producing on top of the last PoW block
timestamp = compute_time_at_slot(state, state.slot)
return produce_execution_payload(pow_block.block_hash, timestamp)
return execution_engine.assemble_block(pow_block.block_hash, timestamp)
# Post-merge, normal payload
execution_parent_hash = state.latest_execution_payload_header.block_hash