From 46b570a92c8339d60112f17e52d11b560fab926c Mon Sep 17 00:00:00 2001 From: Preston Van Loon Date: Tue, 2 Jul 2024 14:20:21 -0500 Subject: [PATCH] Electra: EIP-7251 Update `process_voluntary_exit` --- beacon-chain/core/blocks/exit.go | 20 +++++++++++++++++-- .../electra/operations/voluntary_exit_test.go | 1 - .../electra/operations/voluntary_exit_test.go | 1 - 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/beacon-chain/core/blocks/exit.go b/beacon-chain/core/blocks/exit.go index 046b9bbc1a49..4b789613052a 100644 --- a/beacon-chain/core/blocks/exit.go +++ b/beacon-chain/core/blocks/exit.go @@ -98,6 +98,8 @@ func ProcessVoluntaryExits( // 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 +// # 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 Electra:EIP7251] // # Verify signature // domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) // signing_root = compute_signing_root(voluntary_exit, domain) @@ -128,7 +130,7 @@ func VerifyExitAndSignature( } exit := signed.Exit - if err := verifyExitConditions(validator, currentSlot, exit); err != nil { + if err := verifyExitConditions(state, validator, currentSlot, exit); err != nil { return err } domain, err := signing.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot) @@ -157,13 +159,15 @@ func VerifyExitAndSignature( // 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 +// # 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 Electra:EIP7251] // # 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) // # Initiate exit // initiate_validator_exit(state, voluntary_exit.validator_index) -func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot primitives.Slot, exit *ethpb.VoluntaryExit) error { +func verifyExitConditions(st state.ReadOnlyBeaconState, validator state.ReadOnlyValidator, currentSlot primitives.Slot, exit *ethpb.VoluntaryExit) error { currentEpoch := slots.ToEpoch(currentSlot) // Verify the validator is active. if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) { @@ -186,6 +190,18 @@ func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot primiti params.BeaconConfig().ShardCommitteePeriod, validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod, ) + } + + if st.Version() >= version.Electra { + // Only exit validator if it has no pending withdrawals in the queue. + pbw, err := st.PendingBalanceToWithdraw(exit.ValidatorIndex) + if err != nil { + return fmt.Errorf("unable to retrieve pending balance to withdraw for validator %d: %w", exit.ValidatorIndex, err) + } + if pbw != 0 { + return fmt.Errorf("validator %d must have no pending balance to withdraw, got %d pending balance to withdraw", exit.ValidatorIndex, pbw) + } } + return nil } diff --git a/testing/spectest/mainnet/electra/operations/voluntary_exit_test.go b/testing/spectest/mainnet/electra/operations/voluntary_exit_test.go index ed87d6df8b87..c0f18adecf2f 100644 --- a/testing/spectest/mainnet/electra/operations/voluntary_exit_test.go +++ b/testing/spectest/mainnet/electra/operations/voluntary_exit_test.go @@ -7,6 +7,5 @@ import ( ) func TestMainnet_Electra_Operations_VoluntaryExit(t *testing.T) { - t.Skip("TODO: Electra") operations.RunVoluntaryExitTest(t, "mainnet") } diff --git a/testing/spectest/minimal/electra/operations/voluntary_exit_test.go b/testing/spectest/minimal/electra/operations/voluntary_exit_test.go index ab3098ed6b0c..ef54818ada01 100644 --- a/testing/spectest/minimal/electra/operations/voluntary_exit_test.go +++ b/testing/spectest/minimal/electra/operations/voluntary_exit_test.go @@ -7,6 +7,5 @@ import ( ) func TestMinimal_Electra_Operations_VoluntaryExit(t *testing.T) { - t.Skip("TODO: Electra") operations.RunVoluntaryExitTest(t, "minimal") }