diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index d2d491d794c..dd3dc4e4b33 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -339,7 +339,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) pro ec.lggr.Debugw("Finished RebroadcastWhereNecessary", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") mark = time.Now() - if err := ec.EnsureConfirmedTransactionsInLongestChain(ctx, head, latestFinalizedHead.BlockNumber()); err != nil { + if err := ec.EnsureConfirmedTransactionsInLongestChain(ctx, head); err != nil { return fmt.Errorf("EnsureConfirmedTransactionsInLongestChain failed: %w", err) } @@ -1072,19 +1072,20 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han // // If any of the confirmed transactions does not have a receipt in the chain, it has been // re-org'd out and will be rebroadcast. -func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) EnsureConfirmedTransactionsInLongestChain(ctx context.Context, head types.Head[BLOCK_HASH], latestFinalizedHeadNumber int64) error { +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) EnsureConfirmedTransactionsInLongestChain(ctx context.Context, head types.Head[BLOCK_HASH]) error { logArgs := []interface{}{ - "chainLength", head.ChainLength(), "latestFinalizedHead number", latestFinalizedHeadNumber, - } - - if head.BlockNumber() < latestFinalizedHeadNumber { - errMsg := "current head is shorter than latest finalized head" - ec.lggr.Errorw(errMsg, append(logArgs, "head block number", head.BlockNumber())...) - return errors.New(errMsg) - } - - calculatedFinalityDepth := uint32(head.BlockNumber() - latestFinalizedHeadNumber) - if head.ChainLength() < calculatedFinalityDepth { + "chainLength", head.ChainLength(), + } + + //Here, we rely on the finalized block provided in the chain instead of the one + //provided via a dedicated method to avoid the false warning of the chain being + //too short. When `FinalityTagBypass = true,` HeadTracker tracks `finality depth + //+ history depth` to prevent excessive CPU usage. Thus, the provided chain may + //be shorter than the chain from the latest to the latest finalized, marked with + //a tag. A proper fix of this issue and complete switch to finality tag support + //will be introduced in BCFR-620 + latestFinalized := head.LatestFinalizedHead() + if latestFinalized == nil || !latestFinalized.IsValid() { if ec.nConsecutiveBlocksChainTooShort > logAfterNConsecutiveBlocksChainTooShort { warnMsg := "Chain length supplied for re-org detection was shorter than the depth from the latest head to the finalized head. Re-org protection is not working properly. This could indicate a problem with the remote RPC endpoint, a compatibility issue with a particular blockchain, a bug with this particular blockchain, heads table being truncated too early, remote node out of sync, or something else. If this happens a lot please raise a bug with the Chainlink team including a log output sample and details of the chain and RPC endpoint you are using." ec.lggr.Warnw(warnMsg, append(logArgs, "nConsecutiveBlocksChainTooShort", ec.nConsecutiveBlocksChainTooShort)...) diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 03a43a61cf0..d468d1b4c10 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -2742,11 +2742,6 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { gconfig, config := newTestChainScopedConfig(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) - latestFinalizedHead := evmtypes.Head{ - Number: 8, - Hash: testutils.NewHash(), - } - h8 := &evmtypes.Head{ Number: 8, Hash: testutils.NewHash(), @@ -2762,14 +2757,14 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { } head.Parent.Store(h9) t.Run("does nothing if there aren't any transactions", func(t *testing.T) { - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) }) t.Run("does nothing to unconfirmed transactions", func(t *testing.T) { etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2781,7 +2776,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2794,7 +2789,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { mustInsertEthReceipt(t, txStore, h8.Number-1, testutils.NewHash(), etx.TxAttempts[0].Hash) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2815,7 +2810,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2838,7 +2833,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2873,7 +2868,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2893,7 +2888,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { // Add receipt that is higher than head mustInsertEthReceipt(t, txStore, head.Number+1, testutils.NewHash(), attempt.Hash) - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err)