eth2.0-specs/specs/phase0/weak-subjectivity.md

171 lines
7.3 KiB
Markdown
Raw Normal View History

2020-09-16 00:10:39 +00:00
# Ethereum 2.0 Phase 0 -- Weak Subjectivity Guide
2020-09-16 00:33:01 +00:00
## Table of contents
2020-09-16 00:33:01 +00:00
<!-- TOC -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Introduction](#introduction)
- [Prerequisites](#prerequisites)
- [Constants](#constants)
- [Weak Subjectivity Checkpoint](#weak-subjectivity-checkpoint)
- [Weak Subjectivity Period](#weak-subjectivity-period)
- [Calculating the Weak Subjectivity Period](#calculating-the-weak-subjectivity-period)
- [Weak Subjectivity Sync](#weak-subjectivity-sync)
- [Weak Subjectivity Sync Procedure](#weak-subjectivity-sync-procedure)
- [Checking for Stale Weak Subjectivity Checkpoint](#checking-for-stale-weak-subjectivity-checkpoint)
- [Distributing Weak Subjectivity Checkpoints](#distributing-weak-subjectivity-checkpoints)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
2020-09-16 00:10:39 +00:00
## Introduction
This document is a guide for implementing the Weak Subjectivity protections in Phase 0 of Ethereum 2.0.
This document is still a work-in-progress, and is subject to large changes.
For more information about weak subjectivity and why it is required, please refer to:
2020-09-16 00:10:39 +00:00
- [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2)
- [Proof of Stake: How I Learned to Love Weak Subjectivity](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/)
## Prerequisites
This document uses data structures, constants, functions, and terminology from
[Phase 0 -- The Beacon Chain](./beacon-chain.md) and [Phase 0 -- Beacon Chain Fork Choice](./fork-choice.md).
2020-09-16 00:10:39 +00:00
## Constants
2020-09-16 00:10:39 +00:00
| Name | Value |
|----------------|--------------|
| `SAFETY_DECAY` | `uint64(10)` |
## Weak Subjectivity Checkpoint
Any `Checkpoint` object can be used as a Weak Subjectivity Checkpoint.
These Weak Subjectivity Checkpoints are distributed by providers,
downloaded by users and/or distributed as a part of clients, and used as input while syncing a client.
2020-09-16 00:10:39 +00:00
## Weak Subjectivity Period
The Weak Subjectivity Period is the number of recent epochs within which there
must be a Weak Subjectivity Checkpoint to ensure that an attacker who takes control
of the validator set at the beginning of the period is slashed at least a minimum threshold
in the event that a conflicting `Checkpoint` is finalized.
`SAFETY_DECAY` is defined as the maximum percentage tolerable loss in the one-third
safety margin of FFG finality. Thus, any attack exploiting the Weak Subjectivity Period has
a safety margin of at least `1/3 - SAFETY_DECAY/100`.
2020-09-16 00:10:39 +00:00
### Calculating the Weak Subjectivity Period
2021-01-19 09:53:12 +00:00
A detailed analysis of the calculation of the weak subjectivity period is made in [this report](https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf). The expressions in the report use fractions, whereas we only use uint64 arithmetic in eth2.0-specs. The expressions have been simplified to avoid computing fractions, and more details can be found [here](https://www.overleaf.com/read/wgjzjdjpvpsd).
2020-09-16 00:10:39 +00:00
```python
2021-01-19 09:53:12 +00:00
def get_active_validator_count(state: BeaconState) -> uint64:
active_validator_count = len(get_active_validator_indices(state, get_current_epoch(state)))
return active_validator_count
def compute_avg_active_validator_balance(state: BeaconState) -> Gwei:
total_active_balance = get_total_active_balance(state)
active_validator_count = get_active_validator_count(state)
avg_active_validator_balance = total_active_balance // active_validator_count
return avg_active_validator_balance//10**9
def compute_weak_subjectivity_period(state: BeaconState) -> uint64:
2021-01-19 09:53:12 +00:00
ws_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY
N = get_active_validator_count(state)
t = compute_avg_active_validator_balance(state)
T = MAX_EFFECTIVE_BALANCE//10**9
delta = get_validator_churn_limit(state)
Delta = MAX_DEPOSITS * SLOTS_PER_EPOCH
D = SAFETY_DECAY
case = (
T*(200+3*D) < t*(200+12*D)
)
if case == 1:
arg1 = (
N*(t*(200+12*D) - T*(200+3*D)) // (600*delta*(2*t+T))
)
arg2 = (
N*(200+3*D) // (600*Delta)
)
ws_period += max(arg1, arg2)
2020-09-16 00:10:39 +00:00
else:
2021-01-19 09:53:12 +00:00
ws_period += (
3*N*D*t // (200*Delta*(T-t))
)
return ws_period
2020-09-16 00:10:39 +00:00
```
A brief reference for what these values look like in practice:
2021-01-19 09:53:12 +00:00
| SAFETY_DECAY | validator_count | average_active_validator_balance | weak_subjectivity_period |
| ---- | ---- | ---- | ---- |
| 10 | 8192 | 28 | 318 |
| 10 | 8192 | 32 | 358 |
| 10 | 16384 | 28 | 380 |
| 10 | 16384 | 32 | 460 |
| 10 | 32768 | 28 | 504 |
| 10 | 32768 | 32 | 665 |
| 20 | 8192 | 28 | 411 |
| 20 | 8192 | 32 | 460 |
| 20 | 16384 | 28 | 566 |
| 20 | 16384 | 32 | 665 |
| 20 | 32768 | 28 | 876 |
| 20 | 32768 | 32 | 1075 |
| 33 | 8192 | 28 | 532 |
| 33 | 8192 | 32 | 593 |
| 33 | 16384 | 28 | 808 |
| 33 | 16384 | 32 | 931 |
| 33 | 32768 | 28 | 1360 |
| 33 | 32768 | 32 | 1607 |
2020-09-16 00:10:39 +00:00
## Weak Subjectivity Sync
Clients should allow users to input a Weak Subjectivity Checkpoint at startup, and guarantee that any successful sync leads to the given Weak Subjectivity Checkpoint along the canonical chain. If such a sync is not possible, the client should treat this as a critical and irrecoverable failure.
2020-09-16 00:10:39 +00:00
2020-09-16 00:21:38 +00:00
### Weak Subjectivity Sync Procedure
1. Input a Weak Subjectivity Checkpoint as a CLI parameter in `block_root:epoch_number` format,
where `block_root` (an "0x" prefixed 32-byte hex string) and `epoch_number` (an integer) represent a valid `Checkpoint`.
Example of the format:
2021-01-19 09:53:12 +00:00
```
2020-09-16 00:10:39 +00:00
0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544
```
2021-01-19 09:53:12 +00:00
2. Check the weak subjectivity requirements:
- *IF* `epoch_number > store.finalized_checkpoint.epoch`,
then *ASSERT* during block sync that block with root `block_root` is in the sync path at epoch `epoch_number`.
Emit descriptive critical error if this assert fails, then exit client process.
- *IF* `epoch_number <= store.finalized_checkpoint.epoch`,
2021-01-19 09:53:12 +00:00
then *ASSERT* that the block in the canonical chain at epoch `epoch_number` has root `block_root`.
Emit descriptive critical error if this assert fails, then exit client process.
2020-09-16 00:10:39 +00:00
2020-09-16 00:21:38 +00:00
### Checking for Stale Weak Subjectivity Checkpoint
2021-01-19 09:53:12 +00:00
Clients may choose to validate that the input Weak Subjectivity Checkpoint is not stale at the time of startup.
To support this mechanism, the client needs to take the state at the Weak Subjectivity Checkpoint as
a CLI parameter input (or fetch the state associated with the input Weak Subjectivity Checkpoint from some source).
The check can be implemented in the following way:
2020-09-16 00:10:39 +00:00
```python
def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_checkpoint: Checkpoint) -> bool:
2020-09-16 00:10:39 +00:00
# Clients may choose to validate the input state against the input Weak Subjectivity Checkpoint
assert ws_state.latest_block_header.state_root == ws_checkpoint.root
assert compute_epoch_at_slot(ws_state.slot) == ws_checkpoint.epoch
2020-09-16 00:10:39 +00:00
ws_period = compute_weak_subjectivity_period(ws_state)
ws_state_epoch = compute_epoch_at_slot(ws_state.slot)
current_epoch = compute_epoch_at_slot(get_current_slot(store))
return current_epoch <= ws_state_epoch + ws_period
2020-09-16 00:10:39 +00:00
```
## Distributing Weak Subjectivity Checkpoints
2021-01-19 09:53:12 +00:00
2020-09-16 00:10:39 +00:00
This section will be updated soon.