Skip to content

fix(jsonrpc): ensure toJsonHex returns valid hex for empty byte arrays #6225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

cranycrane
Copy link

What does this PR do?
This PR fixes the toJsonHex method to return "0x00" instead of "0x" when the input byte array is empty or null. This ensures that all returned hex values follow a valid format.

Why are these changes required?
Previously, when an empty byte array (new byte[0]) was passed, the method returned "0x", which is not a valid hex representation. This could cause issues with JSON-RPC clients that expect an even-length hex string. The fix ensures compatibility and proper formatting, which causes error, when parsing incorrect hex string.

This PR has been tested by:
✅ Unit Tests
✅ Manual Testing

Follow up
No additional changes are required at this time. However, it may be beneficial to audit other methods returning hex strings to ensure consistency across the project.

@waynercheung
Copy link
Contributor

@cranycrane Hi, from unformatted-data-encoding, we can see that:

Unformatted data
When encoding unformatted data (byte arrays, account addresses, hashes, bytecode arrays): encode as hex, prefix with "0x", two hex digits per byte.

Here are some examples:

0x41 (size 1, "A")
0x004200 (size 3, "0B0")
0x (size 0, "")
WRONG: 0xf0f0f (must be even number of digits)
WRONG: 004200 (must be prefixed 0x)

So for empty array or null, 0x (size 0, "") may be a better expression.

This could cause issues with JSON-RPC clients that expect an even-length hex string.

And about This could cause issues with JSON-RPC clients that expect an even-length hex string. you mentioned above, can you give some examples?

@waynercheung
Copy link
Contributor

Here is an example for 0x in ETH.
When you send a request to eth node:

curl --location 'http://127.0.0.1:8545/' \
--header 'Content-Type: application/json' \
--data '{
    "jsonrpc": "2.0",
    "method": "eth_getBlockByNumber",
    "params": [
        "0x1003b",
        false
    ],
    "id": 1
}'

You will get:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "difficulty": "0x1c4493f2a95",
        "extraData": "0x",
        "gasLimit": "0x2fefd8",
        "gasUsed": "0x0",
        "hash": "0x7a8db7b551b470db5a3270ccfb121e308c4bd6176e8d5b17d45baf99aae19679",
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "miner": "0xf927a40c8b7f6e07c5af7fa2155b4864a4112b13",
        "mixHash": "0x0a92410d7df415ca807143f09de613cdc76f6d4ae564833cff25680fafe082ef",
        "nonce": "0x10742b3a1dfb0427",
        "number": "0x1003b",
        "parentHash": "0xdabc360f7554340c8e6a0170dfbd4bc438efb0f073a3c752b9b4542ce6c0d373",
        "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
        "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
        "size": "0x205",
        "stateRoot": "0x8759014dfc457b274e9d8c86543d3cab19e91a088684d86d93c537a712970f78",
        "timestamp": "0x55c90ddc",
        "totalDifficulty": "0x1098ca98d6e849d",
        "transactions": [],
        "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
        "uncles": []
    }
}

For "extraData" its value is "0x".

@cranycrane
Copy link
Author

cranycrane commented Mar 14, 2025

Thanks for your response! I understand "0x" is valid for some fields like extraData, but stateRoot should always be a 32-byte hex string for Ethereum compatibility.

Ethereum vs. TRON
Ethereum always returns a valid 32-byte hash, e.g.:
"stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d"

TRON returns "0x", which breaks Ethereum-compatible clients expecting a fixed-length value.

Proposal:

To align with Ethereum, TRON should return "0x000...000" (32 zero bytes) instead of "0x" when stateRoot is empty. This ensures compatibility and avoids parsing errors.

A similar issue with "0x" was discussed in #6126 Issue

@waynercheung
Copy link
Contributor

Hi, thanks for your advice.

About the stateRoot, I found there is a commit as 1ea99a2.
It modified the value from ByteArray.toJsonHex(new byte[32]) which is "0x000...000" (32 zero bytes) to be account_state_root which is 0x, because TRON does not have a stateRoot.
Due to the source branch as feature/graph_jsonrpc, I think this code change might be intended to make it compatible with The Graph, I will do some more research for it.

And for the another issue #6126 , it also discussed the value of stateRoot. For Foundry, using 0x as the value of stateRoot may cause Foundry not working properly. But extending stateRoot to "0x000...0" (a 32-byte length value)? This change might impact other developers as well.

Besides, you also have mentioned that This could cause issues with JSON-RPC clients that expect an even-length hex string, can you give some more details about the JSON-RPC clients? It is also Foundry or something else? And can you give some more example about the errors when the client got 0x as a result?

@waynercheung
Copy link
Contributor

waynercheung commented Mar 21, 2025

@cranycrane Hi, would you mind close this pr soon?
And if you want to continue discussing the stateRoot, you can talk about it in #6126 .

@cranycrane
Copy link
Author

Yes, thank you. I will continue in that discussion there.

@waynercheung
Copy link
Contributor

waynercheung commented Mar 22, 2025

@cranycrane
Thanks.
If you don’t mind, please close this PR, I don’t have the right to close it.

@cranycrane cranycrane closed this Mar 23, 2025
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