diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index dcd3094e3029..37d83038eb83 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -79,6 +79,7 @@ go_test( "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/core/altair/sync_committee.go b/beacon-chain/core/altair/sync_committee.go index 9bfcd8434c6e..88ef8650763d 100644 --- a/beacon-chain/core/altair/sync_committee.go +++ b/beacon-chain/core/altair/sync_committee.go @@ -18,6 +18,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/math" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" ) @@ -101,7 +102,8 @@ func NextSyncCommittee(ctx context.Context, s state.BeaconState) (*ethpb.SyncCom // candidate_index = active_validator_indices[shuffled_index] // 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: +// # [Modified in Electra:EIP7251] +// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_byte: // sync_committee_indices.append(candidate_index) // i += 1 // return sync_committee_indices @@ -121,6 +123,11 @@ func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]primi cIndices := make([]primitives.ValidatorIndex, 0, syncCommitteeSize) hashFunc := hash.CustomSHA256Hasher() + maxEB := cfg.MaxEffectiveBalanceElectra + if s.Version() < version.Electra { + maxEB = cfg.MaxEffectiveBalance + } + for i := primitives.ValidatorIndex(0); uint64(len(cIndices)) < params.BeaconConfig().SyncCommitteeSize; i++ { if ctx.Err() != nil { return nil, ctx.Err() @@ -140,7 +147,7 @@ func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]primi } effectiveBal := v.EffectiveBalance() - if effectiveBal*maxRandomByte >= cfg.MaxEffectiveBalance*uint64(randomByte) { + if effectiveBal*maxRandomByte >= maxEB*uint64(randomByte) { cIndices = append(cIndices, cIndex) } } diff --git a/beacon-chain/core/altair/sync_committee_test.go b/beacon-chain/core/altair/sync_committee_test.go index c9406d876a8e..9e38b0065440 100644 --- a/beacon-chain/core/altair/sync_committee_test.go +++ b/beacon-chain/core/altair/sync_committee_test.go @@ -13,13 +13,14 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" prysmTime "github.com/prysmaticlabs/prysm/v5/time" ) func TestSyncCommitteeIndices_CanGet(t *testing.T) { - getState := func(t *testing.T, count uint64) state.BeaconState { + getState := func(t *testing.T, count uint64, vers int) state.BeaconState { validators := make([]*ethpb.Validator, count) for i := 0; i < len(validators); i++ { validators[i] = ðpb.Validator{ @@ -27,17 +28,28 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) { EffectiveBalance: params.BeaconConfig().MinDepositAmount, } } - st, err := state_native.InitializeFromProtoAltair(ðpb.BeaconStateAltair{ - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - }) + var st state.BeaconState + var err error + switch vers { + case version.Altair: + st, err = state_native.InitializeFromProtoAltair(ðpb.BeaconStateAltair{ + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + }) + case version.Electra: + st, err = state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{ + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + }) + default: + t.Fatal("Unknown version") + } require.NoError(t, err) require.NoError(t, st.SetValidators(validators)) return st } type args struct { - state state.BeaconState - epoch primitives.Epoch + validatorCount uint64 + epoch primitives.Epoch } tests := []struct { name string @@ -48,32 +60,32 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) { { name: "genesis validator count, epoch 0", args: args{ - state: getState(t, params.BeaconConfig().MinGenesisActiveValidatorCount), - epoch: 0, + validatorCount: params.BeaconConfig().MinGenesisActiveValidatorCount, + epoch: 0, }, wantErr: false, }, { name: "genesis validator count, epoch 100", args: args{ - state: getState(t, params.BeaconConfig().MinGenesisActiveValidatorCount), - epoch: 100, + validatorCount: params.BeaconConfig().MinGenesisActiveValidatorCount, + epoch: 100, }, wantErr: false, }, { name: "less than optimal validator count, epoch 100", args: args{ - state: getState(t, params.BeaconConfig().MaxValidatorsPerCommittee), - epoch: 100, + validatorCount: params.BeaconConfig().MaxValidatorsPerCommittee, + epoch: 100, }, wantErr: false, }, { name: "no active validators, epoch 100", args: args{ - state: getState(t, 0), // Regression test for divide by zero. Issue #13051. - epoch: 100, + validatorCount: 0, // Regression test for divide by zero. Issue #13051. + epoch: 100, }, wantErr: true, errString: "no active validator indices", @@ -81,13 +93,18 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - helpers.ClearCache() - got, err := altair.NextSyncCommitteeIndices(context.Background(), tt.args.state) - if tt.wantErr { - require.ErrorContains(t, tt.errString, err) - } else { - require.NoError(t, err) - require.Equal(t, int(params.BeaconConfig().SyncCommitteeSize), len(got)) + for _, v := range []int{version.Altair, version.Electra} { + t.Run(version.String(v), func(t *testing.T) { + helpers.ClearCache() + st := getState(t, tt.args.validatorCount, v) + got, err := altair.NextSyncCommitteeIndices(context.Background(), st) + if tt.wantErr { + require.ErrorContains(t, tt.errString, err) + } else { + require.NoError(t, err) + require.Equal(t, int(params.BeaconConfig().SyncCommitteeSize), len(got)) + } + }) } }) }