From 16928c85bb32ccaff020fd5389f956c63baa7388 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 4 Oct 2018 11:21:33 +0100 Subject: [PATCH 01/10] Clean up codes, flags, types This includes: * Optimised values (e.g. `PENALIZED` now fits in a single byte) * More consistent values (e.g. the flags start at 0) * Added types for specials --- specs/beacon-chain.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 5437e32ad..26c7bd4a5 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -51,18 +51,20 @@ The primary source of load on the beacon chain are "attestations". Attestations * The `BASE_REWARD_QUOTIENT` constant is the per-slot interest rate assuming all validators are participating, assuming total deposits of 1 ETH. It corresponds to ~3.88% annual interest assuming 10 million participating ETH. * At most `1/MAX_VALIDATOR_CHURN_QUOTIENT` of the validators can change during each dynasty. -**Status codes** +**Codes, flags, types** -| Status code | Value | -| - | :-: | -| `PENDING_LOG_IN` | `0` | -| `LOGGED_IN` | `1` | -| `PENDING_EXIT` | `2` | -| `PENDING_WITHDRAW` | `3` | -| `WITHDRAWN` | `4` | -| `PENALIZED` | `128` | -| `ENTRY` | `1` | -| `EXIT` | `2` | +| Name | Value | Category | +| - | :-: | :-: | +| `PENDING_LOG_IN` | `0` | code | +| `LOGGED_IN` | `1` | code | +| `PENDING_EXIT` | `2` | code | +| `PENDING_WITHDRAW` | `3` | code | +| `WITHDRAWN` | `4` | code | +| `PENALIZED` | `127` | code | +| `ENTRY` | `0` | flag | +| `EXIT` | `1` | flag | +| `LOGOUT` | `0` | type | +| `CASPER_SLASHING` | `1` | type | ### PoW chain registration contract @@ -525,8 +527,8 @@ Let `committees` be the set of committees processed and `time_since_last_confirm For each `SpecialObject` `obj` in `active_state.pending_specials`: -* **[covers logouts]**: If `obj.type == 0`, interpret `data[0]` as a validator index as an `int32` and `data[1]` as a signature. If `BLSVerify(pubkey=validators[data[0]].pubkey, msg=hash("bye bye"), sig=data[1])`, and `validators[i].status == LOGGED_IN`, set `validators[i].status = PENDING_EXIT` and `validators[i].exit_slot = current_slot` -* **[covers `NO_DBL_VOTE`, `NO_SURROUND`, `NO_DBL_PROPOSE` slashing conditions]:** If `obj.type == 1`, interpret `data[0]` as a list of concatenated `int32` values where each value represents an index into `validators`, `data[1]` as the data being signed and `data[2]` as an aggregate signature. Interpret `data[3:6]` similarly. Verify that both signatures are valid, that the two signatures are signing distinct data, and that they are either signing the same slot number, or that one surrounds the other (ie. `source1 < source2 < target2 < target1`). Let `inds` be the list of indices in both signatures; verify that its length is at least 1. For each validator index `v` in `inds`, set their end dynasty to equal the current dynasty plus 1, and if its `status` does not equal `PENALIZED`, then: +* **[covers logouts]**: If `obj.type == LOGOUT`, interpret `data[0]` as a validator index as an `int32` and `data[1]` as a signature. If `BLSVerify(pubkey=validators[data[0]].pubkey, msg=hash("bye bye"), sig=data[1])`, and `validators[i].status == LOGGED_IN`, set `validators[i].status = PENDING_EXIT` and `validators[i].exit_slot = current_slot` +* **[covers `NO_DBL_VOTE`, `NO_SURROUND`, `NO_DBL_PROPOSE` slashing conditions]:** If `obj.type == CASPER_SLASHING`, interpret `data[0]` as a list of concatenated `int32` values where each value represents an index into `validators`, `data[1]` as the data being signed and `data[2]` as an aggregate signature. Interpret `data[3:6]` similarly. Verify that both signatures are valid, that the two signatures are signing distinct data, and that they are either signing the same slot number, or that one surrounds the other (ie. `source1 < source2 < target2 < target1`). Let `inds` be the list of indices in both signatures; verify that its length is at least 1. For each validator index `v` in `inds`, set their end dynasty to equal the current dynasty plus 1, and if its `status` does not equal `PENALIZED`, then: 1. Set its `exit_slot` to equal the current `slot` 2. Set its `status` to `PENALIZED` From 5306c1e728db72fb819b6d6a19ad987e714594c0 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 4 Oct 2018 14:16:31 +0100 Subject: [PATCH 02/10] Update beacon-chain.md --- specs/beacon-chain.md | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 26c7bd4a5..57d992c16 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -1,7 +1,6 @@ # Ethereum 2.0 spec—Casper and sharding ###### tags: `spec`, `eth2.0`, `casper`, `sharding` -###### spec version: 2.2 (October 2018) **NOTICE**: This document is a work-in-progress for researchers and implementers. It reflects recent spec changes and takes precedence over the [Python proof-of-concept implementation](https://github.com/ethereum/beacon_chain). @@ -44,6 +43,7 @@ The primary source of load on the beacon chain are "attestations". Attestations | `WITHDRAWAL_PERIOD` | 2**19 (= 524,288) | slots | ~97 days | | `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — | | `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — | +| `LOGOUT_MESSAGE` | `"LOGOUT"` | — | **Notes** @@ -51,20 +51,30 @@ The primary source of load on the beacon chain are "attestations". Attestations * The `BASE_REWARD_QUOTIENT` constant is the per-slot interest rate assuming all validators are participating, assuming total deposits of 1 ETH. It corresponds to ~3.88% annual interest assuming 10 million participating ETH. * At most `1/MAX_VALIDATOR_CHURN_QUOTIENT` of the validators can change during each dynasty. -**Codes, flags, types** +**Validator status codes** -| Name | Value | Category | -| - | :-: | :-: | -| `PENDING_LOG_IN` | `0` | code | -| `LOGGED_IN` | `1` | code | -| `PENDING_EXIT` | `2` | code | -| `PENDING_WITHDRAW` | `3` | code | -| `WITHDRAWN` | `4` | code | -| `PENALIZED` | `127` | code | -| `ENTRY` | `0` | flag | -| `EXIT` | `1` | flag | -| `LOGOUT` | `0` | type | -| `CASPER_SLASHING` | `1` | type | +| Name | Value | +| - | :-: | +| `PENDING_LOG_IN` | `0` | +| `LOGGED_IN` | `1` | +| `PENDING_EXIT` | `2` | +| `PENDING_WITHDRAW` | `3` | +| `WITHDRAWN` | `4` | +| `PENALIZED` | `127` | + +**Special record types** + +| Name | Value | +| - | :-: | +| `LOGOUT` | `0` | +| `CASPER_SLASHING` | `1` | + +**Validator set delta flags** + +| Name | Value | +| - | :-: | +| `ENTRY` | `0` | +| `EXIT` | `1` | ### PoW chain registration contract @@ -527,8 +537,8 @@ Let `committees` be the set of committees processed and `time_since_last_confirm For each `SpecialObject` `obj` in `active_state.pending_specials`: -* **[covers logouts]**: If `obj.type == LOGOUT`, interpret `data[0]` as a validator index as an `int32` and `data[1]` as a signature. If `BLSVerify(pubkey=validators[data[0]].pubkey, msg=hash("bye bye"), sig=data[1])`, and `validators[i].status == LOGGED_IN`, set `validators[i].status = PENDING_EXIT` and `validators[i].exit_slot = current_slot` -* **[covers `NO_DBL_VOTE`, `NO_SURROUND`, `NO_DBL_PROPOSE` slashing conditions]:** If `obj.type == CASPER_SLASHING`, interpret `data[0]` as a list of concatenated `int32` values where each value represents an index into `validators`, `data[1]` as the data being signed and `data[2]` as an aggregate signature. Interpret `data[3:6]` similarly. Verify that both signatures are valid, that the two signatures are signing distinct data, and that they are either signing the same slot number, or that one surrounds the other (ie. `source1 < source2 < target2 < target1`). Let `inds` be the list of indices in both signatures; verify that its length is at least 1. For each validator index `v` in `inds`, set their end dynasty to equal the current dynasty plus 1, and if its `status` does not equal `PENALIZED`, then: +* **[covers logouts]**: If `obj.type == LOGOUT`, interpret `data[0]` as a validator index as an `int32` and `data[1]` as a signature. If `BLSVerify(pubkey=validators[data[0]].pubkey, msg=hash(LOGOUT_MESSAGE), sig=data[1])`, and `validators[i].status == LOGGED_IN`, set `validators[i].status = PENDING_EXIT` and `validators[i].exit_slot = current_slot` +* **[covers `NO_DBL_VOTE`, `NO_SURROUND`, `NO_DBL_PROPOSE` slashing conditions]:** If `obj.type == CASPER_SLASHING`, interpret `data[0]` as a list of concatenated `int32` values where each value represents an index into `validators`, `data[1]` as the data being signed and `data[2]` as an aggregate signature. Interpret `data[3:6]` similarly. Verify that both signatures are valid, that the two signatures are signing distinct data, and that they are either signing the same slot number, or that one surrounds the other (ie. `source1 < source2 < target2 < target1`). Let `indices` be the list of indices in both signatures; verify that its length is at least 1. For each validator index `v` in `indices`, set their end dynasty to equal the current dynasty plus 1, and if its `status` does not equal `PENALIZED`, then: 1. Set its `exit_slot` to equal the current `slot` 2. Set its `status` to `PENALIZED` From d6395fa67831de6af042b3ac10c7bad396482c45 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 5 Oct 2018 11:25:52 +0100 Subject: [PATCH 03/10] Fix typo calling AttestationSignedData --- specs/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 16be55464..644a9b06b 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -496,7 +496,7 @@ For each one of these attestations: * Verify that `len(attester_bitfield) == ceil_div8(len(attestation_indices))`, where `ceil_div8 = (x + 7) // 8`. Verify that bits `len(attestation_indices)....` and higher, if present (i.e. `len(attestation_indices)` is not a multiple of 8), are all zero * Derive a group public key by adding the public keys of all of the attesters in `attestation_indices` for whom the corresponding bit in `attester_bitfield` (the ith bit is `(attester_bitfield[i // 8] >> (7 - (i %8))) % 2`) equals 1 * Let `version = pre_fork_version if slot < fork_slot_number else post_fork_version`. -* Verify that `aggregate_sig` verifies using the group pubkey generated and the serialized form of `AttestationSignedData(version, slot, parent_hashes, shard, shard_block_hash, justified_slot)` as the message. +* Verify that `aggregate_sig` verifies using the group pubkey generated and the serialized form of `AttestationSignedData(version, slot, shard, parent_hashes, shard_block_hash, justified_slot)` as the message. Extend the list of `AttestationRecord` objects in the `active_state` with those included in the block, ordering the new additions in the same order as they came in the block. Similarly extend the list of `SpecialRecord` objects in the `active_state` with those included in the block. From 1cbde6f3c807a092b1e768fb33b1e0065fc69766 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 5 Oct 2018 11:34:38 +0100 Subject: [PATCH 04/10] Change balances to Gwei See discussion here https://github.com/ethereum/eth2.0-specs/issues/34 --- specs/beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 16be55464..ca17e206f 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -219,7 +219,7 @@ A `ValidatorRecord` has the following fields: # RANDAO commitment 'randao_commitment': 'hash32', # Balance - 'balance': 'int128', + 'balance': 'int64', # Status code 'status': 'int8', # Slot when validator exited (or 0) @@ -448,7 +448,7 @@ def add_validator(validators, pubkey, proof_of_possession, withdrawal_shard, withdrawal_shard=withdrawal_shard, withdrawal_address=withdrawal_address, randao_commitment=randao_commitment, - balance=DEPOSIT_SIZE, # in WEI + balance=DEPOSIT_SIZE * 10**9, # in Gwei status=PENDING_LOG_IN, exit_slot=0 ) @@ -585,9 +585,9 @@ def change_validators(validators): active_validators = get_active_validator_indices(validators, dynasty) # The total size of active deposits total_deposits = sum([v.balance for i, v in enumerate(validators) if i in active_validators]) - # The maximum total wei that can deposit+withdraw + # The maximum total Gwei that can be deposited and withdrawn max_allowable_change = max( - DEPOSIT_SIZE * 2, + 2 * DEPOSIT_SIZE * 10**9, total_deposits // MAX_VALIDATOR_CHURN_QUOTIENT ) # Go through the list start to end depositing+withdrawing as many as possible From cb6e94a115169527e0ec75bdee958fd6b7af135d Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 5 Oct 2018 11:38:30 +0100 Subject: [PATCH 05/10] Make status codes consistent with "active" validators --- specs/beacon-chain.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 16be55464..cf1d303b5 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -55,8 +55,8 @@ The primary source of load on the beacon chain are "attestations". Attestations | Status code | Value | | - | :-: | -| `PENDING_LOG_IN` | `0` | -| `LOGGED_IN` | `1` | +| `PENDING_ACTIVATION` | `0` | +| `ACTIVE` | `1` | | `PENDING_EXIT` | `2` | | `PENDING_WITHDRAW` | `3` | | `WITHDRAWN` | `4` | @@ -300,7 +300,7 @@ We start off by defining some helper algorithms. First, the function that select ```python def get_active_validator_indices(validators): - return [i for i, v in enumerate(validators) if v.status == LOGGED_IN] + return [i for i, v in enumerate(validators) if v.status == ACTIVE] ``` Now, a function that shuffles this list: @@ -449,7 +449,7 @@ def add_validator(validators, pubkey, proof_of_possession, withdrawal_shard, withdrawal_address=withdrawal_address, randao_commitment=randao_commitment, balance=DEPOSIT_SIZE, # in WEI - status=PENDING_LOG_IN, + status=PENDING_ACTIVATION, exit_slot=0 ) index = min_empty_validator(validators) @@ -554,7 +554,7 @@ Let `committees` be the set of committees processed and `time_since_last_confirm For each `SpecialRecord` `obj` in `active_state.pending_specials`: -* **[covers logouts]**: If `obj.kind == 0`, interpret `data[0]` as a validator index as an `int32` and `data[1]` as a signature. If `BLSVerify(pubkey=validators[data[0]].pubkey, msg=hash("bye bye"), sig=data[1])`, and `validators[i].status == LOGGED_IN`, set `validators[i].status = PENDING_EXIT` and `validators[i].exit_slot = current_slot` +* **[covers logouts]**: If `obj.kind == 0`, interpret `data[0]` as a validator index as an `int32` and `data[1]` as a signature. If `BLSVerify(pubkey=validators[data[0]].pubkey, msg=hash("bye bye"), sig=data[1])`, and `validators[i].status == ACTIVE`, set `validators[i].status = PENDING_EXIT` and `validators[i].exit_slot = current_slot` * **[covers `NO_DBL_VOTE`, `NO_SURROUND`, `NO_DBL_PROPOSE` slashing conditions]:** If `obj.kind == 1`, interpret `data[0]` as a list of concatenated `int32` values where each value represents an index into `validators`, `data[1]` as the data being signed and `data[2]` as an aggregate signature. Interpret `data[3:6]` similarly. Verify that both signatures are valid, that the two signatures are signing distinct data, and that they are either signing the same slot number, or that one surrounds the other (ie. `source1 < source2 < target2 < target1`). Let `inds` be the list of indices in both signatures; verify that its length is at least 1. For each validator index `v` in `inds`, set their end dynasty to equal the current dynasty plus 1, and if its `status` does not equal `PENALIZED`, then: 1. Set its `exit_slot` to equal the current `slot` @@ -593,8 +593,8 @@ def change_validators(validators): # Go through the list start to end depositing+withdrawing as many as possible total_changed = 0 for i in range(len(validators)): - if validators[i].status == PENDING_LOG_IN: - validators[i].status = LOGGED_IN + if validators[i].status == PENDING_ACTIVATION: + validators[i].status = ACTIVE total_changed += DEPOSIT_SIZE add_validator_set_change_record(crystallized_state, i, validators[i].pubkey, ENTRY) if validators[i].status == PENDING_EXIT: From e3c1eeb569e0f33779f799c8d41d0a7908c636be Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 5 Oct 2018 11:49:18 +0100 Subject: [PATCH 06/10] Update beacon-chain.md --- specs/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index ca17e206f..8b427bde5 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -522,8 +522,8 @@ For all (`shard`, `shard_block_hash`) tuples, compute the total deposit size of Let `time_since_finality = block.slot - last_finalized_slot`, and let `B` be the balance of any given validator whose balance we are adjusting, not including any balance changes from this round of state recalculation. Let: -* `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, dynasty)])` and `total_deposits_in_ETH = total_deposits // 10**18` -* `reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_deposits_in_ETH)` (`1/reward_quotient` is the per-slot max interest rate) +* `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, dynasty)])` and `total_deposits_in_gwei = total_deposits // 10**9` +* `reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_deposits_in_gwei)` (`1/reward_quotient` is the per-slot max interest rate) * `quadratic_penalty_quotient = SQRT_E_DROP_TIME**2` (after `D` slots about `D*D/2/quadratic_penalty_quotient` is the portion lost by offline validators) For each slot `S` in the range `last_state_recalculation_slot - CYCLE_LENGTH ... last_state_recalculation_slot - 1`: From ef4b2c45425f481ec0f936c0b81f42814fcf91dd Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 5 Oct 2018 12:01:03 +0100 Subject: [PATCH 07/10] Update beacon-chain.md --- specs/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 8b427bde5..c8992f8ae 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -522,8 +522,8 @@ For all (`shard`, `shard_block_hash`) tuples, compute the total deposit size of Let `time_since_finality = block.slot - last_finalized_slot`, and let `B` be the balance of any given validator whose balance we are adjusting, not including any balance changes from this round of state recalculation. Let: -* `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, dynasty)])` and `total_deposits_in_gwei = total_deposits // 10**9` -* `reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_deposits_in_gwei)` (`1/reward_quotient` is the per-slot max interest rate) +* `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, dynasty)])` and `total_deposits_in_ETH = total_deposits // 10**9` +* `reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_deposits_in_ETH)` (`1/reward_quotient` is the per-slot max interest rate) * `quadratic_penalty_quotient = SQRT_E_DROP_TIME**2` (after `D` slots about `D*D/2/quadratic_penalty_quotient` is the portion lost by offline validators) For each slot `S` in the range `last_state_recalculation_slot - CYCLE_LENGTH ... last_state_recalculation_slot - 1`: From 64ba1aa931578d312703c3bb07e35a8801a27522 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 5 Oct 2018 21:16:02 +0600 Subject: [PATCH 08/10] Get rid of redundant recent_block_hashes entry --- specs/beacon-chain.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 16be55464..f98d8dd56 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -157,8 +157,6 @@ The `ActiveState` has the following fields: ```python { - # Most recent 2 * CYCLE_LENGTH block hashes, oldest to newest - 'recent_block_hashes': ['hash32'], # Attestations not yet processed 'pending_attestations': [AttestationRecord], # Specials not yet been processed From d495b0ec4f297eb7221789ed543ad0f46b02cc49 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 5 Oct 2018 12:05:09 -0400 Subject: [PATCH 09/10] clear up a comment in AttestationSignedData --- specs/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 644a9b06b..56555792f 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -133,7 +133,7 @@ An `AttestationSignedData` has the following fields: 'parent_hashes': ['hash32'], # Shard block hash 'shard_block_hash': 'hash32', - # Slot of last justified block + # Slot of last justified block referenced in the attestation 'justified_slot': 'int64' } ``` From fedfe61d6ce571a73af67c280e427305e5261109 Mon Sep 17 00:00:00 2001 From: Justin Date: Sat, 6 Oct 2018 13:02:08 +0100 Subject: [PATCH 10/10] Update beacon-chain.md --- specs/beacon-chain.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index c8992f8ae..978e91cbe 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -35,6 +35,7 @@ The primary source of load on the beacon chain are "attestations". Attestations | --- | --- | :---: | - | | `SHARD_COUNT` | 2**10 (= 1,024)| shards | | `DEPOSIT_SIZE` | 2**5 (= 32) | ETH | +| `GWEI_PER_ETH` | 10**9 | Gwei/ETH | | `MIN_COMMITTEE_SIZE` | 2**7 (= 128) | validators | | `GENESIS_TIME` | **TBD** | seconds | | `SLOT_DURATION` | 2**4 (= 16) | seconds | @@ -448,7 +449,7 @@ def add_validator(validators, pubkey, proof_of_possession, withdrawal_shard, withdrawal_shard=withdrawal_shard, withdrawal_address=withdrawal_address, randao_commitment=randao_commitment, - balance=DEPOSIT_SIZE * 10**9, # in Gwei + balance=DEPOSIT_SIZE * GWEI_PER_ETH, # in Gwei status=PENDING_LOG_IN, exit_slot=0 ) @@ -522,7 +523,7 @@ For all (`shard`, `shard_block_hash`) tuples, compute the total deposit size of Let `time_since_finality = block.slot - last_finalized_slot`, and let `B` be the balance of any given validator whose balance we are adjusting, not including any balance changes from this round of state recalculation. Let: -* `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, dynasty)])` and `total_deposits_in_ETH = total_deposits // 10**9` +* `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, dynasty)])` and `total_deposits_in_ETH = total_deposits // GWEI_PER_ETH` * `reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_deposits_in_ETH)` (`1/reward_quotient` is the per-slot max interest rate) * `quadratic_penalty_quotient = SQRT_E_DROP_TIME**2` (after `D` slots about `D*D/2/quadratic_penalty_quotient` is the portion lost by offline validators) @@ -587,7 +588,7 @@ def change_validators(validators): total_deposits = sum([v.balance for i, v in enumerate(validators) if i in active_validators]) # The maximum total Gwei that can be deposited and withdrawn max_allowable_change = max( - 2 * DEPOSIT_SIZE * 10**9, + 2 * DEPOSIT_SIZE * GWEI_PER_ETH, total_deposits // MAX_VALIDATOR_CHURN_QUOTIENT ) # Go through the list start to end depositing+withdrawing as many as possible