Summary
Align java-tron's JSON-RPC behavior with the Ethereum Execution API standard in three areas: contract revert error codes, LiteNode pruned-history responses, and JSON-RPC 2.0 request validation. This improves compatibility with Ethereum tooling, makes LiteNode failure modes explicit, and adds an opt-in strict protocol validation mode.
Problem
Motivation
java-tron's JSON-RPC behavior currently diverges from the Ethereum Execution API standard in ways that can break compatibility with wallets, DApps, SDKs, and debugging tools that assume Ethereum-compatible semantics.
Current State
eth_call and eth_estimateGas currently return -32000 for all execution failures, without distinguishing TVM revert from other failures such as OUT_OF_ENERGY.
- On LiteNode which historical blocks have been pruned, clients cannot distinguish between "data was pruned" and "data does not exist". The
earliest tag is also treated as the genesis block rather than the lowest available block on the node.
- java-tron relies on jsonrpc4j's default behavior, which does not strictly validate the
jsonrpc: "2.0" field. In addition, certain id values are handled in a way that is not suitable for blockchain node scenarios, for example treating "id": null as a notification and returning no response.
Limitations or Risks
- DApps and tooling cannot reliably distinguish contract
revert from internal execution failures, which affects error handling and UX.
- LiteNode clients cannot make informed fallback decisions, such as retrying against an archive node, because pruned-history cases are not explicitly signaled.
- Protocol-level request handling is less consistent with mainstream Ethereum clients such as geth, which increases cross-client compatibility risk.
Proposed Solution
Proposed Design
Introduce the following behavior changes:
eth_call and eth_estimateGas return error code 3 for contract revert, and include the revert payload in the data field as hex. Non-revert execution failures continue to return -32000.
- On LiteNode, return error code
4444 with message Pruned history unavailable when the requested block range is deterministically below the node's lowest available block. This applies to:
eth_getBlockByNumber
eth_getBlockTransactionCountByNumber
eth_getTransactionByBlockNumberAndIndex
eth_getBlockReceipts when block number/tag is used
eth_getLogs
eth_newFilter
- Resolve
earliest to the node's lowest available block number instead of always mapping it to the genesis block. For single-block queries, explicit 0x0 keeps its genesis-block meaning.
- Add a new config item
node.jsonrpc.strictComplianceMode, disabled by default. When enabled:
- requests missing
jsonrpc: "2.0" or carrying an invalid version return -32600 Invalid Request
- invalid
id types return responses with id: null
- Limit pruned-history handling to selectors that can be deterministically evaluated by block number or tag. Hash-only methods such as
eth_getBlockByHash and eth_getTransactionByHash remain out of scope.
Key Changes
- Modules
- JSON-RPC execution error mapping
- LiteNode block selector / history availability handling
- JSON-RPC Servlet request validation
- Configuration
- add
node.jsonrpc.strictComplianceMode = false
- API / Behavior Surface
eth_call
eth_estimateGas
eth_getBlockByNumber
eth_getBlockTransactionCountByNumber
eth_getTransactionByBlockNumberAndIndex
eth_getBlockReceipts
eth_getLogs
eth_newFilter
- Testing
- add regression coverage for error mapping, pruned-history handling,
earliest resolution, and strict mode validation
Impact
This change primarily affects API compatibility and developer experience, with positive impact on interoperability with Ethereum tooling. Performance impact should be negligible: protocol validation is an O(1) field check, and pruned-history validation happens before deeper business logic, which can reduce unnecessary I/O on LiteNode.
Compatibility
- Breaking Change: Yes
- Default Behavior Change: Partial.
eth_call / eth_estimateGas revert responses and LiteNode pruned-history responses change behavior immediately; strictComplianceMode is added but remains disabled by default.
- Migration Required: Possibly. Clients that currently rely on
-32000 for all execution failures or expect null for pruned LiteNode data may need to adjust. Clients that omit the jsonrpc field are unaffected unless strictComplianceMode is explicitly enabled.
References
Additional Notes
- Do you have ideas regarding implementation? Yes
- Are you willing to implement this feature? Yes
Summary
Align java-tron's JSON-RPC behavior with the Ethereum Execution API standard in three areas: contract revert error codes, LiteNode pruned-history responses, and JSON-RPC 2.0 request validation. This improves compatibility with Ethereum tooling, makes LiteNode failure modes explicit, and adds an opt-in strict protocol validation mode.
Problem
Motivation
java-tron's JSON-RPC behavior currently diverges from the Ethereum Execution API standard in ways that can break compatibility with wallets, DApps, SDKs, and debugging tools that assume Ethereum-compatible semantics.
Current State
eth_callandeth_estimateGascurrently return-32000for all execution failures, without distinguishing TVMrevertfrom other failures such asOUT_OF_ENERGY.earliesttag is also treated as the genesis block rather than the lowest available block on the node.jsonrpc: "2.0"field. In addition, certainidvalues are handled in a way that is not suitable for blockchain node scenarios, for example treating"id": nullas a notification and returning no response.Limitations or Risks
revertfrom internal execution failures, which affects error handling and UX.Proposed Solution
Proposed Design
Introduce the following behavior changes:
eth_callandeth_estimateGasreturn error code3for contractrevert, and include the revert payload in thedatafield as hex. Non-revert execution failures continue to return-32000.4444with messagePruned history unavailablewhen the requested block range is deterministically below the node's lowest available block. This applies to:eth_getBlockByNumbereth_getBlockTransactionCountByNumbereth_getTransactionByBlockNumberAndIndexeth_getBlockReceiptswhen block number/tag is usedeth_getLogseth_newFilterearliestto the node's lowest available block number instead of always mapping it to the genesis block. For single-block queries, explicit0x0keeps its genesis-block meaning.node.jsonrpc.strictComplianceMode, disabled by default. When enabled:jsonrpc: "2.0"or carrying an invalid version return-32600 Invalid Requestidtypes return responses withid: nulleth_getBlockByHashandeth_getTransactionByHashremain out of scope.Key Changes
node.jsonrpc.strictComplianceMode = falseeth_calleth_estimateGaseth_getBlockByNumbereth_getBlockTransactionCountByNumbereth_getTransactionByBlockNumberAndIndexeth_getBlockReceiptseth_getLogseth_newFilterearliestresolution, and strict mode validationImpact
This change primarily affects API compatibility and developer experience, with positive impact on interoperability with Ethereum tooling. Performance impact should be negligible: protocol validation is an O(1) field check, and pruned-history validation happens before deeper business logic, which can reduce unnecessary I/O on LiteNode.
Compatibility
eth_call/eth_estimateGasrevert responses and LiteNode pruned-history responses change behavior immediately;strictComplianceModeis added but remains disabled by default.-32000for all execution failures or expectnullfor pruned LiteNode data may need to adjust. Clients that omit thejsonrpcfield are unaffected unlessstrictComplianceModeis explicitly enabled.References
Additional Notes