Skip to content

Add TXMv2 fixes - #540

Merged
dimriou merged 11 commits into
developfrom
oev-1709_txmv2_fixes
Sep 3, 2026
Merged

Add TXMv2 fixes#540
dimriou merged 11 commits into
developfrom
oev-1709_txmv2_fixes

Conversation

@dimriou

@dimriou dimriou commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

This PR:

  • Fixes nonce initialization
  • Optimizes pending nonce check during initial transmission.
  • Fixes an edge case with MetaClient.
  • Cleanup

Best if it gets merged after the StuckTxDetection fixes:

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

⚠️ API Diff Results - github.com/smartcontractkit/chainlink-evm

⚠️ Breaking Changes (3)

pkg/txm (1)
  • NewTxm — Type changed:
func(
  github.com/smartcontractkit/chainlink-common/pkg/logger.Logger, 
  *math/big.Int, 
  Client, 
  AttemptBuilder, 
  TxStore, 
  StuckTxDetector, 
  Config, 
  - github.com/smartcontractkit/chainlink-evm/pkg/keys.AddressLister, 
  + Keystore, 
  ErrorHandler, 
  Metrics
)
*Txm
pkg/txm.Keystore (2)
  • EnabledAddresses — ➕ Added

  • EnabledAddressesForChain — 🗑️ Removed


📄 View full apidiff report

Base automatically changed from oev-1708_fix_stuck_tx_detector to develop September 1, 2026 16:16
@dimriou
dimriou force-pushed the oev-1709_txmv2_fixes branch from 11488b8 to adafa6a Compare September 2, 2026 09:56
@dimriou
dimriou marked this pull request as ready for review September 2, 2026 10:35
@dimriou
dimriou requested review from a team as code owners September 2, 2026 10:35
Copilot AI lite review requested due to automatic review settings September 2, 2026 10:35

This comment was marked as off-topic.

@dimriou
dimriou enabled auto-merge (squash) September 2, 2026 11:03
Comment thread pkg/txm/txm.go Outdated
Comment on lines +256 to +259
broadcastTimer.Reset(broadcastWithBackoff.Duration())
} else {
broadcastWithBackoff.Reset()
broadcastCh = time.After(timeutil.JitterPct(0.1).Apply(broadcastInterval))
broadcastTimer.Reset(timeutil.JitterPct(0.1).Apply(broadcastInterval))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're at it, maybe add a comment about the reason for doing this? Kinda hard to understand why

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This simply re-uses a single timer instead of creating a new one each time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, but from reading it it's hard to see the reason for the timer and why we reset it with a duration in one place while resetting it with the broadcast interval in the other place

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we got at it, I moved around a few things to make the loop method cleaner, including the backoff mechanism and why it's there.

Comment thread pkg/txm/txm.go Outdated
if tx.LastBroadcastAt == nil ||
time.Since(*tx.LastBroadcastAt) > (time.Duration(t.config.RetryBlockThreshold)*t.config.BlockTime) ||
tx.IsPurgeable {
t.lggr.Info("Rebroadcasting attempt for txID: ", tx.ID)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great if we could add our transactionLifecycleID tracing here, but I guess that's not easily done since that's specific to the dualContractTransmitter, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I can still add it anyway.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment thread pkg/txm/txm.go
// RPC calls. The upper limit is always MaxInFlightTransactions regardless of the pending nonce.
if unconfirmedCount >= MaxInFlightSubset {
if unconfirmedCount > MaxInFlightTransactions {
if unconfirmedCount >= MaxInFlightTransactions {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would've expected there to be a test to be updated for this change, don't we have unit tests for this functionality?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test was checking for MaxInFlightTransactions + 1 although the limit was at MaxInFlightTransactions, hence why it still passes. Now it checks exactly at the limit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool

Comment thread pkg/txm/txm.go
for {
start := time.Now()
bo, err := t.BroadcastTransaction(ctx, address)
shouldBackoff, err := t.BroadcastTransaction(ctx, address) // use a backoff if transmission is being throttled.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it makes sense, thanks!

@dimriou
dimriou merged commit 88ee103 into develop Sep 3, 2026
35 checks passed
@dimriou
dimriou deleted the oev-1709_txmv2_fixes branch September 3, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants