eth2.0-specs/sync/optimistic.md

291 lines
11 KiB
Markdown
Raw Normal View History

2021-12-05 23:07:54 +00:00
# Optimistic Sync
## Introduction
2021-12-13 06:09:09 +00:00
In order to provide a syncing execution engine with a partial view of the head
of the chain, it may be desirable for a consensus engine to import beacon
blocks without verifying the execution payloads. This partial sync is called an
*optimistic sync*.
2021-12-05 23:07:54 +00:00
2021-12-19 03:44:21 +00:00
## Constants
|Name|Value|Unit
|---|---|---|
2021-12-21 05:49:43 +00:00
|`SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY`| `128` | slots
2021-12-19 23:15:51 +00:00
*Note: the `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY` must be user-configurable. See
2021-12-19 23:32:45 +00:00
[Fork Choice Poisoning](#fork-choice-poisoning).*
2021-12-19 03:44:21 +00:00
## Helpers
Let `head_block: BeaconBlock` be the result of calling of the fork choice
2021-12-20 06:46:42 +00:00
algorithm at the time of block production.
Let `justified_block: BeaconBlock` be the latest current justified ancestor
ancestor of the `head_block`.
2021-12-19 03:44:21 +00:00
2021-12-19 23:41:50 +00:00
Let `optimistic_roots: Set[Root]` be the set of `hash_tree_root(block)` for all
optimistically imported blocks which have yet to receive an `INVALID` or
`VALID` designation from an execution engine.
2021-12-19 03:44:21 +00:00
```python
def is_optimistic(block: BeaconBlock, optimistic_roots: Set[Root]) -> bool:
return hash_tree_root(block) in optimistic_roots
2021-12-19 03:44:21 +00:00
```
```python
def latest_verified_ancestor(block: BeaconBlock) -> BeaconBlock:
2021-12-19 03:44:21 +00:00
while True:
if not is_optimistic(block) or block.parent_root == Root():
return block
2021-12-19 03:44:21 +00:00
block = get_block(block.parent_root)
```
```python
def is_execution_block(block: BeaconBlock) -> BeaconBlock:
return block.body.execution_payload != ExecutionPayload()
2021-12-19 03:44:21 +00:00
```
2021-12-19 03:56:46 +00:00
```python
def should_optimistically_import_block(current_slot: Slot, block: BeaconBlock) -> bool:
return block.slot + SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY <= current_slot
2021-12-19 03:56:46 +00:00
```
Let only a node which returns `is_optimistic(head) is True` be an *optimistic
2021-12-19 03:44:21 +00:00
node*. Let only a validator on an optimistic node be an *optimistic validator*.
When this specification only defines behaviour for an optimistic
node/validator, but *not* for the non-optimistic case, assume default
behaviours without regard for optimistic sync.
2021-12-05 23:07:54 +00:00
## Mechanisms
### When to optimistically import blocks
2021-12-19 03:44:21 +00:00
2021-12-19 03:56:46 +00:00
A block MUST NOT be optimistically imported, unless either of the following
conditions are met:
1. The justified checkpoint has execution enabled. I.e.,
2021-12-20 00:12:11 +00:00
`is_execution_block(get_block(get_state(head_block).current_justified_checkpoint.root))`
2021-12-19 03:56:46 +00:00
1. The current slot (as per the system clock) is at least `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY` ahead of
the slot of the block being imported. I.e., `should_optimistically_import_block(current_slot, block) == True`.
2021-12-19 03:44:21 +00:00
2021-12-19 23:32:45 +00:00
*See [Fork Choice Poisoning](#fork-choice-poisoning) for the motivations behind
these conditions.*
### How to optimistically import blocks
2021-12-19 03:44:21 +00:00
To optimistically import a block:
2021-12-05 23:07:54 +00:00
- The [`execute_payload`](../specs/merge/beacon-chain.md#execute_payload) function MUST return `True` if the execution
2021-12-13 06:09:09 +00:00
engine returns `SYNCING` or `VALID`. An `INVALID` response MUST return `False`.
- The [`validate_merge_block`](../specs/merge/fork-choice.md#validate_merge_block) function MUST NOT raise an assertion if both the
2021-12-20 06:55:10 +00:00
`pow_block` and `pow_parent` are unknown to the execution engine.
- The parent of the block MUST NOT have an INVALID execution payload.
2021-12-05 23:07:54 +00:00
2021-12-19 23:41:50 +00:00
In addition to this change to validation, the consensus engine MUST be able to
2021-12-20 00:12:11 +00:00
ascertain, after import, which blocks returned `SYNCING` and which returned
`VALID`.
2021-12-05 23:07:54 +00:00
2021-12-20 00:12:11 +00:00
Optimistically imported blocks MUST pass all verifications included in
`process_block` (withstanding the modifications to `execute_payload`).
2021-12-14 05:21:30 +00:00
2021-12-05 23:07:54 +00:00
A consensus engine MUST be able to retrospectively (i.e., after import) modify
2021-12-13 06:09:09 +00:00
the status of `SYNCING` blocks to be either `VALID` or `INVALID` based upon responses
2021-12-05 23:07:54 +00:00
from an execution engine. I.e., perform the following transitions:
2021-12-13 06:09:09 +00:00
- `SYNCING` -> `VALID`
- `SYNCING` -> `INVALID`
2021-12-05 23:07:54 +00:00
2021-12-20 00:12:11 +00:00
When a block transitions from `SYNCING` -> `VALID`, all *ancestors* of the
block MUST also transition from `SYNCING` -> `VALID`. Such a block is no longer
considered "optimistically imported".
2021-12-05 23:07:54 +00:00
2021-12-13 06:09:09 +00:00
When a block transitions from `SYNCING` -> `INVALID`, all *descendants* of the
block MUST also transition from `SYNCING` -> `INVALID`.
2021-12-20 06:46:42 +00:00
When a block transitions from the `SYNCING` state it is removed from the set of
`optimistic_roots`.
2021-12-13 06:09:09 +00:00
### Execution Engine Errors
2021-12-19 03:34:43 +00:00
2021-12-20 00:12:11 +00:00
When an execution engine returns an error or fails to respond to a payload
2021-12-20 07:32:47 +00:00
validity request for some block, a consensus engine:
2021-12-20 00:12:11 +00:00
- MUST NOT optimistically import the block.
2021-12-20 03:04:33 +00:00
- MUST NOT apply the block to the fork choice store.
2021-12-20 00:12:11 +00:00
- MAY queue the block for later processing.
2021-12-13 06:09:09 +00:00
2021-12-14 04:44:15 +00:00
### Assumptions about Execution Engine Behaviour
This specification assumes execution engines will only return `SYNCING` when
there is insufficient information available to make a `VALID` or `INVALID`
determination on the given `ExecutionPayload` (e.g., the parent payload is
2021-12-20 06:46:42 +00:00
unknown). Specifically, `SYNCING` responses should be fork-specific, in that
the search for a block on one chain MUST NOT trigger a `SYNCING` response for
another chain.
2021-12-14 04:44:15 +00:00
2021-12-14 05:42:35 +00:00
### Re-Orgs
The consensus engine MUST support any chain reorganisation which does *not*
affect the justified checkpoint. The consensus engine MAY support re-orgs
beyond the justified checkpoint.
If the justified checkpoint transitions from `SYNCING` -> `INVALID`, a
consensus engine MAY choose to alert the user and force the application to
exit.
2021-12-19 23:32:45 +00:00
## Fork Choice
2021-12-20 06:46:42 +00:00
Consensus engines MUST support removing blocks from fork choice that transition
2021-12-19 23:32:45 +00:00
from `SYNCING` to `INVALID`. Specifically, a block deemed `INVALID` at any
point MUST NOT be included in the canonical chain and the weights from those
`INVALID` blocks MUST NOT be applied to any `VALID` or `SYNCING` ancestors.
### Fork Choice Poisoning
2021-12-19 23:15:51 +00:00
During the merge transition it is possible for an attacker to craft a
`BeaconBlock` with an execution payload that references an
2021-12-20 06:46:42 +00:00
eternally-unavailable `body.execution_payload.parent_hash` (i.e., the parent
hash is random bytes). In rare circumstances, it is possible that an attacker
can build atop such a block to trigger justification. If an optimistic node
imports this malicious chain, that node will have a "poisoned" fork choice
store, such that the node is unable to produce a block that descends from the
head (due to the invalid chain of payloads) and the node is unable to produce a
block that forks around the head (due to the justification of the malicious
2021-12-19 23:15:51 +00:00
chain).
2021-12-20 07:32:47 +00:00
If honest chain exists which justifies a higher epoch than the malicious chain,
that chain will take precedence and revive any poisoned store. Therefore, the
poisoning attack is temporary if >= 2/3rds of the network is honest and
non-faulty.
2021-12-19 23:15:51 +00:00
The `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY` parameter assumes that the network
will justify a honest chain within some number of slots. With this assumption,
2021-12-20 00:12:11 +00:00
it is acceptable to optimistically import transition blocks during the sync
process. Since there is an assumption that an honest chain with a higher
2021-12-19 23:15:51 +00:00
justified checkpoint exists, any fork choice poisoning will be short-lived and
resolved before that node is required to produce a block.
However, the assumption that the honest, canonical chain will always justify
within `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY` slots is dubious. Therefore,
clients MUST provide the following command line flag to assist with manual
disaster recovery:
2021-12-20 00:12:11 +00:00
- `--safe-slots-to-import-optimistically`: modifies the
2021-12-19 23:15:51 +00:00
`SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY`.
2021-12-14 05:10:19 +00:00
## Checkpoint Sync (Weak Subjectivity Sync)
2021-12-20 06:46:42 +00:00
A consensus engine MAY assume that the `ExecutionPayload` of a block used as an
anchor for checkpoint sync is `VALID` without necessarily providing that
payload to an execution engine.
2021-12-14 05:10:19 +00:00
2021-12-13 08:02:45 +00:00
## Validator assignments
2021-12-20 07:32:54 +00:00
An optimistic node is *not* a full node. It is unable to 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, since it has not fully
verified that block.
2021-12-13 08:02:45 +00:00
2021-12-13 08:15:53 +00:00
### Block Production
2021-12-05 23:07:54 +00:00
An optimistic validator MUST NOT produce a block (i.e., sign across the
2021-12-20 07:32:54 +00:00
`DOMAIN_BEACON_PROPOSER` domain).
2021-12-05 23:07:54 +00:00
### Attesting
An optimistic validator MUST NOT participate in attestation (i.e., sign across the
`DOMAIN_BEACON_ATTESTER`, `DOMAIN_SELECTION_PROOF` or
2021-12-13 08:03:35 +00:00
`DOMAIN_AGGREGATE_AND_PROOF` domains).
2021-12-13 06:09:09 +00:00
### 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).
2021-12-13 08:02:45 +00:00
## P2P Networking
2021-12-13 08:15:53 +00:00
### The Gossip Domain (gossipsub)
2021-12-13 08:02:45 +00:00
#### `beacon_block`
2021-12-13 08:15:53 +00:00
An optimistic validator MAY subscribe to the `beacon_block` topic. Propagation
2021-12-13 08:02:45 +00:00
validation conditions are modified as such:
Do not apply the existing condition:
- [REJECT] The block's parent (defined by `block.parent_root`) passes validation.
2021-12-13 08:02:45 +00:00
Instead, apply the new condition:
- [REJECT] The block's parent (defined by `block.parent_root`) passes all
validation, excluding verification of the `block.body.execution_payload`.
- [IGNORE] The block's parent (defined by `block.parent_root`) passes all
validation, including verification of the `block.body.execution_payload`.
2021-12-20 06:19:32 +00:00
The effect of these modifications is that invalid payloads may be propagated
across the network, but only when contained inside a block that is valid in *all
other aspects*.
2021-12-13 08:02:45 +00:00
2021-12-14 04:51:26 +00:00
#### Other Topics
2021-12-13 08:02:45 +00:00
2021-12-14 04:51:26 +00:00
An optimistic node MUST NOT subscribe to the following topics:
2021-12-13 08:02:45 +00:00
2021-12-14 04:51:26 +00:00
- `beacon_aggregate_and_proof`
- `voluntary_exit`
- `proposer_slashing`
- `attester_slashing`
- `beacon_attestation_{subnet_id}`
- `sync_committee_contribution_and_proof`
- `sync_committee_{subnet_id}`
2021-12-13 08:02:45 +00:00
2021-12-21 22:32:33 +00:00
Once the node ceases to be optimistic, it MAY re-subscribe to the
aforementioned topics.
2021-12-13 08:25:33 +00:00
### The Req/Resp Domain
2021-12-20 05:21:11 +00:00
Non-faulty, optimistic nodes may send blocks which result in an INVALID
response from an execution engine. To prevent network segregation between
optimistic and non-optimistic nodes, transmission of an INVALID payload SHOULD
NOT cause a node to be down-scored or disconnected.
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
## Ethereum Beacon APIs
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
Consensus engines which provide an implementation of the [Ethereum Beacon
APIs](https://github.com/ethereum/beacon-APIs) must take care to avoid
presenting optimistic blocks as fully-verified blocks.
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
### Helpers
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
Let the following response types be defined as any response with the
corresponding HTTP status code:
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
- "Success" Response: Status Codes 200-299.
- "Not Found" Response: Status Code 404.
- "Syncing" Response: Status Code 503.
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
### Requests for Optimistic Blocks
2021-12-13 08:25:33 +00:00
2021-12-20 05:21:11 +00:00
When information about an optimistic block is requested, the consensus engine:
2021-12-14 05:11:40 +00:00
2021-12-20 05:21:11 +00:00
- MUST NOT respond with success.
- MAY respond with not found.
- MAY respond with syncing.
2021-12-14 05:11:40 +00:00
2021-12-20 06:46:42 +00:00
### Requests for an Optimistic Head
2021-12-14 05:11:40 +00:00
When `is_optimistic(head) is True`, the consensus engine:
2021-12-14 05:11:40 +00:00
2021-12-20 06:46:42 +00:00
- MUST NOT return an optimistic `head`.
2021-12-20 05:21:11 +00:00
- MAY substitute the head block with `latest_valid_ancestor(block)`.
- MAY return syncing.
### Requests to Validators Endpoints
2021-12-14 05:11:40 +00:00
When `is_optimistic(head) is True`, the consensus engine MUST return syncing to
2021-12-20 06:46:42 +00:00
all endpoints which match the following pattern:
2021-12-14 05:11:40 +00:00
2021-12-20 06:46:42 +00:00
- `eth/*/validator/*`