Skip to content

Commit cab6932

Browse files
authored
Merge branch 'main' into lli/integrate-rpc-metric
2 parents ddabde5 + be2bc6b commit cab6932

17 files changed

Lines changed: 575 additions & 66 deletions

.github/workflows/api-diff.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Analyze API Changes
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
changed-modules:
11+
name: Determine Changed Modules
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
pull-requests: read
16+
outputs:
17+
modules-json: ${{ steps.changed-modules.outputs.modules-json }}
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v6
21+
with:
22+
fetch-depth: 0
23+
24+
- name: Changed modules
25+
id: changed-modules
26+
uses: smartcontractkit/.github/actions/changed-modules-go@changed-modules-go/v1
27+
with:
28+
file-patterns: |
29+
**/*.go
30+
**/go.mod
31+
**/go.sum
32+
module-patterns: |
33+
**
34+
35+
analyze-api-changes:
36+
if: ${{ needs.changed-modules.outputs.modules-json != '[]' }}
37+
name: Analyze (${{ matrix.module }})
38+
runs-on: ubuntu-latest
39+
needs: changed-modules
40+
permissions:
41+
pull-requests: write
42+
contents: read
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
module: ${{ fromJson(needs.changed-modules.outputs.modules-json) }}
47+
steps:
48+
- name: Checkout the repository
49+
uses: actions/checkout@v6
50+
with:
51+
fetch-depth: 0
52+
53+
- name: Set up Go
54+
uses: actions/setup-go@v5
55+
with:
56+
go-version-file: ${{ matrix.module }}/go.mod
57+
cache: false
58+
59+
- uses: smartcontractkit/.github/actions/apidiff-go@apidiff-go/v2
60+
env:
61+
GITHUB_TOKEN: ${{ github.token }}
62+
with:
63+
module-directory: ${{ matrix.module }}
64+
enforce-compatible: false
65+
post-comment: true

multinode/config/config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type MultiNode struct {
3434
FinalityDepth *uint32
3535
FinalityTagEnabled *bool
3636
FinalizedBlockOffset *uint32
37+
38+
// Finalized State Availability Check
39+
FinalizedStateCheckFailureThreshold *uint32
3740
}
3841

3942
func (c *MultiNodeConfig) Enabled() bool {
@@ -94,6 +97,10 @@ func (c *MultiNodeConfig) FinalityTagEnabled() bool { return *c.MultiNode.Finali
9497

9598
func (c *MultiNodeConfig) FinalizedBlockOffset() uint32 { return *c.MultiNode.FinalizedBlockOffset }
9699

100+
func (c *MultiNodeConfig) FinalizedStateCheckFailureThreshold() uint32 {
101+
return *c.MultiNode.FinalizedStateCheckFailureThreshold
102+
}
103+
97104
func (c *MultiNodeConfig) SetFrom(f *MultiNodeConfig) {
98105
if f.MultiNode.Enabled != nil {
99106
c.MultiNode.Enabled = f.MultiNode.Enabled
@@ -150,4 +157,9 @@ func (c *MultiNodeConfig) SetFrom(f *MultiNodeConfig) {
150157
if f.MultiNode.FinalizedBlockOffset != nil {
151158
c.MultiNode.FinalizedBlockOffset = f.MultiNode.FinalizedBlockOffset
152159
}
160+
161+
// Finalized State Availability Check
162+
if f.MultiNode.FinalizedStateCheckFailureThreshold != nil {
163+
c.MultiNode.FinalizedStateCheckFailureThreshold = f.MultiNode.FinalizedStateCheckFailureThreshold
164+
}
153165
}

multinode/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/pkg/errors v0.9.1
88
github.com/prometheus/client_model v0.6.2
99
github.com/smartcontractkit/chainlink-common v0.10.1-0.20260305114348-b8bbac30bfc7
10-
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260326180413-c69f27e37a13
10+
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260310180305-3ee91a6d9ae9
1111
github.com/stretchr/testify v1.11.1
1212
go.uber.org/zap v1.27.1
1313
)

multinode/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ github.com/smartcontractkit/chainlink-common v0.10.1-0.20260305114348-b8bbac30bf
8080
github.com/smartcontractkit/chainlink-common v0.10.1-0.20260305114348-b8bbac30bfc7/go.mod h1:0ghbAr7tRO0tT5ZqBXhOyzgUO37tNNe33Yn0hskauVM=
8181
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg=
8282
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY=
83-
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260326180413-c69f27e37a13 h1:Homq1KxVUoL1rEtEv1N+BL0JJdMdQcDBnJw53vn+/qY=
84-
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260326180413-c69f27e37a13/go.mod h1:HG/aei0MgBOpsyRLexdKGtOUO8yjSJO3iUu0Uu8KBm4=
83+
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260310180305-3ee91a6d9ae9 h1:GK+2aFpW/Z5ZnMGCa9NU6o7LKHQ/9xJVZx2yMAMudnc=
84+
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260310180305-3ee91a6d9ae9/go.mod h1:HG/aei0MgBOpsyRLexdKGtOUO8yjSJO3iUu0Uu8KBm4=
8585
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9Mww35LrufCdM9wtS9yVi/rEWGI1UnjHbcKKU0nVY=
8686
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU=
8787
github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d h1:LokA9PoCNb8mm8mDT52c3RECPMRsGz1eCQORq+J3n74=

multinode/mock_node_metrics_test.go

Lines changed: 68 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

multinode/mock_pool_chain_info_provider_test.go

Lines changed: 15 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

multinode/mock_rpc_client_test.go

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

multinode/multi_node.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func (c *MultiNode[CHAIN_ID, RPC]) selectNode(ctx context.Context) (node Node[CH
226226
return nil, err
227227
}
228228

229-
c.lggr.Debugw("Switched to a new active node due to prev node heath issues", "prevNode", prevNodeName, "newNode", c.activeNode.String())
229+
c.lggr.Debugw("Switched to a new active node due to prev node health issues", "prevNode", prevNodeName, "newNode", c.activeNode.String())
230230
return c.activeNode, err
231231
}
232232

@@ -254,17 +254,19 @@ func (c *MultiNode[CHAIN_ID, RPC]) awaitNodeSelection(ctx context.Context) (Node
254254
}
255255
}
256256

257-
// LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being marked as out-of-sync.
258-
// Return highest ChainInfo most recently received by the alive nodes.
257+
// LatestChainInfo returns the number of alive nodes in the pool (excluding the node identified by callerName
258+
// from the count) and the highest ChainInfo most recently received by alive nodes.
259259
// E.g. If Node A's the most recent block is 10 and highest 15 and for Node B it's - 12 and 14. This method will return 12.
260-
func (c *MultiNode[CHAIN_ID, RPC]) LatestChainInfo() (int, ChainInfo) {
260+
func (c *MultiNode[CHAIN_ID, RPC]) LatestChainInfo(callerName string) (int, ChainInfo) {
261261
var nLiveNodes int
262262
ch := ChainInfo{
263263
TotalDifficulty: big.NewInt(0),
264264
}
265265
for _, n := range c.primaryNodes {
266266
if s, nodeChainInfo := n.StateAndLatest(); s == nodeStateAlive {
267-
nLiveNodes++
267+
if n.Name() != callerName {
268+
nLiveNodes++
269+
}
268270
ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber)
269271
ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber)
270272
ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty)

multinode/multi_node_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,14 +602,15 @@ func TestMultiNode_ChainInfo(t *testing.T) {
602602
for i := range testCases {
603603
tc := testCases[i]
604604
t.Run(tc.Name, func(t *testing.T) {
605-
for _, params := range tc.NodeParams {
605+
for i, params := range tc.NodeParams {
606606
node := newMockNode[ID, multiNodeRPCClient](t)
607607
mn.primaryNodes = append(mn.primaryNodes, node)
608+
node.On("Name").Return(fmt.Sprintf("node_%d", i)).Maybe()
608609
node.On("StateAndLatest").Return(params.State, params.LatestChainInfo)
609610
node.On("HighestUserObservations").Return(params.HighestUserObservations)
610611
}
611612

612-
nNodes, latestChainInfo := mn.LatestChainInfo()
613+
nNodes, latestChainInfo := mn.LatestChainInfo("")
613614
assert.Equal(t, tc.ExpectedNLiveNodes, nNodes)
614615
assert.Equal(t, tc.ExpectedLatestChainInfo, latestChainInfo)
615616

0 commit comments

Comments
 (0)