From 6e9faa3618554c42ea319a45c9f2310b4215620b Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 4 Aug 2021 08:13:05 -0700 Subject: [PATCH] Epoch: precompute functions for Altair part 1 (#9309) * Add epoch precompute methods * Split into part 1 for better review * Update epoch_precompute_test.go * Preston's feedback * Skip if the valiator is not eligible * Add regression test for non eligible Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- beacon-chain/core/altair/BUILD.bazel | 10 +- beacon-chain/core/altair/attestation.go | 11 + beacon-chain/core/altair/attestation_test.go | 113 +++++++++ beacon-chain/core/altair/epoch_precompute.go | 165 +++++++++++++ .../core/altair/epoch_precompute_test.go | 231 ++++++++++++++++++ 5 files changed, 529 insertions(+), 1 deletion(-) create mode 100644 beacon-chain/core/altair/attestation.go create mode 100644 beacon-chain/core/altair/attestation_test.go create mode 100644 beacon-chain/core/altair/epoch_precompute.go create mode 100644 beacon-chain/core/altair/epoch_precompute_test.go diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index f6578d16d..685209901 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -3,8 +3,10 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "attestation.go", "block.go", "deposit.go", + "epoch_precompute.go", "reward.go", "sync_committee.go", ], @@ -15,6 +17,7 @@ go_library( ], deps = [ "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/p2p/types:go_default_library", "//beacon-chain/state:go_default_library", @@ -26,20 +29,24 @@ go_library( "//shared/params:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@io_opencensus_go//trace:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ + "attestation_test.go", "block_test.go", "deposit_fuzz_test.go", "deposit_test.go", + "epoch_precompute_test.go", "reward_test.go", "sync_committee_test.go", ], + embed = [":go_default_library"], deps = [ - ":go_default_library", + "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/p2p/types:go_default_library", "//beacon-chain/state:go_default_library", @@ -49,6 +56,7 @@ go_test( "//shared/bytesutil:go_default_library", "//shared/params:go_default_library", "//shared/testutil:go_default_library", + "//shared/testutil/assert:go_default_library", "//shared/testutil/require:go_default_library", "//shared/trieutil:go_default_library", "@com_github_google_gofuzz//:go_default_library", diff --git a/beacon-chain/core/altair/attestation.go b/beacon-chain/core/altair/attestation.go new file mode 100644 index 000000000..470efabff --- /dev/null +++ b/beacon-chain/core/altair/attestation.go @@ -0,0 +1,11 @@ +package altair + +// HasValidatorFlag returns true if the flag at position has set. +func HasValidatorFlag(flag, flagPosition uint8) bool { + return ((flag >> flagPosition) & 1) == 1 +} + +// AddValidatorFlag adds new validator flag to existing one. +func AddValidatorFlag(flag, flagPosition uint8) uint8 { + return flag | (1 << flagPosition) +} diff --git a/beacon-chain/core/altair/attestation_test.go b/beacon-chain/core/altair/attestation_test.go new file mode 100644 index 000000000..0aa14622a --- /dev/null +++ b/beacon-chain/core/altair/attestation_test.go @@ -0,0 +1,113 @@ +package altair_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" + "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/testutil/require" +) + +func TestValidatorFlag_Has(t *testing.T) { + tests := []struct { + name string + set uint8 + expected []uint8 + }{ + {name: "none", + set: 0, + expected: []uint8{}, + }, + { + name: "source", + set: 1, + expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex}, + }, + { + name: "target", + set: 2, + expected: []uint8{params.BeaconConfig().TimelyTargetFlagIndex}, + }, + { + name: "head", + set: 4, + expected: []uint8{params.BeaconConfig().TimelyHeadFlagIndex}, + }, + { + name: "source, target", + set: 3, + expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex}, + }, + { + name: "source, head", + set: 5, + expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex}, + }, + { + name: "target, head", + set: 6, + expected: []uint8{params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex}, + }, + { + name: "source, target, head", + set: 7, + expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + for _, f := range tt.expected { + require.Equal(t, true, altair.HasValidatorFlag(tt.set, f)) + } + }) + } +} + +func TestValidatorFlag_Add(t *testing.T) { + tests := []struct { + name string + set []uint8 + expectedTrue []uint8 + expectedFalse []uint8 + }{ + {name: "none", + set: []uint8{}, + expectedTrue: []uint8{}, + expectedFalse: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex}, + }, + { + name: "source", + set: []uint8{params.BeaconConfig().TimelySourceFlagIndex}, + expectedTrue: []uint8{params.BeaconConfig().TimelySourceFlagIndex}, + expectedFalse: []uint8{params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex}, + }, + { + name: "source, target", + set: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex}, + expectedTrue: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex}, + expectedFalse: []uint8{params.BeaconConfig().TimelyHeadFlagIndex}, + }, + { + name: "source, target, head", + set: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex}, + expectedTrue: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex}, + expectedFalse: []uint8{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b := uint8(0) + for _, f := range tt.set { + b = altair.AddValidatorFlag(b, f) + } + for _, f := range tt.expectedFalse { + require.Equal(t, false, altair.HasValidatorFlag(b, f)) + } + for _, f := range tt.expectedTrue { + require.Equal(t, true, altair.HasValidatorFlag(b, f)) + } + }) + } +} diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go new file mode 100644 index 000000000..a2180cc83 --- /dev/null +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -0,0 +1,165 @@ +package altair + +import ( + "context" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" + "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/shared/params" + "go.opencensus.io/trace" +) + +// InitializeEpochValidators gets called at the beginning of process epoch cycle to return +// pre computed instances of validators attesting records and total +// balances attested in an epoch. +func InitializeEpochValidators(ctx context.Context, st state.BeaconStateAltair) ([]*precompute.Validator, *precompute.Balance, error) { + ctx, span := trace.StartSpan(ctx, "altair.InitializeEpochValidators") + defer span.End() + pValidators := make([]*precompute.Validator, st.NumValidators()) + bal := &precompute.Balance{} + prevEpoch := helpers.PrevEpoch(st) + currentEpoch := helpers.CurrentEpoch(st) + inactivityScores, err := st.InactivityScores() + if err != nil { + return nil, nil, err + } + + // This shouldn't happen with a correct beacon state, + // but rather be safe to defend against index out of bound panics. + if st.NumValidators() > len(inactivityScores) { + return nil, nil, errors.New("num of validators can't be greater than length of inactivity scores") + } + if err := st.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { + // Was validator withdrawable or slashed + withdrawable := currentEpoch >= val.WithdrawableEpoch() + pVal := &precompute.Validator{ + IsSlashed: val.Slashed(), + IsWithdrawableCurrentEpoch: withdrawable, + CurrentEpochEffectiveBalance: val.EffectiveBalance(), + InactivityScore: inactivityScores[idx], + } + // Validator active current epoch + if helpers.IsActiveValidatorUsingTrie(val, currentEpoch) { + pVal.IsActiveCurrentEpoch = true + bal.ActiveCurrentEpoch += val.EffectiveBalance() + } + // Validator active previous epoch + if helpers.IsActiveValidatorUsingTrie(val, prevEpoch) { + pVal.IsActivePrevEpoch = true + bal.ActivePrevEpoch += val.EffectiveBalance() + } + + pValidators[idx] = pVal + return nil + }); err != nil { + return nil, nil, errors.Wrap(err, "could not initialize epoch validator") + } + return pValidators, bal, nil +} + +// ProcessInactivityScores of beacon chain. This updates inactivity scores of beacon chain and +// updates the precompute validator struct for later processing. The inactivity scores work as following: +// For fully inactive validators and perfect active validators, the effect is the same as before Altair. +// For a validator is inactive and the chain fails to finalize, the inactivity score increases by a fixed number, the total loss after N epochs is proportional to N**2/2. +// For imperfectly active validators. The inactivity score's behavior is specified by this function: +// If a validator fails to submit an attestation with the correct target, their inactivity score goes up by 4. +// If they successfully submit an attestation with the correct source and target, their inactivity score drops by 1 +// If the chain has recently finalized, each validator's score drops by 16. +func ProcessInactivityScores( + ctx context.Context, + state state.BeaconState, + vals []*precompute.Validator, +) (state.BeaconState, []*precompute.Validator, error) { + cfg := params.BeaconConfig() + if helpers.CurrentEpoch(state) == cfg.GenesisEpoch { + return state, vals, nil + } + + inactivityScores, err := state.InactivityScores() + if err != nil { + return nil, nil, err + } + + bias := cfg.InactivityScoreBias + recoveryRate := cfg.InactivityScoreRecoveryRate + for i, v := range vals { + if !precompute.EligibleForRewards(v) { + continue + } + + if v.IsPrevEpochTargetAttester && !v.IsSlashed { + // Decrease inactivity score when validator gets target correct. + if v.InactivityScore > 0 { + score := uint64(1) + // Prevents underflow below 0. + if score > v.InactivityScore { + score = v.InactivityScore + } + v.InactivityScore -= score + } + } else { + v.InactivityScore += bias + } + + if !helpers.IsInInactivityLeak(helpers.PrevEpoch(state), state.FinalizedCheckpointEpoch()) { + score := recoveryRate + // Prevents underflow below 0. + if score > v.InactivityScore { + score = v.InactivityScore + } + v.InactivityScore -= score + } + inactivityScores[i] = v.InactivityScore + } + + if err := state.SetInactivityScores(inactivityScores); err != nil { + return nil, nil, err + } + + return state, vals, nil +} + +// ProcessEpochParticipation processes the epoch participation in state and updates individual validator's pre computes, +// it also tracks and updates epoch attesting balances. +func ProcessEpochParticipation( + ctx context.Context, + state state.BeaconState, + bal *precompute.Balance, + vals []*precompute.Validator, +) ([]*precompute.Validator, *precompute.Balance, error) { + ctx, span := trace.StartSpan(ctx, "altair.ProcessEpochParticipation") + defer span.End() + + cp, err := state.CurrentEpochParticipation() + if err != nil { + return nil, nil, err + } + cfg := params.BeaconConfig() + targetIdx := cfg.TimelyTargetFlagIndex + sourceIdx := cfg.TimelySourceFlagIndex + headIdx := cfg.TimelyHeadFlagIndex + for i, b := range cp { + if HasValidatorFlag(b, targetIdx) { + vals[i].IsCurrentEpochTargetAttester = true + } + } + pp, err := state.PreviousEpochParticipation() + if err != nil { + return nil, nil, err + } + for i, b := range pp { + if HasValidatorFlag(b, sourceIdx) { + vals[i].IsPrevEpochAttester = true + } + if HasValidatorFlag(b, targetIdx) { + vals[i].IsPrevEpochTargetAttester = true + } + if HasValidatorFlag(b, headIdx) { + vals[i].IsPrevEpochHeadAttester = true + } + } + bal = precompute.UpdateBalance(vals, bal) + return vals, bal, nil +} diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go new file mode 100644 index 000000000..4102c2400 --- /dev/null +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -0,0 +1,231 @@ +package altair + +import ( + "context" + "testing" + + types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" + "github.com/prysmaticlabs/prysm/beacon-chain/state" + stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/testutil/assert" + "github.com/prysmaticlabs/prysm/shared/testutil/require" +) + +func TestInitializeEpochValidators_Ok(t *testing.T) { + ffe := params.BeaconConfig().FarFutureEpoch + s, err := stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{ + Slot: params.BeaconConfig().SlotsPerEpoch, + // Validator 0 is slashed + // Validator 1 is withdrawable + // Validator 2 is active prev epoch and current epoch + // Validator 3 is active prev epoch + Validators: []*ethpb.Validator{ + {Slashed: true, WithdrawableEpoch: ffe, EffectiveBalance: 100}, + {EffectiveBalance: 100}, + {WithdrawableEpoch: ffe, ExitEpoch: ffe, EffectiveBalance: 100}, + {WithdrawableEpoch: ffe, ExitEpoch: 1, EffectiveBalance: 100}, + }, + InactivityScores: []uint64{0, 1, 2, 3}, + }) + require.NoError(t, err) + v, b, err := InitializeEpochValidators(context.Background(), s) + require.NoError(t, err) + assert.DeepEqual(t, &precompute.Validator{ + IsSlashed: true, + CurrentEpochEffectiveBalance: 100, + InactivityScore: 0, + }, v[0], "Incorrect validator 0 status") + assert.DeepEqual(t, &precompute.Validator{ + IsWithdrawableCurrentEpoch: true, + CurrentEpochEffectiveBalance: 100, + InactivityScore: 1, + }, v[1], "Incorrect validator 1 status") + assert.DeepEqual(t, &precompute.Validator{ + IsActivePrevEpoch: true, + IsActiveCurrentEpoch: true, + CurrentEpochEffectiveBalance: 100, + InactivityScore: 2, + }, v[2], "Incorrect validator 2 status") + assert.DeepEqual(t, &precompute.Validator{ + IsActivePrevEpoch: true, + CurrentEpochEffectiveBalance: 100, + InactivityScore: 3, + }, v[3], "Incorrect validator 3 status") + + wantedBalances := &precompute.Balance{ + ActiveCurrentEpoch: 100, + ActivePrevEpoch: 200, + } + assert.DeepEqual(t, wantedBalances, b, "Incorrect wanted balance") +} + +func TestInitializeEpochValidators_BadState(t *testing.T) { + s, err := stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{ + Validators: []*ethpb.Validator{{}}, + InactivityScores: []uint64{}, + }) + require.NoError(t, err) + _, _, err = InitializeEpochValidators(context.Background(), s) + require.ErrorContains(t, "num of validators can't be greater than length of inactivity scores", err) +} + +func TestProcessEpochParticipation(t *testing.T) { + s, err := testState() + require.NoError(t, err) + validators, balance, err := InitializeEpochValidators(context.Background(), s) + require.NoError(t, err) + validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators) + require.NoError(t, err) + require.DeepEqual(t, &precompute.Validator{ + IsActiveCurrentEpoch: true, + IsActivePrevEpoch: true, + IsWithdrawableCurrentEpoch: true, + CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + }, validators[0]) + require.DeepEqual(t, &precompute.Validator{ + IsActiveCurrentEpoch: true, + IsActivePrevEpoch: true, + IsWithdrawableCurrentEpoch: true, + CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + IsPrevEpochAttester: true, + }, validators[1]) + require.DeepEqual(t, &precompute.Validator{ + IsActiveCurrentEpoch: true, + IsActivePrevEpoch: true, + IsWithdrawableCurrentEpoch: true, + CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + IsPrevEpochAttester: true, + IsCurrentEpochTargetAttester: true, + IsPrevEpochTargetAttester: true, + }, validators[2]) + require.DeepEqual(t, &precompute.Validator{ + IsActiveCurrentEpoch: true, + IsActivePrevEpoch: true, + IsWithdrawableCurrentEpoch: true, + CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + IsPrevEpochAttester: true, + IsCurrentEpochTargetAttester: true, + IsPrevEpochTargetAttester: true, + IsPrevEpochHeadAttester: true, + }, validators[3]) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance*3, balance.PrevEpochAttested) + require.Equal(t, balance.CurrentEpochTargetAttested, params.BeaconConfig().MaxEffectiveBalance*2) + require.Equal(t, balance.PrevEpochTargetAttested, params.BeaconConfig().MaxEffectiveBalance*2) + require.Equal(t, balance.PrevEpochHeadAttested, params.BeaconConfig().MaxEffectiveBalance*1) +} + +func TestProcessInactivityScores_CanProcessInactivityLeak(t *testing.T) { + s, err := testState() + require.NoError(t, err) + defaultScore := uint64(5) + require.NoError(t, s.SetInactivityScores([]uint64{defaultScore, defaultScore, defaultScore, defaultScore})) + require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch*types.Slot(params.BeaconConfig().MinEpochsToInactivityPenalty+2))) + validators, balance, err := InitializeEpochValidators(context.Background(), s) + require.NoError(t, err) + validators, _, err = ProcessEpochParticipation(context.Background(), s, balance, validators) + require.NoError(t, err) + s, _, err = ProcessInactivityScores(context.Background(), s, validators) + require.NoError(t, err) + inactivityScores, err := s.InactivityScores() + require.NoError(t, err) + // V0 and V1 didn't vote head. V2 and V3 did. + require.Equal(t, defaultScore+params.BeaconConfig().InactivityScoreBias, inactivityScores[0]) + require.Equal(t, defaultScore+params.BeaconConfig().InactivityScoreBias, inactivityScores[1]) + require.Equal(t, defaultScore-1, inactivityScores[2]) + require.Equal(t, defaultScore-1, inactivityScores[3]) +} + +func TestProcessInactivityScores_CanProcessNonInactivityLeak(t *testing.T) { + s, err := testState() + require.NoError(t, err) + defaultScore := uint64(5) + require.NoError(t, s.SetInactivityScores([]uint64{defaultScore, defaultScore, defaultScore, defaultScore})) + validators, balance, err := InitializeEpochValidators(context.Background(), s) + require.NoError(t, err) + validators, _, err = ProcessEpochParticipation(context.Background(), s, balance, validators) + require.NoError(t, err) + s, _, err = ProcessInactivityScores(context.Background(), s, validators) + require.NoError(t, err) + inactivityScores, err := s.InactivityScores() + require.NoError(t, err) + + require.Equal(t, uint64(0), inactivityScores[0]) + require.Equal(t, uint64(0), inactivityScores[1]) + require.Equal(t, uint64(0), inactivityScores[2]) + require.Equal(t, uint64(0), inactivityScores[3]) +} + +func TestProcessInactivityScores_NonEligibleValidator(t *testing.T) { + s, err := testState() + require.NoError(t, err) + defaultScore := uint64(5) + require.NoError(t, s.SetInactivityScores([]uint64{defaultScore, defaultScore, defaultScore, defaultScore})) + validators, balance, err := InitializeEpochValidators(context.Background(), s) + require.NoError(t, err) + + // v0 is eligible (not active previous epoch, slashed and not withdrawable) + validators[0].IsActivePrevEpoch = false + validators[0].IsSlashed = true + validators[0].IsWithdrawableCurrentEpoch = false + + // v1 is not eligible (not active previous epoch, not slashed and not withdrawable) + validators[1].IsActivePrevEpoch = false + validators[1].IsSlashed = false + validators[1].IsWithdrawableCurrentEpoch = false + + // v2 is not eligible (not active previous epoch, slashed and withdrawable) + validators[2].IsActivePrevEpoch = false + validators[2].IsSlashed = true + validators[2].IsWithdrawableCurrentEpoch = true + + // v3 is eligible (active previous epoch) + validators[3].IsActivePrevEpoch = true + + validators, _, err = ProcessEpochParticipation(context.Background(), s, balance, validators) + require.NoError(t, err) + s, _, err = ProcessInactivityScores(context.Background(), s, validators) + require.NoError(t, err) + inactivityScores, err := s.InactivityScores() + require.NoError(t, err) + + require.Equal(t, uint64(0), inactivityScores[0]) + require.Equal(t, defaultScore, inactivityScores[1]) // Should remain unchanged + require.Equal(t, defaultScore, inactivityScores[2]) // Should remain unchanged + require.Equal(t, uint64(0), inactivityScores[3]) +} + +func testState() (state.BeaconState, error) { + generateParticipation := func(flags ...uint8) byte { + b := byte(0) + for _, flag := range flags { + b = AddValidatorFlag(b, flag) + } + return b + } + return stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{ + Slot: 2 * params.BeaconConfig().SlotsPerEpoch, + Validators: []*ethpb.Validator{ + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch}, + {EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch}, + }, + CurrentEpochParticipation: []byte{ + 0, + generateParticipation(params.BeaconConfig().TimelySourceFlagIndex), + generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex), + generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex), + }, + PreviousEpochParticipation: []byte{ + 0, + generateParticipation(params.BeaconConfig().TimelySourceFlagIndex), + generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex), + generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex), + }, + InactivityScores: []uint64{0, 0, 0, 0}, + Balances: []uint64{0, 0, 0, 0}, + }) +}