Skip to content

fix(lander): track status of all tx#7217

Merged
yjamin merged 5 commits intomainfrom
yjamin/lander-track-all-tx-status
Oct 21, 2025
Merged

fix(lander): track status of all tx#7217
yjamin merged 5 commits intomainfrom
yjamin/lander-track-all-tx-status

Conversation

@yjamin
Copy link
Copy Markdown
Contributor

@yjamin yjamin commented Oct 17, 2025

Description

This PR makes sure that no linkage between tx & nonce is lost. It also ensures that TX are stored in DB in the build stage before sending them to the inclusion stage.

Drive-by changes

Related issues

Linear Issue 2034

Backward compatibility

Testing

Summary by CodeRabbit

  • Bug Fixes

    • Avoids clearing tracked nonces or linked transaction IDs unless they truly match the current transaction, preventing incorrect cleanup when handling multiple transactions.
    • Persists built transactions before forwarding them to the next processing stage to reduce risk of lost transactions if forwarding fails.
  • Tests

    • Added a test verifying nonce linkage is preserved when assigning a new nonce.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Oct 17, 2025

⚠️ No Changeset found

Latest commit: 35ca423

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 17, 2025

📝 Walkthrough

Walkthrough

Two targeted fixes: nonce-tracking cleanup is now conditional on the old nonce being linked to the current tx UUID, and built transactions are persisted before being sent to the inclusion stage.

Changes

Cohort / File(s) Summary
Nonce assignment refinement
rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs
assign_next_nonce now only clears the tracked tx UUID and tracked nonce when old_nonce is actually linked to the provided tx_uuid (checked via get_tracked_tx_uuid(nonce)), preventing unintentional unlinking.
Transaction persistence reordering
rust/main/lander/src/dispatcher/stages/building_stage/building.rs
BuildingStage::handle_tx_building_result was reordered to call self.state.store_tx(&tx).await before send_tx_to_inclusion_stage(tx.clone()), ensuring persistence happens prior to sending.
Tests
rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign/tests/tests_assign.rs
Added async test test_assign_next_nonce_and_keep_old_linkage to verify that assigning a new nonce preserves an unrelated old nonce's tracked linkage.

Sequence Diagram(s)

sequenceDiagram
    participant Builder as BuildingStage
    participant State
    participant Inclusion as InclusionStage

    rect rgb(200,220,240)
    Note over Builder: Tx built
    Builder->>State: store_tx(&tx)    %% NEW: persist before send
    State-->>Builder: Ok
    end

    rect rgb(220,240,220)
    Builder->>Inclusion: send_tx_to_inclusion_stage(tx)
    Inclusion-->>Builder: Ok / Err
    end

    rect rgb(255,240,200)
    Note over Builder: If send fails, tx already persisted
    end
Loading
sequenceDiagram
    participant Caller as NonceAssigner
    participant DB as NonceStateDB

    Caller->>DB: assign_next_nonce(tx_uuid, old_nonce?)
    alt old_nonce is Some(n)
        DB->>DB: get_tracked_tx_uuid(n)
        alt tracked_tx_uuid == tx_uuid
            DB->>DB: clear_tracked_tx_uuid(n)
            DB->>DB: clear_tracked_tx_nonce()
        else tracked to other tx
            Note right of DB: leave linkage intact
        end
    else old_nonce is None
        Note right of DB: nothing to clear
    end
    DB-->>Caller: new_nonce
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • ameten

Poem

A wee nonce stays linked where it ought to be,
Cleared only if the right UUID you see.
Built tx gets tucked in—saved before it roams,
So if the road goes squelch, the ledger still has homes. 🧅🛶

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "fix(lander): track status of all tx" touches on something real in the changes—tracking transaction status and preserving linkage—but it's a bit too broad and vague to clearly communicate what was actually changed. Like an ogre with layers, this PR has specific layers: conditional nonce cleanup logic and tx storage reordering before inclusion stage sending. The title doesn't really capture those specifics, so it leaves a bit of mystery about what's actually going on in the changeset.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed The PR description follows the template structure nicely and fills in the important bits: the Description section clearly explains the two main objectives (preserving tx-nonce linkage and storing tx in DB before inclusion), and the Related issues section provides a proper reference to Linear Issue 2034. The optional sections like Drive-by changes and Backward compatibility are left empty with template placeholders, which is fine—the core information needed to understand the PR is there.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch yjamin/lander-track-all-tx-status

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@yjamin yjamin marked this pull request as draft October 17, 2025 07:34
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e619004 and 9cea2d0.

📒 Files selected for processing (2)
  • rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs (1 hunks)
  • rust/main/lander/src/dispatcher/stages/building_stage/building.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
rust/main/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Run cargo clippy for Rust code linting

Files:

  • rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs
  • rust/main/lander/src/dispatcher/stages/building_stage/building.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: e2e-matrix (radix)
  • GitHub Check: e2e-matrix (starknet)
  • GitHub Check: e2e-matrix (sealevel)
  • GitHub Check: e2e-matrix (cosmosnative)
  • GitHub Check: e2e-matrix (evm)
  • GitHub Check: yarn-install
  • GitHub Check: e2e-matrix (cosmwasm)
  • GitHub Check: lint-rs
  • GitHub Check: test-rs
  • GitHub Check: lander-coverage
🔇 Additional comments (2)
rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs (1)

17-29: Good defensive check, mate.

This conditional cleanup is the right move - it prevents clearing nonce associations that don't actually belong to the transaction in question. Before, any old_nonce would trigger cleanup unconditionally, which could mess up other transactions' nonce linkages. Now you're verifying ownership first.

The error propagation from get_tracked_tx_uuid looks fine, and the warning message on lines 22-25 is still appropriate for when the condition is actually met.

rust/main/lander/src/dispatcher/stages/building_stage/building.rs (1)

102-107: Store-before-send pattern looks good.

Moving the persistence before the send is the right approach. Even if the send fails or gets retried, the transaction is already safely stored. This aligns well with the PR objective of ensuring no transaction tracking is lost.

The retry logic with call_until_success_or_nonretryable_error ensures eventual delivery to the inclusion stage, and the store operation won't be repeated on retries since it happens before the retry loop.

Comment thread rust/main/lander/src/dispatcher/stages/building_stage/building.rs
Comment thread rust/main/lander/src/dispatcher/stages/building_stage/building.rs Outdated
@yjamin yjamin marked this pull request as ready for review October 17, 2025 08:23
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
rust/main/lander/src/dispatcher/stages/building_stage/building.rs (1)

99-99: Error handling for store_tx remains unaddressed.

This concern was previously raised and is still valid. The call to store_tx doesn't surface errors to the caller - if database persistence fails, the transaction will still proceed to the inclusion stage on line 102, defeating the purpose of storing it first.

Without knowing whether storage succeeded, you can't guarantee the transaction won't be lost if the send operation fails later. The whole swamp... er, the whole point of this change is to persist before sending, but silent failures undermine that goal.

🧹 Nitpick comments (1)
rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs (1)

18-28: Consider logging when nonce linkage check fails.

The new conditional properly prevents clearing unrelated nonce associations, which is good defensive coding. However, when old_nonce exists but doesn't match the current tx_uuid, the function silently continues without any indication. This could make debugging difficult if callers expect the old nonce to be cleared.

Consider adding a debug or info log when the check fails, explaining why the cleanup was skipped. Something like:

if *tx_uuid == self.get_tracked_tx_uuid(nonce).await? {
    // existing logic...
} else {
    debug!(
        ?nonce,
        ?tx_uuid,
        "Skipping nonce cleanup - old nonce not associated with this transaction"
    );
}

This would help track down issues where nonces aren't being reassigned as expected.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9cea2d0 and 646b1b0.

📒 Files selected for processing (2)
  • rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs (1 hunks)
  • rust/main/lander/src/dispatcher/stages/building_stage/building.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
rust/main/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Run cargo clippy for Rust code linting

Files:

  • rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign.rs
  • rust/main/lander/src/dispatcher/stages/building_stage/building.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e-matrix (sealevel)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign/tests/tests_assign.rs (1)

18-50: Solid test for preserving nonce linkage across different transactions.

This test nails down an important edge case, mate. When a new transaction grabs a nonce and references an old one that belongs to a different transaction, the old linkage stays put. That's exactly what we want to prevent linkage from getting trampled on.

The test setup is clean and the assertions are spot-on. Nicely done keeping it consistent with the other tests in the file.

A couple optional thoughts if you're feeling fancy:

  1. You might consider storing an actual transaction for other_tx_uuid (like create_tx(other_tx_uuid, TransactionStatus::PendingInclusion) followed by state.tx_db.store_transaction_by_uuid(&tx)), similar to what the other tests do. Makes the scenario a tad more realistic, though it's not strictly necessary for what you're testing here.

  2. Could add an assertion that new_nonce is actually tracked to tx_uuid, though other tests probably cover that ground already.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 646b1b0 and c839343.

📒 Files selected for processing (1)
  • rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign/tests/tests_assign.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
rust/main/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Run cargo clippy for Rust code linting

Files:

  • rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign/tests/tests_assign.rs
🧬 Code graph analysis (1)
rust/main/lander/src/adapter/chains/ethereum/nonce/state/assign/tests/tests_assign.rs (1)
rust/main/lander/src/tests/test_utils.rs (1)
  • tmp_dbs (41-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: infra-test
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: e2e-matrix (radix)
  • GitHub Check: e2e-matrix (starknet)
  • GitHub Check: e2e-matrix (evm)
  • GitHub Check: e2e-matrix (sealevel)
  • GitHub Check: e2e-matrix (cosmosnative)
  • GitHub Check: e2e-matrix (cosmwasm)
  • GitHub Check: lint-rs
  • GitHub Check: lander-coverage
  • GitHub Check: test-rs

@yjamin yjamin added this pull request to the merge queue Oct 20, 2025
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 20, 2025
@yjamin yjamin added this pull request to the merge queue Oct 21, 2025
Merged via the queue into main with commit c3b860b Oct 21, 2025
66 of 69 checks passed
@yjamin yjamin deleted the yjamin/lander-track-all-tx-status branch October 21, 2025 08:02
@github-project-automation github-project-automation Bot moved this from In Review to Done in Hyperlane Tasks Oct 21, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (643fe18) to head (35ca423).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@          Coverage Diff          @@
##            main   #7217   +/-   ##
=====================================
  Coverage   0.00%       0           
=====================================
  Files          1       0    -1     
  Lines         14       0   -14     
=====================================
+ Misses        14       0   -14     
Components Coverage Δ
core ∅ <ø> (∅)
hooks ∅ <ø> (∅)
isms ∅ <ø> (∅)
token ∅ <ø> (∅)
middlewares ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot mentioned this pull request Oct 29, 2025
This was referenced Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants