Skip to content

Commit

Permalink
improve test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaidashenko committed Jan 3, 2025
1 parent 96d802b commit 42eaff6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 24 deletions.
32 changes: 17 additions & 15 deletions core/chains/evm/logpoller/log_poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func (lp *logPoller) Replay(ctx context.Context, fromBlock int64) (err error) {
} else if errors.Is(err, commontypes.ErrFinalityViolated) {
// Replay only declares finality violation and does not resolve it, as it's possible that [fromBlock, savedFinalizedBlockNumber]
// does not contain the violation.
lp.lggr.Errorw("Replay failed due to finality violation", "fromBlock", fromBlock, "err", err)
lp.lggr.Criticalw("Replay failed due to finality violation", "fromBlock", fromBlock, "err", err)
lp.finalityViolated.Store(true)
lp.SvcErrBuffer.Append(err)
}
Expand Down Expand Up @@ -673,14 +673,15 @@ func (lp *logPoller) run() {
continue
}
err := lp.BackupPollAndSaveLogs(ctx)
if err != nil {
switch {
case errors.Is(err, commontypes.ErrFinalityViolated):
// BackupPoll only declares finality violation and does not resolve it, as it's possible that processed range
// does not contain the violation.
lp.lggr.Criticalw("Backup poll failed due to finality violation", "err", err)
lp.finalityViolated.Store(true)
lp.SvcErrBuffer.Append(err)
case err != nil:
lp.lggr.Errorw("Backup poller failed, retrying later", "err", err)
if errors.Is(err, commontypes.ErrFinalityViolated) {
// BackupPoll only declares finality violation and does not resolve it, as it's possible that processed range
// does not contain the violation.
lp.finalityViolated.Store(true)
lp.SvcErrBuffer.Append(err)
}
}
}
}
Expand Down Expand Up @@ -866,7 +867,7 @@ func convertTopics(topics []common.Hash) [][]byte {
return topicsForDB
}

// blocksFromLogs fetches all of the blocks associated with a given list of logs. It will also unconditionally fetch endBlockNumber,
// blocksFromFinalizedLogs fetches all of the blocks associated with a given list of logs. It will also unconditionally fetch endBlockNumber,
// whether or not there are any logs in the list from that block
func (lp *logPoller) blocksFromFinalizedLogs(ctx context.Context, logs []types.Log, endBlockNumber uint64) (blocks []LogPollerBlock, err error) {
numbers := make([]uint64, 0, len(logs))
Expand Down Expand Up @@ -982,8 +983,6 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren
// We will not have the previous currentBlock on initial poll.
havePreviousBlock := err1 == nil
if !havePreviousBlock {
// TODO: do not fetch block by number as we are storing sparse chain, there is a chance that such block won't exists
// it should be safer to fetch ancestor of the current block and use it to verify integrity of the chain
lp.lggr.Infow("Do not have previous block, first poll ever on new chain", "currentBlockNumber", currentBlockNumber)
return currentBlock, nil
}
Expand Down Expand Up @@ -1022,12 +1021,15 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren
// conditions this would be equal to lastProcessed.BlockNumber + 1.
func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int64) {
err := lp.pollAndSaveLogs(ctx, currentBlockNumber)
if errors.Is(err, commontypes.ErrFinalityViolated) {
lp.lggr.Criticalw("Failed to poll and save logs due to finality violation, retrying later", "err", err)
lp.finalityViolated.Store(true)
lp.SvcErrBuffer.Append(err)
return
}

if err != nil {
lp.lggr.Errorw("Failed to poll and save logs, retrying later", "err", err)
if errors.Is(err, commontypes.ErrFinalityViolated) {
lp.finalityViolated.Store(true)
lp.SvcErrBuffer.Append(err)
}
return
}

Expand Down
48 changes: 39 additions & 9 deletions core/chains/evm/logpoller/log_poller_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ func Test_PollAndSaveLogs_BackfillFinalityViolation(t *testing.T) {
ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) {
return newHead(number.Int64()), nil
})
ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{}}, nil).Once()
ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5}}, nil).Once()
mockBatchCallContext(t, ec)
// insert finalized block with different hash than in RPC
require.NoError(t, orm.InsertBlock(tests.Context(t), common.HexToHash("0x123"), 2, time.Unix(10, 0), 2))
Expand All @@ -717,14 +717,12 @@ func Test_PollAndSaveLogs_BackfillFinalityViolation(t *testing.T) {
headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
finalized := newHead(5)
latest := newHead(16)
headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).RunAndReturn(func(ctx context.Context) (*evmtypes.Head, *evmtypes.Head, error) {
return latest, finalized, nil
}).Once()
headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).Return(latest, finalized, nil).Once()
ec := evmclimocks.NewClient(t)
ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) {
return newHead(number.Int64()), nil
})
ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{}}, nil).Once()
ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5}}, nil).Once()
mockBatchCallContextWithHead(t, ec, func(num int64) evmtypes.Head {
// return new hash for every call
return evmtypes.Head{Number: num, Hash: utils.NewHash()}
Expand All @@ -733,10 +731,42 @@ func Test_PollAndSaveLogs_BackfillFinalityViolation(t *testing.T) {
lp.PollAndSaveLogs(tests.Context(t), 4)
require.ErrorIs(t, lp.HealthReport()[lp.Name()], commontypes.ErrFinalityViolated)
})

// ec.EXPECT().HeadByHash(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, hash common.Hash) (*evmtypes.Head, error) {
// return &evmtypes.Head{Number: hash.Big().Int64(), Hash: hash}, nil
// })
t.Run("Log's hash does not match block's", func(t *testing.T) {
lggr, _ := logger.TestObserved(t, zapcore.ErrorLevel)
orm := NewORM(testutils.NewRandomEVMChainID(), db, lggr)
headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
finalized := newHead(5)
latest := newHead(16)
headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).Return(latest, finalized, nil).Once()
ec := evmclimocks.NewClient(t)
ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) {
return newHead(number.Int64()), nil
})
ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5, BlockHash: common.HexToHash("0x123")}}, nil).Once()
mockBatchCallContext(t, ec)
lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts)
lp.PollAndSaveLogs(tests.Context(t), 4)
require.ErrorIs(t, lp.HealthReport()[lp.Name()], commontypes.ErrFinalityViolated)
})
t.Run("Happy path", func(t *testing.T) {
lggr, _ := logger.TestObserved(t, zapcore.ErrorLevel)
chainID := testutils.NewRandomEVMChainID()
orm := NewORM(chainID, db, lggr)
headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t)
finalized := newHead(5)
latest := newHead(16)
headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).Return(latest, finalized, nil).Once()
ec := evmclimocks.NewClient(t)
ec.EXPECT().ConfiguredChainID().Return(chainID)
ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) {
return newHead(number.Int64()), nil
})
ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5, BlockHash: common.BigToHash(big.NewInt(5)), Topics: []common.Hash{{}}}}, nil).Once()
mockBatchCallContext(t, ec)
lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts)
lp.PollAndSaveLogs(tests.Context(t), 4)
require.NoError(t, lp.HealthReport()[lp.Name()])
})
}

func benchmarkFilter(b *testing.B, nFilters, nAddresses, nEvents int) {
Expand Down

0 comments on commit 42eaff6

Please sign in to comment.