Here are two mutually exclusive scenarios the EIP try to prevent/resolve
With the increasing number of chains, in particular in the post-sharding future of EVMs, some people want to use some hash function for collision resilient hashing functions e.g. keccak256(<human-readable-string") as a way to generate new chainIds which will be the full space of uint256
ChainId was being used be added to the parity bit for signatures e.g. EIP-712 which has a ceiling of floor(MAX_UINT64 / 2) - 36 unless we manipulate the algorithm.
These two requirement for chainId space must be resolved and I urge that we make a decision before Shanghai hardfork
One major concern I have with limiting chain IDs to ~63 bits is that you cannot then have a hash used as a chainID. I would want the limit to be 256, 384, or 512, or unspecified.
~63 bits of entropy is not sufficient collision resistance for a hash function, reasonable use or not.
What may be needed is for clients to present loud warning messages when chain IDs that are not supported by hardware wallets are used (and I think 32 bits is the real limit for that). Just a loud obnoxious warning if block height is < 100k (i.e. soon enough to reconsider your chain), not a hard block.
In today’s ACD, @xinbenlv advocated to prioritize EIP-2294 into shanghai fork. @MariusVanDerWijden responded that if it’s low cost, let’s do it, but don’t need to have a deadline to be shipped before Shanghai fork. @MicahZoltu responded support EIP-2294 that bounds chainId at its current proposed ceiling. Because it has been a de facto rule. @MicahZoltu further proposed that we don’t need to do any coding immediately, just need to agree as a group and call it a rule. @shemnon responded whether we should accept such bounding just because no one has ever used any chainId above bounds. Ask to think twice.
I understand that some tooling limits CHAIND, but I don’t see this as a reason to shut down all ChainIDs over 53 bits in length. I see a future where there are large amounts of ephemiral L2 and L3 chains and they will need a mechanical way to set a rational and deterministic means, and a 256 bit hash is that means. Much like how CREATE2 enabled Uniswap and it’s derivatives. I don’t want to kneecap this future because math in JavaScript has non-obvious rules.
Perhaps we need to limit chainIDs expressable by transaction types.
For Type 0/legacy (Frontier) transactions the metamask limit is enforced, since integer math needs to be performed on the chain ID.
For Type 1 (Berlin) and Type 2 (London) transactions a 256 bit limit is enforced. There is no math done for these transactions: it is a binary blob moved around without encoding. The limit here comes from EVM limits of 256 bits returned from the CHAINID operation.
The impact being if you want to use a hashed ChainID you must use a modern transaction container.
I find the “deterministically generated globally unique chain ID” argument to be quite compelling and I think that puts me into the camp of asserting that ChainID is 256 bits.
@MicahZoltu good point. I start to find @shemnon 's argument quite compelling too.
I see a future where there are large amounts of ephemiral L2 and L3 chains and they will need a mechanical way to set a rational and deterministic means
One possible use case: in the future @shemnon described one-day that uint256 bit of ChainId could be used to used on a chain to point to another chain… or bridges between them
I think that is a separate problem. Even if we only support Ethereum and Ethereum L2s and we come up with some Ethereum specific mechanism for avoiding collisions (e.g., something like an on-chain registry for chain IDs), there is still value in 2^256 for “deterministically generated globally unique IDs for short-lived chains”.
In that case, it would still be great to limit chain ID to floor(MAX_UINT256 / 2) - 36, to prevent accidents with type 0/legacy (Frontier) transactions being processed by existing implementations that happily perform integer math on the chain ID.
For example, the deterministic hashing method could always set the top two bits to 0, effectively leading to a list of reserved chain IDs consisting of 0 and the range with one of the top two bits set: [0x4000..., 0xffff...].
In Specification section, the allowed range is [0, MAX_CHAIN_ID], but in Rationale section, language suggests that minimum is 1 instead of 0.
For reference, a value of 0 or less is also disallowed.
As 0 is not currently used, would appreciate going with the Rationale approach of reserving it. This would allow using chain_id = 0 to indicate pre-EIP-155 LegacyTransaction. This would still be compatible with the uint256 hash based approaches.
Cross-posting a conversation between etan and me from discord
(@etan-status ): Heya! I stumbled upon your old EIP-2294. Do you know why it wasn’t adopted yet, given its origin in 2019? Also, you state “For reference, a value of 0 or less is also disallowed.” Where is this specced out?
( @xinbenlv ): On one ACD call I asked, the client teams said it was a de facto case right now that no known ChainIds have exceeded the bound indicated in EIP-2294. There has not been code enforcement inside of clients that I personally know off.
To my knowledge the smallest known id is ChainId=1, ETH Mainnet. I am not aware of any chain using ChainId=0 nor am I aware of ChainId=0 being a reserved for any future or current semantics.
@MicahZoltu could you help correct me if I am wrong?
I honestly don’t think any limitation is necessary, since any value that makes a transaction un-handleable will be rejected by either the wallet, mempool, or chain. A chain will only have chainIDs the clients support, and furthermore one per chain right now. So to wind up on the chain there must be at least one client that can handle it, and then at least one wallet that supports it (or custom submission software). The software will implicitly limit it without need to force it down the rest of the chain. Metamask in effect enforces the 55 bit limit for legacy transactions.
There already exists a consensus rule for chainID bounds: each chain accepts only one. Mainnet and the testnets only accept single bytes at the moment.
Placing a limit on the size of the chainID only places an unneeded limit in innovation. Clients will ignore that the moment it becomes interesting, such as the size limit on ExtraData in the block header, something the python libs ever enforced.
Could ChainId=0 be used to help support multiple wallets / connections to multiple chains? We used a specific chainId to do this for metamask to get it to send txs to mainnet and testnet at the same time.
Agreed that placing a limit in the spec is not useful, was moreso making a note for developers down the line whom may encounter that edge case.