Skip to content

Commit

Permalink
BCFR-1086 return finality violation error in health report (#15548)
Browse files Browse the repository at this point in the history
* return finality violation error in health report

* gomod

* HealthReport tests

* propagate headtracker's errors

* bump chainlink-common
  • Loading branch information
dhaidashenko authored Dec 13, 2024
1 parent 4e84600 commit 2ec4d6c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 5 deletions.
6 changes: 4 additions & 2 deletions core/chains/evm/logpoller/log_poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
pkgerrors "github.com/pkg/errors"
"golang.org/x/exp/maps"

commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink-common/pkg/timeutil"
Expand Down Expand Up @@ -91,6 +93,7 @@ type Client interface {
}

type HeadTracker interface {
services.Service
LatestAndFinalizedBlock(ctx context.Context) (latest, finalized *evmtypes.Head, err error)
}

Expand All @@ -99,7 +102,6 @@ var (
ErrReplayRequestAborted = pkgerrors.New("aborted, replay request cancelled")
ErrReplayInProgress = pkgerrors.New("replay request cancelled, but replay is already in progress")
ErrLogPollerShutdown = pkgerrors.New("replay aborted due to log poller shutdown")
ErrFinalityViolated = pkgerrors.New("finality violated")
)

type logPoller struct {
Expand Down Expand Up @@ -525,7 +527,7 @@ func (lp *logPoller) Close() error {

func (lp *logPoller) Healthy() error {
if lp.finalityViolated.Load() {
return ErrFinalityViolated
return commontypes.ErrFinalityViolated
}
return nil
}
Expand Down
9 changes: 7 additions & 2 deletions core/chains/evm/logpoller/log_poller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"

commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils"

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype"

htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks"
Expand Down Expand Up @@ -1106,7 +1109,8 @@ func TestLogPoller_ReorgDeeperThanFinality(t *testing.T) {

secondPoll := th.PollAndSaveLogs(testutils.Context(t), firstPoll)
assert.Equal(t, firstPoll, secondPoll)
assert.Equal(t, logpoller.ErrFinalityViolated, th.LogPoller.Healthy())
require.Equal(t, commontypes.ErrFinalityViolated, th.LogPoller.Healthy())
require.Equal(t, commontypes.ErrFinalityViolated, th.LogPoller.HealthReport()[th.LogPoller.Name()])

// Manually remove re-org'd chain from the log poller to bring it back to life
// LogPoller should be healthy again after first poll
Expand All @@ -1116,7 +1120,8 @@ func TestLogPoller_ReorgDeeperThanFinality(t *testing.T) {
// Poll from latest
recoveryPoll := th.PollAndSaveLogs(testutils.Context(t), 1)
assert.Equal(t, int64(35), recoveryPoll)
assert.NoError(t, th.LogPoller.Healthy())
require.NoError(t, th.LogPoller.Healthy())
require.NoError(t, th.LogPoller.HealthReport()[th.LogPoller.Name()])
})
}
}
Expand Down
20 changes: 20 additions & 0 deletions core/services/relay/evm/chain_components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package evm_test
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math"
"math/big"
Expand All @@ -12,22 +13,28 @@ import (
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
evmtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient/simulated"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-common/pkg/services"

commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils"
clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests"

htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
lpMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
clevmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
Expand Down Expand Up @@ -206,6 +213,19 @@ func TestContractReaderEventsInitValidation(t *testing.T) {
}
}

func TestChainReader_HealthReport(t *testing.T) {
lp := lpMocks.NewLogPoller(t)
lp.EXPECT().HealthReport().Return(map[string]error{"lp_name": clcommontypes.ErrFinalityViolated}).Once()
ht := htMocks.NewHeadTracker[*clevmtypes.Head, common.Hash](t)
htError := errors.New("head tracker error")
ht.EXPECT().HealthReport().Return(map[string]error{"ht_name": htError}).Once()
cr, err := evm.NewChainReaderService(testutils.Context(t), logger.NullLogger, lp, ht, nil, types.ChainReaderConfig{Contracts: nil})
require.NoError(t, err)
healthReport := cr.HealthReport()
require.True(t, services.ContainsError(healthReport, clcommontypes.ErrFinalityViolated), "expected chain reader to propagate logpoller's error")
require.True(t, services.ContainsError(healthReport, htError), "expected chain reader to propagate headtracker's error")
}

func TestChainComponents(t *testing.T) {
testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCFR-1083")
t.Parallel()
Expand Down
9 changes: 8 additions & 1 deletion core/services/relay/evm/chain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
"github.com/smartcontractkit/chainlink-common/pkg/values"

evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
Expand Down Expand Up @@ -179,7 +180,13 @@ func (cr *chainReader) Close() error {
func (cr *chainReader) Ready() error { return nil }

func (cr *chainReader) HealthReport() map[string]error {
return map[string]error{cr.Name(): nil}
report := map[string]error{
cr.Name(): cr.Healthy(),
}

commonservices.CopyHealth(report, cr.lp.HealthReport())
commonservices.CopyHealth(report, cr.ht.HealthReport())
return report
}

func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundContract) error {
Expand Down

0 comments on commit 2ec4d6c

Please sign in to comment.