Skip to content

Commit

Permalink
Automatically merged updates to draft EIP(s) 1283
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sorpaas authored and eip-automerger committed Aug 9, 2018
1 parent 74d9275 commit 681a524
Showing 1 changed file with 66 additions and 45 deletions.
111 changes: 66 additions & 45 deletions EIPS/eip-1283.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,36 @@ expensive. However, EIP-1087 requires keeping a dirty map for storage
changes, and implictly 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, some implementations do the optimization to
only commit storage 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. For EIP-1087,
they will need to keep a separate dirty map to keep track of gas
costs. This adds additional memory consumptions.
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 incur additional
memory or processing costs.

This EIP proposes an alternative way for gas metering on SSTORE, using
information that is more universially available to most
implementations:

* *Storage slot's original value*. This is the value of the storage if
a call/create reversion happens on the current VM execution
context. It is universially available because all clients need to
keep track of call/create reversion.
* *Storage slot's original value*.
* *Storage slot's current value*.
* Refund counter.

This EIP indeed has edge cases where it may consume more gases
compared with EIP-1087 (see Rationale), but it can be worth the trade
off:

* We don't suffer from the optimization limitation of EIP-1087. 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 those implementations, we
cannot efficiently iterate over a transaction's storage change slots
without doing a full diff of the trie.
* It never costs more gases compared with current scheme.
* It covers most common usages.
We provided two possible specification versions here.

* For both of the two versions, we don't suffer from the optimization
limitation of EIP-1087, and it never costs more gases compared with
current scheme.
* For Version I, it covers most common usages, and we have two edge
cases it do not cover, one of which may potentially be useful.
* For Version II, it covers nearly all usages for a transient
storage. We only have one rare edge case (resetting a storage back
to its original value and then set it again) not covered. Clients
that are easy to implement EIP-1087 will also be easy to implement
Version II. Some other clients might require a little bit extra
refactoring on this. Nonetheless, no extra memory or processing cost
is needed on runtime.

Usages that benefits from this EIP's gas reduction scheme includes:

Expand All @@ -64,12 +63,21 @@ Usages that benefits from this EIP's gas reduction scheme includes:
frame, where this information does not need to be persistent outside
of a transaction. This includes sub-frame error codes and message
passing, etc.
* Passing storage information from parent call frame to sub call
frame, where this information does not need to be persistent outside
of a transaction. This is covered by Version II but not Version I.

## Specification
## Specification (Version I)

Term *original value* is as defined in Motivation. *Current value*
refers to the storage slot value before SSTORE happens. *New value*
refers to the storage slot value after SSTORE happens.
Definitions of terms are as below:

* *Storage slot's original value*: This is the value of the storage if
a call/create reversion happens on the *current VM execution
context*.
* *Storage slot's current value*: This is the value of the storage
before SSTORE operation happens.
* *Storage slot's new value*: This is the value of the storage after
SSTORE operation happens.

Replace SSTORE opcode gas cost calculation (including refunds) with
the following logic:
Expand Down Expand Up @@ -99,6 +107,14 @@ the following logic:
Refund counter works as before -- it is limited to half of the gas
consumed.

## Specification (Version II)

The same as Version I, except we change the definition of *original
value* to:

* *Storage slot's original value*: This is the value of the storage if
a reversion happens on the *current transaction*.

## Explanation

The new gas cost scheme for SSTORE is divided to three different
Expand Down Expand Up @@ -128,18 +144,19 @@ been changed (either on current call frame or a sub-call frame for the
same contract). When going from **Fresh** to **Dirty**, we charge the
gas cost the same as current scheme.

When entering a sub-call frame, a previously-marked **Dirty** storage
slot will again become **Fresh**, but only for this sub-call
frame. Note that we don't charge any more gases compared with current
scheme in this case.
For Version I, when entering a sub-call frame, a previously-marked
**Dirty** storage slot will again become **Fresh**, but only for this
sub-call frame. Note that we don't charge any more gases compared with
current scheme in this case.

In current call frame, a **Dirty** storage slot can be reset back to
**Fresh** via a SSTORE opcode either on current call frame or a
sub-call frame. For current call frame, this dirtiness is tracked, so
we can issue refunds. For sub-call frame, it is not possible to track
this dirtiness reset, so the refunds (for *current call frame*'s
initial SSTORE from **Fresh** to **Dirty**) are not issued. In the
case where refunds are not issued, the gas cost is the same as the
sub-call frame. For Version I, for current call frame, this dirtiness
is tracked, so we can issue refunds. For sub-call frame, it is not
possible to track this dirtiness reset, so the refunds (for *current
call frame*'s initial SSTORE from **Fresh** to **Dirty**) are not
issued. This refund is tracked on Version II, and issued properly. In
the case where refunds are not issued, the gas cost is the same as the
current scheme.

When a storage slot remains at **Dirty**, we charge 200 gas. In this
Expand All @@ -156,9 +173,9 @@ sub-call frame.

Below is a graph ([by
@Arachnid](https://github.com/ethereum/EIPs/pull/1283#issuecomment-410229053))
showing possible state transition of gas costs. Note that this applies
to current call frame only, and we ignore **No-op** state because that
is trivial:
showing possible state transition of gas costs. Note that for Version
I, this applies to current call frame only, and we ignore **No-op**
state because that is trivial:

![State Transition](../assets/eip-1283/state.png)

Expand All @@ -183,12 +200,15 @@ When *original value* is not 0:

## Rationale

This EIP mostly archives what EIP-1087 tries to do, but without the
complexity of introducing the concept of "dirty maps". One limitation
is that for some edge cases dirtiness will not be tracked:
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. One limitation is
that for some edge cases dirtiness will not be tracked:

* The first SSTORE for a storage slot on a sub-call frame for the same
contract won't benefit from gas reduction.
* For Version I, the first SSTORE for a storage slot on a sub-call
frame for the same contract won't benefit from gas reduction. For
Version II, this type of gas reduction is properly tracked and
applied.
* If a storage slot is changed, and it's reset to its original
value. The next SSTORE to the same storage slot won't benefit from
gas reduction.
Expand Down Expand Up @@ -219,7 +239,8 @@ To be added.

## Implementation

To be added.
* Parity Ethereum: [Version I
PR](https://github.com/paritytech/parity-ethereum/pull/9319).

## Copyright

Expand Down

0 comments on commit 681a524

Please sign in to comment.