EIP-2027: State Rent C - Net contract size accounting
Simple Summary
Ethereum starts counting the number of storage slots filled and emptied in the contracts. Since the number of pre-existing slots is not currently accounted in the state, effectively, only net change in the number of slots is tracked. In the subsequent change, called Gross contract size accounting, the total number of storage slots starts being tracked.
Abstract
This is part of the State Rent roadmap. This particular change introduces initial, net accounting of the number of the contract storage slots. Though not very useful on its own, it makes it possible to introduce gross accounting of the number of storage slots, which is useful for number of things:
- Gas cost of operations suchs as
SLOAD
andSSTORE
will need to be increased to compensate for extra bandwidth consumed by the block proofs. Although in the beginning the cost would be fixed, it will later be automatically calibrated depending on the size of the contractSLOAD
andSSTORE
operate on. - Snapshot sync protocols, like fast sync, warp sync, firehose, red queen, and perhaps others, will benefit from having the correct size of the contract storage present in the state (and therefore being provable via Merkle proofs).
Motivation
Ethereum currently does not track the number of contract storage slots at all, and producing such number given the downloaded state cannot be done in constant O(1) time.
Specification
Each contract (account with codeHash
field not equal to 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, which the hash of the empty code) gets a new uint64 field, called storagesize
. On and after block C
, the semantics of the operation SSTORE
(location
, value
) changes as follows:
- If previous value of the [
location
] is 0, and value is not 0, incrementstoragesize
(semantics of increment described below) - If previous value of the [
location
] is not 0, and value is 0, decrementstoragesize
(semantics of decrement described below) - As with other state changes, changes of
storagesize
get reverted when the execution frame reverts, i.e. it needs to use the same techniques as storage values, like journalling (in Geth), and substates (in Parity). Value ofstoragesize
is not observable from contracts at this point.
Semantics of increment storagesize
If storagesize
is not present, storagesize
= HUGE_NUMBER
+ 1.
If storagesize
is present, storagesize
= storagesize
+ 1.
Semantics of decrement storagesize
If storagesize
is not present, storagesize
= HUGE_NUMBER
- 1.
If storagesize
is present, storagesize
= storagesize
- 1.
Note of HUGE_NUMBER
There is a constant HUGE_NUMBER
. It needs to be large enough so that no real metrics (contract storage size, number of accounts, number of contracts, total size of code, total size of storage) will never reach that number, and small enough that it fits in an unsigned 64-bit integer.
Current suggestion is to have HUGE_NUMBER
= 2^63, which is binary representation is the a single bit in a 64-bit number.
The idea is to make it decidable later whether the storagesize was ever incremented/decremented (presence of the field), and whether it has been converted from net to gross (by value being smaller than HUGE_NUMBER/2
- because it will not be possible for any contract be larger than 2^62 at the block C
).
Rationale
A mechanism for estimation of contract storage size has been proposed here. But it does have a big drawback of introducing a lot of complexity into the consensus (in the form of estimation algorithm, which has quite a few edge cases to cater for different sizes of the storage).
Backwards Compatibility
This change is not backwards compatible and requires hard fork to be activated. Since the newly introduced field is not observable, this change does not impact any operations of the existing smart contracts.
Test Cases
Tests cases will be generated out of a reference implementation.
Implementation
There will be proof of concept implementation to refine and clarify the specification.
Copyright
Copyright and related rights waived via CC0.