diff --git a/beacon-chain/core/helpers/validators.go b/beacon-chain/core/helpers/validators.go index ccee87add7c5..231e06351df9 100644 --- a/beacon-chain/core/helpers/validators.go +++ b/beacon-chain/core/helpers/validators.go @@ -17,6 +17,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/hash" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" log "github.com/sirupsen/logrus" "go.opencensus.io/trace" @@ -357,10 +358,10 @@ func BeaconProposerIndexAtSlot(ctx context.Context, state state.ReadOnlyBeaconSt // candidate_index = indices[compute_shuffled_index(i % total, total, seed)] // random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] // effective_balance = state.validators[candidate_index].effective_balance -// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte: +// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_byte: #[Modified in Electra:EIP7251] // return candidate_index // i += 1 -func ComputeProposerIndex(bState state.ReadOnlyValidators, activeIndices []primitives.ValidatorIndex, seed [32]byte) (primitives.ValidatorIndex, error) { +func ComputeProposerIndex(bState state.ReadOnlyBeaconState, activeIndices []primitives.ValidatorIndex, seed [32]byte) (primitives.ValidatorIndex, error) { length := uint64(len(activeIndices)) if length == 0 { return 0, errors.New("empty active indices list") @@ -385,7 +386,12 @@ func ComputeProposerIndex(bState state.ReadOnlyValidators, activeIndices []primi } effectiveBal := v.EffectiveBalance() - if effectiveBal*maxRandomByte >= params.BeaconConfig().MaxEffectiveBalance*uint64(randomByte) { + maxEB := params.BeaconConfig().MaxEffectiveBalance + if bState.Version() >= version.Electra { + maxEB = params.BeaconConfig().MaxEffectiveBalanceElectra + } + + if effectiveBal*maxRandomByte >= maxEB*uint64(randomByte) { return candidateIndex, nil } } diff --git a/beacon-chain/core/helpers/validators_test.go b/beacon-chain/core/helpers/validators_test.go index a5df3c6bf83d..c0ab33d395f1 100644 --- a/beacon-chain/core/helpers/validators_test.go +++ b/beacon-chain/core/helpers/validators_test.go @@ -597,10 +597,11 @@ func TestComputeProposerIndex(t *testing.T) { seed [32]byte } tests := []struct { - name string - args args - want primitives.ValidatorIndex - wantedErr string + name string + isElectraOrAbove bool + args args + want primitives.ValidatorIndex + wantedErr string }{ { name: "all_active_indices", @@ -682,6 +683,54 @@ func TestComputeProposerIndex(t *testing.T) { }, want: 7, }, + { + name: "electra_probability_changes", + isElectraOrAbove: true, + args: args{ + validators: []*ethpb.Validator{ + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + }, + indices: []primitives.ValidatorIndex{3}, + seed: seed, + }, + want: 3, + }, + { + name: "electra_probability_changes_all_active", + isElectraOrAbove: true, + args: args{ + validators: []*ethpb.Validator{ + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, // skip this one + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + }, + indices: []primitives.ValidatorIndex{0, 1, 2, 3, 4}, + seed: seed, + }, + want: 4, + }, + { + name: "electra_probability_returns_first_validator_with_criteria", + isElectraOrAbove: true, + args: args{ + validators: []*ethpb.Validator{ + {EffectiveBalance: 1}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {EffectiveBalance: 1}, + {EffectiveBalance: 1}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + }, + indices: []primitives.ValidatorIndex{1}, + seed: seed, + }, + want: 1, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -690,6 +739,11 @@ func TestComputeProposerIndex(t *testing.T) { bState := ðpb.BeaconState{Validators: tt.args.validators} stTrie, err := state_native.InitializeFromProtoUnsafePhase0(bState) require.NoError(t, err) + if tt.isElectraOrAbove { + stTrie, err = state_native.InitializeFromProtoUnsafeElectra(ðpb.BeaconStateElectra{Validators: tt.args.validators}) + require.NoError(t, err) + } + got, err := helpers.ComputeProposerIndex(stTrie, tt.args.indices, tt.args.seed) if tt.wantedErr != "" { assert.ErrorContains(t, tt.wantedErr, err)