Skip to content

refactor(jsonrpc): centralize block selector parsing into JsonRpcApiUtil#6668

Open
0xbigapple wants to merge 3 commits intotronprotocol:developfrom
0xbigapple:refactor/jsonrpc-block-selector
Open

refactor(jsonrpc): centralize block selector parsing into JsonRpcApiUtil#6668
0xbigapple wants to merge 3 commits intotronprotocol:developfrom
0xbigapple:refactor/jsonrpc-block-selector

Conversation

@0xbigapple
Copy link
Copy Markdown
Collaborator

What does this PR do?
This PR centralizes JSON-RPC block tag and block number resolution in JsonRpcApiUtil so block selectors are parsed consistently across the JSON-RPC layer.

It also removes Wallet's reverse dependency on JSON-RPC code, eliminates the -1 means latest sentinel, and simplifies the block range resolution logic in LogFilterWrapper.

  • Added JsonRpcApiUtil.isBlockTag, parseBlockTag, and parseBlockNumber, and moved block tag constants and related errors, including safe, into JsonRpcApiUtil.
  • Updated TronJsonRpcImpl to delegate block selector parsing to JsonRpcApiUtil; eth_getBlock* paths now use shared block resolution logic.
  • Centralized the existing latest-only validation for state-read APIs such as getTrxBalance, getStorageAt, getABIOfSmartContract, and eth_call.
  • Removed JSON-RPC block parsing helpers from Wallet, replaced the -1 sentinel behavior, and added getHeadBlockNum().
  • Simplified the branching logic in LogFilterWrapper by making block range handling strategy-based and easier to reason about.
  • Added tests for block tag parsing and log filter strategy behavior.

Why are these changes required?
Block selector parsing is currently duplicated across Wallet, JsonRpcApiUtil, and TronJsonRpcImpl, with slightly different responsibilities and control flow in each layer.

This creates several problems:

  • duplicated and inconsistent block tag resolution logic
  • an undesirable reverse dependency from core Wallet code to the JSON-RPC layer
  • ambiguous -1 sentinel handling that forces callers to reinterpret results differently
  • complex block range branching in LogFilterWrapper that is harder to maintain and verify

By centralizing parsing in JsonRpcApiUtil, this PR makes the behavior easier to reason about, reduces coupling, and preserves existing JSON-RPC semantics while removing fragile internal conventions.

This PR has been tested by:

  • Unit Tests
  • Manual Testing

Follow up
None.

Extra details

  • This PR is intended as a refactor and cleanup. All JSON-RPC endpoints return identical results.

Comment thread framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java Outdated
Comment thread framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java Outdated
Comment thread framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java Outdated
…ution, also use longValueExact in eth_getProof block number parsing and clarify the getBlockByNumOrTag comment
}
fromBlockSrc = min(toBlockSrc, currentMaxBlockNum);

} else if (!fromEmpty && toEmpty) {
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.

[NIT] The !toEmpty / !fromEmpty checks are redundant here because the previous branches already exclude those cases, so static analysis reports them as always true when reached. This can be simplified to else if (fromEmpty) and else if (toEmpty).

@waynercheung
Copy link
Copy Markdown
Collaborator

[NIT] A few comments in this PR use the Unicode arrow . This is readable, but I’d prefer plain ASCII -> in source comments/Javadoc for consistency with the rest of the codebase and fewer tooling/font portability issues.

Assert.fail("Expected to be thrown");
} catch (Exception e) {
Assert.assertEquals("TAG [earliest | pending | finalized] not supported",
Assert.assertEquals(TAG_NOT_SUPPORT_ERROR,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The parseBlockTag("safe") test at line 458 is a nice addition — safe was previously unhandled!

nit: Since safe is now part of isBlockTag and the error message was updated to include it, would it be worth adding at least one test case exercising safe through a state-read endpoint like getTrxBalance? The existing tests cover earliest, pending, and finalized through each endpoint but not safe:

try {
  tronJsonRpc.getTrxBalance("", "safe");
  Assert.fail("Expected to be thrown");
} catch (Exception e) {
  Assert.assertEquals(TAG_NOT_SUPPORT_ERROR, e.getMessage());
}

* Reject any block selector that is not "latest".
* Accepts "latest" silently; throws for other tags, numeric blocks, or invalid input.
*/
private void requireLatestBlockTag(String blockNumOrTag)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Really clean extraction — the old code had the same tag-check + hex-parse + quantity-reject sequence copy-pasted across getTrxBalance, getStorageAt, getABIOfSmartContract, and getCall. Pulling it into requireLatestBlockTag with clear error stratification (tag error → number error → quantity error) is a significant readability win. 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants