EIP-7709 - Read BLOCKHASH from storage and update cost

Created 2024-05-18
Status Draft
Category Core
Type Standards Track
Authors
Requires

Abstract

Update the BLOCKHASH (0x40) opcode to read and serve from the system contract storage and charge the additional (cold or warm) storage costs.

Motivation

The BLOCKHASH (0x40) opcode currently assumes that the client has knowledge of the previous blocks, which in Verkle EIP-6800 would prevent stateless execution. However with EIP-2935 blockhashes can be retrieved and served from its system contract storage which allows Verkle blocks to include a storage access witness for stateless execution.

Specification

Parameter Value
FORK_TIMESTAMP TBD
HISTORY_STORAGE_ADDRESS 0x0000F90827F1C53a10cb7A02335B175320002935
BLOCKHASH_SERVE_WINDOW 256

The BLOCKHASH opcode semantics remains the same as before. From the fork_block (defined as fork_block.timestamp >= FORK_TIMESTAMP and fork_block.parent.timestamp < FORK_TIMESTAMP), the BLOCKHASH instruction should be updated to resolve block hash in the following manner:

def resolve_blockhash(block: Block, state: State, arg: uint64):
  # note that outside the BLOCKHASH_SERVE_WINDOW we continue to return 0
  # despite the 2935 history contract being able to serve more hashes
  if arg >= block.number or (arg + BLOCKHASH_SERVE_WINDOW) < block.number
    return 0

  # performs an sload on arg % HISTORY_SERVE_WINDOW including gas charges,
  # warming effects as well as execution accesses
  #
  # note that the `BLOCKHASH_SERVE_WINDOW` and the 2935 ring buffer window
  # `HISTORY_SERVE_WINDOW` for slot calculation are different
  return state.load_slot(HISTORY_STORAGE_ADDRESS, arg % HISTORY_SERVE_WINDOW)

ONLY if the arg is within the correct BLOCKHASH window, clients can choose to either

However the entire semantics and after effects of the SLOAD operation needs to be applied as per the current fork if the arg is within the correct BLOCKHASH window:

Activation

This EIP specifies the transition to the new logic assuming that EIP-2935 has been activated:

The current proposal is to activate this EIP with Verkle to allow for stateless execution of the block.

Gas costs

As described above, if the arg to be resolved is within the correct window, the corresponding SLOAD charges and accesses are to be applied for the slot arg % HISTORY_SERVE_WINDOW. Note that the HISTORY_SERVE_WINDOW and BLOCKHASH_SERVE_WINDOW are different.

Reading from the System contract

Even if the clients choose to resolve BLOCKHASH through system call to EIP-2935 contract, the gas cost for the system code execution (and also the code witnesses if Verkle activated) is not applied. Only the effect of SLOAD is applied as described above.

Rationale

Note that BLOCKHASH opcode only serves a limited BLOCKHASH_SERVE_WINDOW to be backward compatible (and to not extend the above exemptions). For deeper accesses one will need to directly call EIP-2935 system contract which will lead to a normal contract execution (as well as charges and accesses)

Backwards Compatibility

This EIP introduces a significant increase in the cost of BLOCKHASH, which could break use-cases that rely on the previous gas cost. Also, this EIP introduces a breaking change in the case where less than BLOCKHASH_SERVE_WINDOW elapse between the EIP-2935 fork and this EIP's fork (unless EIP-2935 is activated in genesis for e.g. in testnets/devnets) as the EIP-2935 system contract would not have saved the required history.

Test Cases

Security Considerations

No security considerations other than the ones contained in EIP-2935 are determined as of now.

Copyright

Copyright and related rights waived via CC0.