Skip to content

Conversation

@perama-v
Copy link
Contributor

@perama-v perama-v commented Aug 4, 2023

Description

At present, clients implementing methods that have integer inputs MUST accept hex string formats. This PR adds the
requirement that they MUST also accept JSON number types for certain methods.

Rationale

Some clients permit the use of JSON number type in JSON-RPC requests. Primarily this is a convenience
feature, as block numbers and transaction indices are usually represented as decimal.

$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": [17767244, true], "id":1}' http://127.0.0.1:8545

This change standardises this convenience behaviour and is mainly an ergonomics change affecting RPC endpoint users.

Scope

The changes are limited to the parameter in requests. Responses are not modified and still use the hex representation.

Affected methods are those that accept transaction indices, block numbers or filter numbers:

  • eth_getTransactionByBlockHashAndIndex
  • Methods that accept BlockNumberOrTag
    • eth_getTransactionByBlockNumberAndIndex
    • eth_getBlockByNumber
    • eth_getBlockTransactionCountByNumber
    • eth_getUncleCountByBlockNumber
    • eth_estimateGas
    • eth_feeHistory
    • eth_createAccessList
    • debug_getRawHeader
    • debug_getRawBlock
    • debug_getRawReceipts
  • Methods that accept BlockNumberOrTagOrHash
    • eth_call
    • eth_getBalance
    • eth_getStorageAt
    • eth_getTransactionCount
    • eth_getCode
    • eth_getProof
  • Methods that accept Filter
    • eth_newFilter
  • eth_uninstallFilter
  • eth_getFilterChanges
  • eth_getFilterLogs

Changes

  • New uintParam that is defined as either hex string (current) or decimal number (new)
  • Replace uint with uintParam for method parameters
  • Introduce a test case for eth_getBlockByNumber

Security

JSON number type does not differentiate between integer, floating point and SI notation.

Floating point numbers and SI notation should be rejected as invalid parameters. This is clear with block number 100.5, but should also apply to block numbers 100.0 and 1e2.

If clients parse these variants in different ways, end-users will observe different behaviour across clients.

@perama-v perama-v changed the title feat(shemas): Permit hex/dec input via uintParam feat(schemas): Permit hex/dec input via uintParam Aug 4, 2023
@banteg
Copy link

banteg commented Aug 17, 2023

this is sensible and safe for block numbers, i support.

https://datatracker.ietf.org/doc/html/rfc7159#section-6 says

numbers that are integers and are in the range [-(2**53)+1, (2**53)-1] are interoperable in the sense that implementations will agree exactly on their numeric values.

at 12 seconds per block this won't become a problem for the coming 3.42 billion years.

@fjl
Copy link
Contributor

fjl commented Dec 18, 2024

I can say with very high certainty this change will not be included. Even if some clients accept JSON numbers, the official encoding of numbers is a hex string. The rationale for using hex strings goes like this:

In some scripting languages, notably JavaScript, all numbers will be handled as 64 bit floats. The practical limit for integers in float64 is somewhere around 2^53. When decoding a JSON payload containing an integer, it will be stored into a float, and this could lead to a misrepresentation of some values. While it may be safe for block numbers specifically, the protocol does define them as a uint64, and it's easier to just treat them like any other number.

@fjl fjl closed this Dec 18, 2024
@perama-v
Copy link
Contributor Author

perama-v commented Jan 5, 2025

I can say with very high certainty this change will not be included. Even if some clients accept JSON numbers, the official encoding of numbers is a hex string. The rationale for using hex strings goes like this:

In some scripting languages, notably JavaScript, all numbers will be handled as 64 bit floats. The practical limit for integers in float64 is somewhere around 2^53. When decoding a JSON payload containing an integer, it will be stored into a float, and this could lead to a misrepresentation of some values. While it may be safe for block numbers specifically, the protocol does define them as a uint64, and it's easier to just treat them like any other number.

Ok, thanks Felix. That's reasonable

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.

4 participants