prysm-pulse/beacon-chain/rpc/validator/attester_test.go
terence tsao ce725ceec3
Move state pkg to stateV0 pkg (#8620)
* Move state pkg to stateV0 pkg

* Build.bazel

* Remove unused RootsArrayHashTreeRoot

* Revert "Remove unused RootsArrayHashTreeRoot"

This reverts commit bf0bda30d1a8eb7a071f6e3ce9ee85041b45aca6.

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-03-17 19:49:49 +00:00

635 lines
22 KiB
Go

package validator
import (
"context"
"math/rand"
"sync"
"testing"
"time"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
func TestProposeAttestation_OK(t *testing.T) {
db := dbutil.SetupDB(t)
ctx := context.Background()
attesterServer := &Server{
HeadFetcher: &mock.ChainService{},
P2P: &mockp2p.MockBroadcaster{},
BeaconDB: db,
AttestationCache: cache.NewAttestationCache(),
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
}
head := testutil.NewBeaconBlock()
head.Block.Slot = 999
head.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
require.NoError(t, db.SaveBlock(ctx, head))
root, err := head.Block.HashTreeRoot()
require.NoError(t, err)
validators := make([]*ethpb.Validator, 64)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
}
}
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
require.NoError(t, state.SetValidators(validators))
require.NoError(t, db.SaveState(ctx, state, root))
require.NoError(t, db.SaveHeadBlockRoot(ctx, root))
sk, err := bls.RandKey()
require.NoError(t, err)
sig := sk.Sign([]byte("dummy_test_data"))
req := &ethpb.Attestation{
Signature: sig.Marshal(),
Data: &ethpb.AttestationData{
BeaconBlockRoot: root[:],
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
}
_, err = attesterServer.ProposeAttestation(context.Background(), req)
assert.NoError(t, err)
}
func TestProposeAttestation_IncorrectSignature(t *testing.T) {
db := dbutil.SetupDB(t)
attesterServer := &Server{
HeadFetcher: &mock.ChainService{},
P2P: &mockp2p.MockBroadcaster{},
BeaconDB: db,
AttestationCache: cache.NewAttestationCache(),
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
}
req := testutil.HydrateAttestation(&ethpb.Attestation{})
wanted := "Incorrect attestation signature"
_, err := attesterServer.ProposeAttestation(context.Background(), req)
assert.ErrorContains(t, wanted, err)
}
func TestGetAttestationData_OK(t *testing.T) {
ctx := context.Background()
db := dbutil.SetupDB(t)
block := testutil.NewBeaconBlock()
block.Block.Slot = 3*params.BeaconConfig().SlotsPerEpoch + 1
targetBlock := testutil.NewBeaconBlock()
targetBlock.Block.Slot = 1 * params.BeaconConfig().SlotsPerEpoch
justifiedBlock := testutil.NewBeaconBlock()
justifiedBlock.Block.Slot = 2 * params.BeaconConfig().SlotsPerEpoch
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err, "Could not hash beacon block")
justifiedRoot, err := justifiedBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root for justified block")
targetRoot, err := targetBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root for target block")
slot := 3*params.BeaconConfig().SlotsPerEpoch + 1
beaconState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(slot))
err = beaconState.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
})
require.NoError(t, err)
blockRoots := beaconState.BlockRoots()
blockRoots[1] = blockRoot[:]
blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:]
blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:]
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
chainService := &mock.ChainService{
Genesis: time.Now(),
}
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
attesterServer := &Server{
BeaconDB: db,
P2P: &mockp2p.MockBroadcaster{},
SyncChecker: &mockSync.Sync{IsSyncing: false},
AttestationCache: cache.NewAttestationCache(),
HeadFetcher: &mock.ChainService{
State: beaconState, Root: blockRoot[:],
},
FinalizationFetcher: &mock.ChainService{
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
},
TimeFetcher: &mock.ChainService{
Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second),
},
StateNotifier: chainService.StateNotifier(),
}
require.NoError(t, db.SaveState(ctx, beaconState, blockRoot))
require.NoError(t, db.SaveBlock(ctx, block))
require.NoError(t, db.SaveHeadBlockRoot(ctx, blockRoot))
req := &ethpb.AttestationDataRequest{
CommitteeIndex: 0,
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
}
res, err := attesterServer.GetAttestationData(context.Background(), req)
require.NoError(t, err, "Could not get attestation info at slot")
expectedInfo := &ethpb.AttestationData{
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
BeaconBlockRoot: blockRoot[:],
Source: &ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
},
Target: &ethpb.Checkpoint{
Epoch: 3,
Root: blockRoot[:],
},
}
if !proto.Equal(res, expectedInfo) {
t.Errorf("Expected attestation info to match, received %v, wanted %v", res, expectedInfo)
}
}
func TestGetAttestationData_SyncNotReady(t *testing.T) {
as := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: true},
}
_, err := as.GetAttestationData(context.Background(), &ethpb.AttestationDataRequest{})
assert.ErrorContains(t, "Syncing to latest head", err)
}
func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) {
// Scenario:
//
// State slot = 10000
// Last justified slot = epoch start of 1500
// HistoricalRootsLimit = 8192
//
// More background: https://github.com/prysmaticlabs/prysm/issues/2153
// This test breaks if it doesnt use mainnet config
db := dbutil.SetupDB(t)
ctx := context.Background()
// Ensure HistoricalRootsLimit matches scenario
params.SetupTestConfigCleanup(t)
cfg := params.MainnetConfig()
cfg.HistoricalRootsLimit = 8192
params.OverrideBeaconConfig(cfg)
block := testutil.NewBeaconBlock()
block.Block.Slot = 10000
epochBoundaryBlock := testutil.NewBeaconBlock()
var err error
epochBoundaryBlock.Block.Slot, err = helpers.StartSlot(helpers.SlotToEpoch(10000))
require.NoError(t, err)
justifiedBlock := testutil.NewBeaconBlock()
justifiedBlock.Block.Slot, err = helpers.StartSlot(helpers.SlotToEpoch(1500))
require.NoError(t, err)
justifiedBlock.Block.Slot -= 2 // Imagine two skip block
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err, "Could not hash beacon block")
justifiedBlockRoot, err := justifiedBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not hash justified block")
epochBoundaryRoot, err := epochBoundaryBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not hash justified block")
slot := types.Slot(10000)
beaconState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(slot))
err = beaconState.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{
Epoch: helpers.SlotToEpoch(1500),
Root: justifiedBlockRoot[:],
})
require.NoError(t, err)
blockRoots := beaconState.BlockRoots()
blockRoots[1] = blockRoot[:]
blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = epochBoundaryRoot[:]
blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedBlockRoot[:]
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
chainService := &mock.ChainService{
Genesis: time.Now(),
}
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
attesterServer := &Server{
BeaconDB: db,
P2P: &mockp2p.MockBroadcaster{},
AttestationCache: cache.NewAttestationCache(),
HeadFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
FinalizationFetcher: &mock.ChainService{
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
},
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
StateNotifier: chainService.StateNotifier(),
}
require.NoError(t, db.SaveState(ctx, beaconState, blockRoot))
require.NoError(t, db.SaveBlock(ctx, block))
require.NoError(t, db.SaveHeadBlockRoot(ctx, blockRoot))
req := &ethpb.AttestationDataRequest{
CommitteeIndex: 0,
Slot: 10000,
}
res, err := attesterServer.GetAttestationData(context.Background(), req)
require.NoError(t, err, "Could not get attestation info at slot")
expectedInfo := &ethpb.AttestationData{
Slot: req.Slot,
BeaconBlockRoot: blockRoot[:],
Source: &ethpb.Checkpoint{
Epoch: helpers.SlotToEpoch(1500),
Root: justifiedBlockRoot[:],
},
Target: &ethpb.Checkpoint{
Epoch: 312,
Root: blockRoot[:],
},
}
if !proto.Equal(res, expectedInfo) {
t.Errorf("Expected attestation info to match, received %v, wanted %v", res, expectedInfo)
}
}
func TestAttestationDataSlot_handlesInProgressRequest(t *testing.T) {
s := &pbp2p.BeaconState{Slot: 100}
state, err := stateV0.InitializeFromProto(s)
require.NoError(t, err)
ctx := context.Background()
chainService := &mock.ChainService{
Genesis: time.Now(),
}
slot := types.Slot(2)
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
server := &Server{
HeadFetcher: &mock.ChainService{State: state},
AttestationCache: cache.NewAttestationCache(),
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
StateNotifier: chainService.StateNotifier(),
}
req := &ethpb.AttestationDataRequest{
CommitteeIndex: 1,
Slot: slot,
}
res := &ethpb.AttestationData{
CommitteeIndex: 1,
Target: &ethpb.Checkpoint{Epoch: 55, Root: make([]byte, 32)},
}
require.NoError(t, server.AttestationCache.MarkInProgress(req))
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
response, err := server.GetAttestationData(ctx, req)
require.NoError(t, err)
if !proto.Equal(res, response) {
t.Error("Expected equal responses from cache")
}
}()
wg.Add(1)
go func() {
defer wg.Done()
assert.NoError(t, server.AttestationCache.Put(ctx, req, res))
assert.NoError(t, server.AttestationCache.MarkNotInProgress(req))
}()
wg.Wait()
}
func TestServer_GetAttestationData_InvalidRequestSlot(t *testing.T) {
ctx := context.Background()
slot := 3*params.BeaconConfig().SlotsPerEpoch + 1
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
attesterServer := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
}
req := &ethpb.AttestationDataRequest{
Slot: 1000000000000,
}
_, err := attesterServer.GetAttestationData(ctx, req)
assert.ErrorContains(t, "invalid request", err)
}
func TestServer_GetAttestationData_HeadStateSlotGreaterThanRequestSlot(t *testing.T) {
// There exists a rare scenario where the validator may request an attestation for a slot less
// than the head state's slot. The ETH2 spec constraints require that the block root the
// attestation is referencing be less than or equal to the attestation data slot.
// See: https://github.com/prysmaticlabs/prysm/issues/5164
ctx := context.Background()
db := dbutil.SetupDB(t)
slot := 3*params.BeaconConfig().SlotsPerEpoch + 1
block := testutil.NewBeaconBlock()
block.Block.Slot = slot
block2 := testutil.NewBeaconBlock()
block2.Block.Slot = slot - 1
targetBlock := testutil.NewBeaconBlock()
targetBlock.Block.Slot = 1 * params.BeaconConfig().SlotsPerEpoch
justifiedBlock := testutil.NewBeaconBlock()
justifiedBlock.Block.Slot = 2 * params.BeaconConfig().SlotsPerEpoch
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err, "Could not hash beacon block")
blockRoot2, err := block2.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, block2))
justifiedRoot, err := justifiedBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root for justified block")
targetRoot, err := targetBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root for target block")
beaconState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(slot))
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix()-offset)))
err = beaconState.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
ParentRoot: blockRoot2[:],
}))
require.NoError(t, err)
err = beaconState.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
})
require.NoError(t, err)
blockRoots := beaconState.BlockRoots()
blockRoots[1] = blockRoot[:]
blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:]
blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:]
blockRoots[3*params.BeaconConfig().SlotsPerEpoch] = blockRoot2[:]
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
beaconState2 := beaconState.Copy()
require.NoError(t, beaconState2.SetSlot(beaconState2.Slot()-1))
require.NoError(t, db.SaveState(ctx, beaconState2, blockRoot2))
chainService := &mock.ChainService{
Genesis: time.Now(),
}
offset = int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
attesterServer := &Server{
BeaconDB: db,
P2P: &mockp2p.MockBroadcaster{},
SyncChecker: &mockSync.Sync{IsSyncing: false},
AttestationCache: cache.NewAttestationCache(),
HeadFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
FinalizationFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint()},
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
StateNotifier: chainService.StateNotifier(),
StateGen: stategen.New(db),
}
require.NoError(t, db.SaveState(ctx, beaconState, blockRoot))
require.NoError(t, db.SaveBlock(ctx, block))
require.NoError(t, db.SaveHeadBlockRoot(ctx, blockRoot))
req := &ethpb.AttestationDataRequest{
CommitteeIndex: 0,
Slot: slot - 1,
}
res, err := attesterServer.GetAttestationData(ctx, req)
require.NoError(t, err, "Could not get attestation info at slot")
expectedInfo := &ethpb.AttestationData{
Slot: slot - 1,
BeaconBlockRoot: blockRoot2[:],
Source: &ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
},
Target: &ethpb.Checkpoint{
Epoch: 3,
Root: blockRoot2[:],
},
}
if !proto.Equal(res, expectedInfo) {
t.Errorf("Expected attestation info to match, received %v, wanted %v", res, expectedInfo)
}
}
func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) {
ctx := context.Background()
db := dbutil.SetupDB(t)
slot := types.Slot(5)
block := testutil.NewBeaconBlock()
block.Block.Slot = slot
targetBlock := testutil.NewBeaconBlock()
targetBlock.Block.Slot = 0
justifiedBlock := testutil.NewBeaconBlock()
justifiedBlock.Block.Slot = 0
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err, "Could not hash beacon block")
justifiedRoot, err := justifiedBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root for justified block")
targetRoot, err := targetBlock.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root for target block")
beaconState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(slot))
err = beaconState.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{
Epoch: 0,
Root: justifiedRoot[:],
})
require.NoError(t, err)
blockRoots := beaconState.BlockRoots()
blockRoots[1] = blockRoot[:]
blockRoots[1*params.BeaconConfig().SlotsPerEpoch] = targetRoot[:]
blockRoots[2*params.BeaconConfig().SlotsPerEpoch] = justifiedRoot[:]
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
chainService := &mock.ChainService{
Genesis: time.Now(),
}
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
attesterServer := &Server{
BeaconDB: db,
P2P: &mockp2p.MockBroadcaster{},
SyncChecker: &mockSync.Sync{IsSyncing: false},
AttestationCache: cache.NewAttestationCache(),
HeadFetcher: &mock.ChainService{
State: beaconState, Root: blockRoot[:],
},
FinalizationFetcher: &mock.ChainService{
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
},
TimeFetcher: &mock.ChainService{Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second)},
StateNotifier: chainService.StateNotifier(),
}
require.NoError(t, db.SaveState(ctx, beaconState, blockRoot))
require.NoError(t, db.SaveBlock(ctx, block))
require.NoError(t, db.SaveHeadBlockRoot(ctx, blockRoot))
req := &ethpb.AttestationDataRequest{
CommitteeIndex: 0,
Slot: 5,
}
res, err := attesterServer.GetAttestationData(context.Background(), req)
require.NoError(t, err, "Could not get attestation info at slot")
expectedInfo := &ethpb.AttestationData{
Slot: slot,
BeaconBlockRoot: blockRoot[:],
Source: &ethpb.Checkpoint{
Epoch: 0,
Root: justifiedRoot[:],
},
Target: &ethpb.Checkpoint{
Epoch: 0,
Root: blockRoot[:],
},
}
if !proto.Equal(res, expectedInfo) {
t.Errorf("Expected attestation info to match, received %v, wanted %v", res, expectedInfo)
}
}
func TestServer_SubscribeCommitteeSubnets_NoSlots(t *testing.T) {
db := dbutil.SetupDB(t)
attesterServer := &Server{
HeadFetcher: &mock.ChainService{},
P2P: &mockp2p.MockBroadcaster{},
BeaconDB: db,
AttestationCache: cache.NewAttestationCache(),
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
}
_, err := attesterServer.SubscribeCommitteeSubnets(context.Background(), &ethpb.CommitteeSubnetsSubscribeRequest{
Slots: nil,
CommitteeIds: nil,
IsAggregator: nil,
})
assert.ErrorContains(t, "no attester slots provided", err)
}
func TestServer_SubscribeCommitteeSubnets_DifferentLengthSlots(t *testing.T) {
db := dbutil.SetupDB(t)
// fixed seed
s := rand.NewSource(10)
randGen := rand.New(s)
attesterServer := &Server{
HeadFetcher: &mock.ChainService{},
P2P: &mockp2p.MockBroadcaster{},
BeaconDB: db,
AttestationCache: cache.NewAttestationCache(),
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
}
var slots []types.Slot
var comIdxs []types.CommitteeIndex
var isAggregator []bool
for i := types.Slot(100); i < 200; i++ {
slots = append(slots, i)
comIdxs = append(comIdxs, types.CommitteeIndex(randGen.Int63n(64)))
boolVal := randGen.Uint64()%2 == 0
isAggregator = append(isAggregator, boolVal)
}
slots = append(slots, 321)
_, err := attesterServer.SubscribeCommitteeSubnets(context.Background(), &ethpb.CommitteeSubnetsSubscribeRequest{
Slots: slots,
CommitteeIds: comIdxs,
IsAggregator: isAggregator,
})
assert.ErrorContains(t, "request fields are not the same length", err)
}
func TestServer_SubscribeCommitteeSubnets_MultipleSlots(t *testing.T) {
db := dbutil.SetupDB(t)
// fixed seed
s := rand.NewSource(10)
randGen := rand.New(s)
validators := make([]*ethpb.Validator, 64)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
}
}
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetValidators(validators))
attesterServer := &Server{
HeadFetcher: &mock.ChainService{State: state},
P2P: &mockp2p.MockBroadcaster{},
BeaconDB: db,
AttestationCache: cache.NewAttestationCache(),
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
}
var slots []types.Slot
var comIdxs []types.CommitteeIndex
var isAggregator []bool
for i := types.Slot(100); i < 200; i++ {
slots = append(slots, i)
comIdxs = append(comIdxs, types.CommitteeIndex(randGen.Int63n(64)))
boolVal := randGen.Uint64()%2 == 0
isAggregator = append(isAggregator, boolVal)
}
_, err = attesterServer.SubscribeCommitteeSubnets(context.Background(), &ethpb.CommitteeSubnetsSubscribeRequest{
Slots: slots,
CommitteeIds: comIdxs,
IsAggregator: isAggregator,
})
require.NoError(t, err)
for i := types.Slot(100); i < 200; i++ {
subnets := cache.SubnetIDs.GetAttesterSubnetIDs(i)
assert.Equal(t, 1, len(subnets))
if isAggregator[i-100] {
subnets = cache.SubnetIDs.GetAggregatorSubnetIDs(i)
assert.Equal(t, 1, len(subnets))
}
}
}