From 4acd212a1618620f77e7082e303a33f1dd781421 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:33:23 +0100 Subject: [PATCH] polygon/p2p: fix p2p fetcher peer errors on chain tip (#11927) More issues surfaced on chain tip when testing astrid: 1. context deadline exceeded when requesting new block event at tip from peer - can happen, safe to ignore event and continue instead of crashing: ``` [EROR] [09-06|03:41:00.183] [2/6 PolygonSync] stopping node err="await *eth.BlockHeadersPacket66 response interrupted: context deadline exceeded" ``` 2. Noticed we do not penalise peers for penalize-able errors when calling `FetchBlocks` - added that in 3. We got another error that crashed the process - `ErrNonSequentialHeaderNumbers` - it is safe to ignore new block event if this happens and continue ``` EROR[09-05|20:26:35.141] [2/6 PolygonSync] stopping node err="non sequential header numbers in fetch headers response: current=11608859, expected=11608860" ``` 4. Added all other p2p errors that may happen and are safe to ignore at tip event processing 5. Added debug logging for better visibility into chain tip events 6. Fixed missing check for whether we have already processed a new block event (ie if its hash is already contained in the canonical chain builder) --- polygon/p2p/fetcher_base_test.go | 42 ++-- polygon/p2p/fetcher_penalizing.go | 42 +++- polygon/p2p/fetcher_penalizing_test.go | 286 +++++++++++++++++-------- polygon/sync/sync.go | 28 ++- 4 files changed, 284 insertions(+), 114 deletions(-) diff --git a/polygon/p2p/fetcher_base_test.go b/polygon/p2p/fetcher_base_test.go index c3ff695db1c..810d29921c3 100644 --- a/polygon/p2p/fetcher_base_test.go +++ b/polygon/p2p/fetcher_base_test.go @@ -543,27 +543,27 @@ func newFetcherTest(t *testing.T, requestIdGenerator RequestIdGenerator) *fetche messageSender := NewMessageSender(sentryClient) fetcher := newFetcher(fetcherConfig, messageListener, messageSender, requestIdGenerator) return &fetcherTest{ - ctx: ctx, - ctxCancel: cancel, - t: t, - fetcher: fetcher, - logger: logger, - sentryClient: sentryClient, - messageListener: messageListener, - headersRequestResponseMocks: map[uint64]requestResponseMock{}, + ctx: ctx, + ctxCancel: cancel, + t: t, + fetcher: fetcher, + logger: logger, + sentryClient: sentryClient, + messageListener: messageListener, + requestResponseMocks: map[uint64]requestResponseMock{}, } } type fetcherTest struct { - ctx context.Context - ctxCancel context.CancelFunc - t *testing.T - fetcher *fetcher - logger log.Logger - sentryClient *direct.MockSentryClient - messageListener MessageListener - headersRequestResponseMocks map[uint64]requestResponseMock - peerEvents chan *delayedMessage[*sentryproto.PeerEvent] + ctx context.Context + ctxCancel context.CancelFunc + t *testing.T + fetcher *fetcher + logger log.Logger + sentryClient *direct.MockSentryClient + messageListener MessageListener + requestResponseMocks map[uint64]requestResponseMock + peerEvents chan *delayedMessage[*sentryproto.PeerEvent] } func (ft *fetcherTest) run(f func(ctx context.Context, t *testing.T)) { @@ -611,7 +611,7 @@ func (ft *fetcherTest) mockSentryInboundMessagesStream(mocks ...requestResponseM var numInboundMessages int for _, mock := range mocks { numInboundMessages += len(mock.mockResponseInboundMessages) - ft.headersRequestResponseMocks[mock.requestId] = mock + ft.requestResponseMocks[mock.requestId] = mock } inboundMessageStreamChan := make(chan *delayedMessage[*sentryproto.InboundMessage], numInboundMessages) @@ -643,7 +643,7 @@ func (ft *fetcherTest) mockSentryInboundMessagesStream(mocks ...requestResponseM return nil, err } - delete(ft.headersRequestResponseMocks, mock.requestId) + delete(ft.requestResponseMocks, mock.requestId) for _, inboundMessage := range mock.mockResponseInboundMessages { inboundMessageStreamChan <- &delayedMessage[*sentryproto.InboundMessage]{ message: inboundMessage, @@ -668,7 +668,7 @@ func (ft *fetcherTest) mockSendMessageByIdForHeaders(req *sentryproto.SendMessag return requestResponseMock{}, err } - mock, ok := ft.headersRequestResponseMocks[pkt.RequestId] + mock, ok := ft.requestResponseMocks[pkt.RequestId] if !ok { return requestResponseMock{}, fmt.Errorf("unexpected request id %d", pkt.RequestId) } @@ -699,7 +699,7 @@ func (ft *fetcherTest) mockSendMessageByIdForBodies(req *sentryproto.SendMessage return requestResponseMock{}, err } - mock, ok := ft.headersRequestResponseMocks[pkt.RequestId] + mock, ok := ft.requestResponseMocks[pkt.RequestId] if !ok { return requestResponseMock{}, fmt.Errorf("unexpected request id %d", pkt.RequestId) } diff --git a/polygon/p2p/fetcher_penalizing.go b/polygon/p2p/fetcher_penalizing.go index 4a7fd4d2bc7..d9037c6453b 100644 --- a/polygon/p2p/fetcher_penalizing.go +++ b/polygon/p2p/fetcher_penalizing.go @@ -31,23 +31,42 @@ func NewPenalizingFetcher(logger log.Logger, fetcher Fetcher, peerPenalizer Peer } func newPenalizingFetcher(logger log.Logger, fetcher Fetcher, peerPenalizer PeerPenalizer) *penalizingFetcher { + fetchHeadersPenalizeErrs := []error{ + &ErrTooManyHeaders{}, + &ErrNonSequentialHeaderNumbers{}, + } + + fetchBodiesPenalizeErrs := []error{ + &ErrTooManyBodies{}, + } + + fetchBlocksPenalizeErrs := make([]error, 0, len(fetchHeadersPenalizeErrs)+len(fetchBodiesPenalizeErrs)) + fetchBlocksPenalizeErrs = append(fetchBlocksPenalizeErrs, fetchHeadersPenalizeErrs...) + fetchBlocksPenalizeErrs = append(fetchBlocksPenalizeErrs, fetchBodiesPenalizeErrs...) + return &penalizingFetcher{ - Fetcher: fetcher, - logger: logger, - peerPenalizer: peerPenalizer, + Fetcher: fetcher, + logger: logger, + peerPenalizer: peerPenalizer, + fetchHeadersPenalizeErrs: fetchHeadersPenalizeErrs, + fetchBodiesPenalizeErrs: fetchBodiesPenalizeErrs, + fetchBlocksPenalizeErrs: fetchBlocksPenalizeErrs, } } type penalizingFetcher struct { Fetcher - logger log.Logger - peerPenalizer PeerPenalizer + logger log.Logger + peerPenalizer PeerPenalizer + fetchHeadersPenalizeErrs []error + fetchBodiesPenalizeErrs []error + fetchBlocksPenalizeErrs []error } func (pf *penalizingFetcher) FetchHeaders(ctx context.Context, start uint64, end uint64, peerId *PeerId) (FetcherResponse[[]*types.Header], error) { headers, err := pf.Fetcher.FetchHeaders(ctx, start, end, peerId) if err != nil { - return FetcherResponse[[]*types.Header]{}, pf.maybePenalize(ctx, peerId, err, &ErrTooManyHeaders{}, &ErrNonSequentialHeaderNumbers{}) + return FetcherResponse[[]*types.Header]{}, pf.maybePenalize(ctx, peerId, err, pf.fetchHeadersPenalizeErrs...) } return headers, nil @@ -56,12 +75,21 @@ func (pf *penalizingFetcher) FetchHeaders(ctx context.Context, start uint64, end func (pf *penalizingFetcher) FetchBodies(ctx context.Context, headers []*types.Header, peerId *PeerId) (FetcherResponse[[]*types.Body], error) { bodies, err := pf.Fetcher.FetchBodies(ctx, headers, peerId) if err != nil { - return FetcherResponse[[]*types.Body]{}, pf.maybePenalize(ctx, peerId, err, &ErrTooManyBodies{}) + return FetcherResponse[[]*types.Body]{}, pf.maybePenalize(ctx, peerId, err, pf.fetchBodiesPenalizeErrs...) } return bodies, nil } +func (pf *penalizingFetcher) FetchBlocks(ctx context.Context, start uint64, end uint64, peerId *PeerId) (FetcherResponse[[]*types.Block], error) { + blocks, err := pf.Fetcher.FetchBlocks(ctx, start, end, peerId) + if err != nil { + return FetcherResponse[[]*types.Block]{}, pf.maybePenalize(ctx, peerId, err, pf.fetchBlocksPenalizeErrs...) + } + + return blocks, nil +} + func (pf *penalizingFetcher) maybePenalize(ctx context.Context, peerId *PeerId, err error, penalizeErrs ...error) error { var shouldPenalize bool for _, penalizeErr := range penalizeErrs { diff --git a/polygon/p2p/fetcher_penalizing_test.go b/polygon/p2p/fetcher_penalizing_test.go index ad8a897dd85..161fc9d4334 100644 --- a/polygon/p2p/fetcher_penalizing_test.go +++ b/polygon/p2p/fetcher_penalizing_test.go @@ -28,64 +28,205 @@ import ( "github.com/erigontech/erigon/core/types" ) -func TestPenalizingFetcherFetchHeadersShouldPenalizePeerWhenErrTooManyHeaders(t *testing.T) { +func TestPenalizingFetcherShouldPenalizePeerWhenErrTooManyHeaders(t *testing.T) { t.Parallel() - peerId := PeerIdFromUint64(1) - requestId := uint64(1234) - mockInboundMessages := []*sentry.InboundMessage{ + for _, tc := range []struct { + name string + method func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error + }{ { - Id: sentry.MessageId_BLOCK_HEADERS_66, - PeerId: peerId.H512(), - // response should contain 2 headers instead we return 5 - Data: newMockBlockHeadersPacket66Bytes(t, requestId, 5), + name: "FetchHeaders", + method: func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error { + headers, err := test.penalizingFetcher.FetchHeaders(ctx, start, end, peerId) + require.Nil(test.t, headers.Data) + return err + }, }, + { + name: "FetchBlocks", + method: func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error { + blocks, err := test.penalizingFetcher.FetchBlocks(ctx, start, end, peerId) + require.Nil(test.t, blocks.Data) + return err + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + peerId := PeerIdFromUint64(1) + requestId := uint64(1234) + mockInboundMessages := []*sentry.InboundMessage{ + { + Id: sentry.MessageId_BLOCK_HEADERS_66, + PeerId: peerId.H512(), + // response should contain 2 headers instead we return 5 + Data: newMockBlockHeadersPacket66Bytes(t, requestId, 5), + }, + } + mockRequestResponse := requestResponseMock{ + requestId: requestId, + mockResponseInboundMessages: mockInboundMessages, + wantRequestPeerId: peerId, + wantRequestOriginNumber: 1, + wantRequestAmount: 2, + } + + test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) + test.mockSentryStreams(mockRequestResponse) + // setup expectation that peer should be penalized + mockExpectPenalizePeer(t, test.sentryClient, peerId) + test.run(func(ctx context.Context, t *testing.T) { + var errTooManyHeaders *ErrTooManyHeaders + err := tc.method(ctx, 1, 3, peerId, test) + require.ErrorAs(t, err, &errTooManyHeaders) + require.Equal(t, 2, errTooManyHeaders.requested) + require.Equal(t, 5, errTooManyHeaders.received) + }) + }) } - mockRequestResponse := requestResponseMock{ - requestId: requestId, - mockResponseInboundMessages: mockInboundMessages, - wantRequestPeerId: peerId, - wantRequestOriginNumber: 1, - wantRequestAmount: 2, +} + +func TestPenalizingFetcherShouldPenalizePeerWhenErrNonSequentialHeaderNumbers(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + method func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error + }{ + { + name: "FetchHeaders", + method: func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error { + headers, err := test.penalizingFetcher.FetchHeaders(ctx, start, end, peerId) + require.Nil(test.t, headers.Data) + return err + }, + }, + { + name: "FetchBlocks", + method: func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error { + blocks, err := test.penalizingFetcher.FetchBlocks(ctx, start, end, peerId) + require.Nil(test.t, blocks.Data) + return err + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + peerId := PeerIdFromUint64(1) + requestId := uint64(1234) + mockBlockHeaders := newMockBlockHeaders(5) + disconnectedHeaders := make([]*types.Header, 3) + disconnectedHeaders[0] = mockBlockHeaders[0] + disconnectedHeaders[1] = mockBlockHeaders[2] + disconnectedHeaders[2] = mockBlockHeaders[4] + mockInboundMessages := []*sentry.InboundMessage{ + { + Id: sentry.MessageId_BLOCK_HEADERS_66, + PeerId: peerId.H512(), + Data: blockHeadersPacket66Bytes(t, requestId, disconnectedHeaders), + }, + } + mockRequestResponse := requestResponseMock{ + requestId: requestId, + mockResponseInboundMessages: mockInboundMessages, + wantRequestPeerId: peerId, + wantRequestOriginNumber: 1, + wantRequestAmount: 3, + } + + test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) + test.mockSentryStreams(mockRequestResponse) + // setup expectation that peer should be penalized + mockExpectPenalizePeer(t, test.sentryClient, peerId) + test.run(func(ctx context.Context, t *testing.T) { + var errNonSequentialHeaderNumbers *ErrNonSequentialHeaderNumbers + err := tc.method(ctx, 1, 4, peerId, test) + require.ErrorAs(t, err, &errNonSequentialHeaderNumbers) + require.Equal(t, uint64(3), errNonSequentialHeaderNumbers.current) + require.Equal(t, uint64(2), errNonSequentialHeaderNumbers.expected) + }) + }) } +} - test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) - test.mockSentryStreams(mockRequestResponse) - // setup expectation that peer should be penalized - mockExpectPenalizePeer(t, test.sentryClient, peerId) - test.run(func(ctx context.Context, t *testing.T) { - var errTooManyHeaders *ErrTooManyHeaders - headers, err := test.penalizingFetcher.FetchHeaders(ctx, 1, 3, peerId) - require.ErrorAs(t, err, &errTooManyHeaders) - require.Equal(t, 2, errTooManyHeaders.requested) - require.Equal(t, 5, errTooManyHeaders.received) - require.Nil(t, headers.Data) - }) +func TestPenalizingFetcherShouldPenalizePeerWhenHeaderGtRequestedStart(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + method func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error + }{ + { + name: "FetchHeaders", + method: func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error { + headers, err := test.penalizingFetcher.FetchHeaders(ctx, start, end, peerId) + require.Nil(test.t, headers.Data) + return err + }, + }, + { + name: "FetchBlocks", + method: func(ctx context.Context, start, end uint64, peerId *PeerId, test *penalizingFetcherTest) error { + blocks, err := test.penalizingFetcher.FetchBlocks(ctx, start, end, peerId) + require.Nil(test.t, blocks.Data) + return err + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + peerId := PeerIdFromUint64(1) + requestId := uint64(1234) + mockBlockHeaders := newMockBlockHeaders(3) + incorrectOriginHeaders := mockBlockHeaders[1:] + mockInboundMessages := []*sentry.InboundMessage{ + { + Id: sentry.MessageId_BLOCK_HEADERS_66, + PeerId: peerId.H512(), + // response headers should be 2 and start at 1 - instead we start at 2 + Data: blockHeadersPacket66Bytes(t, requestId, incorrectOriginHeaders), + }, + } + mockRequestResponse := requestResponseMock{ + requestId: requestId, + mockResponseInboundMessages: mockInboundMessages, + wantRequestPeerId: peerId, + wantRequestOriginNumber: 1, + wantRequestAmount: 2, + } + + test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) + test.mockSentryStreams(mockRequestResponse) + // setup expectation that peer should be penalized + mockExpectPenalizePeer(t, test.sentryClient, peerId) + test.run(func(ctx context.Context, t *testing.T) { + var errNonSequentialHeaderNumbers *ErrNonSequentialHeaderNumbers + err := tc.method(ctx, 1, 3, peerId, test) + require.ErrorAs(t, err, &errNonSequentialHeaderNumbers) + require.Equal(t, uint64(2), errNonSequentialHeaderNumbers.current) + require.Equal(t, uint64(1), errNonSequentialHeaderNumbers.expected) + }) + }) + } } -func TestPenalizingFetcherFetchHeadersShouldPenalizePeerWhenErrNonSequentialHeaderNumbers(t *testing.T) { +func TestPenalizingFetcherFetchBodiesShouldPenalizePeerWhenErrTooManyBodies(t *testing.T) { t.Parallel() peerId := PeerIdFromUint64(1) requestId := uint64(1234) - mockBlockHeaders := newMockBlockHeaders(5) - disconnectedHeaders := make([]*types.Header, 3) - disconnectedHeaders[0] = mockBlockHeaders[0] - disconnectedHeaders[1] = mockBlockHeaders[2] - disconnectedHeaders[2] = mockBlockHeaders[4] + headers := []*types.Header{{Number: big.NewInt(1)}} + hashes := []common.Hash{headers[0].Hash()} mockInboundMessages := []*sentry.InboundMessage{ { - Id: sentry.MessageId_BLOCK_HEADERS_66, + Id: sentry.MessageId_BLOCK_BODIES_66, PeerId: peerId.H512(), - Data: blockHeadersPacket66Bytes(t, requestId, disconnectedHeaders), + Data: newMockBlockBodiesPacketBytes(t, requestId, &types.Body{}, &types.Body{}), }, } mockRequestResponse := requestResponseMock{ requestId: requestId, mockResponseInboundMessages: mockInboundMessages, wantRequestPeerId: peerId, - wantRequestOriginNumber: 1, - wantRequestAmount: 3, + wantRequestHashes: hashes, } test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) @@ -93,80 +234,57 @@ func TestPenalizingFetcherFetchHeadersShouldPenalizePeerWhenErrNonSequentialHead // setup expectation that peer should be penalized mockExpectPenalizePeer(t, test.sentryClient, peerId) test.run(func(ctx context.Context, t *testing.T) { - var errNonSequentialHeaderNumbers *ErrNonSequentialHeaderNumbers - headers, err := test.penalizingFetcher.FetchHeaders(ctx, 1, 4, peerId) - require.ErrorAs(t, err, &errNonSequentialHeaderNumbers) - require.Equal(t, uint64(3), errNonSequentialHeaderNumbers.current) - require.Equal(t, uint64(2), errNonSequentialHeaderNumbers.expected) - require.Nil(t, headers.Data) + var errTooManyBodies *ErrTooManyBodies + bodies, err := test.penalizingFetcher.FetchBodies(ctx, headers, peerId) + require.ErrorAs(t, err, &errTooManyBodies) + require.Equal(t, 1, errTooManyBodies.requested) + require.Equal(t, 2, errTooManyBodies.received) + require.Nil(t, bodies.Data) }) } -func TestPenalizingFetcherFetchHeadersShouldPenalizePeerWhenIncorrectOrigin(t *testing.T) { +func TestPenalizingFetcherFetchBlocksShouldPenalizePeerWhenErrTooManyBodies(t *testing.T) { t.Parallel() peerId := PeerIdFromUint64(1) - requestId := uint64(1234) - mockBlockHeaders := newMockBlockHeaders(3) - incorrectOriginHeaders := mockBlockHeaders[1:] - mockInboundMessages := []*sentry.InboundMessage{ + requestId1 := uint64(1233) + headers := newMockBlockHeaders(1) + mockInboundMessages1 := []*sentry.InboundMessage{ { Id: sentry.MessageId_BLOCK_HEADERS_66, PeerId: peerId.H512(), - // response headers should be 2 and start at 1 - instead we start at 2 - Data: blockHeadersPacket66Bytes(t, requestId, incorrectOriginHeaders), + Data: blockHeadersPacket66Bytes(t, requestId1, headers), }, } - mockRequestResponse := requestResponseMock{ - requestId: requestId, - mockResponseInboundMessages: mockInboundMessages, + mockRequestResponse1 := requestResponseMock{ + requestId: requestId1, + mockResponseInboundMessages: mockInboundMessages1, wantRequestPeerId: peerId, wantRequestOriginNumber: 1, - wantRequestAmount: 2, + wantRequestAmount: 1, } - - test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) - test.mockSentryStreams(mockRequestResponse) - // setup expectation that peer should be penalized - mockExpectPenalizePeer(t, test.sentryClient, peerId) - test.run(func(ctx context.Context, t *testing.T) { - var errNonSequentialHeaderNumbers *ErrNonSequentialHeaderNumbers - headers, err := test.penalizingFetcher.FetchHeaders(ctx, 1, 3, peerId) - require.ErrorAs(t, err, &errNonSequentialHeaderNumbers) - require.Equal(t, uint64(2), errNonSequentialHeaderNumbers.current) - require.Equal(t, uint64(1), errNonSequentialHeaderNumbers.expected) - require.Nil(t, headers.Data) - }) -} - -func TestPenalizingFetcherFetchBodiesShouldPenalizePeerWhenErrTooManyBodies(t *testing.T) { - t.Parallel() - - peerId := PeerIdFromUint64(1) - requestId := uint64(1234) - headers := []*types.Header{{Number: big.NewInt(1)}} - hashes := []common.Hash{headers[0].Hash()} - mockInboundMessages := []*sentry.InboundMessage{ + requestId2 := uint64(1234) + mockInboundMessages2 := []*sentry.InboundMessage{ { Id: sentry.MessageId_BLOCK_BODIES_66, PeerId: peerId.H512(), - Data: newMockBlockBodiesPacketBytes(t, requestId, &types.Body{}, &types.Body{}), + Data: newMockBlockBodiesPacketBytes(t, requestId2, &types.Body{}, &types.Body{}), }, } - mockRequestResponse := requestResponseMock{ - requestId: requestId, - mockResponseInboundMessages: mockInboundMessages, + mockRequestResponse2 := requestResponseMock{ + requestId: requestId2, + mockResponseInboundMessages: mockInboundMessages2, wantRequestPeerId: peerId, - wantRequestHashes: hashes, + wantRequestHashes: []common.Hash{headers[0].Hash()}, } - test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId)) - test.mockSentryStreams(mockRequestResponse) + test := newPenalizingFetcherTest(t, newMockRequestGenerator(requestId1, requestId2)) + test.mockSentryStreams(mockRequestResponse1, mockRequestResponse2) // setup expectation that peer should be penalized mockExpectPenalizePeer(t, test.sentryClient, peerId) test.run(func(ctx context.Context, t *testing.T) { var errTooManyBodies *ErrTooManyBodies - bodies, err := test.penalizingFetcher.FetchBodies(ctx, headers, peerId) + bodies, err := test.penalizingFetcher.FetchBlocks(ctx, 1, 2, peerId) require.ErrorAs(t, err, &errTooManyBodies) require.Equal(t, 1, errTooManyBodies.requested) require.Equal(t, 2, errTooManyBodies.received) diff --git a/polygon/sync/sync.go b/polygon/sync/sync.go index 52f1e92bbb4..ae98e75e71a 100644 --- a/polygon/sync/sync.go +++ b/polygon/sync/sync.go @@ -151,6 +151,13 @@ func (s *Sync) applyNewMilestoneOnTip( return nil } + s.logger.Debug( + syncLogPrefix("applying new milestone event"), + "milestoneStartBlockNum", milestone.StartBlock().Uint64(), + "milestoneEndBlockNum", milestone.EndBlock().Uint64(), + "milestoneRootHash", milestone.RootHash(), + ) + milestoneHeaders := ccBuilder.HeadersInRange(milestone.StartBlock().Uint64(), milestone.Length()) err := s.milestoneVerifier(milestone, milestoneHeaders) if errors.Is(err, ErrBadHeadersRootHash) { @@ -171,10 +178,17 @@ func (s *Sync) applyNewBlockOnTip( newBlockHeader := event.NewBlock.Header() newBlockHeaderNum := newBlockHeader.Number.Uint64() rootNum := ccBuilder.Root().Number.Uint64() - if newBlockHeaderNum <= rootNum { + if newBlockHeaderNum <= rootNum || ccBuilder.ContainsHash(newBlockHeader.Hash()) { return nil } + s.logger.Debug( + syncLogPrefix("applying new block event"), + "blockNum", newBlockHeaderNum, + "blockHash", newBlockHeader.Hash(), + "parentBlockHash", newBlockHeader.ParentHash, + ) + var blockChain []*types.Block if ccBuilder.ContainsHash(newBlockHeader.ParentHash) { blockChain = []*types.Block{event.NewBlock} @@ -254,6 +268,12 @@ func (s *Sync) applyNewBlockHashesOnTip( continue } + s.logger.Debug( + syncLogPrefix("applying new block hash event"), + "blockNum", headerHashNum.Number, + "blockHash", headerHashNum.Hash, + ) + newBlocks, err := s.p2pService.FetchBlocks(ctx, headerHashNum.Number, headerHashNum.Number+1, event.PeerId) if err != nil { if s.ignoreFetchBlocksErrOnTipEvent(err) { @@ -386,6 +406,10 @@ func (s *Sync) sync(ctx context.Context, tip *types.Header, tipDownloader tipDow func (s *Sync) ignoreFetchBlocksErrOnTipEvent(err error) bool { return errors.Is(err, &p2p.ErrIncompleteHeaders{}) || + errors.Is(err, &p2p.ErrNonSequentialHeaderNumbers{}) || + errors.Is(err, &p2p.ErrTooManyHeaders{}) || errors.Is(err, &p2p.ErrMissingBodies{}) || - errors.Is(err, p2p.ErrPeerNotFound) + errors.Is(err, &p2p.ErrTooManyBodies{}) || + errors.Is(err, p2p.ErrPeerNotFound) || + errors.Is(err, context.DeadlineExceeded) }