From 33b1abf560462c976335b68f7d24f47ac5567540 Mon Sep 17 00:00:00 2001 From: Dimitris Date: Mon, 27 Nov 2023 18:35:55 +0200 Subject: [PATCH 1/5] Change difficulty from Big to BigInt --- common/client/mock_head_test.go | 11 ++-- common/client/mock_node_test.go | 14 ++--- common/client/multi_node.go | 6 +- common/client/multi_node_test.go | 28 +++++----- common/client/node.go | 8 +-- common/client/node_fsm.go | 7 +-- common/client/node_lifecycle.go | 16 +++--- common/client/node_lifecycle_test.go | 55 ++++++++++--------- .../client/node_selector_total_difficulty.go | 4 +- .../node_selector_total_difficulty_test.go | 34 ++++++------ common/client/types.go | 3 +- common/fee/models.go | 2 +- common/txmgr/broadcaster.go | 3 +- common/types/head.go | 5 +- core/chains/evm/assets/wei.go | 2 +- core/chains/evm/client/erroring_node.go | 3 +- core/chains/evm/client/helpers_test.go | 3 +- core/chains/evm/client/node.go | 7 +-- core/chains/evm/client/node_fsm.go | 7 +-- core/chains/evm/client/node_lifecycle.go | 16 +++--- core/chains/evm/client/node_lifecycle_test.go | 25 ++++----- .../client/node_selector_total_difficulty.go | 6 +- .../node_selector_total_difficulty_test.go | 34 ++++++------ core/chains/evm/client/pool.go | 4 +- .../evm/client/simulated_backend_client.go | 2 +- core/chains/evm/gas/models.go | 2 +- core/chains/evm/mocks/node.go | 12 ++-- core/chains/evm/txmgr/transmitchecker.go | 2 +- core/chains/evm/types/models.go | 10 ++-- core/utils/big.go | 2 +- 30 files changed, 164 insertions(+), 169 deletions(-) diff --git a/common/client/mock_head_test.go b/common/client/mock_head_test.go index b9cf0a5866f..1b69eedf438 100644 --- a/common/client/mock_head_test.go +++ b/common/client/mock_head_test.go @@ -3,7 +3,8 @@ package client import ( - utils "github.com/smartcontractkit/chainlink/v2/core/utils" + big "math/big" + mock "github.com/stretchr/testify/mock" ) @@ -13,15 +14,15 @@ type mockHead struct { } // BlockDifficulty provides a mock function with given fields: -func (_m *mockHead) BlockDifficulty() *utils.Big { +func (_m *mockHead) BlockDifficulty() *big.Int { ret := _m.Called() - var r0 *utils.Big - if rf, ok := ret.Get(0).(func() *utils.Big); ok { + var r0 *big.Int + if rf, ok := ret.Get(0).(func() *big.Int); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*utils.Big) + r0 = ret.Get(0).(*big.Int) } } diff --git a/common/client/mock_node_test.go b/common/client/mock_node_test.go index bd704cd2c6f..ea0e7d1a120 100644 --- a/common/client/mock_node_test.go +++ b/common/client/mock_node_test.go @@ -4,11 +4,11 @@ package client import ( context "context" + big "math/big" - types "github.com/smartcontractkit/chainlink/v2/common/types" mock "github.com/stretchr/testify/mock" - utils "github.com/smartcontractkit/chainlink/v2/core/utils" + types "github.com/smartcontractkit/chainlink/v2/common/types" ) // mockNode is an autogenerated mock type for the Node type @@ -115,13 +115,13 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) State() nodeState { } // StateAndLatest provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *utils.Big) { +func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *big.Int) { ret := _m.Called() var r0 nodeState var r1 int64 - var r2 *utils.Big - if rf, ok := ret.Get(0).(func() (nodeState, int64, *utils.Big)); ok { + var r2 *big.Int + if rf, ok := ret.Get(0).(func() (nodeState, int64, *big.Int)); ok { return rf() } if rf, ok := ret.Get(0).(func() nodeState); ok { @@ -136,11 +136,11 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *ut r1 = ret.Get(1).(int64) } - if rf, ok := ret.Get(2).(func() *utils.Big); ok { + if rf, ok := ret.Get(2).(func() *big.Int); ok { r2 = rf() } else { if ret.Get(2) != nil { - r2 = ret.Get(2).(*utils.Big) + r2 = ret.Get(2).(*big.Int) } } diff --git a/common/client/multi_node.go b/common/client/multi_node.go index 48a4d37ad8c..d327833e112 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -13,12 +13,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/config" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -260,8 +260,8 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP // nLiveNodes returns the number of currently alive nodes, as well as the highest block number and greatest total difficulty. // totalDifficulty will be 0 if all nodes return nil. -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) nLiveNodes() (nLiveNodes int, blockNumber int64, totalDifficulty *utils.Big) { - totalDifficulty = utils.NewBigI(0) +func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT]) nLiveNodes() (nLiveNodes int, blockNumber int64, totalDifficulty *big.Int) { + totalDifficulty = big.NewInt(0) for _, n := range c.nodes { if s, num, td := n.StateAndLatest(); s == nodeStateAlive { nLiveNodes++ diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 4c0ebb1db93..6f320a02e11 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -2,6 +2,7 @@ package client import ( "fmt" + big "math/big" "math/rand" "testing" "time" @@ -17,14 +18,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) -type multiNodeRPCClient RPC[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any, +type multiNodeRPCClient RPC[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable]] type testMultiNode struct { - *multiNode[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any, + *multiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient] } @@ -46,19 +46,19 @@ func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode { opts.logger = logger.TestLogger(t) } - result := NewMultiNode[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any, + result := NewMultiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient](opts.logger, opts.selectionMode, opts.leaseDuration, opts.noNewHeadsThreshold, opts.nodes, opts.sendonlys, opts.chainID, opts.chainType, opts.chainFamily, opts.sendOnlyErrorParser) return testMultiNode{ - result.(*multiNode[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any, + result.(*multiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient]), } } -func newMultiNodeRPCClient(t *testing.T) *mockRPC[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any, +func newMultiNodeRPCClient(t *testing.T) *mockRPC[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable]] { - return newMockRPC[types.ID, *utils.Big, Hashable, Hashable, any, Hashable, any, any, + return newMockRPC[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable]](t) } @@ -424,40 +424,40 @@ func TestMultiNode_nLiveNodes(t *testing.T) { t.Parallel() type nodeParams struct { BlockNumber int64 - TotalDifficulty *utils.Big + TotalDifficulty *big.Int State nodeState } testCases := []struct { Name string ExpectedNLiveNodes int ExpectedBlockNumber int64 - ExpectedTotalDifficulty *utils.Big + ExpectedTotalDifficulty *big.Int NodeParams []nodeParams }{ { Name: "no nodes", - ExpectedTotalDifficulty: utils.NewBigI(0), + ExpectedTotalDifficulty: big.NewInt(0), }, { Name: "Best node is not healthy", - ExpectedTotalDifficulty: utils.NewBigI(10), + ExpectedTotalDifficulty: big.NewInt(10), ExpectedBlockNumber: 20, ExpectedNLiveNodes: 3, NodeParams: []nodeParams{ { State: nodeStateOutOfSync, BlockNumber: 1000, - TotalDifficulty: utils.NewBigI(2000), + TotalDifficulty: big.NewInt(2000), }, { State: nodeStateAlive, BlockNumber: 20, - TotalDifficulty: utils.NewBigI(9), + TotalDifficulty: big.NewInt(9), }, { State: nodeStateAlive, BlockNumber: 19, - TotalDifficulty: utils.NewBigI(10), + TotalDifficulty: big.NewInt(10), }, { State: nodeStateAlive, diff --git a/common/client/node.go b/common/client/node.go index 5faaa5da627..421f262ad5f 100644 --- a/common/client/node.go +++ b/common/client/node.go @@ -3,6 +3,7 @@ package client import ( "context" "fmt" + "math/big" "net/url" "sync" "time" @@ -15,7 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const QueryTimeout = 10 * time.Second @@ -53,7 +53,7 @@ type Node[ // State returns nodeState State() nodeState // StateAndLatest returns nodeState with the latest received block number & total difficulty. - StateAndLatest() (nodeState, int64, *utils.Big) + StateAndLatest() (nodeState, int64, *big.Int) // Name is a unique identifier for this node. Name() string String() string @@ -90,7 +90,7 @@ type node[ state nodeState // Each node is tracking the last received head number and total difficulty stateLatestBlockNumber int64 - stateLatestTotalDifficulty *utils.Big + stateLatestTotalDifficulty *big.Int // nodeCtx is the node lifetime's context nodeCtx context.Context @@ -103,7 +103,7 @@ type node[ // 1. see how many live nodes there are in total, so we can prevent the last alive node in a pool from being // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all. // 2. compare against the highest head (by number or difficulty) to ensure we don't fall behind too far. - nLiveNodes func() (count int, blockNumber int64, totalDifficulty *utils.Big) + nLiveNodes func() (count int, blockNumber int64, totalDifficulty *big.Int) } func NewNode[ diff --git a/common/client/node_fsm.go b/common/client/node_fsm.go index d4fc19140e9..74a5814f773 100644 --- a/common/client/node_fsm.go +++ b/common/client/node_fsm.go @@ -2,11 +2,10 @@ package client import ( "fmt" + "math/big" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -110,7 +109,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) State() nodeState { return n.state } -func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *utils.Big) { +func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *big.Int) { n.stateMu.RLock() defer n.stateMu.RUnlock() return n.state, n.stateLatestBlockNumber, n.stateLatestTotalDifficulty @@ -182,7 +181,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInSync(fn func()) { // declareOutOfSync puts a node into OutOfSync state, disconnecting all current // clients and making it unavailable for use until back in-sync. -func (n *node[CHAIN_ID, HEAD, RPC]) declareOutOfSync(isOutOfSync func(num int64, td *utils.Big) bool) { +func (n *node[CHAIN_ID, HEAD, RPC]) declareOutOfSync(isOutOfSync func(num int64, td *big.Int) bool) { n.transitionToOutOfSync(func() { n.lfcLog.Errorw("RPC Node is out of sync", "nodeState", n.state) n.wg.Add(1) diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 4193560e296..615534e4d31 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -4,12 +4,14 @@ import ( "context" "fmt" "math" + "math/big" "time" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -48,7 +50,7 @@ func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration { return utils.WithJitter(interval) } -func (n *node[CHAIN_ID, HEAD, RPC]) setLatestReceived(blockNumber int64, totalDifficulty *utils.Big) { +func (n *node[CHAIN_ID, HEAD, RPC]) setLatestReceived(blockNumber int64, totalDifficulty *big.Int) { n.stateMu.Lock() defer n.stateMu.Unlock() n.stateLatestBlockNumber = blockNumber @@ -214,13 +216,13 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { continue } } - n.declareOutOfSync(func(num int64, td *utils.Big) bool { return num < highestReceivedBlockNumber }) + n.declareOutOfSync(func(num int64, td *big.Int) bool { return num < highestReceivedBlockNumber }) return } } } -func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSync(num int64, td *utils.Big) (outOfSync bool) { +func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSync(num int64, td *big.Int) (outOfSync bool) { outOfSync, _ = n.syncStatus(num, td) return } @@ -228,7 +230,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSync(num int64, td *utils.Big) (outOf // syncStatus returns outOfSync true if num or td is more than SyncThresold behind the best node. // Always returns outOfSync false for SyncThreshold 0. // liveNodes is only included when outOfSync is true. -func (n *node[CHAIN_ID, HEAD, RPC]) syncStatus(num int64, td *utils.Big) (outOfSync bool, liveNodes int) { +func (n *node[CHAIN_ID, HEAD, RPC]) syncStatus(num int64, td *big.Int) (outOfSync bool, liveNodes int) { if n.nLiveNodes == nil { return // skip for tests } @@ -243,8 +245,8 @@ func (n *node[CHAIN_ID, HEAD, RPC]) syncStatus(num int64, td *utils.Big) (outOfS case NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel: return num < highest-int64(threshold), ln case NodeSelectionModeTotalDifficulty: - bigThreshold := utils.NewBigI(int64(threshold)) - return td.Cmp(greatest.Sub(bigThreshold)) < 0, ln + bigThreshold := big.NewInt(int64(threshold)) + return td.Cmp(bigmath.Sub(greatest, bigThreshold)) < 0, ln default: panic("unrecognized NodeSelectionMode: " + mode) } @@ -256,7 +258,7 @@ const ( ) // outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status -func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td *utils.Big) bool) { +func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td *big.Int) bool) { defer n.wg.Done() { diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go index 0dffe935fe0..082da91d22e 100644 --- a/common/client/node_lifecycle_test.go +++ b/common/client/node_lifecycle_test.go @@ -2,6 +2,7 @@ package client import ( "fmt" + big "math/big" "sync/atomic" "testing" @@ -11,12 +12,12 @@ import ( "github.com/stretchr/testify/mock" "go.uber.org/zap" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/common/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { @@ -188,8 +189,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { - return 1, 20, utils.NewBigI(10) + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { + return 1, 20, big.NewInt(10) } pollError := errors.New("failed to get ClientVersion") rpc.On("ClientVersion", mock.Anything).Return("", pollError) @@ -213,8 +214,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() node.stateLatestBlockNumber = 20 - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { - return 10, syncThreshold + node.stateLatestBlockNumber + 1, utils.NewBigI(10) + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { + return 10, syncThreshold + node.stateLatestBlockNumber + 1, big.NewInt(10) } rpc.On("ClientVersion", mock.Anything).Return("", nil) // tries to redial in outOfSync @@ -244,8 +245,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() node.stateLatestBlockNumber = 20 - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { - return 1, syncThreshold + node.stateLatestBlockNumber + 1, utils.NewBigI(10) + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { + return 1, syncThreshold + node.stateLatestBlockNumber + 1, big.NewInt(10) } rpc.On("ClientVersion", mock.Anything).Return("", nil) node.declareAlive() @@ -266,8 +267,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() node.stateLatestBlockNumber = 20 - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { - return 1, node.stateLatestBlockNumber + 100, utils.NewBigI(10) + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { + return 1, node.stateLatestBlockNumber + 100, big.NewInt(10) } rpc.On("ClientVersion", mock.Anything).Return("", nil) node.declareAlive() @@ -310,8 +311,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { - return 1, 20, utils.NewBigI(10) + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { + return 1, 20, big.NewInt(10) } node.declareAlive() tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState)) @@ -353,7 +354,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() expectedBlockNumber := rand.Int64() - expectedDiff := utils.NewBigI(rand.Int64()) + expectedDiff := big.NewInt(rand.Int64()) rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) go writeHeads(t, ch, head{BlockNumber: expectedBlockNumber, BlockDifficulty: expectedDiff}) @@ -367,14 +368,14 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { node.declareAlive() tests.AssertEventually(t, func() bool { state, block, diff := node.StateAndLatest() - return state == nodeStateAlive && block == expectedBlockNumber == diff.Equal(expectedDiff) + return state == nodeStateAlive && block == expectedBlockNumber == bigmath.Equal(diff, expectedDiff) }) }) } type head struct { BlockNumber int64 - BlockDifficulty *utils.Big + BlockDifficulty *big.Int } func writeHeads(t *testing.T, ch chan<- Head, heads ...head) { @@ -411,7 +412,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { return node } - stubIsOutOfSync := func(num int64, td *utils.Big) bool { + stubIsOutOfSync := func(num int64, td *big.Int) bool { return false } @@ -448,7 +449,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }).Return(outOfSyncSubscription, nil).Once() rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - node.declareOutOfSync(func(num int64, td *utils.Big) bool { + node.declareOutOfSync(func(num int64, td *big.Int) bool { return true }) tests.AssertLogCountEventually(t, observedLogs, msgReceivedBlock, len(heads)) @@ -614,7 +615,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { setupRPCForAliveLoop(t, rpc) - node.declareOutOfSync(func(num int64, td *utils.Big) bool { + node.declareOutOfSync(func(num int64, td *big.Int) bool { return num < highestBlock }) tests.AssertLogEventually(t, observedLogs, msgReceivedBlock) @@ -635,8 +636,8 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { - return 0, 100, utils.NewBigI(200) + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { + return 0, 100, big.NewInt(200) } rpc.On("Dial", mock.Anything).Return(nil).Once() @@ -943,7 +944,7 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { }) t.Run("skip if syncThreshold is not configured", func(t *testing.T) { node := newTestNode(t, testNodeOpts{}) - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { return } outOfSync, liveNodes := node.syncStatus(0, nil) @@ -954,7 +955,7 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { node := newTestNode(t, testNodeOpts{ config: testNodeConfig{syncThreshold: 1}, }) - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { + node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { return } assert.Panics(t, func() { @@ -1000,13 +1001,13 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { selectionMode: selectionMode, }, }) - node.nLiveNodes = func() (int, int64, *utils.Big) { - return nodesNum, highestBlock, utils.NewBigI(totalDifficulty) + node.nLiveNodes = func() (int, int64, *big.Int) { + return nodesNum, highestBlock, big.NewInt(totalDifficulty) } for _, td := range []int64{totalDifficulty - syncThreshold - 1, totalDifficulty - syncThreshold, totalDifficulty, totalDifficulty + 1} { for _, testCase := range testCases { t.Run(fmt.Sprintf("%s: selectionMode: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) { - outOfSync, liveNodes := node.syncStatus(testCase.blockNumber, utils.NewBigI(td)) + outOfSync, liveNodes := node.syncStatus(testCase.blockNumber, big.NewInt(td)) assert.Equal(t, nodesNum, liveNodes) assert.Equal(t, testCase.outOfSync, outOfSync) }) @@ -1053,13 +1054,13 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { selectionMode: NodeSelectionModeTotalDifficulty, }, }) - node.nLiveNodes = func() (int, int64, *utils.Big) { - return nodesNum, highestBlock, utils.NewBigI(totalDifficulty) + node.nLiveNodes = func() (int, int64, *big.Int) { + return nodesNum, highestBlock, big.NewInt(totalDifficulty) } for _, hb := range []int64{highestBlock - syncThreshold - 1, highestBlock - syncThreshold, highestBlock, highestBlock + 1} { for _, testCase := range testCases { t.Run(fmt.Sprintf("%s: selectionMode: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) { - outOfSync, liveNodes := node.syncStatus(hb, utils.NewBigI(testCase.totalDifficulty)) + outOfSync, liveNodes := node.syncStatus(hb, big.NewInt(testCase.totalDifficulty)) assert.Equal(t, nodesNum, liveNodes) assert.Equal(t, testCase.outOfSync, outOfSync) }) diff --git a/common/client/node_selector_total_difficulty.go b/common/client/node_selector_total_difficulty.go index 9b29642d033..35491503bcc 100644 --- a/common/client/node_selector_total_difficulty.go +++ b/common/client/node_selector_total_difficulty.go @@ -1,7 +1,7 @@ package client import ( - "github.com/smartcontractkit/chainlink/v2/core/utils" + "math/big" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -22,7 +22,7 @@ func NewTotalDifficultyNodeSelector[ func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] { // NodeNoNewHeadsThreshold may not be enabled, in this case all nodes have td == nil - var highestTD *utils.Big + var highestTD *big.Int var nodes []Node[CHAIN_ID, HEAD, RPC] var aliveNodes []Node[CHAIN_ID, HEAD, RPC] diff --git a/common/client/node_selector_total_difficulty_test.go b/common/client/node_selector_total_difficulty_test.go index 4eecb859db9..5c43cdd8472 100644 --- a/common/client/node_selector_total_difficulty_test.go +++ b/common/client/node_selector_total_difficulty_test.go @@ -1,10 +1,10 @@ package client import ( + big "math/big" "testing" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" ) @@ -27,10 +27,10 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil) } else if i == 1 { // second node is alive - node.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(7)) + node.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(7)) } else { // third node is alive and best - node.On("StateAndLatest").Return(nodeStateAlive, int64(2), utils.NewBigI(8)) + node.On("StateAndLatest").Return(nodeStateAlive, int64(2), big.NewInt(8)) } node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -42,7 +42,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("stick to the same node", func(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) // fourth node is alive (same as 3rd) - node.On("StateAndLatest").Return(nodeStateAlive, int64(2), utils.NewBigI(8)) + node.On("StateAndLatest").Return(nodeStateAlive, int64(2), big.NewInt(8)) node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -53,7 +53,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("another best node", func(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) // fifth node is alive (better than 3rd and 4th) - node.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(11)) + node.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(11)) node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -88,7 +88,7 @@ func TestTotalDifficultyNodeSelector_None(t *testing.T) { node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil) } else { // others are unreachable - node.On("StateAndLatest").Return(nodeStateUnreachable, int64(1), utils.NewBigI(7)) + node.On("StateAndLatest").Return(nodeStateUnreachable, int64(1), big.NewInt(7)) } nodes = append(nodes, node) } @@ -106,7 +106,7 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("same td and order", func(t *testing.T) { for i := 0; i < 3; i++ { node := newMockNode[types.ID, Head, nodeClient](t) - node.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(10)) + node.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(10)) node.On("Order").Return(int32(2)) nodes = append(nodes, node) } @@ -117,15 +117,15 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("same td but different order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(10)) + node1.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(10)) node1.On("Order").Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(10)) + node2.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(10)) node2.On("Order").Return(int32(1)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), utils.NewBigI(10)) + node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(10)) node3.On("Order").Return(int32(2)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3} @@ -136,15 +136,15 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("different td but same order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(10)) + node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(10)) node1.On("Order").Maybe().Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(11)) + node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(11)) node2.On("Order").Maybe().Return(int32(3)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(12)) + node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(12)) node3.On("Order").Return(int32(3)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3} @@ -155,19 +155,19 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("different head and different order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(100)) + node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(100)) node1.On("Order").Maybe().Return(int32(4)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(110)) + node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(110)) node2.On("Order").Maybe().Return(int32(5)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(110)) + node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(110)) node3.On("Order").Maybe().Return(int32(1)) node4 := newMockNode[types.ID, Head, nodeClient](t) - node4.On("StateAndLatest").Return(nodeStateAlive, int64(1), utils.NewBigI(105)) + node4.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(105)) node4.On("Order").Maybe().Return(int32(2)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3, node4} diff --git a/common/client/types.go b/common/client/types.go index 6d3a22cee77..32d4da98b50 100644 --- a/common/client/types.go +++ b/common/client/types.go @@ -7,7 +7,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // RPC includes all the necessary methods for a multi-node client to interact directly with any RPC endpoint. @@ -51,7 +50,7 @@ type RPC[ //go:generate mockery --quiet --name Head --structname mockHead --filename "mock_head_test.go" --inpackage --case=underscore type Head interface { BlockNumber() int64 - BlockDifficulty() *utils.Big + BlockDifficulty() *big.Int } // NodeClient includes all the necessary RPC methods required by a node. diff --git a/common/fee/models.go b/common/fee/models.go index f980c73fc1b..454fe723353 100644 --- a/common/fee/models.go +++ b/common/fee/models.go @@ -5,9 +5,9 @@ import ( "github.com/pkg/errors" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink/v2/common/chains/label" "github.com/smartcontractkit/chainlink/v2/core/logger" - bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) var ( diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index d9a72e367ac..7f4d3accb97 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/common/client" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" @@ -246,7 +247,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) clos eb.initSync.Lock() defer eb.initSync.Unlock() if !eb.isStarted { - return errors.Wrap(utils.ErrAlreadyStopped, "Broadcaster is not started") + return errors.Wrap(services.ErrAlreadyStopped, "Broadcaster is not started") } close(eb.chStop) eb.wg.Wait() diff --git a/common/types/head.go b/common/types/head.go index 000bad2390e..c363fd5d0f2 100644 --- a/common/types/head.go +++ b/common/types/head.go @@ -1,9 +1,8 @@ package types import ( + "math/big" "time" - - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Head provides access to a chain's head, as needed by the TxManager. @@ -36,5 +35,5 @@ type Head[BLOCK_HASH Hashable] interface { // Returns the total difficulty of the block. For chains who do not have a concept of block // difficulty, return 0. - BlockDifficulty() *utils.Big + BlockDifficulty() *big.Int } diff --git a/core/chains/evm/assets/wei.go b/core/chains/evm/assets/wei.go index 7d1240d384c..be0143b3a86 100644 --- a/core/chains/evm/assets/wei.go +++ b/core/chains/evm/assets/wei.go @@ -10,8 +10,8 @@ import ( "github.com/shopspring/decimal" "golang.org/x/exp/constraints" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink/v2/core/utils" - bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) const ( diff --git a/core/chains/evm/client/erroring_node.go b/core/chains/evm/client/erroring_node.go index 21c4d269ea4..c33891728a7 100644 --- a/core/chains/evm/client/erroring_node.go +++ b/core/chains/evm/client/erroring_node.go @@ -5,7 +5,6 @@ import ( "math/big" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -132,7 +131,7 @@ func (e *erroringNode) State() NodeState { return NodeStateUnreachable } -func (e *erroringNode) StateAndLatest() (NodeState, int64, *utils.Big) { +func (e *erroringNode) StateAndLatest() (NodeState, int64, *big.Int) { return NodeStateUnreachable, -1, nil } diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index b1d477b1a29..912817afe48 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type TestNodePoolConfig struct { @@ -45,7 +44,7 @@ func NewClientWithTestNode(t *testing.T, nodePoolCfg config.NodePool, noNewHeads lggr := logger.TestLogger(t) n := NewNode(nodePoolCfg, noNewHeadsThreshold, lggr, *parsed, rpcHTTPURL, "eth-primary-0", id, chainID, 1) - n.(*node).setLatestReceived(0, utils.NewBigI(0)) + n.(*node).setLatestReceived(0, big.NewInt(0)) primaries := []Node{n} var sendonlys []SendOnlyNode diff --git a/core/chains/evm/client/node.go b/core/chains/evm/client/node.go index b3ce489cf50..5d0a0cb82c6 100644 --- a/core/chains/evm/client/node.go +++ b/core/chains/evm/client/node.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -90,7 +89,7 @@ type Node interface { // State returns NodeState State() NodeState // StateAndLatest returns NodeState with the latest received block number & total difficulty. - StateAndLatest() (state NodeState, blockNum int64, totalDifficulty *utils.Big) + StateAndLatest() (state NodeState, blockNum int64, totalDifficulty *big.Int) // Name is a unique identifier for this node. Name() string ChainID() *big.Int @@ -150,7 +149,7 @@ type node struct { state NodeState // Each node is tracking the last received head number and total difficulty stateLatestBlockNumber int64 - stateLatestTotalDifficulty *utils.Big + stateLatestTotalDifficulty *big.Int // Need to track subscriptions because closing the RPC does not (always?) // close the underlying subscription @@ -174,7 +173,7 @@ type node struct { // 1. see how many live nodes there are in total, so we can prevent the last alive node in a pool from being // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all. // 2. compare against the highest head (by number or difficulty) to ensure we don't fall behind too far. - nLiveNodes func() (count int, blockNumber int64, totalDifficulty *utils.Big) + nLiveNodes func() (count int, blockNumber int64, totalDifficulty *big.Int) } // NewNode returns a new *node as Node diff --git a/core/chains/evm/client/node_fsm.go b/core/chains/evm/client/node_fsm.go index 2d74512eac9..ab088a2a519 100644 --- a/core/chains/evm/client/node_fsm.go +++ b/core/chains/evm/client/node_fsm.go @@ -2,11 +2,10 @@ package client import ( "fmt" + "math/big" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -110,7 +109,7 @@ func (n *node) State() NodeState { return n.state } -func (n *node) StateAndLatest() (NodeState, int64, *utils.Big) { +func (n *node) StateAndLatest() (NodeState, int64, *big.Int) { n.stateMu.RLock() defer n.stateMu.RUnlock() return n.state, n.stateLatestBlockNumber, n.stateLatestTotalDifficulty @@ -182,7 +181,7 @@ func (n *node) transitionToInSync(fn func()) { // declareOutOfSync puts a node into OutOfSync state, disconnecting all current // clients and making it unavailable for use until back in-sync. -func (n *node) declareOutOfSync(isOutOfSync func(num int64, td *utils.Big) bool) { +func (n *node) declareOutOfSync(isOutOfSync func(num int64, td *big.Int) bool) { n.transitionToOutOfSync(func() { n.lfcLog.Errorw("RPC Node is out of sync", "nodeState", n.state) n.wg.Add(1) diff --git a/core/chains/evm/client/node_lifecycle.go b/core/chains/evm/client/node_lifecycle.go index 609d1522ea5..06f508611fd 100644 --- a/core/chains/evm/client/node_lifecycle.go +++ b/core/chains/evm/client/node_lifecycle.go @@ -4,12 +4,14 @@ import ( "context" "fmt" "math" + "math/big" "time" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -49,7 +51,7 @@ func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration { return utils.WithJitter(interval) } -func (n *node) setLatestReceived(blockNumber int64, totalDifficulty *utils.Big) { +func (n *node) setLatestReceived(blockNumber int64, totalDifficulty *big.Int) { n.stateMu.Lock() defer n.stateMu.Unlock() n.stateLatestBlockNumber = blockNumber @@ -213,13 +215,13 @@ func (n *node) aliveLoop() { continue } } - n.declareOutOfSync(func(num int64, td *utils.Big) bool { return num < highestReceivedBlockNumber }) + n.declareOutOfSync(func(num int64, td *big.Int) bool { return num < highestReceivedBlockNumber }) return } } } -func (n *node) isOutOfSync(num int64, td *utils.Big) (outOfSync bool) { +func (n *node) isOutOfSync(num int64, td *big.Int) (outOfSync bool) { outOfSync, _ = n.syncStatus(num, td) return } @@ -227,7 +229,7 @@ func (n *node) isOutOfSync(num int64, td *utils.Big) (outOfSync bool) { // syncStatus returns outOfSync true if num or td is more than SyncThresold behind the best node. // Always returns outOfSync false for SyncThreshold 0. // liveNodes is only included when outOfSync is true. -func (n *node) syncStatus(num int64, td *utils.Big) (outOfSync bool, liveNodes int) { +func (n *node) syncStatus(num int64, td *big.Int) (outOfSync bool, liveNodes int) { if n.nLiveNodes == nil { return // skip for tests } @@ -242,8 +244,8 @@ func (n *node) syncStatus(num int64, td *utils.Big) (outOfSync bool, liveNodes i case NodeSelectionMode_HighestHead, NodeSelectionMode_RoundRobin, NodeSelectionMode_PriorityLevel: return num < highest-int64(threshold), ln case NodeSelectionMode_TotalDifficulty: - bigThreshold := utils.NewBigI(int64(threshold)) - return td.Cmp(greatest.Sub(bigThreshold)) < 0, ln + bigThreshold := big.NewInt(int64(threshold)) + return td.Cmp(bigmath.Sub(greatest, bigThreshold)) < 0, ln default: panic("unrecognized NodeSelectionMode: " + mode) } @@ -255,7 +257,7 @@ const ( ) // outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status -func (n *node) outOfSyncLoop(isOutOfSync func(num int64, td *utils.Big) bool) { +func (n *node) outOfSyncLoop(isOutOfSync func(num int64, td *big.Int) bool) { defer n.wg.Done() { diff --git a/core/chains/evm/client/node_lifecycle_test.go b/core/chains/evm/client/node_lifecycle_test.go index 05b8af13ec5..3be4941d53c 100644 --- a/core/chains/evm/client/node_lifecycle_test.go +++ b/core/chains/evm/client/node_lifecycle_test.go @@ -16,7 +16,6 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func standardHandler(method string, _ gjson.Result) (resp testutils.JSONRPCResponse) { @@ -161,7 +160,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { } return }) - n.nLiveNodes = func() (int, int64, *utils.Big) { return 1, 0, nil } + n.nLiveNodes = func() (int, int64, *big.Int) { return 1, 0, nil } dial(t, n) defer func() { assert.NoError(t, n.Close()) }() @@ -308,7 +307,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { iN := NewNode(pollDisabledCfg, testutils.TestInterval, lggr, *s.WSURL(), nil, "test node", 42, testutils.FixtureChainID, 1) n := iN.(*node) - n.nLiveNodes = func() (int, int64, *utils.Big) { return 1, 0, nil } + n.nLiveNodes = func() (int, int64, *big.Int) { return 1, 0, nil } dial(t, n) defer func() { assert.NoError(t, n.Close()) }() @@ -353,7 +352,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { iN := NewNode(cfg, 0*time.Second, logger.TestLogger(t), *s.WSURL(), nil, "test node", 42, testutils.FixtureChainID, 1) n := iN.(*node) - n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { + n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { return 2, highestHead.Load(), nil } @@ -415,7 +414,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { iN := NewNode(cfg, 0*time.Second, logger.TestLogger(t), *s.WSURL(), nil, "test node", 42, testutils.FixtureChainID, 1) n := iN.(*node) - n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { + n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { return 2, highestHead.Load(), nil } @@ -474,7 +473,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { iN := NewNode(cfg, 0*time.Second, lggr, *s.WSURL(), nil, "test node", 42, testutils.FixtureChainID, 1) n := iN.(*node) - n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { + n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { return 1, highestHead.Load(), nil } @@ -521,7 +520,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { n.wg.Add(1) go func() { defer close(ch) - n.outOfSyncLoop(func(num int64, td *utils.Big) bool { return false }) + n.outOfSyncLoop(func(num int64, td *big.Int) bool { return false }) }() assert.NoError(t, n.Close()) testutils.WaitWithTimeout(t, ch, "expected outOfSyncLoop to exit") @@ -536,7 +535,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { n.wg.Add(1) - n.outOfSyncLoop(func(num int64, td *utils.Big) bool { return num == 0 }) + n.outOfSyncLoop(func(num int64, td *big.Int) bool { return num == 0 }) assert.Equal(t, NodeStateUnreachable, n.State()) }) @@ -565,7 +564,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { defer func() { assert.NoError(t, n.Close()) }() n.wg.Add(1) - go n.outOfSyncLoop(func(num int64, td *utils.Big) bool { return num == 0 }) + go n.outOfSyncLoop(func(num int64, td *big.Int) bool { return num == 0 }) testutils.WaitWithTimeout(t, chSubbed, "timed out waiting for initial subscription") @@ -612,7 +611,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { defer func() { assert.NoError(t, n.Close()) }() n.wg.Add(1) - go n.outOfSyncLoop(func(num int64, td *utils.Big) bool { return num < 43 }) + go n.outOfSyncLoop(func(num int64, td *big.Int) bool { return num < 43 }) testutils.WaitWithTimeout(t, chSubbed, "timed out waiting for initial subscription") @@ -661,7 +660,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { iN := NewNode(cfg, time.Second*0, lggr, *s.WSURL(), nil, "test node", 0, testutils.FixtureChainID, 1) n := iN.(*node) - n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *utils.Big) { + n.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { return 2, stall + int64(cfg.SyncThreshold()), nil } @@ -717,14 +716,14 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { iN := NewNode(cfg, testutils.TestInterval, logger.TestLogger(t), *s.WSURL(), nil, "test node", 42, testutils.FixtureChainID, 1) n := iN.(*node) - n.nLiveNodes = func() (int, int64, *utils.Big) { return 0, 0, nil } + n.nLiveNodes = func() (int, int64, *big.Int) { return 0, 0, nil } dial(t, n) n.setState(NodeStateOutOfSync) defer func() { assert.NoError(t, n.Close()) }() n.wg.Add(1) - go n.outOfSyncLoop(func(num int64, td *utils.Big) bool { return num == 0 }) + go n.outOfSyncLoop(func(num int64, td *big.Int) bool { return num == 0 }) testutils.WaitWithTimeout(t, chSubbed, "timed out waiting for initial subscription") diff --git a/core/chains/evm/client/node_selector_total_difficulty.go b/core/chains/evm/client/node_selector_total_difficulty.go index a368422e49f..2290f3e568c 100644 --- a/core/chains/evm/client/node_selector_total_difficulty.go +++ b/core/chains/evm/client/node_selector_total_difficulty.go @@ -1,8 +1,6 @@ package client -import ( - "github.com/smartcontractkit/chainlink/v2/core/utils" -) +import "math/big" type totalDifficultyNodeSelector []Node @@ -12,7 +10,7 @@ func NewTotalDifficultyNodeSelector(nodes []Node) NodeSelector { func (s totalDifficultyNodeSelector) Select() Node { // NodeNoNewHeadsThreshold may not be enabled, in this case all nodes have td == nil - var highestTD *utils.Big + var highestTD *big.Int var nodes []Node var aliveNodes []Node diff --git a/core/chains/evm/client/node_selector_total_difficulty_test.go b/core/chains/evm/client/node_selector_total_difficulty_test.go index d42a7461dee..486a421477e 100644 --- a/core/chains/evm/client/node_selector_total_difficulty_test.go +++ b/core/chains/evm/client/node_selector_total_difficulty_test.go @@ -1,11 +1,11 @@ package client_test import ( + "math/big" "testing" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/mocks" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" ) @@ -27,10 +27,10 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { node.On("StateAndLatest").Return(evmclient.NodeStateOutOfSync, int64(-1), nil) } else if i == 1 { // second node is alive - node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(7)) + node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(7)) } else { // third node is alive and best - node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(2), utils.NewBigI(8)) + node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(2), big.NewInt(8)) } node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -42,7 +42,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("stick to the same node", func(t *testing.T) { node := evmmocks.NewNode(t) // fourth node is alive (same as 3rd) - node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(2), utils.NewBigI(8)) + node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(2), big.NewInt(8)) node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -53,7 +53,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("another best node", func(t *testing.T) { node := evmmocks.NewNode(t) // fifth node is alive (better than 3rd and 4th) - node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), utils.NewBigI(11)) + node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), big.NewInt(11)) node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -87,7 +87,7 @@ func TestTotalDifficultyNodeSelector_None(t *testing.T) { node.On("StateAndLatest").Return(evmclient.NodeStateOutOfSync, int64(-1), nil) } else { // others are unreachable - node.On("StateAndLatest").Return(evmclient.NodeStateUnreachable, int64(1), utils.NewBigI(7)) + node.On("StateAndLatest").Return(evmclient.NodeStateUnreachable, int64(1), big.NewInt(7)) } nodes = append(nodes, node) } @@ -104,7 +104,7 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("same td and order", func(t *testing.T) { for i := 0; i < 3; i++ { node := evmmocks.NewNode(t) - node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(10)) + node.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(10)) node.On("Order").Return(int32(2)) nodes = append(nodes, node) } @@ -115,15 +115,15 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("same td but different order", func(t *testing.T) { node1 := evmmocks.NewNode(t) - node1.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), utils.NewBigI(10)) + node1.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), big.NewInt(10)) node1.On("Order").Return(int32(3)) node2 := evmmocks.NewNode(t) - node2.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), utils.NewBigI(10)) + node2.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), big.NewInt(10)) node2.On("Order").Return(int32(1)) node3 := evmmocks.NewNode(t) - node3.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), utils.NewBigI(10)) + node3.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(3), big.NewInt(10)) node3.On("Order").Return(int32(2)) nodes := []evmclient.Node{node1, node2, node3} @@ -134,15 +134,15 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("different td but same order", func(t *testing.T) { node1 := evmmocks.NewNode(t) - node1.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(10)) + node1.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(10)) node1.On("Order").Maybe().Return(int32(3)) node2 := evmmocks.NewNode(t) - node2.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(11)) + node2.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(11)) node2.On("Order").Maybe().Return(int32(3)) node3 := evmmocks.NewNode(t) - node3.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(12)) + node3.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(12)) node3.On("Order").Return(int32(3)) nodes := []evmclient.Node{node1, node2, node3} @@ -153,19 +153,19 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("different head and different order", func(t *testing.T) { node1 := evmmocks.NewNode(t) - node1.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(100)) + node1.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(100)) node1.On("Order").Maybe().Return(int32(4)) node2 := evmmocks.NewNode(t) - node2.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(110)) + node2.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(110)) node2.On("Order").Maybe().Return(int32(5)) node3 := evmmocks.NewNode(t) - node3.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(110)) + node3.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(110)) node3.On("Order").Maybe().Return(int32(1)) node4 := evmmocks.NewNode(t) - node4.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), utils.NewBigI(105)) + node4.On("StateAndLatest").Return(evmclient.NodeStateAlive, int64(1), big.NewInt(105)) node4.On("Order").Maybe().Return(int32(2)) nodes := []evmclient.Node{node1, node2, node3, node4} diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go index 289a402a1c6..429d51f326f 100644 --- a/core/chains/evm/client/pool.go +++ b/core/chains/evm/client/pool.go @@ -168,8 +168,8 @@ func (p *Pool) Dial(ctx context.Context) error { // nLiveNodes returns the number of currently alive nodes, as well as the highest block number and greatest total difficulty. // totalDifficulty will be 0 if all nodes return nil. -func (p *Pool) nLiveNodes() (nLiveNodes int, blockNumber int64, totalDifficulty *utils.Big) { - totalDifficulty = utils.NewBigI(0) +func (p *Pool) nLiveNodes() (nLiveNodes int, blockNumber int64, totalDifficulty *big.Int) { + totalDifficulty = big.NewInt(0) for _, n := range p.nodes { if s, num, td := n.StateAndLatest(); s == NodeStateAlive { nLiveNodes++ diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index e922715eb9c..71c4d55d76f 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -301,7 +301,7 @@ func (c *SimulatedBackendClient) SubscribeNewHead( case h := <-ch: var head *evmtypes.Head if h != nil { - head = &evmtypes.Head{Difficulty: (*utils.Big)(h.Difficulty), Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: utils.NewBig(c.chainId)} + head = &evmtypes.Head{Difficulty: h.Difficulty, Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: utils.NewBig(c.chainId)} lastHead = head } select { diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index b6f34ab87a5..d176e2a9523 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/services" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink/v2/common/config" commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" @@ -22,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) // EvmFeeEstimator provides a unified interface that wraps EvmEstimator and can determine if legacy or dynamic fee estimation should be used diff --git a/core/chains/evm/mocks/node.go b/core/chains/evm/mocks/node.go index 85db2e0ca0f..69020d411f4 100644 --- a/core/chains/evm/mocks/node.go +++ b/core/chains/evm/mocks/node.go @@ -19,8 +19,6 @@ import ( rpc "github.com/ethereum/go-ethereum/rpc" types "github.com/ethereum/go-ethereum/core/types" - - utils "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Node is an autogenerated mock type for the Node type @@ -519,13 +517,13 @@ func (_m *Node) State() client.NodeState { } // StateAndLatest provides a mock function with given fields: -func (_m *Node) StateAndLatest() (client.NodeState, int64, *utils.Big) { +func (_m *Node) StateAndLatest() (client.NodeState, int64, *big.Int) { ret := _m.Called() var r0 client.NodeState var r1 int64 - var r2 *utils.Big - if rf, ok := ret.Get(0).(func() (client.NodeState, int64, *utils.Big)); ok { + var r2 *big.Int + if rf, ok := ret.Get(0).(func() (client.NodeState, int64, *big.Int)); ok { return rf() } if rf, ok := ret.Get(0).(func() client.NodeState); ok { @@ -540,11 +538,11 @@ func (_m *Node) StateAndLatest() (client.NodeState, int64, *utils.Big) { r1 = ret.Get(1).(int64) } - if rf, ok := ret.Get(2).(func() *utils.Big); ok { + if rf, ok := ret.Get(2).(func() *big.Int); ok { r2 = rf() } else { if ret.Get(2) != nil { - r2 = ret.Get(2).(*utils.Big) + r2 = ret.Get(2).(*big.Int) } } diff --git a/core/chains/evm/txmgr/transmitchecker.go b/core/chains/evm/txmgr/transmitchecker.go index eb6edd3f587..8cd0f2355d7 100644 --- a/core/chains/evm/txmgr/transmitchecker.go +++ b/core/chains/evm/txmgr/transmitchecker.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -22,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/utils" - bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) type ( diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index 83b90b4d539..314180a7e98 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -39,8 +39,8 @@ type Head struct { ReceiptsRoot common.Hash TransactionsRoot common.Hash StateRoot common.Hash - Difficulty *utils.Big - TotalDifficulty *utils.Big + Difficulty *big.Int + TotalDifficulty *big.Int } var _ commontypes.Head[common.Hash] = &Head{} @@ -80,7 +80,7 @@ func (h *Head) GetTimestamp() time.Time { return h.Timestamp } -func (h *Head) BlockDifficulty() *utils.Big { +func (h *Head) BlockDifficulty() *big.Int { return h.Difficulty } @@ -283,8 +283,8 @@ func (h *Head) UnmarshalJSON(bs []byte) error { h.ReceiptsRoot = jsonHead.ReceiptsRoot h.TransactionsRoot = jsonHead.TransactionsRoot h.StateRoot = jsonHead.StateRoot - h.Difficulty = utils.NewBig(jsonHead.Difficulty.ToInt()) - h.TotalDifficulty = utils.NewBig(jsonHead.TotalDifficulty.ToInt()) + h.Difficulty = jsonHead.Difficulty.ToInt() + h.TotalDifficulty = jsonHead.TotalDifficulty.ToInt() return nil } diff --git a/core/utils/big.go b/core/utils/big.go index 22cd8e64e55..69fab223de7 100644 --- a/core/utils/big.go +++ b/core/utils/big.go @@ -8,8 +8,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes" - bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" ) const base10 = 10 From 59fef6c73059d783bcaed7423be9a2afc46a93c4 Mon Sep 17 00:00:00 2001 From: Dimitris Date: Mon, 27 Nov 2023 19:10:21 +0200 Subject: [PATCH 2/5] Fix headtracker mock head --- common/headtracker/types/mocks/head.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/common/headtracker/types/mocks/head.go b/common/headtracker/types/mocks/head.go index 1de1f78de8c..79c483c9978 100644 --- a/common/headtracker/types/mocks/head.go +++ b/common/headtracker/types/mocks/head.go @@ -3,13 +3,13 @@ package mocks import ( - time "time" + big "math/big" mock "github.com/stretchr/testify/mock" - types "github.com/smartcontractkit/chainlink/v2/common/types" + time "time" - utils "github.com/smartcontractkit/chainlink/v2/core/utils" + types "github.com/smartcontractkit/chainlink/v2/common/types" ) // Head is an autogenerated mock type for the Head type @@ -18,15 +18,15 @@ type Head[BLOCK_HASH types.Hashable, CHAIN_ID types.ID] struct { } // BlockDifficulty provides a mock function with given fields: -func (_m *Head[BLOCK_HASH, CHAIN_ID]) BlockDifficulty() *utils.Big { +func (_m *Head[BLOCK_HASH, CHAIN_ID]) BlockDifficulty() *big.Int { ret := _m.Called() - var r0 *utils.Big - if rf, ok := ret.Get(0).(func() *utils.Big); ok { + var r0 *big.Int + if rf, ok := ret.Get(0).(func() *big.Int); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*utils.Big) + r0 = ret.Get(0).(*big.Int) } } From d5b3da0fcbf3fb82bedae89c0e48b9c02d65a4e1 Mon Sep 17 00:00:00 2001 From: Dimitris Date: Tue, 28 Nov 2023 12:27:57 +0200 Subject: [PATCH 3/5] Remove EsnureClosed --- common/txmgr/txmgr.go | 12 +++++++----- core/utils/utils.go | 11 ----------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index b49c2b72f15..7b861920101 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -389,12 +389,14 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() // be in an Unstarted state here, if execReset exited early. // // In this case, we don't care about stopping them since they are - // already "stopped", hence the usage of utils.EnsureClosed. - if err := utils.EnsureClosed(b.broadcaster); err != nil { - b.logger.Panicw(fmt.Sprintf("Failed to Close Broadcaster: %v", err), "err", err) + // already "stopped". + err := b.broadcaster.Close() + if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { + b.logger.Errorw(fmt.Sprintf("Failed to Close Broadcaster: %v", err), "err", err) } - if err := utils.EnsureClosed(b.confirmer); err != nil { - b.logger.Panicw(fmt.Sprintf("Failed to Close Confirmer: %v", err), "err", err) + err = b.confirmer.Close() + if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { + b.logger.Errorw(fmt.Sprintf("Failed to Close Confirmer: %v", err), "err", err) } return case <-keysChanged: diff --git a/core/utils/utils.go b/core/utils/utils.go index 69597fb9e4a..0df280775b5 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -9,7 +9,6 @@ import ( "encoding/json" "errors" "fmt" - "io" "math" "math/big" mrand "math/rand" @@ -771,16 +770,6 @@ var ( // Deprecated: use services.StateMachine type StartStopOnce = services.StateMachine -// EnsureClosed closes the io.Closer, returning nil if it was already -// closed or not started yet -func EnsureClosed(c io.Closer) error { - err := c.Close() - if errors.Is(err, ErrAlreadyStopped) || errors.Is(err, ErrCannotStopUnstarted) { - return nil - } - return err -} - // WithJitter adds +/- 10% to a duration func WithJitter(d time.Duration) time.Duration { // #nosec From ea10d90a40b10af18b2b7a8c19c039c47a99c5e7 Mon Sep 17 00:00:00 2001 From: Dimitris Date: Tue, 28 Nov 2023 13:18:16 +0200 Subject: [PATCH 4/5] Fix mock heads --- common/types/mocks/head.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go index 82fd910a08b..99d2a265b44 100644 --- a/common/types/mocks/head.go +++ b/common/types/mocks/head.go @@ -3,13 +3,12 @@ package mocks import ( + big "math/big" time "time" mock "github.com/stretchr/testify/mock" types "github.com/smartcontractkit/chainlink/v2/common/types" - - utils "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Head is an autogenerated mock type for the Head type @@ -18,15 +17,15 @@ type Head[BLOCK_HASH types.Hashable] struct { } // BlockDifficulty provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) BlockDifficulty() *utils.Big { +func (_m *Head[BLOCK_HASH]) BlockDifficulty() *big.Int { ret := _m.Called() - var r0 *utils.Big - if rf, ok := ret.Get(0).(func() *utils.Big); ok { + var r0 *big.Int + if rf, ok := ret.Get(0).(func() *big.Int); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*utils.Big) + r0 = ret.Get(0).(*big.Int) } } From 9d28014d16155feabf292aa562cfc93b06dd35e6 Mon Sep 17 00:00:00 2001 From: Dimitris Date: Wed, 29 Nov 2023 13:57:10 +0200 Subject: [PATCH 5/5] Fix Tracker close on txm --- common/txmgr/txmgr.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 2c6f9c90bca..0a50bb66385 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -410,8 +410,9 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { b.logger.Errorw(fmt.Sprintf("Failed to Close Confirmer: %v", err), "err", err) } - if err := utils.EnsureClosed(b.tracker); err != nil { - b.logger.Panicw(fmt.Sprintf("Failed to Close Tracker: %v", err), "err", err) + err = b.tracker.Close() + if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { + b.logger.Errorw(fmt.Sprintf("Failed to Close Tracker: %v", err), "err", err) } return case <-keysChanged: