github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/prysm/v1alpha1/beacon/committees_test.go (about) 1 package beacon 2 3 import ( 4 "context" 5 "encoding/binary" 6 "testing" 7 "time" 8 9 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 10 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 11 dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 12 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 13 "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" 14 pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 15 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 16 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 17 "github.com/prysmaticlabs/prysm/shared/params" 18 "github.com/prysmaticlabs/prysm/shared/testutil" 19 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 20 "github.com/prysmaticlabs/prysm/shared/testutil/require" 21 "github.com/prysmaticlabs/prysm/shared/timeutils" 22 "google.golang.org/protobuf/proto" 23 "gopkg.in/d4l3k/messagediff.v1" 24 ) 25 26 func TestServer_ListBeaconCommittees_CurrentEpoch(t *testing.T) { 27 db := dbTest.SetupDB(t) 28 helpers.ClearCache() 29 30 numValidators := 128 31 ctx := context.Background() 32 headState := setupActiveValidators(t, numValidators) 33 34 offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot)) 35 m := &mock.ChainService{ 36 Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second), 37 } 38 bs := &Server{ 39 HeadFetcher: m, 40 GenesisTimeFetcher: m, 41 StateGen: stategen.New(db), 42 } 43 b := testutil.NewBeaconBlock() 44 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) 45 gRoot, err := b.Block.HashTreeRoot() 46 require.NoError(t, err) 47 require.NoError(t, db.SaveGenesisBlockRoot(ctx, gRoot)) 48 require.NoError(t, db.SaveState(ctx, headState, gRoot)) 49 50 activeIndices, err := helpers.ActiveValidatorIndices(headState, 0) 51 require.NoError(t, err) 52 attesterSeed, err := helpers.Seed(headState, 0, params.BeaconConfig().DomainBeaconAttester) 53 require.NoError(t, err) 54 committees, err := computeCommittees(0, activeIndices, attesterSeed) 55 require.NoError(t, err) 56 57 wanted := ðpb.BeaconCommittees{ 58 Epoch: 0, 59 Committees: committees.SlotToUint64(), 60 ActiveValidatorCount: uint64(numValidators), 61 } 62 res, err := bs.ListBeaconCommittees(context.Background(), ðpb.ListCommitteesRequest{ 63 QueryFilter: ðpb.ListCommitteesRequest_Genesis{Genesis: true}, 64 }) 65 require.NoError(t, err) 66 if !proto.Equal(res, wanted) { 67 t.Errorf("Expected %v, received %v", wanted, res) 68 } 69 } 70 71 func TestServer_ListBeaconCommittees_PreviousEpoch(t *testing.T) { 72 params.UseMainnetConfig() 73 ctx := context.Background() 74 75 db := dbTest.SetupDB(t) 76 helpers.ClearCache() 77 78 numValidators := 128 79 headState := setupActiveValidators(t, numValidators) 80 81 mixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) 82 for i := 0; i < len(mixes); i++ { 83 mixes[i] = make([]byte, 32) 84 } 85 require.NoError(t, headState.SetRandaoMixes(mixes)) 86 require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) 87 88 b := testutil.NewBeaconBlock() 89 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) 90 gRoot, err := b.Block.HashTreeRoot() 91 require.NoError(t, err) 92 require.NoError(t, db.SaveState(ctx, headState, gRoot)) 93 require.NoError(t, db.SaveGenesisBlockRoot(ctx, gRoot)) 94 95 offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot)) 96 m := &mock.ChainService{ 97 State: headState, 98 Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second), 99 } 100 bs := &Server{ 101 HeadFetcher: m, 102 GenesisTimeFetcher: m, 103 StateGen: stategen.New(db), 104 } 105 106 activeIndices, err := helpers.ActiveValidatorIndices(headState, 1) 107 require.NoError(t, err) 108 attesterSeed, err := helpers.Seed(headState, 1, params.BeaconConfig().DomainBeaconAttester) 109 require.NoError(t, err) 110 startSlot, err := helpers.StartSlot(1) 111 require.NoError(t, err) 112 wanted, err := computeCommittees(startSlot, activeIndices, attesterSeed) 113 require.NoError(t, err) 114 115 tests := []struct { 116 req *ethpb.ListCommitteesRequest 117 res *ethpb.BeaconCommittees 118 }{ 119 { 120 req: ðpb.ListCommitteesRequest{ 121 QueryFilter: ðpb.ListCommitteesRequest_Epoch{Epoch: 1}, 122 }, 123 res: ðpb.BeaconCommittees{ 124 Epoch: 1, 125 Committees: wanted.SlotToUint64(), 126 ActiveValidatorCount: uint64(numValidators), 127 }, 128 }, 129 } 130 helpers.ClearCache() 131 for i, test := range tests { 132 res, err := bs.ListBeaconCommittees(context.Background(), test.req) 133 require.NoError(t, err) 134 if !proto.Equal(res, test.res) { 135 diff, _ := messagediff.PrettyDiff(res, test.res) 136 t.Errorf("%d/ Diff between responses %s", i, diff) 137 } 138 } 139 } 140 141 func TestRetrieveCommitteesForRoot(t *testing.T) { 142 143 db := dbTest.SetupDB(t) 144 helpers.ClearCache() 145 ctx := context.Background() 146 147 numValidators := 128 148 headState := setupActiveValidators(t, numValidators) 149 150 offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot)) 151 m := &mock.ChainService{ 152 Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second), 153 } 154 bs := &Server{ 155 HeadFetcher: m, 156 GenesisTimeFetcher: m, 157 StateGen: stategen.New(db), 158 } 159 b := testutil.NewBeaconBlock() 160 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) 161 gRoot, err := b.Block.HashTreeRoot() 162 require.NoError(t, err) 163 require.NoError(t, db.SaveGenesisBlockRoot(ctx, gRoot)) 164 require.NoError(t, db.SaveState(ctx, headState, gRoot)) 165 stateSummary := &pbp2p.StateSummary{ 166 Slot: 0, 167 Root: gRoot[:], 168 } 169 require.NoError(t, db.SaveStateSummary(ctx, stateSummary)) 170 171 // Store the genesis seed. 172 seed, err := helpers.Seed(headState, 0, params.BeaconConfig().DomainBeaconAttester) 173 require.NoError(t, err) 174 require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch*10)) 175 176 activeIndices, err := helpers.ActiveValidatorIndices(headState, 0) 177 require.NoError(t, err) 178 179 wanted, err := computeCommittees(0, activeIndices, seed) 180 require.NoError(t, err) 181 committees, activeIndices, err := bs.retrieveCommitteesForRoot(context.Background(), gRoot[:]) 182 require.NoError(t, err) 183 184 wantedRes := ðpb.BeaconCommittees{ 185 Epoch: 0, 186 Committees: wanted.SlotToUint64(), 187 ActiveValidatorCount: uint64(numValidators), 188 } 189 receivedRes := ðpb.BeaconCommittees{ 190 Epoch: 0, 191 Committees: committees.SlotToUint64(), 192 ActiveValidatorCount: uint64(len(activeIndices)), 193 } 194 assert.DeepEqual(t, wantedRes, receivedRes) 195 } 196 197 func setupActiveValidators(t *testing.T, count int) iface.BeaconState { 198 balances := make([]uint64, count) 199 validators := make([]*ethpb.Validator, 0, count) 200 for i := 0; i < count; i++ { 201 pubKey := make([]byte, params.BeaconConfig().BLSPubkeyLength) 202 binary.LittleEndian.PutUint64(pubKey, uint64(i)) 203 balances[i] = uint64(i) 204 validators = append(validators, ðpb.Validator{ 205 PublicKey: pubKey, 206 ActivationEpoch: 0, 207 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 208 WithdrawalCredentials: make([]byte, 32), 209 }) 210 } 211 s, err := testutil.NewBeaconState() 212 require.NoError(t, err) 213 if err := s.SetValidators(validators); err != nil { 214 t.Error(err) 215 return nil 216 } 217 if err := s.SetBalances(balances); err != nil { 218 t.Error(err) 219 return nil 220 } 221 return s 222 }