From 79e0674f4078a8e77daf161ef1879d8441775e40 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 09:27:18 -0700 Subject: [PATCH 01/18] Add client implementation --- validator/client/validator.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/validator/client/validator.go b/validator/client/validator.go index 0e8b5e75b720..0d1174490f97 100644 --- a/validator/client/validator.go +++ b/validator/client/validator.go @@ -337,6 +337,13 @@ func (v *validator) RolesAt(ctx context.Context, slot uint64) (map[[48]byte][]pb roles = append(roles, pb.ValidatorRole_AGGREGATOR) } + if _, err := v.validatorClient.SubscribeCommitteeSubnet(ctx, ðpb.CommitteeSubnetSubscribeRequest{ + Slot: slot, + CommitteeId: duty.CommitteeIndex, + IsAggregator: aggregator, + }); err != nil { + return nil, err + } } if len(roles) == 0 { roles = append(roles, pb.ValidatorRole_UNKNOWN) From 17b771b901bac288db6d18b9749426422959021d Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 09:27:44 -0700 Subject: [PATCH 02/18] Update workspace --- WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WORKSPACE b/WORKSPACE index fe391cf7900b..23fe21149443 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1309,7 +1309,7 @@ go_repository( go_repository( name = "com_github_prysmaticlabs_ethereumapis", - commit = "90224d88dd65813ba2f35197bb1bb8915b2d0c6b", + commit = "3f6a75ac9460621b140270b90057a5a445d66436", importpath = "github.com/prysmaticlabs/ethereumapis", patch_args = ["-p1"], patches = [ From d7cf6901fefa8bfb77fa35f1248a069ec10c5e81 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 09:27:57 -0700 Subject: [PATCH 03/18] Update server --- beacon-chain/cache/committee_ids.go | 22 ++++++++++-------- beacon-chain/rpc/validator/assignments.go | 7 ------ beacon-chain/rpc/validator/attester.go | 23 +++++++++---------- .../sync/initial-sync/blocks_fetcher.go | 11 ++++----- 4 files changed, 29 insertions(+), 34 deletions(-) diff --git a/beacon-chain/cache/committee_ids.go b/beacon-chain/cache/committee_ids.go index 85672884f166..fa054508556c 100644 --- a/beacon-chain/cache/committee_ids.go +++ b/beacon-chain/cache/committee_ids.go @@ -4,6 +4,7 @@ import ( "sync" lru "github.com/hashicorp/golang-lru" + "github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/sliceutil" ) @@ -16,27 +17,30 @@ type committeeIDs struct { var CommitteeIDs = newCommitteeIDs() func newCommitteeIDs() *committeeIDs { - cache, err := lru.New(8) + maxCommitteesPerEpoch := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch) + cache, err := lru.New(maxCommitteesPerEpoch) if err != nil { panic(err) } return &committeeIDs{cache: cache} } -// AddIDs to the cache for attestation committees by epoch. -func (t *committeeIDs) AddIDs(indices []uint64, epoch uint64) { +// AddID adds committee ID for subscribing subnet for the attester and/or aggregator of a given slot. +func (t *committeeIDs) AddID(committeeID uint64, slot uint64) { t.lock.Lock() defer t.lock.Unlock() - val, exists := t.cache.Get(epoch) + + committeeIDs := []uint64{committeeID} + val, exists := t.cache.Get(slot) if exists { - indices = sliceutil.UnionUint64(append(indices, val.([]uint64)...)) + committeeIDs = sliceutil.UnionUint64(append(val.([]uint64), committeeIDs...)) } - t.cache.Add(epoch, indices) + t.cache.Add(slot, committeeIDs) } -// GetIDs from the cache for attestation committees by epoch. -func (t *committeeIDs) GetIDs(epoch uint64) []uint64 { - val, exists := t.cache.Get(epoch) +// GetIDs gets the committee ID for subscribing subnet for attester and/or aggregator of the slot. +func (t *committeeIDs) GetIDs(slot uint64) []uint64 { + val, exists := t.cache.Get(slot) if !exists { return []uint64{} } diff --git a/beacon-chain/rpc/validator/assignments.go b/beacon-chain/rpc/validator/assignments.go index c282e1e3cb0c..ceca4f6b28f7 100644 --- a/beacon-chain/rpc/validator/assignments.go +++ b/beacon-chain/rpc/validator/assignments.go @@ -4,10 +4,8 @@ import ( "context" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" - "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/state" - "github.com/prysmaticlabs/prysm/shared/featureconfig" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -87,11 +85,6 @@ func (vs *Server) GetDuties(ctx context.Context, req *ethpb.DutiesRequest) (*eth } - if featureconfig.Get().EnableDynamicCommitteeSubnets { - cache.CommitteeIDs.AddIDs(committeeIDs, req.Epoch) - cache.CommitteeIDs.AddIDs(nextCommitteeIDs, req.Epoch+1) - } - return ðpb.DutiesResponse{ Duties: validatorAssignments, }, nil diff --git a/beacon-chain/rpc/validator/attester.go b/beacon-chain/rpc/validator/attester.go index f813ad395bd1..15f0b8bce442 100644 --- a/beacon-chain/rpc/validator/attester.go +++ b/beacon-chain/rpc/validator/attester.go @@ -4,6 +4,7 @@ import ( "context" "time" + ptypes "github.com/gogo/protobuf/types" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" "github.com/prysmaticlabs/prysm/beacon-chain/cache" @@ -36,12 +37,6 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation trace.Int64Attribute("committeeIndex", int64(req.CommitteeIndex)), ) - // If attestation committee subnets are enabled, we track the committee - // index into a cache. - if featureconfig.Get().EnableDynamicCommitteeSubnets { - cache.CommitteeIDs.AddIDs([]uint64{req.CommitteeIndex}, helpers.SlotToEpoch(req.Slot)) - } - if vs.SyncChecker.Syncing() { return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond") } @@ -159,12 +154,6 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature") } - // If attestation committee subnets are enabled, we track the committee - // index into a cache. - if featureconfig.Get().EnableDynamicCommitteeSubnets { - cache.CommitteeIDs.AddIDs([]uint64{att.Data.CommitteeIndex}, helpers.SlotToEpoch(att.Data.Slot)) - } - root, err := ssz.HashTreeRoot(att.Data) if err != nil { return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err) @@ -235,3 +224,13 @@ func (vs *Server) waitToOneThird(ctx context.Context, slot uint64) { } } } + +// SubscribeCommitteeSubnet subscribes to the committee ID subnet given subscribe request. +func (vs *Server) SubscribeCommitteeSubnet(ctx context.Context, req *ethpb.CommitteeSubnetSubscribeRequest) (*ptypes.Empty, error) { + if req.IsAggregator { + cache.CommitteeIDs.AddID(req.CommitteeId, req.Slot) + } else { + // What should we do here as an attester? + } + return &ptypes.Empty{}, nil +} diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher.go b/beacon-chain/sync/initial-sync/blocks_fetcher.go index 752fc6ce921f..c373bc62fc5b 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher.go @@ -82,7 +82,7 @@ func newBlocksFetcher(ctx context.Context, cfg *blocksFetcherConfig) *blocksFetc rateLimiter := leakybucket.NewCollector( allowedBlocksPerSecond, /* rate */ allowedBlocksPerSecond, /* capacity */ - false /* deleteEmptyBuckets */) + false /* deleteEmptyBuckets */) return &blocksFetcher{ ctx: ctx, @@ -466,7 +466,7 @@ func (f *blocksFetcher) selectPeers(peers []peer.ID) []peer.ID { // nonSkippedSlotAfter checks slots after the given one in an attempt to find non-empty future slot. func (f *blocksFetcher) nonSkippedSlotAfter(ctx context.Context, slot uint64) (uint64, error) { headEpoch := helpers.SlotToEpoch(f.headFetcher.HeadSlot()) - root, epoch, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) + _, epoch, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) if len(peers) == 0 { return 0, errNoPeersAvailable } @@ -481,10 +481,9 @@ func (f *blocksFetcher) nonSkippedSlotAfter(ctx context.Context, slot uint64) (u for slot <= helpers.StartSlot(epoch+1) { req := &p2ppb.BeaconBlocksByRangeRequest{ - HeadBlockRoot: root, - StartSlot: slot + 1, - Count: blockBatchSize, - Step: 1, + StartSlot: slot + 1, + Count: blockBatchSize, + Step: 1, } blocks, err := f.requestBlocks(ctx, req, nextPID()) From d7615ea99e30075cf7af18fa572fdbc2ca7c0abd Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 09:35:39 -0700 Subject: [PATCH 04/18] Update service --- .../beacon_node_validator_service_mock.go | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/validator/internal/beacon_node_validator_service_mock.go b/validator/internal/beacon_node_validator_service_mock.go index 554384c440dd..28b3cfe8c053 100644 --- a/validator/internal/beacon_node_validator_service_mock.go +++ b/validator/internal/beacon_node_validator_service_mock.go @@ -10,7 +10,9 @@ import ( ptypes "github.com/gogo/protobuf/types" gomock "github.com/golang/mock/gomock" + eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" + "github.com/prysmaticlabs/prysm/bazel-prysm/external/com_github_golang_protobuf/ptypes/empty" grpc "google.golang.org/grpc" metadata "google.golang.org/grpc/metadata" ) @@ -967,3 +969,23 @@ func (mr *MockBeaconNodeValidator_WaitForChainStartServerMockRecorder) RecvMsg(m mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockBeaconNodeValidator_WaitForChainStartServer)(nil).RecvMsg), m) } + +// SubscribeCommitteeSubnet mocks base method +func (m *MockBeaconNodeValidatorClient) SubscribeCommitteeSubnet(arg0 context.Context, arg1 *eth.CommitteeSubnetSubscribeRequest, arg2 ...grpc.CallOption) (*empty.Empty, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "SubscribeCommitteeSubnet", varargs...) + ret0, _ := ret[0].(*empty.Empty) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SubscribeCommitteeSubnet indicates an expected call of SubscribeCommitteeSubnet +func (mr *MockBeaconNodeValidatorClientMockRecorder) SubscribeCommitteeSubnet(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeCommitteeSubnet", reflect.TypeOf((*MockBeaconNodeValidatorClient)(nil).SubscribeCommitteeSubnet), varargs...) +} From 10ca5c8eda72335299c35aa815dca1e6134dadce Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 09:38:22 -0700 Subject: [PATCH 05/18] Gaz --- ...thub_prysmaticlabs_ethereumapis-tags.patch | 22 ++++++++++--------- validator/internal/BUILD.bazel | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/third_party/com_github_prysmaticlabs_ethereumapis-tags.patch b/third_party/com_github_prysmaticlabs_ethereumapis-tags.patch index 854a3fd74082..47c06b1940ed 100644 --- a/third_party/com_github_prysmaticlabs_ethereumapis-tags.patch +++ b/third_party/com_github_prysmaticlabs_ethereumapis-tags.patch @@ -447,7 +447,7 @@ index 8ee263b..60607de 100644 // The epoch for which this set of validator assignments is valid. diff --git a/eth/v1alpha1/validator.proto b/eth/v1alpha1/validator.proto -index 068a04c..80f73b8 100644 +index 3455de7..f4fab59 100644 --- a/eth/v1alpha1/validator.proto +++ b/eth/v1alpha1/validator.proto @@ -15,6 +15,7 @@ syntax = "proto3"; @@ -458,7 +458,7 @@ index 068a04c..80f73b8 100644 import "google/api/annotations.proto"; import "google/protobuf/empty.proto"; import "eth/v1alpha1/beacon_block.proto"; -@@ -197,7 +198,7 @@ message DomainResponse { +@@ -208,7 +209,7 @@ message DomainResponse { message ValidatorActivationRequest { // A list of 48 byte validator public keys. @@ -467,7 +467,7 @@ index 068a04c..80f73b8 100644 } message ValidatorActivationResponse { -@@ -223,7 +224,7 @@ message ChainStartResponse { +@@ -234,7 +235,7 @@ message ChainStartResponse { message ValidatorIndexRequest { // A 48 byte validator public key. @@ -476,7 +476,7 @@ index 068a04c..80f73b8 100644 } message ValidatorIndexResponse { -@@ -233,7 +234,7 @@ message ValidatorIndexResponse { +@@ -244,7 +245,7 @@ message ValidatorIndexResponse { message ValidatorStatusRequest { // A 48 byte validator public key. @@ -485,7 +485,7 @@ index 068a04c..80f73b8 100644 } enum ValidatorStatus { -@@ -271,7 +272,7 @@ message DutiesRequest { +@@ -282,7 +283,7 @@ message DutiesRequest { uint64 epoch = 1; // Array of byte encoded BLS public keys. @@ -494,7 +494,7 @@ index 068a04c..80f73b8 100644 } message DutiesResponse { -@@ -290,7 +291,7 @@ message DutiesResponse { +@@ -301,7 +302,7 @@ message DutiesResponse { uint64 proposer_slot = 4; // 48 byte BLS public key for the validator who's assigned to perform a duty. @@ -503,7 +503,7 @@ index 068a04c..80f73b8 100644 // The current status of the validator assigned to perform the duty. ValidatorStatus status = 6; -@@ -305,15 +306,16 @@ message BlockRequest { +@@ -316,15 +317,16 @@ message BlockRequest { uint64 slot = 1; // Validator's 32 byte randao reveal secret of the current epoch. @@ -523,7 +523,7 @@ index 068a04c..80f73b8 100644 } message AttestationDataRequest { -@@ -326,7 +328,7 @@ message AttestationDataRequest { +@@ -337,7 +339,7 @@ message AttestationDataRequest { message AttestResponse { // The root of the attestation data successfully submitted to the beacon node. @@ -532,7 +532,7 @@ index 068a04c..80f73b8 100644 } message AggregateSelectionRequest { -@@ -335,10 +337,10 @@ message AggregateSelectionRequest { +@@ -346,10 +348,10 @@ message AggregateSelectionRequest { // Committee index of the validator at the given slot. uint64 committee_index = 2; // 48 byte public key of the validator. @@ -545,7 +545,7 @@ index 068a04c..80f73b8 100644 } message AggregateSelectionResponse { -@@ -353,16 +355,16 @@ message SignedAggregateSubmitRequest { +@@ -364,7 +366,7 @@ message SignedAggregateSubmitRequest { message SignedAggregateSubmitResponse { // The 32 byte hash tree root of the aggregated attestation data. @@ -553,6 +553,8 @@ index 068a04c..80f73b8 100644 + bytes attestation_data_root = 1 [(gogoproto.moretags) = "ssz-size:\"32\""]; } + message CommitteeSubnetSubscribeRequest { +@@ -381,10 +383,10 @@ message CommitteeSubnetSubscribeRequest { // An Ethereum 2.0 validator. message Validator { // 48 byte BLS public key used for the validator's activities. diff --git a/validator/internal/BUILD.bazel b/validator/internal/BUILD.bazel index 52ab303ee136..452656cb98b1 100644 --- a/validator/internal/BUILD.bazel +++ b/validator/internal/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "@com_github_gogo_protobuf//types:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library", + "@com_github_prysmaticlabs_prysm//bazel-prysm/external/com_github_golang_protobuf/ptypes/empty:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", ], From 5950ab6a9bd4fd9970ff81fcf73a9af553e40bd0 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 09:55:58 -0700 Subject: [PATCH 06/18] Mocks --- validator/internal/BUILD.bazel | 1 - validator/internal/beacon_node_validator_service_mock.go | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/validator/internal/BUILD.bazel b/validator/internal/BUILD.bazel index 452656cb98b1..52ab303ee136 100644 --- a/validator/internal/BUILD.bazel +++ b/validator/internal/BUILD.bazel @@ -13,7 +13,6 @@ go_library( "@com_github_gogo_protobuf//types:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library", - "@com_github_prysmaticlabs_prysm//bazel-prysm/external/com_github_golang_protobuf/ptypes/empty:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", ], diff --git a/validator/internal/beacon_node_validator_service_mock.go b/validator/internal/beacon_node_validator_service_mock.go index 28b3cfe8c053..1be712ad60a4 100644 --- a/validator/internal/beacon_node_validator_service_mock.go +++ b/validator/internal/beacon_node_validator_service_mock.go @@ -12,7 +12,6 @@ import ( gomock "github.com/golang/mock/gomock" eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" - "github.com/prysmaticlabs/prysm/bazel-prysm/external/com_github_golang_protobuf/ptypes/empty" grpc "google.golang.org/grpc" metadata "google.golang.org/grpc/metadata" ) @@ -971,14 +970,14 @@ func (mr *MockBeaconNodeValidator_WaitForChainStartServerMockRecorder) RecvMsg(m } // SubscribeCommitteeSubnet mocks base method -func (m *MockBeaconNodeValidatorClient) SubscribeCommitteeSubnet(arg0 context.Context, arg1 *eth.CommitteeSubnetSubscribeRequest, arg2 ...grpc.CallOption) (*empty.Empty, error) { +func (m *MockBeaconNodeValidatorClient) SubscribeCommitteeSubnet(arg0 context.Context, arg1 *eth.CommitteeSubnetSubscribeRequest, arg2 ...grpc.CallOption) (*ptypes.Empty, error) { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} for _, a := range arg2 { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "SubscribeCommitteeSubnet", varargs...) - ret0, _ := ret[0].(*empty.Empty) + ret0, _ := ret[0].(*ptypes.Empty) ret1, _ := ret[1].(error) return ret0, ret1 } From cd7a23627d2dddda8712e7802063d22063a61671 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 10:07:21 -0700 Subject: [PATCH 07/18] Fixed validator tests --- validator/client/validator_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/validator/client/validator_test.go b/validator/client/validator_test.go index 81f4a290416b..dae939574cd2 100644 --- a/validator/client/validator_test.go +++ b/validator/client/validator_test.go @@ -604,11 +604,22 @@ func TestRolesAt_OK(t *testing.T) { gomock.Any(), // ctx gomock.Any(), // epoch ).Return(ðpb.DomainResponse{}, nil /*err*/) + m.validatorClient.EXPECT().DomainData( gomock.Any(), // ctx gomock.Any(), // epoch ).Return(ðpb.DomainResponse{}, nil /*err*/) + m.validatorClient.EXPECT().SubscribeCommitteeSubnet( + gomock.Any(), // ctx + gomock.Any(), // epoch + ).Return(nil, nil /*err*/) + + m.validatorClient.EXPECT().SubscribeCommitteeSubnet( + gomock.Any(), // ctx + gomock.Any(), // epoch + ).Return(nil, nil /*err*/) + roleMap, err := v.RolesAt(context.Background(), 1) if err != nil { t.Fatal(err) @@ -671,6 +682,11 @@ func TestRolesAt_DoesNotAssignProposer_Slot0(t *testing.T) { gomock.Any(), // epoch ).Return(ðpb.DomainResponse{}, nil /*err*/) + m.validatorClient.EXPECT().SubscribeCommitteeSubnet( + gomock.Any(), // ctx + gomock.Any(), // epoch + ).Return(nil, nil /*err*/) + roleMap, err := v.RolesAt(context.Background(), 0) if err != nil { t.Fatal(err) From d8f76901c3d25222a99fefd4f97bfa794bbe56fb Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 10:16:00 -0700 Subject: [PATCH 08/18] Add round tirp tests --- beacon-chain/cache/BUILD.bazel | 1 + beacon-chain/cache/committee_ids.go | 2 +- beacon-chain/cache/committee_ids_test.go | 33 ++++++++++++++++++++++++ beacon-chain/rpc/validator/attester.go | 4 +-- 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 beacon-chain/cache/committee_ids_test.go diff --git a/beacon-chain/cache/BUILD.bazel b/beacon-chain/cache/BUILD.bazel index 9b508498b301..87454c83b8c5 100644 --- a/beacon-chain/cache/BUILD.bazel +++ b/beacon-chain/cache/BUILD.bazel @@ -41,6 +41,7 @@ go_test( "attestation_data_test.go", "checkpoint_state_test.go", "committee_fuzz_test.go", + "committee_ids_test.go", "committee_test.go", "eth1_data_test.go", "feature_flag_test.go", diff --git a/beacon-chain/cache/committee_ids.go b/beacon-chain/cache/committee_ids.go index fa054508556c..5277247b0f63 100644 --- a/beacon-chain/cache/committee_ids.go +++ b/beacon-chain/cache/committee_ids.go @@ -26,7 +26,7 @@ func newCommitteeIDs() *committeeIDs { } // AddID adds committee ID for subscribing subnet for the attester and/or aggregator of a given slot. -func (t *committeeIDs) AddID(committeeID uint64, slot uint64) { +func (t *committeeIDs) AddID(slot uint64, committeeID uint64) { t.lock.Lock() defer t.lock.Unlock() diff --git a/beacon-chain/cache/committee_ids_test.go b/beacon-chain/cache/committee_ids_test.go new file mode 100644 index 000000000000..9d47da162761 --- /dev/null +++ b/beacon-chain/cache/committee_ids_test.go @@ -0,0 +1,33 @@ +package cache + +import ( + "reflect" + "testing" +) + +func TestCommitteeIDCache_RoundTrip(t *testing.T) { + c := newCommitteeIDs() + slot := uint64(100) + committeeIDs := c.GetIDs(slot) + if len(committeeIDs) != 0 { + t.Errorf("Empty cache returned an object: %v", committeeIDs) + } + + c.AddID(slot, 1) + res := c.GetIDs(slot) + if !reflect.DeepEqual(res, []uint64{1}) { + t.Error("Expected equal value to return from cache") + } + + c.AddID(slot, 2) + res = c.GetIDs(slot) + if !reflect.DeepEqual(res, []uint64{1, 2}) { + t.Error("Expected equal value to return from cache") + } + + c.AddID(slot, 3) + res = c.GetIDs(slot) + if !reflect.DeepEqual(res, []uint64{1, 2, 3}) { + t.Error("Expected equal value to return from cache") + } +} diff --git a/beacon-chain/rpc/validator/attester.go b/beacon-chain/rpc/validator/attester.go index 15f0b8bce442..5bf432fd6590 100644 --- a/beacon-chain/rpc/validator/attester.go +++ b/beacon-chain/rpc/validator/attester.go @@ -228,9 +228,9 @@ func (vs *Server) waitToOneThird(ctx context.Context, slot uint64) { // SubscribeCommitteeSubnet subscribes to the committee ID subnet given subscribe request. func (vs *Server) SubscribeCommitteeSubnet(ctx context.Context, req *ethpb.CommitteeSubnetSubscribeRequest) (*ptypes.Empty, error) { if req.IsAggregator { - cache.CommitteeIDs.AddID(req.CommitteeId, req.Slot) + cache.CommitteeIDs.AddID(req.Slot, req.CommitteeId) } else { - // What should we do here as an attester? + // What should be done for an attester? } return &ptypes.Empty{}, nil } From 5a996dbf0bea06e4c19050c3da6169cb9b083464 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 10:31:40 -0700 Subject: [PATCH 09/18] Fixed subnet test --- beacon-chain/p2p/subnets_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon-chain/p2p/subnets_test.go b/beacon-chain/p2p/subnets_test.go index a8a34270c0dd..9ab6e17d365b 100644 --- a/beacon-chain/p2p/subnets_test.go +++ b/beacon-chain/p2p/subnets_test.go @@ -109,7 +109,7 @@ func TestStartDiscV5_DiscoverPeersWithSubnets(t *testing.T) { // Update ENR of a peer. testService := &Service{dv5Listener: listeners[0]} - cache.CommitteeIDs.AddIDs([]uint64{10}, 0) + cache.CommitteeIDs.AddID(0, 10) testService.RefreshENR(0) time.Sleep(2 * time.Second) From e9d1ee1d10861907f5d2dd55d42f36721e275576 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 15:25:41 -0700 Subject: [PATCH 10/18] Comment --- beacon-chain/rpc/validator/attester.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon-chain/rpc/validator/attester.go b/beacon-chain/rpc/validator/attester.go index 38134d4d61e9..42b862f3f855 100644 --- a/beacon-chain/rpc/validator/attester.go +++ b/beacon-chain/rpc/validator/attester.go @@ -228,9 +228,9 @@ func (vs *Server) waitToOneThird(ctx context.Context, slot uint64) { // SubscribeCommitteeSubnet subscribes to the committee ID subnet given subscribe request. func (vs *Server) SubscribeCommitteeSubnet(ctx context.Context, req *ethpb.CommitteeSubnetSubscribeRequest) (*ptypes.Empty, error) { if req.IsAggregator { - cache.CommitteeIDs.AddID(req.Slot, req.CommitteeId) + // What should a node cache for an aggregator? } else { - // What should be done for an attester? + cache.CommitteeIDs.AddID(req.Slot, req.CommitteeId) } return &ptypes.Empty{}, nil } From de6b1ce5361440198ff77f4d25b4488a55d57583 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 21:47:36 -0700 Subject: [PATCH 11/18] Update committee cache --- beacon-chain/cache/committee_ids.go | 66 ++++++++++++++++++------ beacon-chain/cache/committee_ids_test.go | 37 ++++++++++--- 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/beacon-chain/cache/committee_ids.go b/beacon-chain/cache/committee_ids.go index 5277247b0f63..bdde07c7295f 100644 --- a/beacon-chain/cache/committee_ids.go +++ b/beacon-chain/cache/committee_ids.go @@ -9,38 +9,72 @@ import ( ) type committeeIDs struct { - cache *lru.Cache - lock sync.RWMutex + attester *lru.Cache + attesterLock sync.RWMutex + aggregator *lru.Cache + aggregatorLock sync.RWMutex } -// CommitteeIDs for attestations. +// CommitteeIDs for attester and aggregator. var CommitteeIDs = newCommitteeIDs() func newCommitteeIDs() *committeeIDs { maxCommitteesPerEpoch := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch) - cache, err := lru.New(maxCommitteesPerEpoch) + attesterCache, err := lru.New(maxCommitteesPerEpoch) if err != nil { panic(err) } - return &committeeIDs{cache: cache} + aggregatorCache, err := lru.New(maxCommitteesPerEpoch) + if err != nil { + panic(err) + } + return &committeeIDs{attester: attesterCache, aggregator: aggregatorCache} +} + +// AddAttesterCommiteeID adds committee ID for subscribing subnet for the attester of a given slot. +func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) { + c.attesterLock.Lock() + defer c.attesterLock.Unlock() + + ids := []uint64{committeeID} + val, exists := c.attester.Get(slot) + if exists { + ids = sliceutil.UnionUint64(append(val.([]uint64), ids...)) + } + c.attester.Add(slot, ids) } -// AddID adds committee ID for subscribing subnet for the attester and/or aggregator of a given slot. -func (t *committeeIDs) AddID(slot uint64, committeeID uint64) { - t.lock.Lock() - defer t.lock.Unlock() +// GetAttesterCommitteeIDs gets the committee ID for subscribing subnet for attester of the slot. +func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 { + c.attesterLock.Lock() + defer c.attesterLock.Unlock() - committeeIDs := []uint64{committeeID} - val, exists := t.cache.Get(slot) + val, exists := c.attester.Get(slot) + if !exists { + return []uint64{} + } + return val.([]uint64) +} + +// AddAggregatorCommiteeID adds committee ID for subscribing subnet for the aggregator of a given slot. +func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64) { + c.aggregatorLock.Lock() + defer c.aggregatorLock.Unlock() + + ids := []uint64{committeeID} + val, exists := c.aggregator.Get(slot) if exists { - committeeIDs = sliceutil.UnionUint64(append(val.([]uint64), committeeIDs...)) + ids = sliceutil.UnionUint64(append(val.([]uint64), ids...)) } - t.cache.Add(slot, committeeIDs) + c.aggregator.Add(slot, ids) } -// GetIDs gets the committee ID for subscribing subnet for attester and/or aggregator of the slot. -func (t *committeeIDs) GetIDs(slot uint64) []uint64 { - val, exists := t.cache.Get(slot) +// GetAggregatorCommitteeIDs gets the committee ID for subscribing subnet for aggregator of the slot. +func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 { + c.aggregatorLock.Lock() + defer c.aggregatorLock.Unlock() + + val, exists := c.aggregator.Get(slot) if !exists { return []uint64{} } diff --git a/beacon-chain/cache/committee_ids_test.go b/beacon-chain/cache/committee_ids_test.go index 9d47da162761..3ae97533a825 100644 --- a/beacon-chain/cache/committee_ids_test.go +++ b/beacon-chain/cache/committee_ids_test.go @@ -8,26 +8,49 @@ import ( func TestCommitteeIDCache_RoundTrip(t *testing.T) { c := newCommitteeIDs() slot := uint64(100) - committeeIDs := c.GetIDs(slot) + committeeIDs := c.GetAggregatorCommitteeIDs(slot) if len(committeeIDs) != 0 { t.Errorf("Empty cache returned an object: %v", committeeIDs) } - c.AddID(slot, 1) - res := c.GetIDs(slot) + c.AddAggregatorCommiteeID(slot, 1) + res := c.GetAggregatorCommitteeIDs(slot) if !reflect.DeepEqual(res, []uint64{1}) { t.Error("Expected equal value to return from cache") } - c.AddID(slot, 2) - res = c.GetIDs(slot) + c.AddAggregatorCommiteeID(slot, 2) + res = c.GetAggregatorCommitteeIDs(slot) if !reflect.DeepEqual(res, []uint64{1, 2}) { t.Error("Expected equal value to return from cache") } - c.AddID(slot, 3) - res = c.GetIDs(slot) + c.AddAggregatorCommiteeID(slot, 3) + res = c.GetAggregatorCommitteeIDs(slot) if !reflect.DeepEqual(res, []uint64{1, 2, 3}) { t.Error("Expected equal value to return from cache") } + + committeeIDs = c.GetAttesterCommitteeIDs(slot) + if len(committeeIDs) != 0 { + t.Errorf("Empty cache returned an object: %v", committeeIDs) + } + + c.AddAttesterCommiteeID(slot, 11) + res = c.GetAttesterCommitteeIDs(slot) + if !reflect.DeepEqual(res, []uint64{11}) { + t.Error("Expected equal value to return from cache") + } + + c.AddAttesterCommiteeID(slot, 22) + res = c.GetAttesterCommitteeIDs(slot) + if !reflect.DeepEqual(res, []uint64{11, 22}) { + t.Error("Expected equal value to return from cache") + } + + c.AddAttesterCommiteeID(slot, 33) + res = c.GetAttesterCommitteeIDs(slot) + if !reflect.DeepEqual(res, []uint64{11, 22, 33}) { + t.Error("Expected equal value to return from cache") + } } From 38f9b68ce9213498d01b6c6aa26b237768224e16 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 21:49:06 -0700 Subject: [PATCH 12/18] Comment --- beacon-chain/cache/committee_ids.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/beacon-chain/cache/committee_ids.go b/beacon-chain/cache/committee_ids.go index bdde07c7295f..447f600817c8 100644 --- a/beacon-chain/cache/committee_ids.go +++ b/beacon-chain/cache/committee_ids.go @@ -19,12 +19,14 @@ type committeeIDs struct { var CommitteeIDs = newCommitteeIDs() func newCommitteeIDs() *committeeIDs { - maxCommitteesPerEpoch := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch) - attesterCache, err := lru.New(maxCommitteesPerEpoch) + // Given a node can calculate committee assignments of current epoch and next epoch. + // Max size is set to 2 epoch length. + cacheSize := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch * 2) + attesterCache, err := lru.New(cacheSize) if err != nil { panic(err) } - aggregatorCache, err := lru.New(maxCommitteesPerEpoch) + aggregatorCache, err := lru.New(cacheSize) if err != nil { panic(err) } From cb1a4c6f0f5974d49e266ac17e99ce32575de20e Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 21:50:35 -0700 Subject: [PATCH 13/18] Update RPC --- beacon-chain/rpc/validator/attester.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon-chain/rpc/validator/attester.go b/beacon-chain/rpc/validator/attester.go index 42b862f3f855..e9b7438622c3 100644 --- a/beacon-chain/rpc/validator/attester.go +++ b/beacon-chain/rpc/validator/attester.go @@ -227,10 +227,10 @@ func (vs *Server) waitToOneThird(ctx context.Context, slot uint64) { // SubscribeCommitteeSubnet subscribes to the committee ID subnet given subscribe request. func (vs *Server) SubscribeCommitteeSubnet(ctx context.Context, req *ethpb.CommitteeSubnetSubscribeRequest) (*ptypes.Empty, error) { + cache.CommitteeIDs.AddAttesterCommiteeID(req.Slot, req.CommitteeId) if req.IsAggregator { - // What should a node cache for an aggregator? - } else { - cache.CommitteeIDs.AddID(req.Slot, req.CommitteeId) + cache.CommitteeIDs.AddAggregatorCommiteeID(req.Slot, req.CommitteeId) } + return &ptypes.Empty{}, nil } From 3190aa3930590a276602f37b45048e163aa4bb72 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 21:56:06 -0700 Subject: [PATCH 14/18] Fixed test --- beacon-chain/cache/committee_ids.go | 8 ++++---- beacon-chain/p2p/service.go | 4 ++-- beacon-chain/p2p/subnets_test.go | 2 +- beacon-chain/rpc/validator/attester.go | 1 + .../sync/subscriber_committee_index_beacon_attestation.go | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/beacon-chain/cache/committee_ids.go b/beacon-chain/cache/committee_ids.go index 447f600817c8..4a6a00eb6897 100644 --- a/beacon-chain/cache/committee_ids.go +++ b/beacon-chain/cache/committee_ids.go @@ -48,8 +48,8 @@ func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) { // GetAttesterCommitteeIDs gets the committee ID for subscribing subnet for attester of the slot. func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 { - c.attesterLock.Lock() - defer c.attesterLock.Unlock() + c.attesterLock.RLock() + defer c.attesterLock.RUnlock() val, exists := c.attester.Get(slot) if !exists { @@ -73,8 +73,8 @@ func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64) // GetAggregatorCommitteeIDs gets the committee ID for subscribing subnet for aggregator of the slot. func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 { - c.aggregatorLock.Lock() - defer c.aggregatorLock.Unlock() + c.aggregatorLock.RLock() + defer c.aggregatorLock.RUnlock() val, exists := c.aggregator.Get(slot) if !exists { diff --git a/beacon-chain/p2p/service.go b/beacon-chain/p2p/service.go index 189cf196f5a9..c9f905f62c9b 100644 --- a/beacon-chain/p2p/service.go +++ b/beacon-chain/p2p/service.go @@ -348,13 +348,13 @@ func (s *Service) MetadataSeq() uint64 { // RefreshENR uses an epoch to refresh the enr entry for our node // with the tracked committee id's for the epoch, allowing our node // to be dynamically discoverable by others given our tracked committee id's. -func (s *Service) RefreshENR(epoch uint64) { +func (s *Service) RefreshENR(slot uint64) { // return early if discv5 isnt running if s.dv5Listener == nil { return } bitV := bitfield.NewBitvector64() - committees := cache.CommitteeIDs.GetIDs(epoch) + committees := cache.CommitteeIDs.GetAttesterCommitteeIDs(slot) for _, idx := range committees { bitV.SetBitAt(idx, true) } diff --git a/beacon-chain/p2p/subnets_test.go b/beacon-chain/p2p/subnets_test.go index 9ab6e17d365b..a28259dad605 100644 --- a/beacon-chain/p2p/subnets_test.go +++ b/beacon-chain/p2p/subnets_test.go @@ -109,7 +109,7 @@ func TestStartDiscV5_DiscoverPeersWithSubnets(t *testing.T) { // Update ENR of a peer. testService := &Service{dv5Listener: listeners[0]} - cache.CommitteeIDs.AddID(0, 10) + cache.CommitteeIDs.AddAttesterCommiteeID(0, 10) testService.RefreshENR(0) time.Sleep(2 * time.Second) diff --git a/beacon-chain/rpc/validator/attester.go b/beacon-chain/rpc/validator/attester.go index e9b7438622c3..184143fa757f 100644 --- a/beacon-chain/rpc/validator/attester.go +++ b/beacon-chain/rpc/validator/attester.go @@ -228,6 +228,7 @@ func (vs *Server) waitToOneThird(ctx context.Context, slot uint64) { // SubscribeCommitteeSubnet subscribes to the committee ID subnet given subscribe request. func (vs *Server) SubscribeCommitteeSubnet(ctx context.Context, req *ethpb.CommitteeSubnetSubscribeRequest) (*ptypes.Empty, error) { cache.CommitteeIDs.AddAttesterCommiteeID(req.Slot, req.CommitteeId) + if req.IsAggregator { cache.CommitteeIDs.AddAggregatorCommiteeID(req.Slot, req.CommitteeId) } diff --git a/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go b/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go index a95c91711fd9..d5dad5bf853d 100644 --- a/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go +++ b/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go @@ -51,6 +51,6 @@ func (r *Service) committeesCount() int { func (r *Service) committeeIndices() []uint64 { currentEpoch := helpers.SlotToEpoch(r.chain.HeadSlot()) - return sliceutil.UnionUint64(cache.CommitteeIDs.GetIDs(currentEpoch), - cache.CommitteeIDs.GetIDs(currentEpoch+1)) + return sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(currentEpoch), + cache.CommitteeIDs.GetAttesterCommitteeIDs(currentEpoch+1)) } From 81da6d995f6d87ac9c2cf6b259839207e2ce209f Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 22:14:34 -0700 Subject: [PATCH 15/18] Nishant's comment --- beacon-chain/p2p/service.go | 4 +++- .../sync/subscriber_committee_index_beacon_attestation.go | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/beacon-chain/p2p/service.go b/beacon-chain/p2p/service.go index c9f905f62c9b..d9a60f2ce793 100644 --- a/beacon-chain/p2p/service.go +++ b/beacon-chain/p2p/service.go @@ -34,6 +34,7 @@ import ( "github.com/prysmaticlabs/prysm/shared" "github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/runutil" + "github.com/prysmaticlabs/prysm/shared/sliceutil" "github.com/sirupsen/logrus" ) @@ -354,7 +355,8 @@ func (s *Service) RefreshENR(slot uint64) { return } bitV := bitfield.NewBitvector64() - committees := cache.CommitteeIDs.GetAttesterCommitteeIDs(slot) + committees := sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(slot), + cache.CommitteeIDs.GetAggregatorCommitteeIDs(slot)) for _, idx := range committees { bitV.SetBitAt(idx, true) } diff --git a/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go b/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go index d5dad5bf853d..eb5b3e4ae1ad 100644 --- a/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go +++ b/beacon-chain/sync/subscriber_committee_index_beacon_attestation.go @@ -50,7 +50,7 @@ func (r *Service) committeesCount() int { } func (r *Service) committeeIndices() []uint64 { - currentEpoch := helpers.SlotToEpoch(r.chain.HeadSlot()) - return sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(currentEpoch), - cache.CommitteeIDs.GetAttesterCommitteeIDs(currentEpoch+1)) + currentSlot := r.chain.CurrentSlot() + return sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(currentSlot), + cache.CommitteeIDs.GetAggregatorCommitteeIDs(currentSlot)) } From a8e07844eaa4f25b646f734d44fcf5ab477cca13 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 3 Apr 2020 22:24:04 -0700 Subject: [PATCH 16/18] Gaz --- beacon-chain/p2p/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/beacon-chain/p2p/BUILD.bazel b/beacon-chain/p2p/BUILD.bazel index 166513e9b002..23f9ace13559 100644 --- a/beacon-chain/p2p/BUILD.bazel +++ b/beacon-chain/p2p/BUILD.bazel @@ -43,6 +43,7 @@ go_library( "//shared/iputils:go_default_library", "//shared/params:go_default_library", "//shared/runutil:go_default_library", + "//shared/sliceutil:go_default_library", "//shared/traceutil:go_default_library", "@com_github_btcsuite_btcd//btcec:go_default_library", "@com_github_dgraph_io_ristretto//:go_default_library", From 62f98178f7aa0e1d075ce9ecabf9a0e0072e5bc8 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Sat, 4 Apr 2020 07:35:37 -0700 Subject: [PATCH 17/18] Refresh ENR is for epoch --- beacon-chain/p2p/service.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/beacon-chain/p2p/service.go b/beacon-chain/p2p/service.go index d9a60f2ce793..1e4634e66f06 100644 --- a/beacon-chain/p2p/service.go +++ b/beacon-chain/p2p/service.go @@ -349,14 +349,18 @@ func (s *Service) MetadataSeq() uint64 { // RefreshENR uses an epoch to refresh the enr entry for our node // with the tracked committee id's for the epoch, allowing our node // to be dynamically discoverable by others given our tracked committee id's. -func (s *Service) RefreshENR(slot uint64) { +func (s *Service) RefreshENR(epoch uint64) { // return early if discv5 isnt running if s.dv5Listener == nil { return } bitV := bitfield.NewBitvector64() - committees := sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(slot), - cache.CommitteeIDs.GetAggregatorCommitteeIDs(slot)) + + var committees []uint64 + epochStartSlot := helpers.StartSlot(epoch) + for i := epochStartSlot; i < epochStartSlot+2*params.BeaconConfig().SlotsPerEpoch; i++ { + committees = sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(i), cache.CommitteeIDs.GetAggregatorCommitteeIDs(i)) + } for _, idx := range committees { bitV.SetBitAt(idx, true) } From 9155e7824b85baa1bff6d968b11c0e038faaa094 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Sat, 4 Apr 2020 07:38:34 -0700 Subject: [PATCH 18/18] Needs to be append --- beacon-chain/p2p/service.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beacon-chain/p2p/service.go b/beacon-chain/p2p/service.go index 1e4634e66f06..3e457d5c315c 100644 --- a/beacon-chain/p2p/service.go +++ b/beacon-chain/p2p/service.go @@ -359,7 +359,8 @@ func (s *Service) RefreshENR(epoch uint64) { var committees []uint64 epochStartSlot := helpers.StartSlot(epoch) for i := epochStartSlot; i < epochStartSlot+2*params.BeaconConfig().SlotsPerEpoch; i++ { - committees = sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(i), cache.CommitteeIDs.GetAggregatorCommitteeIDs(i)) + committees = append(committees, sliceutil.UnionUint64(cache.CommitteeIDs.GetAttesterCommitteeIDs(i), + cache.CommitteeIDs.GetAggregatorCommitteeIDs(i))...) } for _, idx := range committees { bitV.SetBitAt(idx, true)