Tidy, finish duties

This commit is contained in:
Paul Hauner 2021-12-13 17:09:09 +11:00
parent c99e48c60c
commit 38fffd3e2f
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
1 changed files with 74 additions and 31 deletions

View File

@ -2,52 +2,71 @@
## Introduction ## Introduction
In order to provide a syncing execution engine with a (partially-verified) view In order to provide a syncing execution engine with a partial view of the head
of the head of the chain, it may be desirable for a consensus engine to import of the chain, it may be desirable for a consensus engine to import beacon
beacon blocks without verifying the execution payloads. This partial sync is blocks without verifying the execution payloads. This partial sync is called an
called an *optimistic sync*. *optimistic sync*.
## Mechanisms ## Mechanisms
To perform an optimistic sync: To perform an optimistic sync:
- The `execute_payload` function MUST return `True` if the execution - The `execute_payload` function MUST return `True` if the execution
engine returns SYNCING or VALID. An INVALID response MUST return `False`. engine returns `SYNCING` or `VALID`. An `INVALID` response MUST return `False`.
- The `validate_merge_block` function MUST NOT raise an assertion if both the - The `validate_merge_block` function MUST NOT raise an assertion if both the
`pow_block` and `pow_parent` are unknown to the execution engine. `pow_block` and `pow_parent` are unknown to the execution engine.
In addition to these changes to validation, the consensus engine MUST be able In addition to these changes to validation, the consensus engine MUST be able
to ascertain, after import, which blocks returned SYNCING and which returned to ascertain, after import, which blocks returned `SYNCING` and which returned
VALID. This document will assume consensus engines store the following sets: `VALID`. This document will assume that consensus engines store the following
sets:
- `valid_roots: Set[Root]`: `hash_tree_root(block)` where - `valid_roots: Set[Root]`: `hash_tree_root(block)` where
`block.body.execution_payload` is known to be VALID. `block.body.execution_payload` is known to be `VALID`.
- `optimistic_roots: Set[Root]`: `hash_tree_root(block)` where - `optimistic_roots: Set[Root]`: `hash_tree_root(block)` where
`block.body.execution_payload` is known to be SYNCING. `block.body.execution_payload` is known to be `SYNCING`.
Notably, `optimistic_roots` only includes blocks which have execution enabled Notably, `optimistic_roots` only includes blocks which have execution enabled.
whilst `valid_roots` contains blocks *with or without* execution enabled (i.e., On the other hand, `valid_roots` contains blocks *with or without* execution
all blocks). enabled (i.e., all blocks).
A consensus engine MUST be able to retrospectively (i.e., after import) modify A consensus engine MUST be able to retrospectively (i.e., after import) modify
the status of SYNCING blocks to be either VALID or INVALID based upon responses the status of `SYNCING` blocks to be either `VALID` or `INVALID` based upon responses
from an execution engine. I.e., perform the following transitions: from an execution engine. I.e., perform the following transitions:
- SYNCING -> VALID - `SYNCING` -> `VALID`
- SYNCING -> INVALID - `SYNCING` -> `INVALID`
When a block transitions from SYNCING -> VALID, all *ancestors* of the block MUST When a block transitions from `SYNCING` -> `VALID`, all *ancestors* of the block MUST
also transition from SYNCING -> VALID. also transition from `SYNCING` -> `VALID`.
When a block transitions from SYNCING -> INVALID, all *descendants* of the When a block transitions from `SYNCING` -> `INVALID`, all *descendants* of the
block MUST also transition from SYNCING -> INVALID. block MUST also transition from `SYNCING` -> `INVALID`.
### Execution Engine Errors
A consensus engine MUST NOT interpret an error or failure to respond to a
message as a `SYNCING`, `VALID` or `INVALID` response. A consensus engine MAY
queue such a message for later processing.
## Merge Transition
To protect against attacks during the transition from empty `ExecutionPayload`
values to those which include the terminal PoW block, a consensus engine MUST
NOT perform an optimistic sync unless the `finalized_checkpoint.root` of the head
block references a block for which
`is_execution_enabled(head_state, head_block.body) == True`.
TODO: this restriction is very onerous, however it is the best known remedy for
the attack described in https://hackmd.io/S5ZEVhsNTqqfJirTAkBPlg I hope we can
do better.
## Fork Choice ## Fork Choice
Consensus engines MUST support removing blocks that transition from SYNCING to Consensus engines MUST support removing from fork choice blocks that transition
INVALID. Specifically, an INVALID block MUST NOT be included in the canonical from `SYNCING` to `INVALID`. Specifically, a block deemed `INVALID` at any
chain and the weights from INVALID blocks MUST NOT be applied to any VALID or point MUST NOT be included in the canonical chain and the weights from those
SYNCING ancestors. `INVALID` blocks MUST NOT be applied to any `VALID` or `SYNCING` ancestors.
## Validator assignments ## Validator assignments
@ -56,6 +75,8 @@ produce blocks, since an execution engine cannot produce a payload upon an
unknown parent. It cannot faithfully attest to the head block of the chain, unknown parent. It cannot faithfully attest to the head block of the chain,
since it has not fully verified that block. since it has not fully verified that block.
### Helpers
Let `head_block: BeaconBlock` be the result of calling of the fork choice Let `head_block: BeaconBlock` be the result of calling of the fork choice
algorithm at the time of block production. Let `justified_block: BeaconBlock` algorithm at the time of block production. Let `justified_block: BeaconBlock`
be the latest current justified ancestor ancestor of the `head_block`. be the latest current justified ancestor ancestor of the `head_block`.
@ -75,8 +96,18 @@ def latest_valid_ancestor(block: BeaconBlock) -> Optional[BeaconBlock]:
return None return None
``` ```
Let a node which returns `is_optimistic(head) == True` be an *optimistic ```python
node*. Let a validator on an optimistic node be an *optimistic validator*. def recent_valid_ancestor(block: BeaconBlock) -> Optional[BeaconBlock]:
ancestor = latest_valid_ancestor(block)
if ancestor is None or ancestor.slot + SLOTS_PER_EPOCH >= block.slot:
return None
return ancestor
```
Let only a node which returns `is_optimistic(head) == True` be an *optimistic
node*. Let only a validator on an optimistic node be an *optimistic validator*.
### Block production ### Block production
@ -86,9 +117,11 @@ A optimistic validator MUST NOT produce a block (i.e., sign across the
#### Exception 1. #### Exception 1.
If the justified block is fully verified (i.e., `not If the justified block is fully verified (i.e., `not
is_optimistic(justified_block)`, the validator MUST produce a block upon is_optimistic(justified_block)`, the validator MAY produce a block upon
`latest_valid_ancestor(head)`. `latest_valid_ancestor(head)`.
If the latest valid ancestor is `None`, the validator MUST NOT produce a block.
### Attesting ### Attesting
An optimistic validator MUST NOT participate in attestation (i.e., sign across the An optimistic validator MUST NOT participate in attestation (i.e., sign across the
@ -96,10 +129,20 @@ An optimistic validator MUST NOT participate in attestation (i.e., sign across t
`DOMAIN_AGGREGATE_AND_PROOF` domains), unless one of the follow exceptions are `DOMAIN_AGGREGATE_AND_PROOF` domains), unless one of the follow exceptions are
met: met:
#### Exception
#### Exception 1. #### Exception 1.
If a validator *does not* have an optimistic head (i.e., `not If the justified block is fully verified (i.e., `not
is_optimistic(head_block)`), the node is *fully synced*. is_optimistic(justified_block)`, the validator MAY sign across the following
The validator may produce an attestation. domains:
- `DOMAIN_BEACON_ATTESTER`: where `attestation.data.beacon_block_root == hash_tree_root(recent_valid_ancestor(head))`.
- `DOMAIN_AGGREGATE_AND_PROOF` and `DOMAIN_SELECTION_PROOF`: where `aggregate.message.aggregate.data.beacon_block_root == hash_tree_root(recent_valid_ancestor(head))`
If the recent valid ancestor is `None`, the validator MUST NOT participate in
attestation.
### Participating in Sync Committees
An optimistic validator MUST NOT participate in sync committees (i.e., sign across the
`DOMAIN_SYNC_COMMITTEE`, `DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF` or
`DOMAIN_CONTRIBUTION_AND_PROOF` domains).