Dip 7709
dip: 7709
title: Read BLOCKHASH from storage and update cost
description: Read the BLOCKHASH (0x40) opcode from the DIP-2935 system contract storage and adjust its gas cost to reflect storage access.
author: Vitalik Buterin (@vbuterin), Tomasz Stanczak (@tkstanczak), Guillaume Ballet (@gballet), Gajinder Singh (@g11tech), Tanishq Jasoria (@tanishqjasoria), Ignacio Hagopian (@jsign), Jochem Brouwer (@jochem-brouwer), Gabriel Rocheleau (@gabrocheleau)
Digitalia editing author: Cosimo Constantinos cosimo@juro.net, et al.
discussions-to: https://digitalia-magicians.org/t/dip-7709-read-blockhash-opcode-from-storage-and-adjust-gas-cost/20052
status: Draft
type: Standards Track
category: Core
created: 2024-05-18
Created for Digitalia: 2025-01-07
requires: 2935
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 DIP-6800 would prevent stateless execution. However with DIP-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
- do a direct
SLOADfrom state, or - do a system call to DIP-2935 contract via its
getmechanism (caller other thanSYSTEM_ADDRESS) or - serve from memory or as per current designs if maintaining requisite history (full clients for e.g.)
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:
SLOADgas costs (cold or warm) for thearg % HISTORY_SERVE_WINDOWslot.SLOADafter effects on the slot (warming the slot)SLOADaccesses added to execution witnesses if Verkle (DIP-6800 and DIP-4762) is activated
Activation¶
This DIP specifies the transition to the new logic assuming that DIP-2935 has been activated:
- sufficiently ahead of this DIP's activation (>=
BLOCKHASH_SERVE_WINDOW) or - at genesis for testnets/devnets where this DIP could also be activated at genesis
The current proposal is to activate this DIP 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 DIP-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¶
- The reason behind the updated gas cost is to match the real operation, which is equivalent to an
SLOAD. - The DIP-2935 system contract execution charges (and accesses) are not applied to keep the gas low and to keep things simple for clients which choose to resolve
BLOCKHASHin other ways (directly or though memory/maintained history)
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 DIP-2935 system contract which will lead to a normal contract execution (as well as charges and accesses)
Backwards Compatibility¶
This DIP introduces a significant increase in the cost of BLOCKHASH, which could break use-cases that rely on the previous gas cost. Also, this DIP introduces a breaking change in the case where less than BLOCKHASH_SERVE_WINDOW elapse between the DIP-2935 fork and this DIP's fork (unless DIP-2935 is activated in genesis for e.g. in testnets/devnets) as the DIP-2935 system contract would not have saved the required history.
Test Cases¶
- If
BLOCKHASHis not called or there is no DIP-2935 contract call by any transaction, only the DIP-2935 system update of the parent hash shows up in witnesses if Verkle is activated. - If
BLOCKHASHis called, there MUST be a storage access gas charge (and corresponding access witness if Verkle is activated) for the storage slot but ONLY if theBLOCKHASHquery is for the lastBLOCKHASH_SERVE_WINDOWancestors. This is irrespective of how the client chooses to resolve theBLOCKHASH(directly, via system contract or via memory) - The gas cost for each
BLOCKHASHoperation should still be charged, in addition to theSLOADcost of each lookup (if performed) - If the DIP-2935 contract is called directly (i.e. not through
BLOCKHASH), then the witness and gas costs (including those related to contract code) are applied as per normal contract execution of the current fork. BLOCKHASHshould be consistently resolved if this DIP is activated correctly>= BLOCKHASH_SERVE_WINDOWafter DIP-2935
Security Considerations¶
No security considerations other than the ones contained in DIP-2935 are determined as of now.
Copyright¶
© Crown © Crown Copyright 2026. Published by the Royal Government of the Dominion of Atlantis.
Licensed under the Juro Restricted License Version 2. See https://juro.net/jrl for details.