mirror of https://github.com/status-im/EIPs.git
Automatically merged updates to draft EIP(s) 1283
Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
This commit is contained in:
parent
f2f879361e
commit
001ccad32d
167
EIPS/eip-1283.md
167
EIPS/eip-1283.md
|
@ -12,30 +12,20 @@ created: 2018-08-01
|
|||
|
||||
## Abstract
|
||||
|
||||
This EIP proposes net gas metering changes for SSTORE opcode, as an
|
||||
alternative for EIP-1087. It tries to be friendlier to implementations
|
||||
that use different optimization strategies for storage change
|
||||
caches.
|
||||
This EIP proposes net gas metering changes for SSTORE opcode, enabling
|
||||
new usages for contract storage, and reducing excessive gas costs
|
||||
where it doesn't match how most implementation works.
|
||||
|
||||
This acts as an alternative for EIP-1087, where it tries to be
|
||||
friendlier to implementations that use different optimization
|
||||
strategies for storage change caches.
|
||||
|
||||
## Motivation
|
||||
|
||||
EIP-1087 proposes a way to adjust gas metering for SSTORE opcode,
|
||||
enabling new usages on these opcodes where it is previously too
|
||||
expensive. However, EIP-1087 requires keeping a dirty map for storage
|
||||
changes, and implicitly makes the assumption that a transaction's
|
||||
storage changes are committed to the storage trie at the end of a
|
||||
transaction. This works well for some implementations, but not for
|
||||
others. After EIP-658, an efficient storage cache implementation would
|
||||
probably use an in-memory trie (without RLP encoding/decoding) or
|
||||
other immutable data structures to keep track of storage changes, and
|
||||
only commit changes at the end of a block. For them, it is possible to
|
||||
know a storage's original value and current value, but it is not
|
||||
possible to iterate over all storage changes without incurring additional
|
||||
memory or processing costs.
|
||||
|
||||
This EIP proposes an alternative way for gas metering on SSTORE, using
|
||||
information that is more universally available to most
|
||||
implementations:
|
||||
This EIP proposes a way for gas metering on SSTORE (as an alternative
|
||||
for EIP-1087 and EIP-1153), using information that is more universally
|
||||
available to most implementations, and require as little change in
|
||||
implementation structures as possible.
|
||||
|
||||
* *Storage slot's original value*.
|
||||
* *Storage slot's current value*.
|
||||
|
@ -97,7 +87,18 @@ the following logic:
|
|||
* Otherwise, add 4800 gas to refund counter.
|
||||
|
||||
Refund counter works as before -- it is limited to half of the gas
|
||||
consumed.
|
||||
consumed. On a transaction level, refund counter will never go below
|
||||
zero. However, there are some important notes depending on the
|
||||
implementation details:
|
||||
|
||||
* If an implementation uses "transaction level" refund counter (refund
|
||||
is checkpointed at each call frame), then the refund counter
|
||||
continues to be unsigned.
|
||||
* If an implementation uses "execution-frame level" refund counter
|
||||
(a new refund counter is created at each call frame, and then merged
|
||||
back to parent when the call frame finishes), then the refund
|
||||
counter needs to be changed to signed -- at internal calls, a child
|
||||
refund can go below zero.
|
||||
|
||||
## Explanation
|
||||
|
||||
|
@ -169,6 +170,28 @@ This EIP mostly archives what a transient storage tries to do
|
|||
(EIP-1087 and EIP-1153), but without the complexity of introducing the
|
||||
concept of "dirty maps", or an extra storage struct.
|
||||
|
||||
* We don't suffer from the optimization limitation of
|
||||
EIP-1087. EIP-1087 requires keeping a dirty map for storage changes,
|
||||
and implicitly makes the assumption that a transaction's storage
|
||||
changes are committed to the storage trie at the end of a
|
||||
transaction. This works well for some implementations, but not for
|
||||
others. After EIP-658, an efficient storage cache implementation
|
||||
would probably use an in-memory trie (without RLP encoding/decoding)
|
||||
or other immutable data structures to keep track of storage changes,
|
||||
and only commit changes at the end of a block. For them, it is
|
||||
possible to know a storage's original value and current value, but
|
||||
it is not possible to iterate over all storage changes without
|
||||
incurring additional memory or processing costs.
|
||||
* It never costs more gas compared with the current scheme.
|
||||
* It covers all usages for a transient storage. Clients that are easy
|
||||
to implement EIP-1087 will also be easy to implement this
|
||||
specification. Some other clients might require a little bit extra
|
||||
refactoring on this. Nonetheless, no extra memory or processing cost
|
||||
is needed on runtime.
|
||||
|
||||
Regarding SSTORE gas cost and refunds, see Appendix for proofs of
|
||||
properties that this EIP satisfies.
|
||||
|
||||
* For *absolute gas used* (that is, actual *gas used* minus *refund*),
|
||||
this EIP is equivalent to EIP-1087 for all cases.
|
||||
* For one particular case, where a storage slot is changed, reset to
|
||||
|
@ -218,6 +241,106 @@ slot is reset and then set again.
|
|||
| `0x600160005560006000556001600055` | 40218 | 19800 | 0 | 1 | 0 | 1 |
|
||||
| `0x600060005560016000556000600055` | 10218 | 19800 | 1 | 0 | 1 | 0 |
|
||||
|
||||
## Appendix: Proof
|
||||
|
||||
Because the *storage slot's original value* is defined as the value
|
||||
when a reversion happens on the *current transaction*, it's easy to
|
||||
see that call frames won't interfere SSTORE gas calculation. So
|
||||
although the below proof is discussed without call frames, it applies
|
||||
to all situations with call frames. Below we will discuss the case
|
||||
separately for *original value* being zero and not zero, and use
|
||||
*induction* to prove some properties of SSTORE gas cost.
|
||||
|
||||
*Final value* is the value of a particular storage slot at the end of
|
||||
a transaction. *Absolute gas used* is the absolute value of *gas used*
|
||||
minus *refund*. We use `N` to represent the total number of SSTORE
|
||||
operations on a storage slot. For states discussed below, refer to
|
||||
*State Transition* in *Explanation* section.
|
||||
|
||||
### Original Value Being Zero
|
||||
|
||||
When *original value* is 0, we want to prove that:
|
||||
|
||||
* **Case I**: If the *final value* ends up still being 0, we want to charge `200 *
|
||||
N` gases, because no disk write is needed.
|
||||
* **Case II**: If the *final value* ends up being a non-zero value, we want to
|
||||
charge `20000 + 200 * (N-1)` gas, because it requires writing this
|
||||
slot to disk.
|
||||
|
||||
#### Base Case
|
||||
|
||||
We always start at state A. The first SSTORE can:
|
||||
|
||||
* Go to state A: 200 gas is deducted. We satisfy *Case I* because
|
||||
`200 * N == 200 * 1`.
|
||||
* Go to state B: 20000 gas is deducted. We satisfy *Case II* because
|
||||
`20000 + 200 * (N-1) == 20000 + 200 * 0`.
|
||||
|
||||
#### Inductive Step
|
||||
|
||||
* From A to A. The previous gas cost is `200 * (N-1)`. The current
|
||||
gas cost is `200 + 200 * (N-1)`. It satisfy *Case I*.
|
||||
* From A to B. The previous gas cost is `200 * (N-1)`. The current
|
||||
gas cost is `20000 + 200 * (N-1)`. It satisfy *Case II*.
|
||||
* From B to B. The previous gas cost is `20000 + 200 * (N-2)`. The
|
||||
current gas cost is `200 + 20000 + 200 * (N-2)`. It satisfy
|
||||
*Case II*.
|
||||
* From B to A. The previous gas cost is `20000 + 200 * (N-2)`. The
|
||||
current gas cost is `200 - 19800 + 20000 + 200 * (N-2)`. It satisfy
|
||||
*Case I*.
|
||||
|
||||
### Original Value Not Being Zero
|
||||
|
||||
When *original value* is not 0, we want to prove that:
|
||||
|
||||
* **Case I**: If the *final value* ends up unchanged, we want to
|
||||
charge `200 * N` gases, because no disk write is needed.
|
||||
* **Case II**: If the *final value* ends up being zero, we want to
|
||||
charge `5000 - 15000 + 200 * (N-1)` gas. Note that `15000` is the
|
||||
refund in actual defintion.
|
||||
* **Case III**: If the *final value* ends up being a changed non-zero
|
||||
value, we want to charge `5000 + 200 * (N-1)` gas.
|
||||
|
||||
#### Base Case
|
||||
|
||||
We always start at state X. The first SSTORE can:
|
||||
|
||||
* Go to state X: 200 gas is deducted. We satisfy *Case I* because
|
||||
`200 * N == 200 * 1`.
|
||||
* Go to state Y: 5000 gas is deducted. We satisfy *Case III* because
|
||||
`5000 + 200 * (N-1) == 5000 + 200 * 0`.
|
||||
* Go to state Z: The absolute gas used is `5000 - 15000` where 15000
|
||||
is the refund. We satisfy *Case II* because `5000 - 15000 + 200 *
|
||||
(N-1) == 5000 - 15000 + 200 * 0`.
|
||||
|
||||
#### Inductive Step
|
||||
|
||||
* From X to X. The previous gas cost is `200 * (N-1)`. The current gas
|
||||
cost is `200 + 200 * (N-1)`. It satisfy *Case I*.
|
||||
* From X to Y. The previous gas cost is `200 * (N-1)`. The current gas
|
||||
cost is `5000 + 200 * (N-1)`. It satisfy *Case III*.
|
||||
* From X to Z. The previous gas cost is `200 * (N-1)`. The current
|
||||
absolute gas cost is `5000 - 15000 + 200 * (N-1)`. It satisfy *Case
|
||||
II*.
|
||||
* From Y to X. The previous gas cost is `5000 + 200 * (N-2)`. The
|
||||
absolute current gas cost is `200 - 4800 + 5000 + 200 * (N-2)`. It
|
||||
satisfy *Case I*.
|
||||
* From Y to Y. The previous gas cost is `5000 + 200 * (N-2)`. The
|
||||
current gas cost is `200 + 5000 + 200 * (N-2)`. It satisfy *Case
|
||||
III*.
|
||||
* From Y to Z. The previous gas cost is `5000 + 200 * (N-2)`. The
|
||||
current absolute gas cost is `200 - 15000 + 5000 + 200 * (N-2)`. It
|
||||
satisfy *Case II*.
|
||||
* From Z to X. The previous gas cost is `5000 - 15000 + 200 *
|
||||
(N-2)`. The current absolute gas cost is `200 + 10200 + 5000 -
|
||||
15000 + 200 * (N-2)`. It satisfy *Case I*.
|
||||
* From Z to Y. The previous gas cost is `5000 - 15000 + 200 *
|
||||
(N-2)`. The current absolute gas cost is `200 + 15000 + 5000 -
|
||||
15000 + 200 * (N-2)`. It satisfy *Case III*.
|
||||
* From Z to Z. The previous gas cost is `5000 - 15000 + 200 *
|
||||
(N-2)`. The current absolute gas cost is `200 + 5000 - 15000 + 200 *
|
||||
(N-2)`. It satisfy *Case II*.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
Loading…
Reference in New Issue