Skip to content
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

Apply new terminology to the merge spec #2319

Merged
merged 4 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 53 additions & 55 deletions specs/merge/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,25 @@
- [`BeaconBlockBody`](#beaconblockbody)
- [`BeaconState`](#beaconstate)
- [New containers](#new-containers)
- [`ApplicationPayload`](#applicationpayload)
- [`ApplicationBlockHeader`](#applicationblockheader)
- [`ExecutionPayload`](#executionpayload)
- [`ExecutionPayloadHeader`](#executionpayloadheader)
- [Helper functions](#helper-functions)
- [Misc](#misc)
- [`is_transition_completed`](#is_transition_completed)
- [`is_transition_block`](#is_transition_block)
- [Block processing](#block-processing)
- [Application payload processing](#application-payload-processing)
- [`get_application_state`](#get_application_state)
- [`application_state_transition`](#application_state_transition)
- [`process_application_payload`](#process_application_payload)
- [Execution payload processing](#execution-payload-processing)
- [`get_execution_state`](#get_execution_state)
- [`execution_state_transition`](#execution_state_transition)
- [`process_execution_payload`](#process_execution_payload)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->

## Introduction

This is a patch implementing the executable beacon chain proposal.
It enshrines application-layer execution and validity as a first class citizen at the core of the beacon chain.
It enshrines transaction execution and validity as a first class citizen at the core of the beacon chain.

## Custom types

Expand Down Expand Up @@ -73,32 +73,32 @@ order and append any additional fields to the end.

#### `BeaconBlockBody`

*Note*: `BeaconBlockBody` fields remain unchanged other than the addition of `application_payload`.
*Note*: `BeaconBlockBody` fields remain unchanged other than the addition of `execution_payload`.

```python
class BeaconBlockBody(phase0.BeaconBlockBody):
application_payload: ApplicationPayload # [New in Merge] application payload
execution_payload: ExecutionPayload # [New in Merge]
```

#### `BeaconState`

*Note*: `BeaconState` fields remain unchanged other than addition of `latest_application_block_header`.
*Note*: `BeaconState` fields remain unchanged other than addition of `latest_execution_payload_header`.

```python
class BeaconState(phase0.BeaconState):
# Application-layer
latest_application_block_header: ApplicationBlockHeader # [New in Merge]
# Execution-layer
latest_execution_payload_header: ExecutionPayloadHeader # [New in Merge]
```

### New containers

#### `ApplicationPayload`
#### `ExecutionPayload`

The application payload included in a `BeaconBlockBody`.
The execution payload included in a `BeaconBlockBody`.

```python
class ApplicationPayload(Container):
block_hash: Bytes32 # Hash of application block
class ExecutionPayload(Container):
block_hash: Bytes32 # Hash of execution block
parent_hash: Bytes32
coinbase: Bytes20
state_root: Bytes32
Expand All @@ -110,15 +110,15 @@ class ApplicationPayload(Container):
transactions: List[OpaqueTransaction, MAX_APPLICATION_TRANSACTIONS]
```

#### `ApplicationBlockHeader`
#### `ExecutionPayloadHeader`

The application block header included in a `BeaconState`.
The execution payload header included in a `BeaconState`.

*Note:* Holds application payload data without transaction list.
*Note:* Holds execution payload data without transaction bodies.

```python
class ApplicationBlockHeader(Container):
block_hash: Bytes32 # Hash of application block
class ExecutionPayloadHeader(Container):
block_hash: Bytes32 # Hash of execution block
parent_hash: Bytes32
coinbase: Bytes20
state_root: Bytes32
Expand All @@ -138,14 +138,14 @@ class ApplicationBlockHeader(Container):

```python
def is_transition_completed(state: BeaconState) -> boolean:
return state.latest_application_block_header.block_hash != Bytes32()
return state.latest_execution_payload_header != ExecutionPayloadHeader()
```

#### `is_transition_block`

```python
def is_transition_block(state: BeaconState, block_body: BeaconBlockBody) -> boolean:
return state.latest_application_block_header.block_hash == Bytes32() and block_body.application_payload.block_hash != Bytes32()
return not is_transition_completed(state) and block_body.execution_payload != ExecutionPayload()
```

### Block processing
Expand All @@ -156,54 +156,52 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
process_randao(state, block.body)
process_eth1_data(state, block.body)
process_operations(state, block.body)
process_application_payload(state, block.body) # [New in Merge]
process_execution_payload(state, block.body) # [New in Merge]
```

#### Application payload processing
#### Execution payload processing

##### `get_application_state`
##### `get_execution_state`

*Note*: `ApplicationState` class is an abstract class representing ethereum application state.
*Note*: `ExecutionState` class is an abstract class representing Ethereum execution state.

Let `get_application_state(application_state_root: Bytes32) -> ApplicationState` be the function that given the root hash returns a copy of ethereum application state.
Let `get_execution_state(execution_state_root: Bytes32) -> ExecutionState` be the function that given the root hash returns a copy of Ethereum execution state.
The body of the function is implementation dependent.

##### `application_state_transition`
##### `execution_state_transition`

Let `application_state_transition(application_state: ApplicationState, application_payload: ApplicationPayload) -> None` be the transition function of ethereum application state.
Let `execution_state_transition(execution_state: ExecutionState, execution_payload: ExecutionPayload) -> None` be the transition function of Ethereum execution state.
The body of the function is implementation dependent.

*Note*: `application_state_transition` must throw `AssertionError` if either the transition itself or one of the post-transition verifications has failed.
*Note*: `execution_state_transition` must throw `AssertionError` if either the transition itself or one of the pre or post conditions has failed.

##### `process_application_payload`
##### `process_execution_payload`

```python
def process_application_payload(state: BeaconState, body: BeaconBlockBody) -> None:
def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None:
"""
Note: This function is designed to be able to be run in parallel with the other `process_block` sub-functions
"""

if not is_transition_completed(state):
assert body.application_payload == ApplicationPayload()
return

if not is_transition_block(state, body):
assert body.application_payload.parent_hash == state.latest_application_block_header.block_hash
assert body.application_payload.number == state.latest_application_block_header.number + 1

application_state = get_application_state(state.latest_application_block_header.state_root)
application_state_transition(application_state, body.application_payload)

state.latest_application_block_header = ApplicationBlockHeader(
block_hash=application_payload.block_hash,
parent_hash=application_payload.parent_hash,
coinbase=application_payload.coinbase,
state_root=application_payload.state_root,
number=application_payload.number,
gas_limit=application_payload.gas_limit,
gas_used=application_payload.gas_used,
receipt_root=application_payload.receipt_root,
logs_bloom=application_payload.logs_bloom,
transactions_root=hash_tree_root(application_payload.transactions),
execution_payload = body.execution_payload

if is_transition_completed(state):
assert execution_payload.parent_hash == state.latest_execution_payload_header.block_hash
assert execution_payload.number == state.latest_execution_payload_header.number + 1

execution_state = get_execution_state(state.latest_execution_payload_header.state_root)
djrtwo marked this conversation as resolved.
Show resolved Hide resolved
execution_state_transition(execution_state, execution_payload)

state.latest_execution_payload_header = ExecutionPayloadHeader(
block_hash=execution_payload.block_hash,
parent_hash=execution_payload.parent_hash,
coinbase=execution_payload.coinbase,
state_root=execution_payload.state_root,
number=execution_payload.number,
gas_limit=execution_payload.gas_limit,
gas_used=execution_payload.gas_used,
receipt_root=execution_payload.receipt_root,
logs_bloom=execution_payload.logs_bloom,
transactions_root=hash_tree_root(execution_payload.transactions),
)
```
2 changes: 1 addition & 1 deletion specs/merge/fork-choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
# [New in Merge]
if is_transition_block(pre_state, block.body):
# Delay consideration of block until PoW block is processed by the PoW node
pow_block = get_pow_block(block.body.application_payload.parent_hash)
pow_block = get_pow_block(block.body.execution_payload.parent_hash)
assert pow_block.is_processed
assert is_valid_transition_block(pow_block)

Expand Down
24 changes: 12 additions & 12 deletions specs/merge/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
- [Beacon chain responsibilities](#beacon-chain-responsibilities)
- [Block proposal](#block-proposal)
- [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody)
- [Application Payload](#application-payload)
- [Execution Payload](#execution-payload)
- [`get_pow_chain_head`](#get_pow_chain_head)
- [`produce_application_payload`](#produce_application_payload)
- [`produce_execution_payload`](#produce_execution_payload)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
Expand All @@ -34,37 +34,37 @@ All terminology, constants, functions, and protocol mechanics defined in the upd

## Beacon chain responsibilities

All validator responsibilities remain unchanged other than those noted below. Namely, the transition block handling and the addition of `ApplicationPayload`.
All validator responsibilities remain unchanged other than those noted below. Namely, the transition block handling and the addition of `ExecutionPayload`.

### Block proposal

#### Constructing the `BeaconBlockBody`

##### Application Payload
##### Execution Payload

###### `get_pow_chain_head`

Let `get_pow_chain_head() -> PowBlock` be the function that returns the head of the PoW chain. The body of the function is implementation specific.

###### `produce_application_payload`
###### `produce_execution_payload`

Let `produce_application_payload(parent_hash: Bytes32) -> ApplicationPayload` be the function that produces new instance of application payload.
Let `produce_execution_payload(parent_hash: Bytes32) -> ExecutionPayload` be the function that produces new instance of execution payload.
The body of this function is implementation dependent.

* Set `block.body.application_payload = get_application_payload(state)` where:
* Set `block.body.execution_payload = get_execution_payload(state)` where:

```python
def get_application_payload(state: BeaconState) -> ApplicationPayload:
def get_execution_payload(state: BeaconState) -> ExecutionPayload:
if not is_transition_completed(state):
pow_block = get_pow_chain_head()
if not is_valid_transition_block(pow_block):
# Pre-merge, empty payload
return ApplicationPayload()
return ExecutionPayload()
else:
# Signify merge via producing on top of the last PoW block
return produce_application_payload(pow_block.block_hash)
return produce_execution_payload(pow_block.block_hash)

# Post-merge, normal payload
application_parent_hash = state.latest_application_block_header.block_hash
return produce_application_payload(application_parent_hash)
execution_parent_hash = state.latest_execution_payload_header.block_hash
return produce_execution_payload(execution_parent_hash)
```