-
Notifications
You must be signed in to change notification settings - Fork 1.3k
EIP-7251: misc changes #3636
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
Merged
Merged
EIP-7251: misc changes #3636
Changes from 10 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
cda10d0
Refactor EL withdraw request processing
mkalinin 6f5cc4b
Replace MIN_ACTIVATION_BALANCE with MAX_EFFECTIVE_BALANCE
mkalinin 31142b0
Require sufficient EB to emit partial withdrawal
mkalinin 46638d3
Remove unused method
mkalinin 517f741
Abort voluntary exit if validator has pending partial withdrawals
mkalinin 915f90e
Strictly check withdrawal address upon consolidation
mkalinin 534bcfc
Use source.effective_balance for consolidaiton churn
mkalinin d004391
Merge branch 'dev' into eip-7251
mkalinin 7bbecfb
Revert "Replace MIN_ACTIVATION_BALANCE with MAX_EFFECTIVE_BALANCE"
mkalinin 221f273
Fix lint
mkalinin 4f8fb6f
Update specs/_features/eip7251/beacon-chain.md
mkalinin ace9db9
Set FULL_EXIT_REQUEST_AMOUNT to 0
mkalinin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |||||
|
|
||||||
| - [Introduction](#introduction) | ||||||
| - [Constants](#constants) | ||||||
| - [Misc](#misc) | ||||||
| - [Withdrawal prefixes](#withdrawal-prefixes) | ||||||
| - [Domains](#domains) | ||||||
| - [Presets](#presets) | ||||||
|
|
@@ -43,9 +44,9 @@ | |||||
| - [New `get_activation_exit_churn_limit`](#new-get_activation_exit_churn_limit) | ||||||
| - [New `get_consolidation_churn_limit`](#new-get_consolidation_churn_limit) | ||||||
| - [New `get_active_balance`](#new-get_active_balance) | ||||||
| - [New `get_pending_balance_to_withdraw`](#new-get_pending_balance_to_withdraw) | ||||||
| - [Beacon state mutators](#beacon-state-mutators) | ||||||
| - [Updated `initiate_validator_exit`](#updated--initiate_validator_exit) | ||||||
| - [New `set_compounding_withdrawal_credentials`](#new-set_compounding_withdrawal_credentials) | ||||||
| - [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator) | ||||||
| - [New `queue_excess_active_balance`](#new-queue_excess_active_balance) | ||||||
| - [New `compute_exit_epoch_and_update_churn`](#new-compute_exit_epoch_and_update_churn) | ||||||
|
|
@@ -72,6 +73,8 @@ | |||||
| - [New `process_execution_layer_withdraw_request`](#new-process_execution_layer_withdraw_request) | ||||||
| - [Consolidations](#consolidations) | ||||||
| - [New `process_consolidation`](#new-process_consolidation) | ||||||
| - [Voluntary exits](#voluntary-exits) | ||||||
| - [Updated `process_voluntary_exit`](#updated-process_voluntary_exit) | ||||||
|
|
||||||
| <!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||||||
| <!-- /TOC --> | ||||||
|
|
@@ -87,6 +90,12 @@ See [a modest proposal](https://notes.ethereum.org/@mikeneuder/increase-maxeb), | |||||
|
|
||||||
| The following values are (non-configurable) constants used throughout the specification. | ||||||
|
|
||||||
| ### Misc | ||||||
|
|
||||||
| | Name | Value | | ||||||
| | - | - | | ||||||
| | `FULL_EXIT_REQUEST_AMOUNT` | `uint64(2**64 - 1)` | | ||||||
|
|
||||||
| ### Withdrawal prefixes | ||||||
|
|
||||||
| | Name | Value | | ||||||
|
|
@@ -412,6 +421,14 @@ def get_active_balance(state: BeaconState, validator_index: ValidatorIndex) -> G | |||||
| return min(state.balances[validator_index], active_balance_ceil) | ||||||
| ``` | ||||||
|
|
||||||
| #### New `get_pending_balance_to_withdraw` | ||||||
|
|
||||||
| ```python | ||||||
| def get_pending_balance_to_withdraw(state: BeaconState, validator_index: ValidatorIndex) -> Gwei: | ||||||
| return sum( | ||||||
| withdrawal.amount for withdrawal in state.pending_partial_withdrawals if withdrawal.index == validator_index) | ||||||
| ``` | ||||||
|
|
||||||
| ### Beacon state mutators | ||||||
|
|
||||||
| #### Updated `initiate_validator_exit` | ||||||
|
|
@@ -434,15 +451,6 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: | |||||
| validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY) | ||||||
| ``` | ||||||
|
|
||||||
| #### New `set_compounding_withdrawal_credentials` | ||||||
|
|
||||||
| ```python | ||||||
| def set_compounding_withdrawal_credentials(state: BeaconState, index: ValidatorIndex) -> None: | ||||||
| validator = state.validators[index] | ||||||
| if has_eth1_withdrawal_credential(validator): | ||||||
| validator.withdrawal_credentials[:1] = COMPOUNDING_WITHDRAWAL_PREFIX | ||||||
| ``` | ||||||
|
|
||||||
| #### New `switch_to_compounding_validator` | ||||||
|
|
||||||
| ```python | ||||||
|
|
@@ -682,7 +690,9 @@ def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], | |||||
| break | ||||||
|
|
||||||
| validator = state.validators[withdrawal.index] | ||||||
| if validator.exit_epoch == FAR_FUTURE_EPOCH and state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE: | ||||||
| has_sufficient_effective_balance = validator.effective_balance == MIN_ACTIVATION_BALANCE | ||||||
|
ralexstokes marked this conversation as resolved.
|
||||||
| has_excess_balance = state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE | ||||||
| if validator.exit_epoch == FAR_FUTURE_EPOCH and has_sufficient_effective_balance and has_excess_balance: | ||||||
| withdrawable_balance = min(state.balances[withdrawal.index] - MIN_ACTIVATION_BALANCE, withdrawal.amount) | ||||||
| withdrawals.append(Withdrawal( | ||||||
| index=withdrawal_index, | ||||||
|
|
@@ -771,7 +781,7 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: | |||||
| for_ops(body.attester_slashings, process_attester_slashing) | ||||||
| for_ops(body.attestations, process_attestation) | ||||||
| for_ops(body.deposits, process_deposit) # [Modified in EIP7251] | ||||||
| for_ops(body.voluntary_exits, process_voluntary_exit) | ||||||
| for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in EIP7251] | ||||||
| for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) | ||||||
| for_ops(body.execution_payload.withdraw_requests, process_execution_layer_withdraw_request) # New in EIP7251 | ||||||
| for_ops(body.consolidations, process_consolidation) # New in EIP7251 | ||||||
|
|
@@ -866,7 +876,8 @@ def process_execution_layer_withdraw_request( | |||||
| execution_layer_withdraw_request: ExecutionLayerWithdrawRequest | ||||||
| ) -> None: | ||||||
| amount = execution_layer_withdraw_request.amount | ||||||
| is_full_exit_request = amount == 0 | ||||||
| is_full_exit_request = amount == FULL_EXIT_REQUEST_AMOUNT | ||||||
|
|
||||||
| # If partial withdrawal queue is full, only full exits are processed | ||||||
| if len(state.pending_partial_withdrawals) >= PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request: | ||||||
| return | ||||||
|
|
@@ -888,20 +899,21 @@ def process_execution_layer_withdraw_request( | |||||
| and get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD | ||||||
| ): | ||||||
| return | ||||||
| # New condition: only allow partial withdrawals with compounding withdrawal credentials | ||||||
| if not (is_full_exit_request or has_compounding_withdrawal_credential(validator)): | ||||||
| return | ||||||
|
|
||||||
| pending_balance_to_withdraw = sum( | ||||||
| item.amount for item in state.pending_partial_withdrawals if item.index == index | ||||||
| ) | ||||||
| # only exit validator if it has no pending withdrawals in the queue | ||||||
| if is_full_exit_request and pending_balance_to_withdraw > 0: | ||||||
| return | ||||||
| pending_balance_to_withdraw = get_pending_balance_to_withdraw(state, index) | ||||||
|
|
||||||
| if is_full_exit_request: | ||||||
| initiate_validator_exit(state, index) | ||||||
| elif state.balances[index] > MIN_ACTIVATION_BALANCE + pending_balance_to_withdraw: | ||||||
| # Only exit validator if it has no pending withdrawals in the queue | ||||||
| if pending_balance_to_withdraw == 0: | ||||||
| initiate_validator_exit(state, index) | ||||||
|
|
||||||
| return | ||||||
|
|
||||||
| has_sufficient_effective_balance = validator.effective_balance == MIN_ACTIVATION_BALANCE | ||||||
|
Contributor
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.
Suggested change
|
||||||
| has_excess_balance = state.balances[index] > MIN_ACTIVATION_BALANCE + pending_balance_to_withdraw | ||||||
|
|
||||||
| # Only allow partial withdrawals with compounding withdrawal credentials | ||||||
| if has_compounding_withdrawal_credential(validator) and has_sufficient_effective_balance and has_excess_balance: | ||||||
| to_withdraw = min( | ||||||
| state.balances[index] - MIN_ACTIVATION_BALANCE - pending_balance_to_withdraw, | ||||||
| amount | ||||||
|
|
@@ -945,7 +957,7 @@ def process_consolidation(state: BeaconState, signed_consolidation: SignedConsol | |||||
| assert has_execution_withdrawal_credential(source_validator) | ||||||
| assert has_execution_withdrawal_credential(target_validator) | ||||||
| # Verify the same withdrawal address | ||||||
| assert source_validator.withdrawal_credentials[1:] == target_validator.withdrawal_credentials[1:] | ||||||
| assert source_validator.withdrawal_credentials[12:] == target_validator.withdrawal_credentials[12:] | ||||||
|
|
||||||
| # Verify consolidation is signed by the source and the target | ||||||
| domain = compute_domain(DOMAIN_CONSOLIDATION, genesis_validators_root=state.genesis_validators_root) | ||||||
|
|
@@ -954,8 +966,8 @@ def process_consolidation(state: BeaconState, signed_consolidation: SignedConsol | |||||
| assert bls.FastAggregateVerify(pubkeys, signing_root, signed_consolidation.signature) | ||||||
|
|
||||||
| # Initiate source validator exit and append pending consolidation | ||||||
| active_balance = get_active_balance(state, consolidation.source_index) | ||||||
| source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn(state, active_balance) | ||||||
| source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn( | ||||||
| state, source_validator.effective_balance) | ||||||
| source_validator.withdrawable_epoch = Epoch( | ||||||
| source_validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY | ||||||
| ) | ||||||
|
|
@@ -965,3 +977,28 @@ def process_consolidation(state: BeaconState, signed_consolidation: SignedConsol | |||||
| )) | ||||||
| ``` | ||||||
|
|
||||||
| ##### Voluntary exits | ||||||
|
|
||||||
| ###### Updated `process_voluntary_exit` | ||||||
|
|
||||||
| ```python | ||||||
| def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None: | ||||||
| voluntary_exit = signed_voluntary_exit.message | ||||||
| validator = state.validators[voluntary_exit.validator_index] | ||||||
| # Verify the validator is active | ||||||
| assert is_active_validator(validator, get_current_epoch(state)) | ||||||
| # Verify exit has not been initiated | ||||||
| assert validator.exit_epoch == FAR_FUTURE_EPOCH | ||||||
| # Exits must specify an epoch when they become valid; they are not valid before then | ||||||
| assert get_current_epoch(state) >= voluntary_exit.epoch | ||||||
| # Verify the validator has been active long enough | ||||||
| assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD | ||||||
| # Verify signature | ||||||
| domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) | ||||||
| signing_root = compute_signing_root(voluntary_exit, domain) | ||||||
| assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature) | ||||||
| # Only exit validator if it has no pending withdrawals in the queue | ||||||
| assert get_pending_balance_to_withdraw(state, voluntary_exit.validator_index) == 0 # [New in EIP7251] | ||||||
| # Initiate exit | ||||||
| initiate_validator_exit(state, voluntary_exit.validator_index) | ||||||
| ``` | ||||||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.