Skip to content

Fix double-submissions to Espresso#375

Merged
QuentinI merged 2 commits intocelo-integration-rebase-14.2from
ag/conf-time
Mar 19, 2026
Merged

Fix double-submissions to Espresso#375
QuentinI merged 2 commits intocelo-integration-rebase-14.2from
ag/conf-time

Conversation

@QuentinI
Copy link
Copy Markdown
Collaborator

This PR:

  • Replaces the wall-clock VERIFY_RECEIPT_TIMEOUT (4 seconds) with a block-count-based approach (VERIFY_RECEIPT_MAX_BLOCKS = 3). After submitting a transaction to Espresso, we now wait for 3 HotShot blocks to pass before re-submitting, instead of a fixed 4-second window.
  • Adds a single trackBlockHeight goroutine that polls FetchLatestBlockHeight every 100ms and stores the result in a shared atomic.Uint64. All 4 verify workers read from this — no per-worker height fetching.
  • Keeps a wall-clock safety backstop (VERIFY_RECEIPT_SAFETY_TIMEOUT = 5 min) in case the block height tracker is stale or broken.

Why:

The old 4-second timeout was tied to an assumption of ~2s HotShot block times. In practice, block times on decaf testnet have been highly variable (2s–66s, currently averaging ~16s), causing every verification to time out and triggering constant unnecessary re-submissions. Using block count instead of wall clock makes us resilient to variable block times across different Espresso networks.

This PR does not:

  • Add new CLI flags — the constants (VERIFY_RECEIPT_MAX_BLOCKS = 3, VERIFY_RECEIPT_SAFETY_TIMEOUT = 5 min) are reasonable defaults for any block time. Can be made configurable later if needed.
  • Change the submit path, retry delay (100ms), worker pool sizes (4+4), or queue capacities.
  • Touch any files outside op-batcher/batcher/espresso.go.

Key places to review:

  • op-batcher/batcher/espresso.go:307-320 — new constants replacing VERIFY_RECEIPT_TIMEOUT.
  • op-batcher/batcher/espresso.go:335-374evaluateVerification() now checks block count first, then wall-clock backstop.
  • op-batcher/batcher/espresso.go:622-626 — verify worker snapshots startHeight on first attempt.
  • op-batcher/batcher/espresso.go:669-688trackBlockHeight() goroutine (shared height poller).

How to test this PR:

  • go build ./op-batcher/... — compiles clean.
  • go vet ./op-batcher/... — passes.
  • Observe batcher logs: "Verification timed out by block count, re-submitting" should appear instead of constant rapid re-submissions. The log includes startHeight, currentHeight, and maxBlocks for debugging.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the Espresso receipt verification timeout mechanism to improve robustness against fluctuating HotShot block times. By transitioning from a fixed time-based timeout to a block-count-based approach, the system can adapt better to network conditions, reducing unnecessary re-submissions. A shared, atomic block height tracker was introduced to efficiently provide current block height information to verification workers, complemented by a generous wall-clock safety timeout to handle edge cases where block height tracking might fail.

Highlights

  • Timeout Mechanism Refactor: Replaced the fixed wall-clock VERIFY_RECEIPT_TIMEOUT (4 seconds) with a block-count-based approach (VERIFY_RECEIPT_MAX_BLOCKS = 3), making transaction receipt verification more resilient to variable HotShot block times.
  • Shared Block Height Tracking: Introduced a single trackBlockHeight goroutine that periodically polls FetchLatestBlockHeight and stores it in a shared atomic.Uint64, eliminating redundant per-worker height fetching.
  • Wall-Clock Safety Backstop: Implemented a VERIFY_RECEIPT_SAFETY_TIMEOUT (5 minutes) as a wall-clock fallback, ensuring re-submission even if the block height tracker becomes stale or broken.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a solid improvement, replacing the fixed wall-clock timeout for Espresso receipt verification with a more resilient block-count-based approach. The introduction of a shared, atomic block height tracker is a good optimization that avoids redundant queries. My review includes a couple of suggestions: one for a minor efficiency improvement and another to enhance the robustness of the new block height tracking goroutine to prevent potential busy-looping under certain conditions.

@QuentinI QuentinI changed the title refactor: block-count-based timeout for Espresso receipt verification Fix double-submissions to Espresso Mar 18, 2026
@QuentinI QuentinI marked this pull request as ready for review March 19, 2026 11:44
QuentinI and others added 2 commits March 19, 2026 17:59
…tion

Replace the wall-clock VERIFY_RECEIPT_TIMEOUT (4s) with a block-count-based
approach (VERIFY_RECEIPT_MAX_BLOCKS = 3). This makes receipt verification
resilient to variable HotShot block times across different Espresso networks.

A single trackBlockHeight goroutine polls FetchLatestBlockHeight and stores the
result in a shared atomic, which all verify workers read from. On the first
verification attempt the current height is snapshotted; subsequent attempts
compare against it to decide when to re-submit.

A wall-clock safety backstop (5 min) is kept in case the height tracker is
stale or broken.

Co-authored-by: OpenCode <noreply@opencode.ai>
@QuentinI QuentinI merged commit 0626a37 into celo-integration-rebase-14.2 Mar 19, 2026
45 of 46 checks passed
@QuentinI QuentinI deleted the ag/conf-time branch March 19, 2026 18:05
shenkeyao pushed a commit that referenced this pull request Mar 20, 2026
* refactor: use block-count-based timeout for Espresso receipt verification

Replace the wall-clock VERIFY_RECEIPT_TIMEOUT (4s) with a block-count-based
approach (VERIFY_RECEIPT_MAX_BLOCKS = 3). This makes receipt verification
resilient to variable HotShot block times across different Espresso networks.

A single trackBlockHeight goroutine polls FetchLatestBlockHeight and stores the
result in a shared atomic, which all verify workers read from. On the first
verification attempt the current height is snapshotted; subsequent attempts
compare against it to decide when to re-submit.

A wall-clock safety backstop (5 min) is kept in case the height tracker is
stale or broken.

Co-authored-by: OpenCode <noreply@opencode.ai>

* Pin eth2-val-tools

---------

Co-authored-by: OpenCode <noreply@opencode.ai>
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