Skip to content

feat(l1-sender): Add ability to resubmit transactions#1138

Open
Artemka374 wants to merge 37 commits intomainfrom
afo/l1-sender-enhancements
Open

feat(l1-sender): Add ability to resubmit transactions#1138
Artemka374 wants to merge 37 commits intomainfrom
afo/l1-sender-enhancements

Conversation

@Artemka374
Copy link
Copy Markdown
Contributor

@Artemka374 Artemka374 commented Apr 2, 2026

Core Problem Fixed

Previously, a single missed/timed-out L1 transaction would crash the entire pipeline and require a manual restart.

Improvements

  • Automatic transaction resubmission: Each SendToL1 command now runs a dedicated submit-and-watch loop. On timeout, it re-estimates fees, applies a ≥10% EIP-1559 replacement bump, and rebroadcasts — repeating until a receipt is confirmed.

  • Resilience to network conditions: The pipeline stays alive through network congestion and gas price spikes instead of crashing on the first confirmation timeout.

  • Fee capping on every attempt: All fee fields (max_fee_per_gas, max_priority_fee_per_gas) are capped at the operator's configured maximums on each resubmission attempt. Blob fee cap is applied only for commit transactions that carry a sidecar.

  • Cap-exceeded handling: If bumped fees would exceed configured caps, the sender re-watches the original transaction (instead of crashing) and increments a tx_confirmation_timeouts counter to alert operators that cap limits may need adjustment.

  • Blob fee estimation: Blob fees are now explicitly estimated (with a fallback on estimation error) and reported via metrics.

  • Required confirmations: Added support for configurable required confirmations before a transaction is considered finalized.

New Observability (Grafana metrics)

l1_sender_configured_ metrics are purely for observability of whether we are exceeding the caps.

Metric Description
l1_sender_configured_max_fee_per_gas Operator-configured EIP-1559 fee cap
l1_sender_configured_max_priority_fee_per_gas Operator-configured priority fee cap
l1_sender_configured_max_fee_per_blob_gas Operator-configured blob fee cap
l1_sender_tx_confirmation_timeouts_total Count of timeouted transactions

Artemka374-claude and others added 6 commits April 1, 2026 12:47
Each SendToL1 command now spawns an independent submit_and_confirm task
that owns the full submit → poll → resubmit lifecycle via a oneshot
channel. The main loop awaits completion in submission order, keeping
nonce sequencing correct while allowing the poll/resubmit loop to run
concurrently with fee-cap estimation for the next transaction.

Key changes:
- New `types.rs`: GasParams (EIP-1559, replacement bump logic) + Backoff
- New `error.rs`: is_transient / is_nonce_too_low predicates
- `config.rs`: transaction_timeout field (default 300 s)
- `lib.rs`: per-tx task design; manual nonce tracking; blocking
  estimate_gas_within_caps; resubmission_action pure decision fn
- Derive Clone on BatchEnvelope, CommitCommand, ProofCommand, ExecuteCommand
- Derive Clone on LatencyDistributionTracker (fresh instance on clone)
- Integration test: l1_sender_resubmits_after_timeout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Anvil 1.5.1 reports a higher base priority fee (~2 gwei) than the
default 1 gwei cap, causing estimate_gas_within_caps to spin forever.
Override max_priority_fee_per_gas (10 gwei) and max_fee_per_gas
(500 gwei) in the test setup so the cap never blocks submission.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

Test results

278 tests   258 ✅  2h 27m 22s ⏱️
 23 suites    0 💤
  1 files     20 ❌

For more details on these failures, see this check.

Results for commit 17fb2e5.

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown
Contributor

@Artemka374-claude Artemka374-claude left a comment

Choose a reason for hiding this comment

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

@Artemka374 requested me to review this PR.
I found a few issues in the new L1 sender resubmission path:

  • Blob commit transactions are re-sent without increasing maxFeePerBlobGas, so timeout-driven replacements can still be rejected by txpools that enforce blob-fee bumps.
  • Submission is now fully concurrent, which lets higher nonces get broadcast even if a lower nonce fails to submit; that is a behavioral regression from the old sequential submit path and interacts badly with the existing lack of in-flight recovery.
  • The new integration test does not prove that a replacement happened; the original pending transaction would also finalize once auto-mining is turned back on.

Comment thread lib/l1_sender/src/lib.rs
Comment thread lib/l1_sender/src/lib.rs Outdated
Comment thread integration-tests/tests/node/l1_sender_resubmission.rs Outdated
Copy link
Copy Markdown
Contributor

@Artemka374-claude Artemka374-claude left a comment

Choose a reason for hiding this comment

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

@Artemka374 requested me to review this PR.
I found one regression in the updated sender loop: the first submission now bypasses the configured L1 fee caps and can broadcast a transaction above the operator's stated max-fee settings. I left an inline comment on the relevant lines.
The earlier concurrency concern looks addressed, and the updated integration test is much stronger about proving that a replacement happened.

Comment thread lib/l1_sender/src/lib.rs Outdated
Copy link
Copy Markdown
Contributor

@Artemka374-claude Artemka374-claude left a comment

Choose a reason for hiding this comment

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

@Artemka374 requested me to review this PR.
I still see two regressions in the new resubmission path:

  • Blob commit transactions are retried with the same maxFeePerBlobGas, so replacement commits can still be rejected as underpriced on txpools that enforce blob-fee bumps.
  • When the 10% replacement bump would exceed the configured EIP-1559 caps, the sender now re-watches the original transaction forever instead of surfacing a failure. A capped transaction that is already unmineable can therefore stall the pipeline indefinitely.
    The earlier sequential-submit concern looks addressed, and the updated integration test is much stronger about proving that a replacement happened. I wasn't able to resolve the older threads because this bot account lacks ResolveReviewThread permission.

Comment thread lib/l1_sender/src/lib.rs
Comment thread lib/l1_sender/src/lib.rs Outdated
Artemka374 and others added 2 commits April 3, 2026 17:15
Resolved conflict in lib/l1_sender/src/lib.rs: kept HEAD's generic
type bounds and build_and_send refactor, incorporated main's
commit_submitted_tx parameter and CommitWatcher notification logic.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@Artemka374 Artemka374 marked this pull request as ready for review April 7, 2026 14:06
@Artemka374 Artemka374 changed the title feat: L1 sender enhancements feat(l1-sender): Add ability to resubmit transactions Apr 7, 2026
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.

2 participants