From 37874f9b790ba457f160f9a77e625af5bd212974 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 19 Jan 2021 01:53:12 -0800 Subject: [PATCH 1/7] Update WS calc --- specs/phase0/weak-subjectivity.md | 101 ++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index a99887926..6e2515185 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -59,38 +59,70 @@ 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. +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). ```python -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 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 * validator_count // (2 * 100 * MIN_PER_EPOCH_CHURN_LIMIT) - return weak_subjectivity_period -``` +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 -*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) +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: + 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) + else: + ws_period += ( + 3*N*D*t // (200*Delta*(T-t)) + ) + + return ws_period +``` A brief reference for what these values look like in practice: -| `validator_count` | `weak_subjectivity_period` | -| ---- | ---- | -| 1024 | 268 | -| 2048 | 281 | -| 4096 | 307 | -| 8192 | 358 | -| 16384 | 460 | -| 32768 | 665 | -| 65536 | 1075 | -| 131072 | 1894 | -| 262144 | 3532 | -| 524288 | 3532 | +| 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 | ## Weak Subjectivity Sync @@ -101,17 +133,21 @@ Clients should allow users to input a Weak Subjectivity Checkpoint at startup, a 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: -``` + +```python 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. + +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`, - 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. + 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). @@ -130,4 +166,5 @@ def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_c ``` ## Distributing Weak Subjectivity Checkpoints + This section will be updated soon. From 93c4c62900de17ebffa5786fe5f118392de9fc36 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 19 Jan 2021 02:04:55 -0800 Subject: [PATCH 2/7] Remove python tag from fenced code block --- 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 6e2515185..f5dcdba98 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -134,7 +134,7 @@ Clients should allow users to input a Weak Subjectivity Checkpoint at startup, a where `block_root` (an "0x" prefixed 32-byte hex string) and `epoch_number` (an integer) represent a valid `Checkpoint`. Example of the format: -```python +``` 0x8584188b86a9296932785cc2827b925f9deebacce6d72ad8d53171fa046b43d9:9544 ``` From 900eb4a83cfb808ab176d35fc3ddd60436dbc2c2 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Wed, 20 Jan 2021 19:33:25 -0800 Subject: [PATCH 3/7] Fixed CI errors --- specs/phase0/weak-subjectivity.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index f5dcdba98..2dd28df3d 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -8,7 +8,9 @@ - [Introduction](#introduction) - [Prerequisites](#prerequisites) +- [Custom Types](#custom-types) - [Constants](#constants) +- [Configuration](#configuration) - [Weak Subjectivity Checkpoint](#weak-subjectivity-checkpoint) - [Weak Subjectivity Period](#weak-subjectivity-period) - [Calculating the Weak Subjectivity Period](#calculating-the-weak-subjectivity-period) @@ -34,10 +36,22 @@ For more information about weak subjectivity and why it is required, please refe 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). +## Custom Types + +| Name | SSZ Equivalent | Description | +|---|---|---| +| `Ether` | `uint64` | an amount in Ether | + ## Constants -| Name | Value | -|----------------|--------------| +| Name | Value | +|---|---| +| `ETH_TO_GWEI` | `uint64(10**9)` | + +## Configuration + +| Name | Value | +|---|---| | `SAFETY_DECAY` | `uint64(10)` | ## Weak Subjectivity Checkpoint @@ -66,11 +80,12 @@ 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: +def compute_avg_active_validator_balance(state: BeaconState) -> Ether: 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 + avg_active_validator_balance_gwei = total_active_balance // active_validator_count + avg_active_validator_balance_eth = avg_active_validator_balance_gwei // ETH_TO_GWEI + return avg_active_validator_balance_eth def compute_weak_subjectivity_period(state: BeaconState) -> uint64: ws_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY @@ -103,7 +118,7 @@ def compute_weak_subjectivity_period(state: BeaconState) -> uint64: A brief reference for what these values look like in practice: -| SAFETY_DECAY | validator_count | average_active_validator_balance | weak_subjectivity_period | +| Safety Decay | Validator Count | Average Active Validator Balance | Weak Subjectivity Period | | ---- | ---- | ---- | ---- | | 10 | 8192 | 28 | 318 | | 10 | 8192 | 32 | 358 | From c932fc279897bcc4a7bdf109a97d70ceac7cd666 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Thu, 21 Jan 2021 17:07:45 -0800 Subject: [PATCH 4/7] Fix linter errors --- specs/phase0/weak-subjectivity.md | 40 +++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 2dd28df3d..75cdbec40 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -14,9 +14,13 @@ - [Weak Subjectivity Checkpoint](#weak-subjectivity-checkpoint) - [Weak Subjectivity Period](#weak-subjectivity-period) - [Calculating the Weak Subjectivity Period](#calculating-the-weak-subjectivity-period) + - [`get_active_validator_count`](#get_active_validator_count) + - [`compute_avg_active_validator_balance`](#compute_avg_active_validator_balance) + - [`compute_weak_subjectivity_period`](#compute_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) + - [`is_within_weak_subjectivity_period`](#is_within_weak_subjectivity_period) - [Distributing Weak Subjectivity Checkpoints](#distributing-weak-subjectivity-checkpoints) @@ -75,43 +79,53 @@ a safety margin of at least `1/3 - SAFETY_DECAY/100`. 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). +#### `get_active_validator_count` + ```python 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 +``` +#### `compute_avg_active_validator_balance` + +```python def compute_avg_active_validator_balance(state: BeaconState) -> Ether: total_active_balance = get_total_active_balance(state) active_validator_count = get_active_validator_count(state) avg_active_validator_balance_gwei = total_active_balance // active_validator_count avg_active_validator_balance_eth = avg_active_validator_balance_gwei // ETH_TO_GWEI return avg_active_validator_balance_eth +``` +#### `compute_weak_subjectivity_period` + +```python def compute_weak_subjectivity_period(state: BeaconState) -> uint64: 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 + 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) + 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) + 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) else: - ws_period += ( - 3*N*D*t // (200*Delta*(T-t)) - ) + ws_period += ( + 3 * N * D * t // (200 * Delta * (T - t)) + ) return ws_period ``` @@ -168,6 +182,8 @@ To support this mechanism, the client needs to take the state at the Weak Subjec 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: +#### `is_within_weak_subjectivity_period` + ```python 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 From 742d21e914b247e7621467cfcdb2b3339bbcd14d Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Wed, 27 Jan 2021 15:16:15 -0800 Subject: [PATCH 5/7] Updates based on review --- specs/phase0/weak-subjectivity.md | 77 ++++++++++++------------------- 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 75cdbec40..42034ed1a 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -14,8 +14,6 @@ - [Weak Subjectivity Checkpoint](#weak-subjectivity-checkpoint) - [Weak Subjectivity Period](#weak-subjectivity-period) - [Calculating the Weak Subjectivity Period](#calculating-the-weak-subjectivity-period) - - [`get_active_validator_count`](#get_active_validator_count) - - [`compute_avg_active_validator_balance`](#compute_avg_active_validator_balance) - [`compute_weak_subjectivity_period`](#compute_weak_subjectivity_period) - [Weak Subjectivity Sync](#weak-subjectivity-sync) - [Weak Subjectivity Sync Procedure](#weak-subjectivity-sync-procedure) @@ -77,44 +75,33 @@ a safety margin of at least `1/3 - SAFETY_DECAY/100`. ### Calculating the Weak Subjectivity Period -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). +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). -#### `get_active_validator_count` +*Note*: The expressions in the report use fractions, whereas eth2.0-specs uses only `uint64` arithmetic. The expressions have been simplified to avoid computing fractions, and more details can be found [here](https://www.overleaf.com/read/wgjzjdjpvpsd). -```python -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 -``` - -#### `compute_avg_active_validator_balance` - -```python -def compute_avg_active_validator_balance(state: BeaconState) -> Ether: - total_active_balance = get_total_active_balance(state) - active_validator_count = get_active_validator_count(state) - avg_active_validator_balance_gwei = total_active_balance // active_validator_count - avg_active_validator_balance_eth = avg_active_validator_balance_gwei // ETH_TO_GWEI - return avg_active_validator_balance_eth -``` +*Note*: The calculations here use `Ether` instead of `Gwei`, because the large magitude of balances in `Gwei` can cause an overflow while computing using `uint64` arithmetic operations. Using `Ether` reduces the magintude of the multiplicative factors by an order of `ETH_TO_GWEI` (`= 10**9`) and avoid the scope for overflows in `uint64`. #### `compute_weak_subjectivity_period` ```python def compute_weak_subjectivity_period(state: BeaconState) -> uint64: + """ + Returns the weak subjectivity period for the current ``state``. + This computation takes into account the effect of: + - validator set churn (bounded by ``get_validator_churn_limit()`` per epoch), and + - validator balance top-ups (bounded by ``MAX_DEPOSITS * SLOTS_PER_EPOCH`` per epoch). + A detailed calculation can be found at: + https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf + """ 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 + N = len(get_active_validator_indices(state, get_current_epoch(state))) + t = get_total_active_balance(state) // N // ETH_TO_GWEI + T = MAX_EFFECTIVE_BALANCE // ETH_TO_GWEI 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: + if T * (200 + 3 * D) < t * (200 + 12 * D): arg1 = ( N * (t * (200 + 12 * D) - T * (200 + 3 * D)) // (600 * delta * (2 * t + T)) ) @@ -130,28 +117,22 @@ def compute_weak_subjectivity_period(state: BeaconState) -> uint64: return ws_period ``` -A brief reference for what these values look like in practice: +A brief reference for what these values look like in practice ([reference script](https://gist.github.com/adiasg/3aceab409b36aa9a9d9156c1baa3c248)): -| Safety Decay | Validator Count | Average Active Validator Balance | Weak Subjectivity Period | +| Safety Decay | Avg. Val. Balance (ETH) | Val. Count | Weak Sub. Period (Epochs) | | ---- | ---- | ---- | ---- | -| 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 | +| 10 | 28 | 32768 | 504 | +| 10 | 28 | 65536 | 752 | +| 10 | 28 | 131072 | 1248 | +| 10 | 28 | 262144 | 2241 | +| 10 | 28 | 524288 | 2241 | +| 10 | 28 | 1048576 | 2241 | +| 10 | 32 | 32768 | 665 | +| 10 | 32 | 65536 | 1075 | +| 10 | 32 | 131072 | 1894 | +| 10 | 32 | 262144 | 3532 | +| 10 | 32 | 524288 | 3532 | +| 10 | 32 | 1048576 | 3532 | ## Weak Subjectivity Sync From a28f52729dde6f79a87c87eddcfd1f82fbc5e014 Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Wed, 27 Jan 2021 15:58:19 -0800 Subject: [PATCH 6/7] Rename variables for clarity --- specs/phase0/weak-subjectivity.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/phase0/weak-subjectivity.md b/specs/phase0/weak-subjectivity.md index 42034ed1a..f91a04d7e 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -102,13 +102,13 @@ def compute_weak_subjectivity_period(state: BeaconState) -> uint64: D = SAFETY_DECAY if T * (200 + 3 * D) < t * (200 + 12 * D): - arg1 = ( + epochs_for_validator_set_churn = ( N * (t * (200 + 12 * D) - T * (200 + 3 * D)) // (600 * delta * (2 * t + T)) ) - arg2 = ( + epochs_for_balance_top_ups = ( N * (200 + 3 * D) // (600 * Delta) ) - ws_period += max(arg1, arg2) + ws_period += max(epochs_for_validator_set_churn, epochs_for_balance_top_ups) else: ws_period += ( 3 * N * D * t // (200 * Delta * (T - t)) From 8b217d9277fd87755cca256e0836999793be297d Mon Sep 17 00:00:00 2001 From: Aditya Asgaonkar Date: Tue, 2 Feb 2021 12:17:56 -0800 Subject: [PATCH 7/7] Fix typo Co-authored-by: Danny Ryan --- 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 f91a04d7e..4137efade 100644 --- a/specs/phase0/weak-subjectivity.md +++ b/specs/phase0/weak-subjectivity.md @@ -79,7 +79,7 @@ A detailed analysis of the calculation of the weak subjectivity period is made i *Note*: The expressions in the report use fractions, whereas eth2.0-specs uses only `uint64` arithmetic. The expressions have been simplified to avoid computing fractions, and more details can be found [here](https://www.overleaf.com/read/wgjzjdjpvpsd). -*Note*: The calculations here use `Ether` instead of `Gwei`, because the large magitude of balances in `Gwei` can cause an overflow while computing using `uint64` arithmetic operations. Using `Ether` reduces the magintude of the multiplicative factors by an order of `ETH_TO_GWEI` (`= 10**9`) and avoid the scope for overflows in `uint64`. +*Note*: The calculations here use `Ether` instead of `Gwei`, because the large magnitude of balances in `Gwei` can cause an overflow while computing using `uint64` arithmetic operations. Using `Ether` reduces the magnitude of the multiplicative factors by an order of `ETH_TO_GWEI` (`= 10**9`) and avoid the scope for overflows in `uint64`. #### `compute_weak_subjectivity_period`