eth2.0-specs/sync/optimistic.md

283 lines
10 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-19 23:15:51 +00:00
|`SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY`| `96` | slots
*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
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 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) -> bool:
hash_tree_root(block) in optimistic_roots
```
```python
def latest_valid_ancestor(block: BeaconBlock) -> BeaconBlock:
while True:
if not is_optimistic(block) or block.parent_root == Root():
return block
block = get_block(block.parent_root)
```
```python
def is_execution_block(block: BeaconBlock) -> BeaconBlock:
block.execution_payload != ExecutionPayload()
```
2021-12-19 03:56:46 +00:00
```python
def should_optimistically_import_block(current_slot: Slot, block: BeaconBlock) -> bool:
block.slot + SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY <= current_slot
```
2021-12-19 03:44:21 +00:00
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*.
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
2021-12-19 03:44:21 +00:00
## When to optimistically import blocks
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) == 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.*
2021-12-19 03:44:21 +00:00
## How to optimistically import blocks
To optimistically import a block:
2021-12-05 23:07:54 +00:00
- The `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`.
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-14 05:22:52 +00:00
When a node 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
validity request some block, a consensus engine:
- 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
unknown). Specifically, `SYNCING` responses should be fork-specific; the search
for a block on one chain MUST NOT trigger a `SYNCING` response for another
chain.
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
Consensus engines MUST support removing from fork choice blocks that transition
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 00:12:11 +00:00
eternally-unavailable `body.execution_payload.parent_hash` value. In rare
2021-12-19 23:15:51 +00:00
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 child of the head (due to the invalid chain of payloads) and the node
is unable to fork around the head (due to the justification of the malicious
chain).
The fork choice poisoning attack is temporary for an individual node, assuming
2021-12-20 00:12:11 +00:00
there exists an honest chain which justifies a higher epoch than the malicious
chain. Such an honest chain will take precedence and revive any poisoned store.
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)
A consensus engine MAY assume that the `ExecutionPayload` of a block used for
2021-12-20 00:12:11 +00:00
checkpoint sync is `VALID` without 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
An entirely optimistically synced 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:15:53 +00:00
### Block Production
2021-12-05 23:07:54 +00:00
A optimistic validator MUST NOT produce a block (i.e., sign across the
2021-12-13 08:15:53 +00:00
`DOMAIN_BEACON_PROPOSER` domain), unless one of the following exceptions are
met:
2021-12-05 23:07:54 +00:00
2021-12-13 08:15:53 +00:00
#### Block Production Exception 1.
2021-12-05 23:07:54 +00:00
If the justified block is fully verified (i.e., `not
2021-12-13 06:09:09 +00:00
is_optimistic(justified_block)`, the validator MAY produce a block upon
2021-12-05 23:07:54 +00:00
`latest_valid_ancestor(head)`.
### 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.
Instead, apply the new condition:
- [REJECT] The block's parent (defined by block.parent_root) passes validation,
*and* `block.parent root not in optimistic_roots`.
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-14 04:51:26 +00:00
Once the node ceases to be optimistic, it MAY re-subscribe to the aformentioned
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 05:21:11 +00:00
### Requests for the Head
2021-12-14 05:11:40 +00:00
2021-12-20 05:21:11 +00:00
When `is_optimistic(head) == True`, the consensus engine:
2021-12-14 05:11:40 +00:00
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) == True`, the consensus engine:
2021-12-20 05:21:11 +00:00
MUST respon