Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State Rent change C draft EIP - Net contract storage size accounting #2027

Merged
merged 10 commits into from
May 24, 2019
74 changes: 74 additions & 0 deletions EIPS/eip-2027.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
eip: 2027
title: State Rent C - Net contract size accounting
author: Alexey Akhunov (@AlexeyAkhunov)
discussions-to: https://ethereum-magicians.org/t/eip-2027-net-contract-size-accounting-change-c-from-state-rent-v3-proposal/3275
status: Draft
type: Standards Track
category: Core
created: 2019-05-14
---

<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->

## Simple Summary
<!--"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP.-->
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
<!--A short (~200 word) description of the technical issue being addressed.-->
It is part of the State Rent roadmap. This particular change introduced 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:
1. Gas cost of operations suchs as `SLOAD` and `SSTORE` will need to be increased to compensate for extra bandwidth consumed by the block proofs. Thought in
the beginning, the cost would be fixed, it later be automatically calibrated depending on the size of the contract `SLOAD` and `SSTORE` operate on.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pardon my ignorance, but I was under the impression that these costs were getting larger because the entire state (of all contracts) increases, not just for a single contract. Is there a good place where I can read about this? This implies that SLOADs / SSTOREs on small contracts are less computationally expensive than on large contracts (small/large meaning the storage size of the contract here).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, SLOAD and SSTORE do get more computationally expensive on large contracts (at least in the most currently implementations). They also get more expensive when the entire state database grows. I tried to describe this in my blog post series, but, of course, I left a lot of things implicit, otherwise I would need to write a while book on it: https://medium.com/@akhounov/looking-back-at-the-ethereum-1x-workshop-26-28-01-2019-part-2-d3d8fdcede10

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great write up. thanks!

Copy link
Member

@MrChico MrChico May 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought

should be though

it later

word missing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, fixed

2. 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
<!--The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright.-->
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
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).-->
Each contract gets a new uint64 field, called `storagesize`. On and after block C, the semantics of the operation `SSTORE` (`location`, `value`) changes as follows:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each contract or account? If contract, can you specify what constitutes as a contract (has non-empty code)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added clarification, thank you

- If previous value of the [`location`] is 0, and value is not 0, *increment* `storagesize` (semantics of *increment* described below)
- If previous value of the [`location`] is not 0, and value is 0, *decrement* `storagesize` (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 of `storagesize` 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 ever reach that number, and small enough that it fits in an unsigned 64-bit integer.
axic marked this conversation as resolved.
Show resolved Hide resolved
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
<!--The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.-->
A mechanism for estimation of contract storage size has been proposed [here](https://medium.com/@akhounov/estimation-approximate-of-the-size-of-contracst-in-ethereum-4642fe92d6fe). 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
<!--All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright.-->
This change is not backwards compatible and requires hard fork to be activated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would mention that since this new field is not observable and it doesn't change anything, it has no effect on contracts (on its own) -- but could with subsequent changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thank you

## Test Cases
<!--Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.-->
Tests cases will be generated out of a reference implementation.

## Implementation
<!--The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.-->
There will be proof of concept implementation to refine and clarify the specification.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).