Skip to content

Commit e773a41

Browse files
Merge branch 'main' into multinode-outofsync
2 parents a23bbb1 + c69f27e commit e773a41

16 files changed

Lines changed: 694 additions & 389 deletions

File tree

.github/workflows/golangci_lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ jobs:
3636
go-version-file: ${{ matrix.module }}/go.mod
3737

3838
- name: Run golangci-lint for ${{ matrix.module }}
39-
uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1
39+
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
4040
with:
4141
args: --config=${{ github.workspace }}/.golangci.yml
4242
only-new-issues: true
43-
version: v1.64.2
43+
version: v2.10.1
4444
working-directory: ${{ matrix.module }}
4545

4646
# Per https://github.com/orgs/community/discussions/4324, we need to capture a matrix-job result

.golangci.yml

Lines changed: 104 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
run:
2-
timeout: 15m0s
1+
version: "2"
32
linters:
43
enable:
54
- containedctx
@@ -10,7 +9,6 @@ linters:
109
- fatcontext
1110
- ginkgolinter
1211
- gocritic
13-
- goimports
1412
- gosec
1513
- loggercheck
1614
- mirror
@@ -25,96 +23,106 @@ linters:
2523
- testifylint
2624
- unconvert
2725
- whitespace
28-
linters-settings:
29-
exhaustive:
30-
default-signifies-exhaustive: true
31-
goimports:
32-
local-prefixes: github.com/smartcontractkit/chainlink
33-
gosec:
34-
excludes:
35-
- G101
36-
- G104
37-
# - G204
38-
# - G304
39-
# - G404
40-
govet:
41-
enable:
42-
- shadow
43-
revive:
44-
confidence: 0.8
45-
rules:
46-
- name: blank-imports
47-
- name: context-as-argument
48-
- name: context-keys-type
49-
- name: dot-imports
50-
- name: error-return
51-
- name: error-strings
52-
- name: error-naming
53-
- name: exported
54-
- name: if-return
55-
- name: increment-decrement
56-
- name: var-naming
57-
- name: var-declaration
58-
- name: package-comments
59-
- name: range
60-
- name: receiver-naming
61-
- name: time-naming
62-
# - name: unexported-return
63-
- name: indent-error-flow
64-
- name: errorf
65-
- name: empty-block
66-
- name: superfluous-else
67-
# - name: unused-parameter
68-
- name: unreachable-code
69-
- name: redefines-builtin-id
70-
- name: waitgroup-by-value
71-
- name: unconditional-recursion
72-
- name: struct-tag
73-
# - name: string-format
74-
- name: string-of-int
75-
- name: range-val-address
76-
- name: range-val-in-closure
77-
- name: modifies-value-receiver
78-
- name: modifies-parameter
79-
- name: identical-branches
80-
- name: get-return
81-
# - name: flag-parameter
82-
- name: early-return
83-
- name: defer
84-
- name: constant-logical-expr
85-
# - name: confusing-naming
86-
# - name: confusing-results
87-
- name: bool-literal-in-expr
88-
- name: atomic
89-
depguard:
90-
rules:
91-
main:
92-
list-mode: lax
93-
deny:
94-
- pkg: cosmossdk.io/errors
95-
desc: Use the standard library instead
96-
- pkg: github.com/gofrs/uuid
97-
desc: Use github.com/google/uuid instead
98-
- pkg: github.com/jackc/pgx3
99-
desc: Use github.com/jackc/pgx4 instead
100-
- pkg: github.com/jackc/pgx5
101-
desc: Use github.com/jackc/pgx4 instead
102-
- pkg: github.com/satori/go.uuid
103-
desc: Use github.com/google/uuid instead
104-
- pkg: github.com/test-go/testify/assert
105-
desc: Use github.com/stretchr/testify/assert instead
106-
- pkg: github.com/test-go/testify/mock
107-
desc: Use github.com/stretchr/testify/mock instead
108-
- pkg: github.com/test-go/testify/require
109-
desc: Use github.com/stretchr/testify/require instead
110-
# TODO https://smartcontract-it.atlassian.net/browse/BCI-2589
111-
# - pkg: go.uber.org/multierr
112-
# desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join
113-
- pkg: gopkg.in/guregu/null.v1
114-
desc: Use gopkg.in/guregu/null.v4 instead
115-
- pkg: gopkg.in/guregu/null.v2
116-
desc: Use gopkg.in/guregu/null.v4 instead
117-
- pkg: gopkg.in/guregu/null.v3
118-
desc: Use gopkg.in/guregu/null.v4 instead
119-
- pkg: github.com/go-gorm/gorm
120-
desc: Use github.com/jmoiron/sqlx directly instead
26+
settings:
27+
depguard:
28+
rules:
29+
main:
30+
list-mode: lax
31+
deny:
32+
- pkg: cosmossdk.io/errors
33+
desc: Use the standard library instead
34+
- pkg: github.com/gofrs/uuid
35+
desc: Use github.com/google/uuid instead
36+
- pkg: github.com/jackc/pgx3
37+
desc: Use github.com/jackc/pgx4 instead
38+
- pkg: github.com/jackc/pgx5
39+
desc: Use github.com/jackc/pgx4 instead
40+
- pkg: github.com/satori/go.uuid
41+
desc: Use github.com/google/uuid instead
42+
- pkg: github.com/test-go/testify/assert
43+
desc: Use github.com/stretchr/testify/assert instead
44+
- pkg: github.com/test-go/testify/mock
45+
desc: Use github.com/stretchr/testify/mock instead
46+
- pkg: github.com/test-go/testify/require
47+
desc: Use github.com/stretchr/testify/require instead
48+
- pkg: gopkg.in/guregu/null.v1
49+
desc: Use gopkg.in/guregu/null.v4 instead
50+
- pkg: gopkg.in/guregu/null.v2
51+
desc: Use gopkg.in/guregu/null.v4 instead
52+
- pkg: gopkg.in/guregu/null.v3
53+
desc: Use gopkg.in/guregu/null.v4 instead
54+
- pkg: github.com/go-gorm/gorm
55+
desc: Use github.com/jmoiron/sqlx directly instead
56+
exhaustive:
57+
default-signifies-exhaustive: true
58+
gosec:
59+
excludes:
60+
- G101
61+
- G104
62+
govet:
63+
enable:
64+
- shadow
65+
revive:
66+
confidence: 0.8
67+
rules:
68+
- name: blank-imports
69+
- name: context-as-argument
70+
- name: context-keys-type
71+
- name: dot-imports
72+
- name: error-return
73+
- name: error-strings
74+
- name: error-naming
75+
- name: exported
76+
- name: if-return
77+
- name: increment-decrement
78+
- name: var-naming
79+
- name: var-declaration
80+
- name: package-comments
81+
- name: range
82+
- name: receiver-naming
83+
- name: time-naming
84+
- name: indent-error-flow
85+
- name: errorf
86+
- name: empty-block
87+
- name: superfluous-else
88+
- name: unreachable-code
89+
- name: redefines-builtin-id
90+
- name: waitgroup-by-value
91+
- name: unconditional-recursion
92+
- name: struct-tag
93+
- name: string-of-int
94+
- name: range-val-address
95+
- name: range-val-in-closure
96+
- name: modifies-value-receiver
97+
- name: modifies-parameter
98+
- name: identical-branches
99+
- name: get-return
100+
- name: early-return
101+
- name: defer
102+
- name: constant-logical-expr
103+
- name: bool-literal-in-expr
104+
- name: atomic
105+
exclusions:
106+
generated: lax
107+
presets:
108+
- comments
109+
- common-false-positives
110+
- legacy
111+
- std-error-handling
112+
paths:
113+
- third_party$
114+
- builtin$
115+
- examples$
116+
formatters:
117+
enable:
118+
- goimports
119+
settings:
120+
goimports:
121+
local-prefixes:
122+
- github.com/smartcontractkit/chainlink
123+
exclusions:
124+
generated: lax
125+
paths:
126+
- third_party$
127+
- builtin$
128+
- examples$

chains/txmgr/broadcaster.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) closeInternal()
228228
return nil
229229
}
230230

231+
func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) SetEnabledAddresses(addrs []ADDR) {
232+
eb.enabledAddresses = addrs
233+
}
234+
231235
func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) SetResumeCallback(callback ResumeCallback) {
232236
eb.resumeCallback = callback
233237
}
@@ -240,6 +244,10 @@ func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) HealthReport() m
240244
return map[string]error{eb.Name(): eb.Healthy()}
241245
}
242246

247+
func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) Ready() error {
248+
return eb.StateMachine.Ready()
249+
}
250+
243251
// Trigger forces the monitor for a particular address to recheck for new txes
244252
// Logs error and does nothing if address was not registered on startup
245253
func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) Trigger(addr ADDR) {
@@ -463,8 +471,8 @@ func (eb *Broadcaster[CID, HEAD, ADDR, THASH, BHASH, SEQ, FEE]) handleInProgress
463471
}
464472

465473
lgr := etx.GetLogger(logger.With(eb.lggr, "fee", attempt.TxFee))
466-
lgr.Infow("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "meta", etx.Meta, "feeLimit", attempt.ChainSpecificFeeLimit, "callerProvidedFeeLimit", etx.FeeLimit, "attempt", attempt, "etx", etx)
467474
errType, err := eb.client.SendTransactionReturnCode(ctx, etx, attempt, lgr)
475+
eb.lggr.Infow("Broadcasted transaction", "txHash", attempt.Hash, "transactionLifecycleID", etx.GetTransactionLifecycleID(lgr), "attempt", attempt, "etxID", etx.ID, "etx", etx, "errType", errType, "err", err)
468476

469477
// The validation below is only applicable to Hedera because it has instant finality and a unique sequence behavior
470478
if eb.chainType == hederaChainType {

chains/txmgr/confirmer.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) closeInternal()
169169
return nil
170170
}
171171

172+
func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) Deliver(head HEAD) {
173+
ec.mb.Deliver(head)
174+
}
175+
176+
func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) SetEnabledAddresses(addrs []ADDR) {
177+
ec.enabledAddresses = addrs
178+
}
179+
172180
func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) SetResumeCallback(callback ResumeCallback) {
173181
ec.resumeCallback = callback
174182
}
@@ -181,6 +189,10 @@ func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) HealthReport()
181189
return map[string]error{ec.Name(): ec.Healthy()}
182190
}
183191

192+
func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) Ready() error {
193+
return ec.StateMachine.Ready()
194+
}
195+
184196
func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) runLoop() {
185197
defer ec.wg.Done()
186198
ctx, cancel := ec.stopCh.NewCtx()
@@ -347,6 +359,7 @@ func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) ProcessIncluded
347359
continue
348360
}
349361
confirmedTxIDs = append(confirmedTxIDs, tx.ID)
362+
ec.lggr.Infow("Transaction confirmed", "etxID", tx.ID, "transactionLifecycleID", tx.GetTransactionLifecycleID(ec.lggr))
350363
observeUntilTxConfirmed(ctx, ec.metrics, tx, head)
351364
}
352365
// Mark the transactions included on-chain with a purge attempt as fatal error with the terminally stuck error message
@@ -796,12 +809,12 @@ func (ec *Confirmer[CID, HEAD, ADDR, THASH, BHASH, R, SEQ, FEE]) ForceRebroadcas
796809
continue
797810
}
798811
attempt.Tx = *etx // for logging
799-
ec.lggr.Debugw("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", attempt.ChainSpecificFeeLimit, "callerProvidedFeeLimit", etx.FeeLimit, "attempt", attempt)
800-
if errCode, err := ec.client.SendTransactionReturnCode(ctx, *etx, attempt, ec.lggr); errCode != multinode.Successful && err != nil {
801-
ec.lggr.Errorw(fmt.Sprintf("ForceRebroadcast: failed to rebroadcast tx %v with sequence %v, gas limit %v, and caller provided fee Limit %v : %s", etx.ID, *etx.Sequence, attempt.ChainSpecificFeeLimit, etx.FeeLimit, err.Error()), "err", err, "fee", attempt.TxFee)
802-
continue
812+
errType, err := ec.client.SendTransactionReturnCode(ctx, *etx, attempt, ec.lggr)
813+
if errType == multinode.Successful || errType == multinode.TransactionAlreadyKnown {
814+
ec.lggr.Infow("ForceRebroadcast: Broadcasted transaction", "txHash", attempt.Hash, "transactionLifecycleID", etx.GetTransactionLifecycleID(ec.lggr), "attempt", attempt, "etxID", etx.ID, "etx", etx, "errType", errType, "err", err)
815+
} else {
816+
ec.lggr.Errorw("ForceRebroadcast: Broadcasted transaction", "txHash", attempt.Hash, "transactionLifecycleID", etx.GetTransactionLifecycleID(ec.lggr), "attempt", attempt, "etxID", etx.ID, "etx", etx, "errType", errType, "err", err)
803817
}
804-
ec.lggr.Infof("ForceRebroadcast: successfully rebroadcast tx %v with hash: 0x%x", etx.ID, attempt.Hash)
805818
}
806819
}
807820
return nil

chains/txmgr/tracker.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) Close() error {
100100
})
101101
}
102102

103+
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) Name() string {
104+
return tr.lggr.Name()
105+
}
106+
107+
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) HealthReport() map[string]error {
108+
return map[string]error{tr.Name(): tr.Healthy()}
109+
}
110+
103111
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) closeInternal() error {
104112
tr.initSync.Lock()
105113
defer tr.initSync.Unlock()
@@ -163,6 +171,10 @@ func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) runLoop(ctx context.Con
163171
}
164172
}
165173

174+
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) Deliver(num int64) {
175+
tr.mb.Deliver(num)
176+
}
177+
166178
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) GetAbandonedAddresses() []ADDR {
167179
tr.lock.Lock()
168180
defer tr.lock.Unlock()
@@ -187,7 +199,7 @@ func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) IsStarted() bool {
187199
return tr.isStarted
188200
}
189201

190-
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) getEnabledAddresses() []ADDR {
202+
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) GetEnabledAddresses() []ADDR {
191203
tr.lock.RLock()
192204
defer tr.lock.RUnlock()
193205
return slices.Collect(maps.Keys(tr.enabledAddrs))
@@ -206,12 +218,12 @@ func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) ensureEnabledAddresses(
206218
if err != nil {
207219
return fmt.Errorf("failed to get enabled addresses for chain: %w", err)
208220
}
209-
tr.setEnabledAddresses(enabledAddrs)
221+
tr.SetEnabledAddresses(enabledAddrs)
210222
return nil
211223
}
212224

213-
// setEnabledAddresses sets enabled addresses. Caller must hold tr.lock, or the Tracker must be unstarted (pre-startInternal, or post-closeInternal).
214-
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) setEnabledAddresses(enabledAddrs []ADDR) {
225+
// SetEnabledAddresses sets enabled addresses. Caller must hold tr.lock, or the Tracker must be unstarted (pre-startInternal, or post-closeInternal).
226+
func (tr *Tracker[CID, ADDR, THASH, BHASH, R, SEQ, FEE]) SetEnabledAddresses(enabledAddrs []ADDR) {
215227
if len(enabledAddrs) == 0 {
216228
tr.lggr.Warnf("enabled address list is empty")
217229
}

0 commit comments

Comments
 (0)