Skip to content

test: PR12 unit-test coverage on external account#24

Open
hzj-edu-nju wants to merge 14 commits intobladehan1:developfrom
hzj-edu-nju:test/pr12-coverage-combined
Open

test: PR12 unit-test coverage on external account#24
hzj-edu-nju wants to merge 14 commits intobladehan1:developfrom
hzj-edu-nju:test/pr12-coverage-combined

Conversation

@hzj-edu-nju
Copy link
Copy Markdown

@hzj-edu-nju hzj-edu-nju commented Apr 24, 2026

External-account test PR for validating unit-test coverage results on origin.\n\nSource code copied from 0xbigapple#12 and pushed via test account branch .\n\nExpected checks:\n- PR Build runs from develop workflow\n- Coverage Gate evaluates coverage for the PR code changes\n- No workflow override from feature branch


Summary by cubic

Hardened ABI parsing and revert-reason handling, added focused unit tests, and fixed reviewer assignment for forked PRs. Improves error clarity in eth_call/eth_estimateGas and increases test coverage.

  • Bug Fixes
    • Safer ABI parsing in ContractEventParser: strict bounds checks, reject negative/oversized lengths, remove truncation, and use UTF‑8 for strings.
    • JSON‑RPC: centralized, size‑bounded revert reason decoding; only parse Error(string) and skip malformed/oversized data; applied to call and estimateGas paths.
    • CI: reviewer auto‑assignment works for fork PRs by switching to pull_request_target and granting pull-requests: write.
    • Added unit tests for parser edge cases, revert‑reason decoding, call/estimateGas success and failure paths.

Written for commit fee9f83. Summary will update on new commits.

Summary by CodeRabbit

Release Notes

  • Bug Fixes & Improvements

    • Strengthened contract event parsing with stricter validation and explicit UTF-8 character encoding to prevent data handling errors.
    • Enhanced JSON RPC error reporting with centralized revert reason decoding, providing clearer failure messages during transaction execution.
    • Improved data validation with granular bounds checking and detailed error messages for better diagnostics.
  • Chores

    • Updated CI/CD workflow automation configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

This PR enhances contract event parsing with stricter bounds and UTF-8 validation, centralizes revert-reason decoding in JSON RPC responses, and updates the CI workflow trigger to pull_request_target for improved security with explicit permissions.

Changes

Cohort / File(s) Summary
CI/CD Workflow
.github/workflows/pr-reviewer.yml
Switched trigger from pull_request to pull_request_target, removed conditional gate, and added explicit contents: read and pull-requests: write permissions for reviewer assignment in the new trigger context.
Contract Event Parsing
framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java
Added stricter bounds checking for dynamically decoded strings/bytes (rejecting negative lengths), explicit UTF-8 charset handling, and enhanced subBytes validation with detailed range checks (negative offsets, oversized lengths, boundary conditions).
JSON RPC Implementation
framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java
Introduced centralized tryDecodeRevertReason helper method with bounded payload parsing (4096-byte limit) and optional selector validation, consolidating revert-reason decoding logic from call and estimateGas methods.
Event Parser Tests
framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java
Expanded coverage for parseDataBytes across ABI types (integers, bool, bytes32, address, dynamic bytes/string) and added edge-case tests for subBytes exception handling and negative offsets.
JSON RPC Call & Gas Estimation Tests
framework/src/test/java/org/tron/core/jsonrpc/JsonRpcCallAndEstimateGasTest.java
New comprehensive test suite verifying getCall and estimateGas revert-reason appending behavior, selector handling, energy hex formatting, and constant result returns with mocked dependencies.
Revert Reason Decoding Tests
framework/src/test/java/org/tron/core/services/jsonrpc/TronJsonRpcRevertReasonTest.java
New test class validating tryDecodeRevertReason handling of null input, invalid selectors, malformed lengths, oversized payloads (4096-byte limit), and correct ABI-encoded error messages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • 317787106
  • halibobo1205

Poem

🐰 With UTF-8 clarity and bounds held tight,
Revert reasons now decode just right,
Parser checks each string with care,
No negative lengths hide anywhere,
Tests bloom like carrots, errors laid bare! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'test: PR12 unit-test coverage on external account' is vague and does not clearly reflect the actual changes. The changeset includes specific improvements to error handling (revert reason decoding), string/bytes validation, and comprehensive test coverage, but the title only mentions 'unit-test coverage on external account' which is generic and doesn't describe the substantive code changes. Revise the title to describe the main technical change, such as 'fix: Add revert reason decoding and stricter bounds validation for contract events' or 'test: Add comprehensive unit tests for JSON-RPC revert handling and event parsing'. Avoid vague phrasing like 'external account' that doesn't convey the actual purpose.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (3)
framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java (1)

80-91: Consider small consistency tweaks in subBytes guards.

Two minor points on the strengthened validation:

  1. The empty-source branch at line 82 produces a message without start/length, while the second branch includes all three values. Unifying the format makes failures easier to grep in logs.
  2. start >= src.length at line 84 also rejects a legitimate zero-length slice at end-of-buffer (start == src.length && length == 0). This isn't exercised by parseDataBytes today (the ternary at line 44 avoids it when length == 0), but if subBytes is ever reused in a new caller the condition will surprise. Allowing length == 0 at start == src.length would be strictly more permissive without weakening the guard.
♻️ Suggested tweak
   protected static byte[] subBytes(byte[] src, int start, int length) {
     if (ArrayUtils.isEmpty(src)) {
-      throw new OutputLengthException("source data is empty");
+      throw new OutputLengthException(
+          "source data is empty, start:" + start + ", length:" + length);
     }
-    if (start < 0 || start >= src.length || length < 0 || length > src.length - start) {
+    if (start < 0 || start > src.length || length < 0 || length > src.length - start) {
       throw new OutputLengthException(
           "data start:" + start + ", length:" + length + ", src.length:" + src.length);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java`
around lines 80 - 91, Update subBytes to (1) use a consistent error message
format that always includes start, length and src.length when throwing
OutputLengthException, and (2) relax the bounds check to permit start ==
src.length when length == 0 (i.e., allow a zero-length slice at end-of-buffer).
Adjust the guard that currently checks "start >= src.length" so it only fails
when start > src.length or when start == src.length and length != 0, and ensure
the thrown OutputLengthException message includes the three values for both the
empty-src and bounds-failure branches; keep parseDataBytes behavior unchanged
except for relying on the now-permissive subBytes behavior.
framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java (1)

474-502: Helper centralizes revert decoding cleanly; boundary semantics are correct and well-tested.

A few observations:

  • Early rejection of null / length <= 4 / wrong selector is correct and avoids calling Hex.toHexString on short buffers (the off+len form would otherwise AIOOBE).
  • The size guard uses strict >, so exactly MAX_REVERT_REASON_PAYLOAD_BYTES (4096) is parsed — this matches testTryDecodeRevertReasonAtPayloadLimit and is intentional.
  • The catch-all around ContractEventParser.parseDataBytes correctly swallows NegativeArraySizeException / IndexOutOfBoundsException / format issues (exercised by the "malformed"/"negative length" tests).

Minor nit: you could drop the BouncyCastle dependency here by using java.util.Arrays.copyOfRange, which would keep the helper self-contained with JDK APIs.

♻️ Optional diff
-      String reason = ContractEventParser.parseDataBytes(
-          org.bouncycastle.util.Arrays.copyOfRange(resData, REVERT_REASON_SELECTOR_LENGTH,
-              resData.length),
-          "string", 0);
+      String reason = ContractEventParser.parseDataBytes(
+          java.util.Arrays.copyOfRange(resData, REVERT_REASON_SELECTOR_LENGTH, resData.length),
+          "string", 0);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java`
around lines 474 - 502, The helper tryDecodeRevertReason currently uses
org.bouncycastle.util.Arrays.copyOfRange to slice the payload before calling
ContractEventParser.parseDataBytes; replace that call with
java.util.Arrays.copyOfRange so the method removes the BouncyCastle dependency
while keeping the same semantics (use REVERT_REASON_SELECTOR_LENGTH as the start
index and resData.length as the end), keeping the existing null/length/selector
checks and the MAX_REVERT_REASON_PAYLOAD_BYTES guard intact.
framework/src/test/java/org/tron/core/jsonrpc/JsonRpcCallAndEstimateGasTest.java (1)

42-53: State restoration in tearDown is correct; a small hardening suggestion.

Capturing originalEstimateEnergy in a field initializer works because JUnit 4 creates a fresh test-class instance per @Test, so there's no cross-test leakage. One minor concern: if a test fails between mutation and tearDown in a way that throws during mockRpc.close(), the setEstimateEnergy restore is still reached only because it follows the null-check block — that's fine as written, just worth being aware of. Mockito.clearAllCaches() is harmless but typically unnecessary with stateless local mocks; consider dropping it to speed up the suite.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@framework/src/test/java/org/tron/core/jsonrpc/JsonRpcCallAndEstimateGasTest.java`
around lines 42 - 53, The tearDown currently restores CommonParameter using the
field originalEstimateEnergy after attempting mockRpc.close(), but if
mockRpc.close() throws the restore may be skipped; update tearDown (method
tearDown and field originalEstimateEnergy) to always restore
CommonParameter.getInstance().setEstimateEnergy(originalEstimateEnergy) even if
mockRpc.close() throws (e.g., use try/finally around mockRpc.close() or
null-check then try/catch/finally), and optionally remove the
Mockito.clearAllCaches() call if you want to speed the suite since local
stateless mocks do not need it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java`:
- Around line 80-91: Update subBytes to (1) use a consistent error message
format that always includes start, length and src.length when throwing
OutputLengthException, and (2) relax the bounds check to permit start ==
src.length when length == 0 (i.e., allow a zero-length slice at end-of-buffer).
Adjust the guard that currently checks "start >= src.length" so it only fails
when start > src.length or when start == src.length and length != 0, and ensure
the thrown OutputLengthException message includes the three values for both the
empty-src and bounds-failure branches; keep parseDataBytes behavior unchanged
except for relying on the now-permissive subBytes behavior.

In `@framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java`:
- Around line 474-502: The helper tryDecodeRevertReason currently uses
org.bouncycastle.util.Arrays.copyOfRange to slice the payload before calling
ContractEventParser.parseDataBytes; replace that call with
java.util.Arrays.copyOfRange so the method removes the BouncyCastle dependency
while keeping the same semantics (use REVERT_REASON_SELECTOR_LENGTH as the start
index and resData.length as the end), keeping the existing null/length/selector
checks and the MAX_REVERT_REASON_PAYLOAD_BYTES guard intact.

In
`@framework/src/test/java/org/tron/core/jsonrpc/JsonRpcCallAndEstimateGasTest.java`:
- Around line 42-53: The tearDown currently restores CommonParameter using the
field originalEstimateEnergy after attempting mockRpc.close(), but if
mockRpc.close() throws the restore may be skipped; update tearDown (method
tearDown and field originalEstimateEnergy) to always restore
CommonParameter.getInstance().setEstimateEnergy(originalEstimateEnergy) even if
mockRpc.close() throws (e.g., use try/finally around mockRpc.close() or
null-check then try/catch/finally), and optionally remove the
Mockito.clearAllCaches() call if you want to speed the suite since local
stateless mocks do not need it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1b992f2c-f9b3-4711-9b06-6d9d9d4fee5f

📥 Commits

Reviewing files that changed from the base of the PR and between cbfc520 and fee9f83.

📒 Files selected for processing (6)
  • .github/workflows/pr-reviewer.yml
  • framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java
  • framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java
  • framework/src/test/java/org/tron/common/logsfilter/EventParserTest.java
  • framework/src/test/java/org/tron/core/jsonrpc/JsonRpcCallAndEstimateGasTest.java
  • framework/src/test/java/org/tron/core/services/jsonrpc/TronJsonRpcRevertReasonTest.java

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/pr-reviewer.yml">

<violation number="1" location=".github/workflows/pr-reviewer.yml:4">
P2: Workflow now runs in privileged `pull_request_target` context with write permissions while using an unpinned action tag (`@v8`), increasing supply-chain risk.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


on:
pull_request:
pull_request_target:
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 24, 2026

Choose a reason for hiding this comment

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

P2: Workflow now runs in privileged pull_request_target context with write permissions while using an unpinned action tag (@v8), increasing supply-chain risk.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/pr-reviewer.yml, line 4:

<comment>Workflow now runs in privileged `pull_request_target` context with write permissions while using an unpinned action tag (`@v8`), increasing supply-chain risk.</comment>

<file context>
@@ -1,15 +1,17 @@
 
 on:
-  pull_request:
+  pull_request_target:
     branches: [ 'develop', 'release_**' ]
     types: [ opened, edited, reopened ]
</file context>
Fix with Cubic

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