Skip to content

fix(rpc): guard TxsResults length before indexing by block tx position - #2175

Open
JayT106 wants to merge 9 commits into
mainfrom
fix/rpc-txsresults-length-guard
Open

fix(rpc): guard TxsResults length before indexing by block tx position#2175
JayT106 wants to merge 9 commits into
mainfrom
fix/rpc-txsresults-length-guard

Conversation

@JayT106

@JayT106 JayT106 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What

x/cronos/rpc paired two independent RPC results — resBlock.Block.Txs and blockRes.TxsResults — then indexed TxsResults[i] positionally in both the receipt loop and the ReplayBlock loop, with no length check. A short TxsResults panics the RPC handler with an index-out-of-range.

Solution

  • Add checkTxsResultsLength, called once in getBlockDetail — the only place the two results are paired and the sole feeder of both loops.
  • Reject any length mismatch, not just a short one: CometBFT's state/execution.go enforces len(block.Txs) == len(TxResults) before commit, so an unequal pair can only come from an inconsistent RPC layer (proxy/multiplexer, or a re-sync/pruning race between the two calls).
  • Error is returned, not panicked, and carries the height plus both lengths.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an RPC issue that could cause failures when transaction results did not match the number of transactions in a block.
    • RPC requests now return a clear error for mismatched transaction data instead of potentially triggering a panic.
    • Improved error handling for block detail requests when transaction data or base-fee information cannot be retrieved.
  • Tests

    • Added coverage for matching transaction counts and both types of mismatches.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The RPC block detail path validates transaction and transaction-result counts before indexing results. It returns nil result fields on related errors. Tests cover matching counts and both mismatch directions. The changelog records the fix.

Changes

RPC transaction results validation

Layer / File(s) Summary
Length validation and block detail wiring
x/cronos/rpc/api.go
Added transaction-result length validation. Updated getBlockDetail to reject mismatches before base fee calculation and return nil result fields on errors.
Validation tests and changelog
x/cronos/rpc/api_test.go, CHANGELOG.md
Added helper and table-driven tests for matching counts and both mismatch directions. Documented the RPC fix.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: randy-cro

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main RPC fix: preventing unsafe indexing of TxsResults by block transaction position.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rpc-txsresults-length-guard

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.

@JayT106
JayT106 force-pushed the fix/rpc-txsresults-length-guard branch from 01412b3 to 5cae236 Compare August 6, 2026 16:34
@JayT106
JayT106 marked this pull request as ready for review August 6, 2026 17:19
@JayT106
JayT106 requested a review from a team as a code owner August 6, 2026 17:19
@JayT106

JayT106 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@claude review

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
x/cronos/rpc/api_test.go (1)

12-48: 🩺 Stability & Availability | 🔵 Trivial | 🏗️ Heavy lift

Add a regression test through getBlockDetail.

The current tests call checkTxsResultsLength directly. They would still pass if getBlockDetail stopped calling the guard. Add a backend-stub or fixture test that supplies mismatched lengths through getBlockDetail and verifies that it returns an error before BaseFee calculation or transaction-result indexing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@x/cronos/rpc/api_test.go` around lines 12 - 48, The current tests only cover
checkTxsResultsLength directly; add a regression test that exercises the public
getBlockDetail flow with mismatched transaction and result counts. Use a backend
stub or fixture to provide the mismatch, then assert getBlockDetail returns the
expected error before BaseFee calculation or transaction-result indexing occurs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@x/cronos/rpc/api_test.go`:
- Around line 12-48: Restructure TestCheckTxsResultsLength as a suite.Suite test
with a testCases table containing name, malleate func(), and expected outcomes,
and add the required doc comment for the exported test function. Move
newResBlock and newBlockRes into setup helpers that call t.Helper() or
s.T().Helper(), while preserving the existing matching, fewer-results, and
extra-results assertions.
- Around line 38-47: Update both checkTxsResultsLength test cases to assert the
complete expected error message, including the block height and both transaction
counts, rather than only checking error presence or a generic substring. Keep
the existing fewer-results and more-results scenarios unchanged while using
exact error comparisons for each case.

---

Nitpick comments:
In `@x/cronos/rpc/api_test.go`:
- Around line 12-48: The current tests only cover checkTxsResultsLength
directly; add a regression test that exercises the public getBlockDetail flow
with mismatched transaction and result counts. Use a backend stub or fixture to
provide the mismatch, then assert getBlockDetail returns the expected error
before BaseFee calculation or transaction-result indexing occurs.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ebde0a1-a775-44b6-a969-30a6b1d7361e

📥 Commits

Reviewing files that changed from the base of the PR and between 28302fd and 9a6b270.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • x/cronos/rpc/api.go
  • x/cronos/rpc/api_test.go

Comment thread x/cronos/rpc/api_test.go Outdated
Comment thread x/cronos/rpc/api_test.go Outdated
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Claude finished @JayT106's task in 1m 7s —— View job


Code Review

  • Gather context and read changed files
  • Review x/cronos/rpc/api.go
  • Review x/cronos/rpc/api_test.go
  • Review CHANGELOG.md
  • Post final review

Summary

The fix is well-targeted and correct. The panic vector is real: getBlockDetail pairs resBlock.Block.Txs and blockRes.TxsResults and both downstream callers (GetTransactionReceiptsByBlock and ReplayBlock) index TxsResults[i] without bounds checking. Adding checkTxsResultsLength once at the point of pairing is the right structural choice.

No state-machine breaking changes — this is purely an RPC-layer guard with no impact on consensus or module state.

Issues Found

Minor — CHANGELOG references wrong PR number

The CHANGELOG entry at line 11 links to #2174, but this PR is #2175:

* [#2174](...) fix(rpc): guard `TxsResults` length ...

Should be #2175. Fix this →

Positive Notes

  • Single call-site guard is correct. getBlockDetail is the sole feeder of both loops, so checking once there is cleaner than adding bounds checks inside each loop.
  • Reject both directions of mismatch. Checking != rather than < correctly handles the case where TxsResults is longer than Txs too — which is also data-corruption evidence.
  • Error message is informative. Including height + both lengths makes debugging a proxy/re-sync race significantly easier.
  • Tests cover all three cases: match, short results, and long results. The byte(i) trick for building distinct dummy txs is clean.
  • No panic — graceful error return. The err = assignment pattern at api.go:120 propagates cleanly through the named return.

Nits

  • The blockNum variable at api.go:107 is declared but only used in the error log at line 117 (which logs blockNum before it's assigned — this is a pre-existing bug, not introduced here). Worth noting but out of scope for this PR.

@github-actions github-actions Bot added the cronos label Aug 6, 2026
Signed-off-by: JayT106 <JayT106@users.noreply.github.com>
Comment thread x/cronos/rpc/api.go
api.logger.Debug("failed to retrieve block results", "height", blockNumber, "error", err.Error())
return resBlock, blockNumber, blockHash, blockRes, baseFee, err
}
if err = checkTxsResultsLength(resBlock, blockRes); err != nil {

@thomas-nguy thomas-nguy Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You are still returning resBlock and blockRes which could be missuses, perhaps some refactoring could be done to clarify the semantic of resBlock and resBlock ?

Do we allow them to have different length or not?

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.

renamed to block and blockResults, and for the returning only return the err info.
This is to match with the consensus raw data check, the length should always the same. if the data mismatch, meaning we need to migrate/patch the data like fix-unlucky-tx in v0.7 before.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
x/cronos/rpc/api_test.go (1)

70-79: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Cover the production call site.

Add a getBlockDetail test with mismatched counts. Assert that it returns the validation error before receipt and ReplayBlock processing. Otherwise, the helper can remain covered while the RPC panic fix regresses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@x/cronos/rpc/api_test.go` around lines 70 - 79, Add a test for the production
getBlockDetail call path using mismatched transaction and result counts, and
assert it returns the expected validation error before receipt handling or
ReplayBlock processing occurs. Keep the existing checkTxsResultsLength tests
unchanged while ensuring the RPC-level behavior and panic fix are covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@x/cronos/rpc/api_test.go`:
- Around line 70-79: Add a test for the production getBlockDetail call path
using mismatched transaction and result counts, and assert it returns the
expected validation error before receipt handling or ReplayBlock processing
occurs. Keep the existing checkTxsResultsLength tests unchanged while ensuring
the RPC-level behavior and panic fix are covered.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b6652b95-85c3-4f8f-9c77-4a61bfa0fcd0

📥 Commits

Reviewing files that changed from the base of the PR and between 9a6b270 and bb380de.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • x/cronos/rpc/api.go
  • x/cronos/rpc/api_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • CHANGELOG.md
  • x/cronos/rpc/api.go

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.

2 participants