From ab89053597086e4abb972328f1c74e871d8ccf99 Mon Sep 17 00:00:00 2001 From: Raul Jordan Date: Fri, 26 Jun 2020 11:35:12 -0500 Subject: [PATCH] QSP-45 Add Check for No Connected Peers BestFinalized (#6402) * no error returned * no target root * fix build * Merge refs/heads/master into best-finalized --- beacon-chain/p2p/peers/BUILD.bazel | 1 - beacon-chain/p2p/peers/status.go | 19 +++++++------------ beacon-chain/p2p/peers/status_test.go | 11 ++++------- .../sync/initial-sync/blocks_fetcher.go | 9 ++++----- .../sync/initial-sync/blocks_fetcher_test.go | 2 +- beacon-chain/sync/initial-sync/round_robin.go | 4 ++-- beacon-chain/sync/initial-sync/service.go | 2 +- beacon-chain/sync/rpc_status.go | 2 +- 8 files changed, 20 insertions(+), 30 deletions(-) diff --git a/beacon-chain/p2p/peers/BUILD.bazel b/beacon-chain/p2p/peers/BUILD.bazel index ef0c17f92..c8be51b36 100644 --- a/beacon-chain/p2p/peers/BUILD.bazel +++ b/beacon-chain/p2p/peers/BUILD.bazel @@ -9,7 +9,6 @@ go_library( deps = [ "//beacon-chain/core/helpers:go_default_library", "//proto/beacon/p2p/v1:go_default_library", - "//shared/bytesutil:go_default_library", "//shared/roughtime:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enr:go_default_library", "@com_github_gogo_protobuf//proto:go_default_library", diff --git a/beacon-chain/p2p/peers/status.go b/beacon-chain/p2p/peers/status.go index fb4189461..415bcb56c 100644 --- a/beacon-chain/p2p/peers/status.go +++ b/beacon-chain/p2p/peers/status.go @@ -34,7 +34,6 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" - "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/roughtime" ) @@ -427,33 +426,29 @@ func (p *Status) Decay() { // Ideally, all peers would be reporting the same finalized epoch but some may be behind due to their own latency, or because of // their finalized epoch at the time we queried them. // Returns the best finalized root, epoch number, and list of peers that are at or beyond that epoch. -func (p *Status) BestFinalized(maxPeers int, ourFinalizedEpoch uint64) ([]byte, uint64, []peer.ID) { +func (p *Status) BestFinalized(maxPeers int, ourFinalizedEpoch uint64) (uint64, []peer.ID) { connected := p.Connected() - finalized := make(map[[32]byte]uint64) - rootToEpoch := make(map[[32]byte]uint64) + finalizedEpochVotes := make(map[uint64]uint64) pidEpoch := make(map[peer.ID]uint64) potentialPIDs := make([]peer.ID, 0, len(connected)) for _, pid := range connected { peerChainState, err := p.ChainState(pid) if err == nil && peerChainState != nil && peerChainState.FinalizedEpoch >= ourFinalizedEpoch { - root := bytesutil.ToBytes32(peerChainState.FinalizedRoot) - finalized[root]++ - rootToEpoch[root] = peerChainState.FinalizedEpoch + finalizedEpochVotes[peerChainState.FinalizedEpoch]++ pidEpoch[pid] = peerChainState.FinalizedEpoch potentialPIDs = append(potentialPIDs, pid) } } // Select the target epoch, which is the epoch most peers agree upon. - var targetRoot [32]byte + var targetEpoch uint64 var mostVotes uint64 - for root, count := range finalized { + for epoch, count := range finalizedEpochVotes { if count > mostVotes { mostVotes = count - targetRoot = root + targetEpoch = epoch } } - targetEpoch := rootToEpoch[targetRoot] // Sort PIDs by finalized epoch, in decreasing order. sort.Slice(potentialPIDs, func(i, j int) bool { @@ -473,7 +468,7 @@ func (p *Status) BestFinalized(maxPeers int, ourFinalizedEpoch uint64) ([]byte, potentialPIDs = potentialPIDs[:maxPeers] } - return targetRoot[:], targetEpoch, potentialPIDs + return targetEpoch, potentialPIDs } // fetch is a helper function that fetches a peer status, possibly creating it. diff --git a/beacon-chain/p2p/peers/status_test.go b/beacon-chain/p2p/peers/status_test.go index cab2f2fd5..b428f2d8e 100644 --- a/beacon-chain/p2p/peers/status_test.go +++ b/beacon-chain/p2p/peers/status_test.go @@ -1,7 +1,6 @@ package peers_test import ( - "bytes" "crypto/rand" "fmt" "reflect" @@ -12,6 +11,7 @@ import ( peer "github.com/libp2p/go-libp2p-peer" ma "github.com/multiformats/go-multiaddr" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers" pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared/params" @@ -561,7 +561,7 @@ func TestTrimmedOrderedPeers(t *testing.T) { FinalizedRoot: mockroot2[:], }) - _, target, pids := p.BestFinalized(maxPeers, 0) + target, pids := p.BestFinalized(maxPeers, 0) if target != expectedTarget { t.Errorf("Incorrect target epoch retrieved; wanted %v but got %v", expectedTarget, target) } @@ -624,10 +624,7 @@ func TestBestPeer(t *testing.T) { FinalizedEpoch: 3, FinalizedRoot: junkRoot[:], }) - retRoot, retEpoch, _ := p.BestFinalized(15, 0) - if !bytes.Equal(retRoot, expectedRoot[:]) { - t.Errorf("Incorrect Finalized Root retrieved; wanted %v but got %v", expectedRoot, retRoot) - } + retEpoch, _ := p.BestFinalized(15, 0) if retEpoch != expectedFinEpoch { t.Errorf("Incorrect Finalized epoch retrieved; wanted %v but got %v", expectedFinEpoch, retEpoch) } @@ -646,7 +643,7 @@ func TestBestFinalized_returnsMaxValue(t *testing.T) { }) } - _, _, pids := p.BestFinalized(maxPeers, 0) + _, pids := p.BestFinalized(maxPeers, 0) if len(pids) != maxPeers { t.Fatalf("returned wrong number of peers, wanted %d, got %d", maxPeers, len(pids)) } diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher.go b/beacon-chain/sync/initial-sync/blocks_fetcher.go index 9130b2d33..8383d995c 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher.go @@ -233,8 +233,7 @@ func (f *blocksFetcher) handleRequest(ctx context.Context, start, count uint64) } headEpoch := helpers.SlotToEpoch(f.headFetcher.HeadSlot()) - _, finalizedEpoch, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) - + finalizedEpoch, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) if len(peers) == 0 { response.err = errNoPeersAvailable return response @@ -401,7 +400,7 @@ func (f *blocksFetcher) waitForMinimumPeers(ctx context.Context) ([]peer.ID, err return nil, ctx.Err() } headEpoch := helpers.SlotToEpoch(f.headFetcher.HeadSlot()) - _, _, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) + _, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) if len(peers) >= required { return peers, nil } @@ -459,7 +458,7 @@ func (f *blocksFetcher) nonSkippedSlotAfter(ctx context.Context, slot uint64) (u defer span.End() headEpoch := helpers.SlotToEpoch(f.headFetcher.HeadSlot()) - _, epoch, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) + epoch, peers := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) var err error peers, err = f.filterPeers(peers, peersPercentagePerRequest) if err != nil { @@ -541,6 +540,6 @@ func (f *blocksFetcher) nonSkippedSlotAfter(ctx context.Context, slot uint64) (u // bestFinalizedSlot returns the highest finalized slot of the majority of connected peers. func (f *blocksFetcher) bestFinalizedSlot() uint64 { headEpoch := helpers.SlotToEpoch(f.headFetcher.HeadSlot()) - _, finalizedEpoch, _ := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) + finalizedEpoch, _ := f.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, headEpoch) return helpers.StartSlot(finalizedEpoch) } diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher_test.go b/beacon-chain/sync/initial-sync/blocks_fetcher_test.go index 68d051b63..0a838cfdd 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher_test.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher_test.go @@ -503,7 +503,7 @@ func TestBlocksFetcher_requestBeaconBlocksByRange(t *testing.T) { p2p: p2p, }) - _, _, peers := p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, helpers.SlotToEpoch(mc.HeadSlot())) + _, peers := p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, helpers.SlotToEpoch(mc.HeadSlot())) req := &p2ppb.BeaconBlocksByRangeRequest{ StartSlot: 1, Step: 1, diff --git a/beacon-chain/sync/initial-sync/round_robin.go b/beacon-chain/sync/initial-sync/round_robin.go index ad8bcf807..e20a241b1 100644 --- a/beacon-chain/sync/initial-sync/round_robin.go +++ b/beacon-chain/sync/initial-sync/round_robin.go @@ -84,11 +84,11 @@ func (s *Service) roundRobinSync(genesis time.Time) error { p2p: s.p2p, headFetcher: s.chain, }) - _, _, pids := s.p2p.Peers().BestFinalized(1 /* maxPeers */, s.highestFinalizedEpoch()) + _, pids := s.p2p.Peers().BestFinalized(1 /* maxPeers */, s.highestFinalizedEpoch()) for len(pids) == 0 { log.Info("Waiting for a suitable peer before syncing to the head of the chain") time.Sleep(refreshTime) - _, _, pids = s.p2p.Peers().BestFinalized(1 /* maxPeers */, s.highestFinalizedEpoch()) + _, pids = s.p2p.Peers().BestFinalized(1 /* maxPeers */, s.highestFinalizedEpoch()) } best := pids[0] diff --git a/beacon-chain/sync/initial-sync/service.go b/beacon-chain/sync/initial-sync/service.go index d659639f5..9641244c4 100644 --- a/beacon-chain/sync/initial-sync/service.go +++ b/beacon-chain/sync/initial-sync/service.go @@ -214,7 +214,7 @@ func (s *Service) waitForMinimumPeers() { required = flags.Get().MinimumSyncPeers } for { - _, _, peers := s.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, s.chain.FinalizedCheckpt().Epoch) + _, peers := s.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, s.chain.FinalizedCheckpt().Epoch) if len(peers) >= required { break } diff --git a/beacon-chain/sync/rpc_status.go b/beacon-chain/sync/rpc_status.go index f46f1dcc9..8708bd895 100644 --- a/beacon-chain/sync/rpc_status.go +++ b/beacon-chain/sync/rpc_status.go @@ -71,7 +71,7 @@ func (s *Service) resyncIfBehind() { runutil.RunEvery(s.ctx, interval, func() { if s.shouldReSync() { syncedEpoch := helpers.SlotToEpoch(s.chain.HeadSlot()) - _, highestEpoch, _ := s.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, syncedEpoch) + highestEpoch, _ := s.p2p.Peers().BestFinalized(params.BeaconConfig().MaxPeersToSync, syncedEpoch) if helpers.StartSlot(highestEpoch) > s.chain.HeadSlot() { log.WithFields(logrus.Fields{ "currentEpoch": helpers.SlotToEpoch(s.chain.CurrentSlot()),