diff --git a/beacon-chain/core/electra/consolidations.go b/beacon-chain/core/electra/consolidations.go index 37145c29a519..52030c29e359 100644 --- a/beacon-chain/core/electra/consolidations.go +++ b/beacon-chain/core/electra/consolidations.go @@ -40,7 +40,7 @@ import ( // // state.pending_consolidations = state.pending_consolidations[next_pending_consolidation:] func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) error { - ctx, span := trace.StartSpan(ctx, "electra.ProcessPendingConsolidations") + _, span := trace.StartSpan(ctx, "electra.ProcessPendingConsolidations") defer span.End() if st == nil || st.IsNil() { @@ -68,7 +68,7 @@ func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) err break } - if err := SwitchToCompoundingValidator(ctx, st, pc.TargetIndex); err != nil { + if err := SwitchToCompoundingValidator(st, pc.TargetIndex); err != nil { return err } diff --git a/beacon-chain/core/electra/upgrade.go b/beacon-chain/core/electra/upgrade.go index ef49f55552aa..7560175e7b33 100644 --- a/beacon-chain/core/electra/upgrade.go +++ b/beacon-chain/core/electra/upgrade.go @@ -295,14 +295,14 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error) } for _, index := range preActivationIndices { - if err := helpers.QueueEntireBalanceAndResetValidator(post, index); err != nil { + if err := QueueEntireBalanceAndResetValidator(post, index); err != nil { return nil, errors.Wrap(err, "failed to queue entire balance and reset validator") } } // Ensure early adopters of compounding credentials go through the activation churn for _, index := range compoundWithdrawalIndices { - if err := helpers.QueueExcessActiveBalance(post, index); err != nil { + if err := QueueExcessActiveBalance(post, index); err != nil { return nil, errors.Wrap(err, "failed to queue excess active balance") } } diff --git a/beacon-chain/core/electra/validator.go b/beacon-chain/core/electra/validator.go index dd9cf503daf3..91fb0a87021a 100644 --- a/beacon-chain/core/electra/validator.go +++ b/beacon-chain/core/electra/validator.go @@ -1,7 +1,6 @@ package electra import ( - "context" "errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" @@ -19,7 +18,7 @@ import ( // if has_eth1_withdrawal_credential(validator): // validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] // queue_excess_active_balance(state, index) -func SwitchToCompoundingValidator(ctx context.Context, s state.BeaconState, idx primitives.ValidatorIndex) error { +func SwitchToCompoundingValidator(s state.BeaconState, idx primitives.ValidatorIndex) error { v, err := s.ValidatorAtIndex(idx) if err != nil { return err @@ -32,12 +31,12 @@ func SwitchToCompoundingValidator(ctx context.Context, s state.BeaconState, idx if err := s.UpdateValidatorAtIndex(idx, v); err != nil { return err } - return queueExcessActiveBalance(ctx, s, idx) + return QueueExcessActiveBalance(s, idx) } return nil } -// queueExcessActiveBalance +// QueueExcessActiveBalance // // Spec definition: // @@ -49,7 +48,7 @@ func SwitchToCompoundingValidator(ctx context.Context, s state.BeaconState, idx // state.pending_balance_deposits.append( // PendingBalanceDeposit(index=index, amount=excess_balance) // ) -func queueExcessActiveBalance(ctx context.Context, s state.BeaconState, idx primitives.ValidatorIndex) error { +func QueueExcessActiveBalance(s state.BeaconState, idx primitives.ValidatorIndex) error { bal, err := s.BalanceAtIndex(idx) if err != nil { return err @@ -80,7 +79,7 @@ func queueExcessActiveBalance(ctx context.Context, s state.BeaconState, idx prim // ) // //nolint:dupword -func QueueEntireBalanceAndResetValidator(ctx context.Context, s state.BeaconState, idx primitives.ValidatorIndex) error { +func QueueEntireBalanceAndResetValidator(s state.BeaconState, idx primitives.ValidatorIndex) error { bal, err := s.BalanceAtIndex(idx) if err != nil { return err diff --git a/beacon-chain/core/electra/validator_test.go b/beacon-chain/core/electra/validator_test.go index b873d17b5f07..b7d898f66420 100644 --- a/beacon-chain/core/electra/validator_test.go +++ b/beacon-chain/core/electra/validator_test.go @@ -2,7 +2,6 @@ package electra_test import ( "bytes" - "context" "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" @@ -11,6 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" ) func TestSwitchToCompoundingValidator(t *testing.T) { @@ -34,10 +34,10 @@ func TestSwitchToCompoundingValidator(t *testing.T) { }) // Test that a validator with no withdrawal credentials cannot be switched to compounding. require.NoError(t, err) - require.ErrorContains(t, "validator has no withdrawal credentials", electra.SwitchToCompoundingValidator(context.TODO(), s, 0)) + require.ErrorContains(t, "validator has no withdrawal credentials", electra.SwitchToCompoundingValidator(s, 0)) // Test that a validator with withdrawal credentials can be switched to compounding. - require.NoError(t, electra.SwitchToCompoundingValidator(context.TODO(), s, 1)) + require.NoError(t, electra.SwitchToCompoundingValidator(s, 1)) v, err := s.ValidatorAtIndex(1) require.NoError(t, err) require.Equal(t, true, bytes.HasPrefix(v.WithdrawalCredentials, []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte}), "withdrawal credentials were not updated") @@ -50,7 +50,7 @@ func TestSwitchToCompoundingValidator(t *testing.T) { require.Equal(t, 0, len(pbd), "pending balance deposits should be empty") // Test that a validator with excess balance can be switched to compounding, excess balance is queued. - require.NoError(t, electra.SwitchToCompoundingValidator(context.TODO(), s, 2)) + require.NoError(t, electra.SwitchToCompoundingValidator(s, 2)) b, err = s.BalanceAtIndex(2) require.NoError(t, err) require.Equal(t, params.BeaconConfig().MinActivationBalance, b, "balance was not changed") @@ -74,7 +74,7 @@ func TestQueueEntireBalanceAndResetValidator(t *testing.T) { }, }) require.NoError(t, err) - require.NoError(t, electra.QueueEntireBalanceAndResetValidator(context.TODO(), s, 0)) + require.NoError(t, electra.QueueEntireBalanceAndResetValidator(s, 0)) b, err := s.BalanceAtIndex(0) require.NoError(t, err) require.Equal(t, uint64(0), b, "balance was not changed") @@ -88,3 +88,57 @@ func TestQueueEntireBalanceAndResetValidator(t *testing.T) { require.Equal(t, params.BeaconConfig().MinActivationBalance+100_000, pbd[0].Amount, "pending balance deposit amount is incorrect") require.Equal(t, primitives.ValidatorIndex(0), pbd[0].Index, "pending balance deposit index is incorrect") } + +func TestSwitchToCompoundingValidator_Ok(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) + vals := st.Validators() + vals[0].WithdrawalCredentials = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte} + require.NoError(t, st.SetValidators(vals)) + bals := st.Balances() + bals[0] = params.BeaconConfig().MinActivationBalance + 1010 + require.NoError(t, st.SetBalances(bals)) + require.NoError(t, electra.SwitchToCompoundingValidator(st, 0)) + + pbd, err := st.PendingBalanceDeposits() + require.NoError(t, err) + require.Equal(t, uint64(1010), pbd[0].Amount) // appends it at the end + val, err := st.ValidatorAtIndex(0) + require.NoError(t, err) + + bytes.HasPrefix(val.WithdrawalCredentials, []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte}) +} + +func TestQueueExcessActiveBalance_Ok(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) + bals := st.Balances() + bals[0] = params.BeaconConfig().MinActivationBalance + 1000 + require.NoError(t, st.SetBalances(bals)) + + err := electra.QueueExcessActiveBalance(st, 0) + require.NoError(t, err) + + pbd, err := st.PendingBalanceDeposits() + require.NoError(t, err) + require.Equal(t, uint64(1000), pbd[0].Amount) // appends it at the end + + bals = st.Balances() + require.Equal(t, params.BeaconConfig().MinActivationBalance, bals[0]) +} + +func TestQueueEntireBalanceAndResetValidator_Ok(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) + // need to manually set this to 0 as after 6110 these balances are now 0 and instead populates pending balance deposits + bals := st.Balances() + bals[0] = params.BeaconConfig().MinActivationBalance - 1000 + require.NoError(t, st.SetBalances(bals)) + err := electra.QueueEntireBalanceAndResetValidator(st, 0) + require.NoError(t, err) + + pbd, err := st.PendingBalanceDeposits() + require.NoError(t, err) + require.Equal(t, 1, len(pbd)) + require.Equal(t, params.BeaconConfig().MinActivationBalance-1000, pbd[0].Amount) + bal, err := st.BalanceAtIndex(0) + require.NoError(t, err) + require.Equal(t, uint64(0), bal) +} diff --git a/beacon-chain/core/helpers/validators.go b/beacon-chain/core/helpers/validators.go index cf7c3de37da0..a45c69562fe6 100644 --- a/beacon-chain/core/helpers/validators.go +++ b/beacon-chain/core/helpers/validators.go @@ -674,68 +674,3 @@ func ValidatorMaxEffectiveBalance(val *ethpb.Validator) uint64 { } return params.BeaconConfig().MinActivationBalance } - -// QueueExcessActiveBalance queues validators with balances above the min activation balance and adds to pending balance deposit. -// -// Spec definition: -// -// def queue_excess_active_balance(state: BeaconState, index: ValidatorIndex) -> None: -// balance = state.balances[index] -// if balance > MIN_ACTIVATION_BALANCE: -// excess_balance = balance - MIN_ACTIVATION_BALANCE -// state.balances[index] = MIN_ACTIVATION_BALANCE -// state.pending_balance_deposits.append( -// PendingBalanceDeposit(index=index, amount=excess_balance) -// ) -func QueueExcessActiveBalance(s state.BeaconState, idx primitives.ValidatorIndex) error { - bal, err := s.BalanceAtIndex(idx) - if err != nil { - return err - } - - if bal > params.BeaconConfig().MinActivationBalance { - excessBalance := bal - params.BeaconConfig().MinActivationBalance - if err := s.UpdateBalancesAtIndex(idx, params.BeaconConfig().MinActivationBalance); err != nil { - return err - } - return s.AppendPendingBalanceDeposit(idx, excessBalance) - } - return nil -} - -// QueueEntireBalanceAndResetValidator queues the entire balance and resets the validator. This is used in electra fork logic. -// -// Spec definition: -// -// def queue_entire_balance_and_reset_validator(state: BeaconState, index: ValidatorIndex) -> None: -// balance = state.balances[index] -// validator = state.validators[index] -// state.balances[index] = 0 -// validator.effective_balance = 0 -// validator.activation_eligibility_epoch = FAR_FUTURE_EPOCH -// state.pending_balance_deposits.append( -// PendingBalanceDeposit(index=index, amount=balance) -// ) -func QueueEntireBalanceAndResetValidator(s state.BeaconState, idx primitives.ValidatorIndex) error { - bal, err := s.BalanceAtIndex(idx) - if err != nil { - return err - } - - if err := s.UpdateBalancesAtIndex(idx, 0); err != nil { - return err - } - - v, err := s.ValidatorAtIndex(idx) - if err != nil { - return err - } - - v.EffectiveBalance = 0 - v.ActivationEligibilityEpoch = params.BeaconConfig().FarFutureEpoch - if err := s.UpdateValidatorAtIndex(idx, v); err != nil { - return err - } - - return s.AppendPendingBalanceDeposit(idx, bal) -} diff --git a/beacon-chain/core/helpers/validators_test.go b/beacon-chain/core/helpers/validators_test.go index 43e0416eca58..efa21c75cb63 100644 --- a/beacon-chain/core/helpers/validators_test.go +++ b/beacon-chain/core/helpers/validators_test.go @@ -18,7 +18,6 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" ) func TestIsActiveValidator_OK(t *testing.T) { @@ -1120,40 +1119,3 @@ func TestValidatorMaxEffectiveBalance(t *testing.T) { // Sanity check that MinActivationBalance equals (pre-electra) MaxEffectiveBalance assert.Equal(t, params.BeaconConfig().MinActivationBalance, params.BeaconConfig().MaxEffectiveBalance) } - -func TestQueueExcessActiveBalance_Ok(t *testing.T) { - st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) - bals := st.Balances() - bals[0] = params.BeaconConfig().MinActivationBalance + 1000 - require.NoError(t, st.SetBalances(bals)) - - err := helpers.QueueExcessActiveBalance(st, 0) - require.NoError(t, err) - - pbd, err := st.PendingBalanceDeposits() - require.NoError(t, err) - require.Equal(t, uint64(1000), pbd[0].Amount) - - bals = st.Balances() - require.Equal(t, params.BeaconConfig().MinActivationBalance, bals[0]) -} - -func TestQueueEntireBalanceAndResetValidator_Ok(t *testing.T) { - st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) - val, err := st.ValidatorAtIndex(0) - require.NoError(t, err) - require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, val.EffectiveBalance) - pbd, err := st.PendingBalanceDeposits() - require.NoError(t, err) - require.Equal(t, 0, len(pbd)) - err = helpers.QueueEntireBalanceAndResetValidator(st, 0) - require.NoError(t, err) - - pbd, err = st.PendingBalanceDeposits() - require.NoError(t, err) - require.Equal(t, 1, len(pbd)) - - val, err = st.ValidatorAtIndex(0) - require.NoError(t, err) - require.Equal(t, uint64(0), val.EffectiveBalance) -}