EIP-1985: Sane limits for certain EVM parameters

I think you meant the year 292277026596.

I have changed my mind on this. Actually, what the EIP proposes is only from the viewpoint of the EVM. And from the perspective of the EVM, a timestamp will always safely fit within int64. Because the EVM knows nothing about uncles, and we never execute transactions within an uncle.

So I think it would be fine to say that

  • The EVM can/should consider TIMESTAMP as fitting inside an int64.

The little devil in the details for node implementors to remember, however, is that the same rule cannot be applied to block header (uncle) validation, where timestamp can be uint64.

1 Like

I actually thought uncles are also fully verified.

Anyway, we intentionally assigned the limits to the EVM only, but consequences of these are also outside of EVM because a node will have to make sure the numbers being passed can fit.

Thatā€™s easy to think, and normally they would be, as an uncle generally exists as a head somewhere before it becomes uncled. However, on the blockchain, uncles are only headers without bodies, so itā€™s impossible to actually execute transactions in an uncle given only the chain of canon blocks ā€“ the transactions are missing (hashes too, only the combined txhash remain).

And it would be a problem of recursion. In order to validate a block, youā€™d need to validate the uncles. In order to validate an uncle, youā€™d neeed to validate itā€™s uncles, and so on indefinitely.

Right, but thatā€™s a simpler thing to fix within the node, just to make sure that whatever environment struct thatā€™s passed to the evm uses only 63 bits. Just as long as the node does not enforce that for uncle timestamps weā€™re fine.

1 Like

Cannot we just go with this to simplify everyoneā€™s life in the long term (while making it worse in the short term)?

Side-note: @winsvega called for a similar clarification https://github.com/ethereum/EIPs/issues/604

In 2016, EIP-92 by @chfast proposed a similar limit. There is a long discussion there about other limits, all of which (with the exception of balance/values) are covered.

I updated EIP-1985 with PC: https://github.com/ethereum/EIPs/pull/2179

It has been also suggested that the buffer limit (2^32 - 1) should also cap the EVM memory.

Although not strictly related to EVM semantics, it seems reasonable to include clarifying the range of other transaction related parameters in this EIP.
There is currently a discrepancy in what geth does and what the TransactionTests enforce when it comes to nonce and gasPrice:
geth uses uint64 for transaction nonces while the TransactionTests use uint256
geth uses uint256 for gas price while the TransactionTests use uint64.

It seems reasonable to me to restrict both nonce and gasPrice to uint64 for transactions.

This EIP originally aimed to describe these restrictions throughout the systems, but weā€™ve decided to focus on the EVM only to make the EIP simpler to argue about (change was made here).

Iā€™m open to making it more comprehensive as long as we can get it accepted and implemented by clients (hopefully without a ā€œhard forkā€ aka. enforcing it starting from genesis).

1 Like

A 64-bit size for Chain ID was proposed during discussion of EIP-1344, but ultimately dropped for brevity of implementation during the upcoming fork. This EIP could make that limit explicit without any issues to existing choices of Chain ID of different networks.

I believe my previous claim about gasPrice is incorrect. It seems both the transaction tests and geth uses uint256 for gasPrice so I guess it cannot be restricted here. For nonce the question remains though (in the transaction validation process)

Someone on the chat list on https://www.youtube.com/watch?v=aZ0S_oLSwhE suggested:

For 1985 I would like to have clarity on the GASPRICE opcode as well

Recommend changing all of the 264-1 limits to 252. I believe there would be no pragmatic difference, and by fitting in 52-bits it means you can store all possible values precisely in a double. Since a lot of Ethereum dapp work (almost all of it) happens in JavaScript at the moment, and since JS only has double and bigint, it would be helpful to limit where we can to 2**52.

I think this is useful insight.

I would have been in favour of this much more 1-2 years ago, but now with the advent of the native bigint API in browsers this seems to be a lesser problem.

2^52 seems like an awkward limit for any machine/language outside of JavaScript. @chfast what do you think?

What would code look like that checks to see if a number is less than 2^63-1 that would be ā€œawkwardā€ to check against 2^52 instead? The obvious (to me) solution would be something simple like if (value > 2^63-1) throw new Error(), in which case `2^52 is actually 2 characters less typing! Are you imagining some sort of signed-int overflow check that would be simpler or faster or something?

Clarifications first.

  1. The max integer you can store in double float type is 2^53-1. Not 2^52 nor 2^52-1.
  2. We definitely want to express this in number of bits required, so it must be in form of 2^N-1.

In general, I think we can lower the upper bound for gas. We were considering this previously in context of EIP-2045: Particle gas costs for EVM opcodes: the 2^53-1 would give as exactly space for 1000 particles per gas unit. However, I was thinking as low as 2^32-1 or even 2^31-1 ā€” these seem to be enough for the current block gas limits. This is to be discussed.

For quantities and indexes around memories / buffers we were also considering 32-bit range.

For TIMESTAMP the 2^53-1 looks fine while 2^31-1 not so much.

That was in my mind.

Can you describe how that would work in a modern language (Rust, Go, Katlin, C#, TypeScript, etc.)? I didnā€™t think that any of those languages exposed the CPU level overflow bit, and instead all of them would bubble an exception/error that is almost certainly more expensive than comparing two numbers.

This is now handled by EIP-2681: Limit account nonce to 2^64-1