From f9b359be09df44e12732c90e87d9c281542dc859 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:03:14 +0900 Subject: [PATCH 01/10] Reuse indexes with full sweep --- specs/_features/reuse_indexes/beacon-chain.md | 45 +++++++++++++++++++ specs/altair/beacon-chain.md | 22 ++++++--- 2 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 specs/_features/reuse_indexes/beacon-chain.md diff --git a/specs/_features/reuse_indexes/beacon-chain.md b/specs/_features/reuse_indexes/beacon-chain.md new file mode 100644 index 000000000..fcf1de896 --- /dev/null +++ b/specs/_features/reuse_indexes/beacon-chain.md @@ -0,0 +1,45 @@ +# Reuse indexes -- The Beacon Chain + +## Table of contents + + + + + +- [Introduction](#introduction) +- [Preset](#preset) + - [Time parameters](#time-parameters) +- [Beacon chain state transition function](#beacon-chain-state-transition-function) + - [Block processing](#block-processing) + - [Modified `assign_index_to_deposit`](#modified-assign_index_to_deposit) + + + + +## Introduction + +This is the beacon chain specification to assign new deposits to existing validator records that have withdrawn long ago. + +*Note:* This specification is built upon [Capella](../../capella/beacon_chain.md) and is under active development. + +## Preset + +### Time parameters + +| Name | Value | Unit | Duration | +| - | - | - | +| `REUSE_VALIDATOR_INDEX_DELAY` | `uint64(2**16)` (= 65,536) | epochs | ~1 year | + +## Beacon chain state transition function + +### Block processing + +#### Modified `assign_index_to_deposit` + +```python +def assign_index_to_deposit(state: BeaconState) -> int: + for index, validator in enumerate(state.validators): + if validator.withdrawable_epoch < get_current_epoch(state) - REUSE_VALIDATOR_INDEX_DELAY: + return index + return len(state.validators) +``` diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 58dfad608..d5b89a387 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -511,16 +511,28 @@ def apply_deposit(state: BeaconState, signing_root = compute_signing_root(deposit_message, domain) # Initialize validator if the deposit signature is valid if bls.Verify(pubkey, signing_root, signature): - state.validators.append(get_validator_from_deposit(pubkey, withdrawal_credentials, amount)) - state.balances.append(amount) + index = assign_index_to_deposit(state) + update_list(state.validators, index, get_validator_from_deposit(pubkey, withdrawal_credentials, amount)) + update_list(state.balances, index, amount) # [New in Altair] - state.previous_epoch_participation.append(ParticipationFlags(0b0000_0000)) - state.current_epoch_participation.append(ParticipationFlags(0b0000_0000)) - state.inactivity_scores.append(uint64(0)) + update_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) + update_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) + update_list(state.inactivity_scores, index, uint64(0)) else: # Increase balance by deposit amount index = ValidatorIndex(validator_pubkeys.index(pubkey)) increase_balance(state, index, amount) + + +def assign_index_to_deposit(state: BeaconState) -> int: + return len(state.validators) + + +def update_list(list: List, index: int, value: Any) -> None: + if index == len(list): + list.append(value) + else: + list[index] = value ``` #### Sync aggregate processing From ee3e1ac63e6e675e58d22cf055431b70a6f39696 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 28 Mar 2023 15:34:07 +0900 Subject: [PATCH 02/10] Apply review comments --- specs/_features/reuse_indexes/beacon-chain.md | 28 ++++++++++++++++--- specs/altair/beacon-chain.md | 16 +++++------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/specs/_features/reuse_indexes/beacon-chain.md b/specs/_features/reuse_indexes/beacon-chain.md index fcf1de896..8677631e5 100644 --- a/specs/_features/reuse_indexes/beacon-chain.md +++ b/specs/_features/reuse_indexes/beacon-chain.md @@ -9,9 +9,12 @@ - [Introduction](#introduction) - [Preset](#preset) - [Time parameters](#time-parameters) +- [Helpers](#helpers) + - [Predicates](#predicates) + - [`is_reusable_validator`](#is_reusable_validator) - [Beacon chain state transition function](#beacon-chain-state-transition-function) - [Block processing](#block-processing) - - [Modified `assign_index_to_deposit`](#modified-assign_index_to_deposit) + - [Modified `get_index_for_new_validator`](#modified-get_index_for_new_validator) @@ -30,16 +33,33 @@ This is the beacon chain specification to assign new deposits to existing valida | - | - | - | | `REUSE_VALIDATOR_INDEX_DELAY` | `uint64(2**16)` (= 65,536) | epochs | ~1 year | +## Helper functions + +### Predicates + +#### `is_reusable_validator` + +```python +def is_reusable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> bool: + """ + Check if ``validator`` index can be re-assigned to a new deposit. + """ + return ( + validator.withdrawable_epoch < epoch - REUSE_VALIDATOR_INDEX_DELAY + and balance == 0 + ) +``` + ## Beacon chain state transition function ### Block processing -#### Modified `assign_index_to_deposit` +#### Modified `get_index_for_new_validator` ```python -def assign_index_to_deposit(state: BeaconState) -> int: +def get_index_for_new_validator(state: BeaconState) -> int: for index, validator in enumerate(state.validators): - if validator.withdrawable_epoch < get_current_epoch(state) - REUSE_VALIDATOR_INDEX_DELAY: + if is_reusable_validator(validator, state.balances[index], get_current_epoch(state)): return index return len(state.validators) ``` diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index d5b89a387..5e24df83e 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -511,24 +511,24 @@ def apply_deposit(state: BeaconState, signing_root = compute_signing_root(deposit_message, domain) # Initialize validator if the deposit signature is valid if bls.Verify(pubkey, signing_root, signature): - index = assign_index_to_deposit(state) - update_list(state.validators, index, get_validator_from_deposit(pubkey, withdrawal_credentials, amount)) - update_list(state.balances, index, amount) + index = get_index_for_new_validator(state) + update_or_append_to_list(state.validators, index, get_validator_from_deposit(pubkey, withdrawal_credentials, amount)) + update_or_append_to_list(state.balances, index, amount) # [New in Altair] - update_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) - update_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) - update_list(state.inactivity_scores, index, uint64(0)) + update_or_append_to_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) + update_or_append_to_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) + update_or_append_to_list(state.inactivity_scores, index, uint64(0)) else: # Increase balance by deposit amount index = ValidatorIndex(validator_pubkeys.index(pubkey)) increase_balance(state, index, amount) -def assign_index_to_deposit(state: BeaconState) -> int: +def get_index_for_new_validator(state: BeaconState) -> int: return len(state.validators) -def update_list(list: List, index: int, value: Any) -> None: +def update_or_append_to_list(list: List, index: int, value: Any) -> None: if index == len(list): list.append(value) else: From c1273bbfa405f7c335d36561c92d169552ef7432 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 28 Mar 2023 15:46:01 +0900 Subject: [PATCH 03/10] Add epoch > REUSE_VALIDATOR_INDEX_DELAY condition --- specs/_features/reuse_indexes/beacon-chain.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/_features/reuse_indexes/beacon-chain.md b/specs/_features/reuse_indexes/beacon-chain.md index 8677631e5..3efa0c869 100644 --- a/specs/_features/reuse_indexes/beacon-chain.md +++ b/specs/_features/reuse_indexes/beacon-chain.md @@ -45,8 +45,9 @@ def is_reusable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> Check if ``validator`` index can be re-assigned to a new deposit. """ return ( - validator.withdrawable_epoch < epoch - REUSE_VALIDATOR_INDEX_DELAY - and balance == 0 + epoch > REUSE_VALIDATOR_INDEX_DELAY + and validator.withdrawable_epoch < epoch - REUSE_VALIDATOR_INDEX_DELAY + and balance == 0 ) ``` From 314b040fff2d5a5aa2ab8e7524c76200f3a64d79 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 28 Mar 2023 17:45:52 +0900 Subject: [PATCH 04/10] Reduce line len --- specs/altair/beacon-chain.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 5e24df83e..9d7c8180e 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -512,7 +512,8 @@ def apply_deposit(state: BeaconState, # Initialize validator if the deposit signature is valid if bls.Verify(pubkey, signing_root, signature): index = get_index_for_new_validator(state) - update_or_append_to_list(state.validators, index, get_validator_from_deposit(pubkey, withdrawal_credentials, amount)) + validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount) + update_or_append_to_list(state.validators, index, validator) update_or_append_to_list(state.balances, index, amount) # [New in Altair] update_or_append_to_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) From f696b30608a1b6402d32c3c87ab01be99e2096bd Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 30 Mar 2023 09:11:36 +0900 Subject: [PATCH 05/10] Address PR review --- specs/_features/reuse_indexes/beacon-chain.md | 13 ++++++------- specs/altair/beacon-chain.md | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/specs/_features/reuse_indexes/beacon-chain.md b/specs/_features/reuse_indexes/beacon-chain.md index 3efa0c869..5ec08ed19 100644 --- a/specs/_features/reuse_indexes/beacon-chain.md +++ b/specs/_features/reuse_indexes/beacon-chain.md @@ -1,4 +1,4 @@ -# Reuse indexes -- The Beacon Chain +# Reuse indices -- The Beacon Chain ## Table of contents @@ -31,7 +31,7 @@ This is the beacon chain specification to assign new deposits to existing valida | Name | Value | Unit | Duration | | - | - | - | -| `REUSE_VALIDATOR_INDEX_DELAY` | `uint64(2**16)` (= 65,536) | epochs | ~1 year | +| `REUSE_VALIDATOR_INDEX_DELAY` | `uint64(2**16)` (= 65,536) | epochs | ~0.8 year | ## Helper functions @@ -45,8 +45,7 @@ def is_reusable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> Check if ``validator`` index can be re-assigned to a new deposit. """ return ( - epoch > REUSE_VALIDATOR_INDEX_DELAY - and validator.withdrawable_epoch < epoch - REUSE_VALIDATOR_INDEX_DELAY + epoch > validator.withdrawable_epoch + REUSE_VALIDATOR_INDEX_DELAY and balance == 0 ) ``` @@ -58,9 +57,9 @@ def is_reusable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> #### Modified `get_index_for_new_validator` ```python -def get_index_for_new_validator(state: BeaconState) -> int: +def get_index_for_new_validator(state: BeaconState) -> ValidatorIndex: for index, validator in enumerate(state.validators): if is_reusable_validator(validator, state.balances[index], get_current_epoch(state)): - return index - return len(state.validators) + return ValidatorIndex(index) + return ValidatorIndex(len(state.validators)) ``` diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 9d7c8180e..df65d984c 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -525,11 +525,11 @@ def apply_deposit(state: BeaconState, increase_balance(state, index, amount) -def get_index_for_new_validator(state: BeaconState) -> int: - return len(state.validators) +def get_index_for_new_validator(state: BeaconState) -> ValidatorIndex: + return ValidatorIndex(len(state.validators)) -def update_or_append_to_list(list: List, index: int, value: Any) -> None: +def update_or_append_to_list(list: List, index: ValidatorIndex, value: Any) -> None: if index == len(list): list.append(value) else: From 3d9c87b27ccc9e8b96c9749abd7c727452bbb44a Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 30 Mar 2023 09:44:34 +0900 Subject: [PATCH 06/10] Move to misc helpers --- specs/altair/beacon-chain.md | 40 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index df65d984c..4c7bb3f9a 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -30,6 +30,8 @@ - [Misc](#misc-1) - [`add_flag`](#add_flag) - [`has_flag`](#has_flag) + - [`get_index_for_new_validator`](#get_index_for_new_validator) + - [`set_or_append_list`](#set_or_append_list) - [Beacon state accessors](#beacon-state-accessors) - [`get_next_sync_committee_indices`](#get_next_sync_committee_indices) - [`get_next_sync_committee`](#get_next_sync_committee) @@ -248,6 +250,23 @@ def has_flag(flags: ParticipationFlags, flag_index: int) -> bool: return flags & flag == flag ``` +#### `get_index_for_new_validator` + +```python +def get_index_for_new_validator(state: BeaconState) -> ValidatorIndex: + return ValidatorIndex(len(state.validators)) +``` + +#### `set_or_append_list` + +```python +def set_or_append_list(list: List[Any], index: ValidatorIndex, value: Any) -> None: + if index == len(list): + list.append(value) + else: + list[index] = value +``` + ### Beacon state accessors #### `get_next_sync_committee_indices` @@ -513,27 +532,16 @@ def apply_deposit(state: BeaconState, if bls.Verify(pubkey, signing_root, signature): index = get_index_for_new_validator(state) validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount) - update_or_append_to_list(state.validators, index, validator) - update_or_append_to_list(state.balances, index, amount) + set_or_append_list(state.validators, index, validator) + set_or_append_list(state.balances, index, amount) # [New in Altair] - update_or_append_to_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) - update_or_append_to_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) - update_or_append_to_list(state.inactivity_scores, index, uint64(0)) + set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) + set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) + set_or_append_list(state.inactivity_scores, index, uint64(0)) else: # Increase balance by deposit amount index = ValidatorIndex(validator_pubkeys.index(pubkey)) increase_balance(state, index, amount) - - -def get_index_for_new_validator(state: BeaconState) -> ValidatorIndex: - return ValidatorIndex(len(state.validators)) - - -def update_or_append_to_list(list: List, index: ValidatorIndex, value: Any) -> None: - if index == len(list): - list.append(value) - else: - list[index] = value ``` #### Sync aggregate processing From 25ea243859329cb7d7131a03051ed78e0abd03c3 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:45:08 +0900 Subject: [PATCH 07/10] PR comments --- .../_features/{reuse_indexes => reuse_indices}/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename specs/_features/{reuse_indexes => reuse_indices}/beacon-chain.md (99%) diff --git a/specs/_features/reuse_indexes/beacon-chain.md b/specs/_features/reuse_indices/beacon-chain.md similarity index 99% rename from specs/_features/reuse_indexes/beacon-chain.md rename to specs/_features/reuse_indices/beacon-chain.md index 5ec08ed19..ecac7fb30 100644 --- a/specs/_features/reuse_indexes/beacon-chain.md +++ b/specs/_features/reuse_indices/beacon-chain.md @@ -30,7 +30,7 @@ This is the beacon chain specification to assign new deposits to existing valida ### Time parameters | Name | Value | Unit | Duration | -| - | - | - | +| - | - | - | - | | `REUSE_VALIDATOR_INDEX_DELAY` | `uint64(2**16)` (= 65,536) | epochs | ~0.8 year | ## Helper functions From 622c9b97bac1a586a8b6692fe1998d3e621a8c30 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:00:09 +0900 Subject: [PATCH 08/10] Fix CI --- specs/_features/reuse_indices/beacon-chain.md | 2 +- specs/altair/beacon-chain.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/_features/reuse_indices/beacon-chain.md b/specs/_features/reuse_indices/beacon-chain.md index ecac7fb30..6dd71e36f 100644 --- a/specs/_features/reuse_indices/beacon-chain.md +++ b/specs/_features/reuse_indices/beacon-chain.md @@ -9,7 +9,7 @@ - [Introduction](#introduction) - [Preset](#preset) - [Time parameters](#time-parameters) -- [Helpers](#helpers) +- [Helper functions](#helper-functions) - [Predicates](#predicates) - [`is_reusable_validator`](#is_reusable_validator) - [Beacon chain state transition function](#beacon-chain-state-transition-function) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 4c7bb3f9a..8c3a8877e 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -260,7 +260,7 @@ def get_index_for_new_validator(state: BeaconState) -> ValidatorIndex: #### `set_or_append_list` ```python -def set_or_append_list(list: List[Any], index: ValidatorIndex, value: Any) -> None: +def set_or_append_list(list: List, index: ValidatorIndex, value: Any) -> None: if index == len(list): list.append(value) else: From accf99fba3b05e6a7c505e4f5bb07168e0921cbb Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 20 Apr 2023 08:47:49 +0900 Subject: [PATCH 09/10] rename to eip6914 --- specs/_features/{reuse_indices => eip6914}/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename specs/_features/{reuse_indices => eip6914}/beacon-chain.md (93%) diff --git a/specs/_features/reuse_indices/beacon-chain.md b/specs/_features/eip6914/beacon-chain.md similarity index 93% rename from specs/_features/reuse_indices/beacon-chain.md rename to specs/_features/eip6914/beacon-chain.md index 6dd71e36f..5f7589594 100644 --- a/specs/_features/reuse_indices/beacon-chain.md +++ b/specs/_features/eip6914/beacon-chain.md @@ -1,4 +1,4 @@ -# Reuse indices -- The Beacon Chain +EIP-6914 -- The Beacon Chain ## Table of contents @@ -21,7 +21,7 @@ ## Introduction -This is the beacon chain specification to assign new deposits to existing validator records that have withdrawn long ago. +This is the beacon chain specification to assign new deposits to existing validator records. Refers to [EIP-6914](https://github.com/ethereum/EIPs/pull/6914). *Note:* This specification is built upon [Capella](../../capella/beacon_chain.md) and is under active development. From 498fbd04a23de5a21e4544e203cb7157679c5282 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 20 Apr 2023 08:52:25 +0900 Subject: [PATCH 10/10] rename SAFE_EPOCHS_TO_REUSE_INDEX --- specs/_features/eip6914/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/_features/eip6914/beacon-chain.md b/specs/_features/eip6914/beacon-chain.md index 5f7589594..2c60c9bdb 100644 --- a/specs/_features/eip6914/beacon-chain.md +++ b/specs/_features/eip6914/beacon-chain.md @@ -31,7 +31,7 @@ This is the beacon chain specification to assign new deposits to existing valida | Name | Value | Unit | Duration | | - | - | - | - | -| `REUSE_VALIDATOR_INDEX_DELAY` | `uint64(2**16)` (= 65,536) | epochs | ~0.8 year | +| `SAFE_EPOCHS_TO_REUSE_INDEX` | `uint64(2**16)` (= 65,536) | epochs | ~0.8 year | ## Helper functions @@ -45,7 +45,7 @@ def is_reusable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> Check if ``validator`` index can be re-assigned to a new deposit. """ return ( - epoch > validator.withdrawable_epoch + REUSE_VALIDATOR_INDEX_DELAY + epoch > validator.withdrawable_epoch + SAFE_EPOCHS_TO_REUSE_INDEX and balance == 0 ) ```