-
Notifications
You must be signed in to change notification settings - Fork 0
[DRAFT] Increase MAX_EFFECTIVE_BALANCE minimal spec change
#3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
0b8bb11
6809439
2b1c7b8
6824f17
67cc34f
1403bdb
cb49250
81f9080
3575804
95a167d
604b876
552cb21
fdcb6bd
2e536a4
2526b9d
b6c476f
4681d67
921e898
b6d5f07
8e56d72
7b5ad56
7e1408c
4b1ee30
2ad9633
d6db57c
bcd6164
2955027
1577082
6f8c3e1
9ae94fc
1e487dc
2cf9b52
6de5355
e7e8f20
02e1bac
40432e8
bc0a782
24871ec
b592974
1aaf390
bb61d09
587542e
5f52180
0e2228a
8a557ae
c063473
9c141fc
88f650b
a39d578
022deb9
b57a7ce
ec33407
63b3633
ccf5acf
f73a996
82d49cf
986e6ad
f4f6538
7801942
fd8aa04
f23f77c
a6c62be
3e927cf
f87def1
fa8f2ee
b489655
6f4750d
ccc0aae
f7b74c3
ff9197c
31e056e
d253ead
be4797b
29066f3
4c12835
dcf1b16
d81d771
2ebf61a
a278951
f398b45
6b9351d
48f4c4d
b9a0284
026be15
7e9292b
c9f1f50
f577511
857b0e0
d6cec95
89f15df
13f93ee
71fd7a8
419baf2
53582d0
55c50d4
93096e2
c242364
e9ad4dc
5d134a2
fe6d697
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,6 +144,7 @@ def floorlog2(x: int) -> uint64: | |
| ENDIANNESS: Final = 'little' | ||
| BLS_WITHDRAWAL_PREFIX = Bytes1('0x00') | ||
| ETH1_ADDRESS_WITHDRAWAL_PREFIX = Bytes1('0x01') | ||
| COMPOUNDING_WITHDRAWAL_PREFIX = Bytes1('0x02') | ||
| DOMAIN_BEACON_PROPOSER = DomainType('0x00000000') | ||
| DOMAIN_BEACON_ATTESTER = DomainType('0x01000000') | ||
| DOMAIN_RANDAO = DomainType('0x02000000') | ||
|
|
@@ -190,7 +191,8 @@ def floorlog2(x: int) -> uint64: | |
| HYSTERESIS_DOWNWARD_MULTIPLIER = uint64(1) | ||
| HYSTERESIS_UPWARD_MULTIPLIER = uint64(5) | ||
| MIN_DEPOSIT_AMOUNT = Gwei(1000000000) | ||
| MAX_EFFECTIVE_BALANCE = Gwei(32000000000) | ||
| MAX_EFFECTIVE_BALANCE = Gwei(2048000000000) | ||
| MIN_ACTIVATION_BALANCE = Gwei(32000000000) | ||
| EFFECTIVE_BALANCE_INCREMENT = Gwei(1000000000) | ||
| MIN_ATTESTATION_INCLUSION_DELAY = uint64(1) | ||
| SLOTS_PER_EPOCH = uint64(32) | ||
|
|
@@ -245,7 +247,7 @@ class Configuration(NamedTuple): | |
| SHARD_COMMITTEE_PERIOD: uint64 | ||
| ETH1_FOLLOW_DISTANCE: uint64 | ||
| EJECTION_BALANCE: Gwei | ||
| MIN_PER_EPOCH_CHURN_LIMIT: uint64 | ||
| MIN_PER_EPOCH_CHURN_LIMIT: Gwei | ||
| CHURN_LIMIT_QUOTIENT: uint64 | ||
| PROPOSER_SCORE_BOOST: uint64 | ||
| INACTIVITY_SCORE_BIAS: uint64 | ||
|
|
@@ -273,7 +275,7 @@ class Configuration(NamedTuple): | |
| SHARD_COMMITTEE_PERIOD=uint64(256), | ||
| ETH1_FOLLOW_DISTANCE=uint64(2048), | ||
| EJECTION_BALANCE=Gwei(16000000000), | ||
| MIN_PER_EPOCH_CHURN_LIMIT=uint64(4), | ||
| MIN_PER_EPOCH_CHURN_LIMIT=Gwei(1280000000000), | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| CHURN_LIMIT_QUOTIENT=uint64(65536), | ||
| PROPOSER_SCORE_BOOST=uint64(40), | ||
| INACTIVITY_SCORE_BIAS=uint64(4), | ||
|
|
@@ -598,7 +600,6 @@ class SignedBLSToExecutionChange(Container): | |
| message: BLSToExecutionChange | ||
| signature: BLSSignature | ||
|
|
||
|
|
||
|
JustinDrake marked this conversation as resolved.
|
||
| class BeaconBlockBody(Container): | ||
| randao_reveal: BLSSignature | ||
| eth1_data: Eth1Data # Eth1 data vote | ||
|
|
@@ -656,6 +657,7 @@ class BeaconState(Container): | |
| # Registry | ||
| validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] | ||
| balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] | ||
| exit_queue_churn: Gwei | ||
|
JustinDrake marked this conversation as resolved.
Outdated
|
||
| # Randomness | ||
| randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] | ||
| # Slashings | ||
|
|
@@ -770,7 +772,6 @@ def integer_squareroot(n: uint64) -> uint64: | |
| y = (x + n // x) // 2 | ||
| return x | ||
|
|
||
|
|
||
|
michaelneuder marked this conversation as resolved.
|
||
| def xor(bytes_1: Bytes32, bytes_2: Bytes32) -> Bytes32: | ||
| """ | ||
| Return the exclusive-or of two 32-byte strings. | ||
|
|
@@ -798,7 +799,7 @@ def is_eligible_for_activation_queue(validator: Validator) -> bool: | |
| """ | ||
| return ( | ||
| validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH | ||
| and validator.effective_balance == MAX_EFFECTIVE_BALANCE | ||
| and validator.effective_balance >= MIN_ACTIVATION_BALANCE | ||
| ) | ||
|
|
||
|
|
||
|
|
@@ -1021,12 +1022,12 @@ def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[V | |
| return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)] | ||
|
|
||
|
|
||
| def get_validator_churn_limit(state: BeaconState) -> uint64: | ||
| def get_validator_churn_limit(state: BeaconState) -> Gwei: | ||
| """ | ||
| Return the validator churn limit for the current epoch. | ||
| """ | ||
| active_validator_indices = get_active_validator_indices(state, get_current_epoch(state)) | ||
| return max(config.MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // config.CHURN_LIMIT_QUOTIENT) | ||
| total_balance = get_total_active_balance(state) | ||
| return max(config.MIN_PER_EPOCH_CHURN_LIMIT, total_balance // config.CHURN_LIMIT_QUOTIENT) | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes32: | ||
|
|
@@ -1146,10 +1147,19 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: | |
| # Compute exit queue epoch | ||
| exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH] | ||
| exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))]) | ||
| exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch]) | ||
| if exit_queue_churn >= get_validator_churn_limit(state): | ||
| exit_queue_epoch += Epoch(1) | ||
|
|
||
| if exit_queue_epoch > max(exit_epochs): | ||
| state.exit_queue_churn = Gwei(0) | ||
| churn_limit = get_validator_churn_limit(state) | ||
| if state.exit_queue_churn + validator.effective_balance <= churn_limit: # the validator fits within the churn of the current exit_queue_epoch | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| state.exit_queue_churn += validator.effective_balance # the full effective balance of the validator contributes to the churn in the exit queue epoch | ||
| else: # the validator does not fit within the churn of the current exit_queue_epoch | ||
| future_epochs_churn_contribution = validator.effective_balance - (churn_limit - state.exit_queue_churn) | ||
| exit_queue_epoch += Epoch((future_epochs_churn_contribution + churn_limit - 1) // churn_limit) # (numerator + denominator - 1) // denominator rounds up. | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| # the validator contributes to the churn in the exit queue epoch, based on how much balance is left over at that point | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| if future_epochs_churn_contribution % churn_limit == 0: | ||
| state.exit_queue_churn = churn_limit | ||
| else: | ||
| state.exit_queue_churn = future_epochs_churn_contribution % churn_limit | ||
| # Set validator exit epoch and withdrawable epoch | ||
| validator.exit_epoch = exit_queue_epoch | ||
| validator.withdrawable_epoch = Epoch(validator.exit_epoch + config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY) | ||
|
|
@@ -1209,7 +1219,7 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, | |
| for index, validator in enumerate(state.validators): | ||
| balance = state.balances[index] | ||
| validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) | ||
| if validator.effective_balance == MAX_EFFECTIVE_BALANCE: | ||
| if validator.effective_balance >= MIN_ACTIVATION_BALANCE: | ||
| validator.activation_eligibility_epoch = GENESIS_EPOCH | ||
| validator.activation_epoch = GENESIS_EPOCH | ||
|
|
||
|
|
@@ -1547,9 +1557,13 @@ def process_registry_updates(state: BeaconState) -> None: | |
| if is_eligible_for_activation(state, validator) | ||
| # Order by the sequence of activation_eligibility_epoch setting and then index | ||
| ], key=lambda index: (state.validators[index].activation_eligibility_epoch, index)) | ||
| # Dequeued validators for activation up to churn limit | ||
| for index in activation_queue[:get_validator_churn_limit(state)]: | ||
| # Dequeue validators for activation up to churn limit [MODIFIED TO BE WEIGHT-SENSITIVE] | ||
|
JustinDrake marked this conversation as resolved.
Outdated
|
||
| max_churn_left = get_validator_churn_limit(state) # This is now a Gwei amount | ||
|
JustinDrake marked this conversation as resolved.
Outdated
|
||
| for index in activation_queue: | ||
| validator = state.validators[index] | ||
| max_churn_left -= validator.effective_balance | ||
| if max_churn_left < 0: | ||
|
JustinDrake marked this conversation as resolved.
Outdated
|
||
| break | ||
| validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) | ||
|
|
||
|
|
||
|
|
@@ -1794,10 +1808,10 @@ def apply_deposit(state: BeaconState, | |
| state.current_epoch_participation.append(ParticipationFlags(0b0000_0000)) | ||
| state.inactivity_scores.append(uint64(0)) | ||
| else: | ||
| # Increase balance by deposit amount | ||
| # Increase balance by deposit amount, up to MIN_ACTIVATION_BALANCE. | ||
|
JustinDrake marked this conversation as resolved.
Outdated
|
||
| index = ValidatorIndex(validator_pubkeys.index(pubkey)) | ||
| increase_balance(state, index, amount) | ||
|
|
||
|
JustinDrake marked this conversation as resolved.
|
||
| top_up = min(amount, MIN_ACTIVATION_BALANCE - state.balances[index]) | ||
| increase_balance(state, index, top_up) | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
|
|
||
| def process_deposit(state: BeaconState, deposit: Deposit) -> None: | ||
| # Verify the Merkle branch | ||
|
|
@@ -2334,9 +2348,14 @@ def get_slot_signature(state: BeaconState, slot: Slot, privkey: int) -> BLSSigna | |
| return bls.Sign(privkey, signing_root) | ||
|
|
||
|
|
||
| def is_aggregator(state: BeaconState, slot: Slot, index: CommitteeIndex, slot_signature: BLSSignature) -> bool: | ||
| def is_aggregator(state: BeaconState, slot: Slot, index: CommitteeIndex, validator_index: ValidatorIndex, slot_signature: BLSSignature) -> bool: | ||
| validator = state.validators[validator_index] | ||
| committee = get_beacon_committee(state, slot, index) | ||
| modulo = max(1, len(committee) // TARGET_AGGREGATORS_PER_COMMITTEE) | ||
| number_virtual_validators = validator.effective_balance // MIN_ACTIVATION_BALANCE | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| committee_balance = get_total_balance(state, set(committee)) | ||
| denominator = committee_balance ** number_virtual_validators | ||
| numerator = denominator - (committee_balance - TARGET_AGGREGATORS_PER_COMMITTEE * MIN_ACTIVATION_BALANCE) ** number_virtual_validators | ||
| modulo = denominator // numerator | ||
| return bytes_to_uint64(hash(slot_signature)[0:8]) % modulo == 0 | ||
|
|
||
|
|
||
|
|
@@ -3540,24 +3559,49 @@ def has_eth1_withdrawal_credential(validator: Validator) -> bool: | |
| return validator.withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX | ||
|
|
||
|
|
||
| def has_compounding_withdrawal_credential(validator: Validator) -> bool: | ||
| """ | ||
| Check if ``validator`` has an 0x02 prefixed "compounding" withdrawal credential. | ||
| """ | ||
| return validator.withdrawal_credentials[:1] == COMPOUNDING_WITHDRAWAL_PREFIX | ||
|
|
||
|
|
||
| def has_withdrawable_credential(validator: Validator) -> bool: | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| """ | ||
| Check if ``validator`` has a withdrawable credential. | ||
| """ | ||
| return has_eth1_withdrawal_credential(validator) or has_compounding_withdrawal_credential(validator) | ||
|
|
||
|
|
||
| def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> bool: | ||
| """ | ||
| Check if ``validator`` is fully withdrawable. | ||
| """ | ||
| return ( | ||
| has_eth1_withdrawal_credential(validator) | ||
| has_withdrawable_credential(validator) | ||
| and validator.withdrawable_epoch <= epoch | ||
| and balance > 0 | ||
| ) | ||
|
|
||
| def get_validator_ceiling(validator: Validator) -> Gwei: | ||
| """ | ||
| Get ceiling balance for paritial withdrawals for ``validator``. | ||
| """ | ||
| if has_compounding_withdrawal_credential(validator): | ||
| return MAX_EFFECTIVE_BALANCE | ||
| return MIN_ACTIVATION_BALANCE | ||
|
|
||
|
|
||
| def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) -> bool: | ||
| """ | ||
| Check if ``validator`` is partially withdrawable. | ||
| """ | ||
| has_max_effective_balance = validator.effective_balance == MAX_EFFECTIVE_BALANCE | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like the check There may be a situation where a validator has lost 0.25 eth below The current code allows partial withdrawals of the validator balance when The same is true for 0x01 type and def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) -> bool:
"""
Check if ``validator`` is partially withdrawable.
"""
if has_eth1_withdrawal_credential(validator) and validator.effective_balance == MIN_ACTIVATION_BALANCE:
return get_validator_excess_balance(validator, balance) > 0
if has_compounding_withdrawal_credential(validator) and validator.effective_balance == MAX_EFFECTIVE_BALANCE:
return get_validator_excess_balance(validator, balance) > 0
return False
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @avsetsin Please can you port your review comments to ethereum#3618 ? |
||
| has_excess_balance = balance > MAX_EFFECTIVE_BALANCE | ||
| return has_eth1_withdrawal_credential(validator) and has_max_effective_balance and has_excess_balance | ||
| if not has_withdrawable_credential(validator): | ||
| return False | ||
| ceiling = get_validator_ceiling(validator) | ||
| has_ceiling_balance = validator.effective_balance == ceiling | ||
| has_excess_balance = balance > ceiling | ||
| return has_ceiling_balance and has_excess_balance | ||
|
|
||
|
|
||
| def process_historical_summaries_update(state: BeaconState) -> None: | ||
|
|
@@ -3589,11 +3633,12 @@ def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]: | |
| )) | ||
| withdrawal_index += WithdrawalIndex(1) | ||
| elif is_partially_withdrawable_validator(validator, balance): | ||
| ceiling = get_validator_ceiling(validator) | ||
| withdrawals.append(Withdrawal( | ||
| index=withdrawal_index, | ||
| validator_index=validator_index, | ||
| address=ExecutionAddress(validator.withdrawal_credentials[12:]), | ||
| amount=balance - MAX_EFFECTIVE_BALANCE, | ||
| amount=balance - ceiling, | ||
|
michaelneuder marked this conversation as resolved.
Outdated
|
||
| )) | ||
| withdrawal_index += WithdrawalIndex(1) | ||
| if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.