diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go index bc7a4910b39..2af17d56b33 100644 --- a/common/headtracker/head_tracker.go +++ b/common/headtracker/head_tracker.go @@ -250,8 +250,8 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) handleNewHead(ctx context.Context } } else { ht.log.Debugw("Got out of order head", "blockNum", head.BlockNumber(), "head", head.BlockHash(), "prevHead", prevHead.BlockNumber()) - prevUnFinalizedHead := prevHead.BlockNumber() - int64(ht.config.FinalityDepth()) - if head.BlockNumber() < prevUnFinalizedHead { + fmt.Println("PREVHEAD:", prevHead, head.BlockNumber()) + if head.BlockNumber() <= prevHead.LatestFinalizedHead().BlockNumber() { promOldHead.WithLabelValues(ht.chainID.String()).Inc() ht.log.Criticalf("Got very old block with number %d (highest seen was %d). This is a problem and either means a very deep re-org occurred, one of the RPC nodes has gotten far out of sync, or the chain went backwards in block numbers. This node may not function correctly without manual intervention.", head.BlockNumber(), prevHead.BlockNumber()) ht.SvcErrBuffer.Append(errors.New("got very old block")) diff --git a/common/types/head.go b/common/types/head.go index 4ecdb981c78..9d927d4f5e4 100644 --- a/common/types/head.go +++ b/common/types/head.go @@ -38,4 +38,7 @@ type Head[BLOCK_HASH Hashable] interface { BlockDifficulty() *big.Int // IsValid returns true if the head is valid. IsValid() bool + + // Returns the latest finalized based on finality tag or depth + LatestFinalizedHead() Head[BLOCK_HASH] } diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go index a8cbca07355..8fcd57a33c9 100644 --- a/common/types/mocks/head.go +++ b/common/types/mocks/head.go @@ -202,6 +202,26 @@ func (_m *Head[BLOCK_HASH]) IsValid() bool { return r0 } +// LatestFinalizedHead provides a mock function with given fields: +func (_m *Head[BLOCK_HASH]) LatestFinalizedHead() types.Head[BLOCK_HASH] { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for LatestFinalizedHead") + } + + var r0 types.Head[BLOCK_HASH] + if rf, ok := ret.Get(0).(func() types.Head[BLOCK_HASH]); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Head[BLOCK_HASH]) + } + } + + return r0 +} + // NewHead creates a new instance of Head. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewHead[BLOCK_HASH types.Hashable](t interface { diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index b8bdb1f5703..654207e1a28 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -64,6 +64,7 @@ func TestHeadTracker_New(t *testing.T) { orm := headtracker.NewORM(cltest.FixtureChainID, db) assert.Nil(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(1))) last := cltest.Head(16) + last.IsFinalized = true assert.Nil(t, orm.IdempotentInsertHead(testutils.Context(t), last)) assert.Nil(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(10))) diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index 1bf47f84726..9895017bab2 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -169,6 +169,7 @@ func (h *Head) ChainHashes() []common.Hash { func (h *Head) LatestFinalizedHead() commontypes.Head[common.Hash] { for h != nil && !h.IsFinalized { + fmt.Println(h.BlockNumber(), h.IsFinalized) h = h.Parent }