Skip to content

fix(cronos): bound concurrent ReplayBlock queries and honor the request context - #2179

Open
JayT106 wants to merge 5 commits into
mainfrom
fix/replay-block-concurrency-bound
Open

fix(cronos): bound concurrent ReplayBlock queries and honor the request context#2179
JayT106 wants to merge 5 commits into
mainfrom
fix/replay-block-concurrency-bound

Conversation

@JayT106

@JayT106 JayT106 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What

/cronos.Query/ReplayBlock is unauthenticated and runs real EVM execution — up to ReplayBlockGasCap (60M, doubled to a 120M gas budget) and MaxReplayBlockMsgs (10000) messages per call. Those per-call caps were already in place, but nothing capped how many calls ran at once, so N concurrent requests meant N × 120M gas of parallel execution. The handler also never looked at the request context, so a client that disconnected or timed out mid-batch left the node grinding through the remaining messages for nothing.

Solution

  • A package-level semaphore caps concurrent replays at 4 (replayBlockConcurrency). Acquire is a select against the caller's context, so a cancelled or expired request gives up instead of waiting.
  • Bounding compute alone isn't enough: waiters were unbounded, and each holds a decoded request (cosmos-sdk's gRPC server sets no MaxConcurrentStreams, so an attacker can open arbitrarily many). An atomic counter now bounds running + queued at 16 and rejects beyond that with ResourceExhausted. The check is a single AddInt32 compared against the bound with rollback on rejection — no check-then-act window, so concurrent callers can't overshoot.
  • ctx.Err() is checked once per message inside the replay loop, converted via status.FromContextError, so a disconnect aborts the batch instead of running it out.

Tradeoff: cronos_replayBlock over JSON-RPC shares this pool, so heavy debugging use can now be rejected rather than queued. 4 is deliberately conservative for a heavy debug query.

Test

grpc_query_replay_concurrency_test.go covers the wait path (asserts the gRPC code, not wall-clock time — the request carries zero messages, so DeadlineExceeded is reachable only through the semaphore select), the proceed path, and the queue-full rejection via test-only counter hooks in export_test.go. Counter balance was traced across rejection, cancellation, panic, and every early return.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@JayT106, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aa3a4f10-7982-4bef-b8ec-7f7d71a8b47f

📥 Commits

Reviewing files that changed from the base of the PR and between 34f4ba2 and e1b991f.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • x/cronos/keeper/export_test.go
  • x/cronos/keeper/grpc_query.go
  • x/cronos/keeper/grpc_query_replay_concurrency_test.go

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.

…st context

Add an aggregate concurrency limit and context cancellation checks to the
unauthenticated ReplayBlock gRPC query, so a handful of concurrent callers
cannot saturate the node's EVM execution capacity even though each call
already caps its own gas.
@JayT106
JayT106 force-pushed the fix/replay-block-concurrency-bound branch from 7026d9e to 264a5a6 Compare August 6, 2026 16:41
JayT106 added 2 commits August 6, 2026 14:11
Drop redundant/verbose comments across export_test.go, grpc_query.go,
and the concurrency test file, keeping only non-obvious rationale.
@JayT106
JayT106 marked this pull request as ready for review August 6, 2026 18:13
@JayT106
JayT106 requested a review from a team as a code owner August 6, 2026 18:13
@JayT106

JayT106 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@claude review

Signed-off-by: JayT106 <JayT106@users.noreply.github.com>
@github-actions github-actions Bot added the cronos label Aug 7, 2026
Signed-off-by: JayT106 <JayT106@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant