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

5.9 KiB

Ethereum 2.0 Phase 0 -- Weak Subjectivity Guide

Notice: This document is a work-in-progress for researchers and implementers.

Table of contents

Introduction

This document is a guide for implementing the Weak Subjectivity protections in Phase 0 of Ethereum 2.0. For more information about weak subjectivity and why it is required, please refer to:

Prerequisites

This document uses data structures, constants, functions, and terminology from Phase 0 -- The Beacon Chain and Phase 0 -- Beacon Chain Fork Choice.

Constants

Name Value
SAFETY_DECAY uint64(10)

Weak Subjectivity Checkpoint

Any Checkpoint can used be 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.

Weak Subjectivity Period

The Weak Subjectivity Period is the number of recent epochs within which there must be a Weak Subjectivity Checkpoint so that an attacker who takes control of the validator set at the beginning of the period is slashed at least a threshold amount in case a conflicting Checkpoint is finalized. SAFETY_DECAY is defined as the maximum percentage tolerable loss in the 1/3rd safety margin of FFG finality, which makes our threshold amount of slashing to be 1/3 - SAFETY_DECAY/100.

Calculating the Weak Subjectivity Period

For more information about this calculation, refer to Weak Subjectivity in Eth2.0.

Note: compute_weak_subjectivity_period() is planned to be updated when a more accurate calculation is made.

  def compute_weak_subjectivity_period(state):
    weak_subjectivity_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY
    val_count = len(get_active_validator_indices(state, get_current_epoch(state)))
    if val_count >= MIN_PER_EPOCH_CHURN_LIMIT * CHURN_LIMIT_QUOTIENT:
        weak_subjectivity_period += SAFETY_DECAY*CHURN_LIMIT_QUOTIENT/(2*100)
    else:
        weak_subjectivity_period += SAFETY_DECAY*val_count/(2*100*MIN_PER_EPOCH_CHURN_LIMIT)
    return weak_subjectivity_period

A brief reference for what these values look like in practice:

val_count weak_subjectivity_period
1024 268
2048 281
4096 307
8192 358
16384 460
32768 665
65536 1075
131072 1894
262144 3532
524288 3532

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 being in the canonical chain. If such a sync is not possible, the client should treat this as a critical and irrecoverable failure.

Weak Subjectivity Sync Procedure

  1. Take a Weak Subjectivity Checkpoint as a CLI parameter input in block_root:epoch_number format, where block_root and epoch_number represent a valid Checkpoint. Example of the format:
0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544
    • 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, 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.

Checking for Stale Weak Subjectivity Checkpoint

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:

  def is_within_weak_subjectivity_period(store, ws_state, ws_checkpoint):
    # 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
    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))
    assert current_epoch <= ws_state_epoch + ws_period, "The input Weak Subjectivity Checkpoint is stale"

Distributing Weak Subjectivity Checkpoints

This section will be updated soon.