From d71bb856e7c49eb0d97697ad62303053f4ef73c1 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 15 Sep 2020 17:10:39 -0700 Subject: [PATCH 1/8] Added weak subjectivity guide --- specs/phase0/weak-subjectivity.md | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 specs/phase0/weak-subjectivity.md diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md new file mode 100644 index 0000000000..26fdc9fdb1 --- /dev/null +++ b/specs/phase0/weak-subjectivity.md @@ -0,0 +1,79 @@ +# Ethereum 2.0 Phase 0 -- Weak Subjectivity Guide + +**Notice**: This document is a work-in-progress for researchers and implementers. + +## 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: +- [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](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md) and [Phase 0 -- Beacon Chain Fork Choice](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/fork-choice.md). + +## 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](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2). + +Note: `compute_weak_subjectivity_period()` is planned to be updated when a more accurate calculation is made. +```python + 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` is the root of a block at epoch `epoch_number`. Example: +``` +0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544 +``` +2. - *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. + +Additionally, 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: +```python + 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. From dc841d4bf690dd339582d80b285718b98237a389 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 15 Sep 2020 17:21:38 -0700 Subject: [PATCH 2/8] Cosmetic changes to WS guide --- specs/phase0/weak-subjectivity.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 26fdc9fdb1..ebc65f78d3 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -55,7 +55,7 @@ A brief reference for what these values look like in practice: ## 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**: +### Weak Subjectivity Sync Procedure 1. Take a Weak Subjectivity Checkpoint as a CLI parameter input in `block_root:epoch_number` format, where `block_root` is the root of a block at epoch `epoch_number`. Example: ``` 0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544 @@ -63,7 +63,8 @@ Clients should allow users to input a Weak Subjectivity Checkpoint at startup, a 2. - *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. -Additionally, 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: +### 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: ```python 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 From 2b81ec9337546eaf5330f43b2f08657f0b4cb4af Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 15 Sep 2020 17:33:01 -0700 Subject: [PATCH 3/8] Added TOC to WS guide --- specs/phase0/weak-subjectivity.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index ebc65f78d3..92a5f738f0 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -2,6 +2,26 @@ **Notice**: This document is a work-in-progress for researchers and implementers. +## Table of contents + + + + + +- [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) + + + + ## 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: - [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) From 3fd0eaa67a2996d55caa152f6c24c194c85df6ab Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 15 Sep 2020 17:37:38 -0700 Subject: [PATCH 4/8] Fix in WS guide --- specs/phase0/weak-subjectivity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 92a5f738f0..880f57094e 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -93,7 +93,7 @@ Clients may choose to validate that the input Weak Subjectivity Checkpoint is no 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" + assert current_epoch <= ws_state_epoch + ws_period, "The input Weak Subjectivity Checkpoint is stale" ``` ## Distributing Weak Subjectivity Checkpoints From 2023b24d72a45f182b1d6d2e955003b61b67ee17 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Wed, 16 Sep 2020 19:52:21 -0700 Subject: [PATCH 5/8] Small change to CLI input description --- specs/phase0/weak-subjectivity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 880f57094e..00bb01c42d 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -76,7 +76,7 @@ A brief reference for what these values look like in practice: 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` is the root of a block at epoch `epoch_number`. Example: +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 ``` From 6b33c766f28e82c23e7482a3996dc7e119df00fc Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Thu, 17 Sep 2020 10:26:49 -0700 Subject: [PATCH 6/8] Apply suggestions from Danny's code review Co-authored-by: Danny Ryan --- specs/phase0/weak-subjectivity.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 00bb01c42d..bb12f6ef53 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -3,6 +3,7 @@ **Notice**: This document is a work-in-progress for researchers and implementers. ## Table of contents + @@ -28,7 +29,7 @@ This document is a guide for implementing the Weak Subjectivity protections in P - [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](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md) and [Phase 0 -- Beacon Chain Fork Choice](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/fork-choice.md). +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). ## Constants | Name | Value | @@ -40,20 +41,23 @@ This document uses data structures, constants, functions, and terminology from [ 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`. +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`. ### Calculating the Weak Subjectivity Period For more information about this calculation, refer to [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2). -Note: `compute_weak_subjectivity_period()` is planned to be updated when a more accurate calculation is made. +*Note*: `compute_weak_subjectivity_period()` is planned to be updated when a more accurate calculation is made. + ```python - def compute_weak_subjectivity_period(state): + def compute_weak_subjectivity_period(state: BeaconState) -> uint64: weak_subjectivity_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY - val_count = len(get_active_validator_indices(state, get_current_epoch(state))) + validator_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) + 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) + weak_subjectivity_period += SAFETY_DECAY * val_count / (2 * 100 * MIN_PER_EPOCH_CHURN_LIMIT) return weak_subjectivity_period ``` @@ -73,10 +77,10 @@ A brief reference for what these values look like in practice: | 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. +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. ### 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: +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: ``` 0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544 ``` @@ -86,7 +90,7 @@ Clients should allow users to input a Weak Subjectivity Checkpoint at startup, a ### 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: ```python - def is_within_weak_subjectivity_period(store, ws_state, ws_checkpoint): + def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_checkpoint: Checkpoint) -> bool: # 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 From 58d225c9be7fa7f78bce7282c1124d4ee7061616 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Thu, 17 Sep 2020 10:34:37 -0700 Subject: [PATCH 7/8] Added WIP note, explanation for WS period calculation --- specs/phase0/weak-subjectivity.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index bb12f6ef53..eaee8e7786 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -24,7 +24,7 @@ ## 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: +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: - [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/) @@ -46,8 +46,6 @@ The Weak Subjectivity Period is the number of recent epochs within which there m `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`. ### Calculating the Weak Subjectivity Period -For more information about this calculation, refer to [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2). - *Note*: `compute_weak_subjectivity_period()` is planned to be updated when a more accurate calculation is made. ```python @@ -61,6 +59,10 @@ For more information about this calculation, refer to [Weak Subjectivity in Eth2 return weak_subjectivity_period ``` +*Details about the calculation*: +- `100` appears in the denominator to get the actual percentage ratio from `SAFETY_DECAY` +- For more information about other terms in this equation, refer to [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) + A brief reference for what these values look like in practice: | `val_count` | `weak_subjectivity_period` | From 8bb05827ab8e0bc2fa3d27e7592dd0bdb092ac9a Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 17 Sep 2020 12:01:25 -0600 Subject: [PATCH 8/8] add weak-subjectivity.md to setup.py build and do final lint cleanups --- setup.py | 2 + specs/phase0/weak-subjectivity.md | 64 +++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/setup.py b/setup.py index d1f7b35cea..dee23cb584 100644 --- a/setup.py +++ b/setup.py @@ -382,12 +382,14 @@ def finalize_options(self): specs/phase0/beacon-chain.md specs/phase0/fork-choice.md specs/phase0/validator.md + specs/phase0/weak-subjectivity.md """ elif self.spec_fork == "phase1": self.md_doc_paths = """ specs/phase0/beacon-chain.md specs/phase0/fork-choice.md specs/phase0/validator.md + specs/phase0/weak-subjectivity.md specs/phase1/custody-game.md specs/phase1/beacon-chain.md specs/phase1/shard-transition.md diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index eaee8e7786..07c3083a3c 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -24,48 +24,65 @@ ## 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: + +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: + - [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). + +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). ## 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. + +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 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`. +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`. ### Calculating the Weak Subjectivity Period + *Note*: `compute_weak_subjectivity_period()` is planned to be updated when a more accurate calculation is made. ```python - def compute_weak_subjectivity_period(state: BeaconState) -> uint64: +def compute_weak_subjectivity_period(state: BeaconState) -> uint64: weak_subjectivity_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY validator_count = len(get_active_validator_indices(state, get_current_epoch(state))) - if val_count >= MIN_PER_EPOCH_CHURN_LIMIT * CHURN_LIMIT_QUOTIENT: + if validator_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) + weak_subjectivity_period += SAFETY_DECAY * validator_count / (2 * 100 * MIN_PER_EPOCH_CHURN_LIMIT) return weak_subjectivity_period ``` *Details about the calculation*: - `100` appears in the denominator to get the actual percentage ratio from `SAFETY_DECAY` -- For more information about other terms in this equation, refer to [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) +- For more information about other terms in this equation, refer to + [Weak Subjectivity in Eth2.0](https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2) A brief reference for what these values look like in practice: -| `val_count` | `weak_subjectivity_period` | +| `validator_count` | `weak_subjectivity_period` | | ---- | ---- | | 1024 | 268 | | 2048 | 281 | @@ -79,27 +96,40 @@ A brief reference for what these values look like in practice: | 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 along 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. 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: + +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: ``` 0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544 ``` -2. - *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. +2. - *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: +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: + ```python - def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_checkpoint: Checkpoint) -> bool: +def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_checkpoint: Checkpoint) -> bool: # 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" + return current_epoch <= ws_state_epoch + ws_period ``` ## Distributing Weak Subjectivity Checkpoints