-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
EIP-1283: Net gas metering for SSTORE without dirty maps #1283
Conversation
Replace SSTORE opcode gas cost calculation (including refunds) with | ||
the following logic: | ||
|
||
* If *current value* equals *new value* (this is a no-op), 200 gas is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following this process, starting with original = 1 and current = 1:
- new = 0; deducts 5k gas and adds 15k gas to the refund counter; current = 0.
- new = 1; adds 4800 gas to the refund counter
- Goto 1.
Thus for every 5k gas deducted from the gas meter, we can add 19800 gas to the refund counter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed! Added an additional clause when storage slot is dirty. If original value is not 0, if current value is 0 (also means that new value is not 0, because of the parent clause "If current value does not equal new value"), deduct 15000 gas.
new = 0, original = 1, current = 1
; deducts 5k gas and adds 15k gas to refund counter.new = 1, original = 1, current = 0
; deducts200 + 15k
gas, adds 4800 gas to the refund counter.original = 1, current = 1
; goto 1; for every round200 + 20k
gas is deducted, and19800
gas in the refund counter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems reasonable. A couple of critiques:
- Unlike the existing proposal, this can result in consuming a lot of gas and adding it to the refund counter. Since refunds are limited to 1/2 the total gas used, you could easily end up paying more than expected if you set a value to and from its original value a number of times.
- It's hard to follow the logic here. Some diagramming, or breaking down the cases more would help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think (1) is a really good point. If there're cases where it can cost a lot most gases compared with the current scheme, then we may break backward compatibility for existing contracts. So in 23ebc94 I changed the clause from deducting 15k gas to removing 15k gas from refund counter. In this way, we will never consume more gases compared with current scheme. Indeed, this adds a new semantics for gas refunds (we never removed gas from refund counter before), so I'm definitely open to better ideas on this. The current rationale/assumption for this is:
- Backward compatibility is important.
- We can prove that refund counter will never go below 0.
- This new semantic of removing gas from refund counter is trivial to implement in most clients.
Talking about other cases where it may cost more gases compared with EIP-1087 -- it happens with sub-call frames to the same contract where we cannot track the dirtiness. But I still think it may be worth the trade off because:
- 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 commons usages like reentry locks, same-contract multi-send, etc.
Still working on (2). Let me try to see whether there are clearer ways to describe the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an explanation section to make the logic more clearer!
…f-block optimizations
So, here's a state transition diagram as best I can establish. This diagram ignores no-op writes, which are trivial. The graph has two parts: one for where the original value is 0, and one for where the original value is nonzero. I agree that there doesn't seem to be a way to "pump" the refund counter. There are a couple of situations where a series of writes can result in moving gas in 5k chunks from gas meter to refund counter still, however - such as when the value is nonzero to start, and it's repeatedly set to another value and then back to its original value. I think a table version of this would probably be useful, too. Each of the two graphs can likely be summarised in a table fairly intuitively. Here's the graphviz source for the diagram:
|
Thanks so much! I added the diagram and the table version to the spec Explanation section (if that's okay for you)!
Yes indeed. That's the case for current scheme as well (repeatedly call SSTORE to set a slot from 0 to non-zero, and then back to zero, each cycle would cost 25k and gets 15k refund). I can't think of a way to use the methodology in this EIP to fix that, though. |
EIPS/eip-1283.md
Outdated
Below are table version of the above diagram. Horizontal shows the | ||
next state, and vertical shows the current state. | ||
|
||
| | `current=orig=0` | `current!=orig` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this be clearer if one axis had (current, original)
and the other axis had new
?
EIPS/eip-1283.md
Outdated
|
||
![State Transition](../assets/eip-1283/state.png) | ||
|
||
Below are table version of the above diagram. Horizontal shows the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you have 'horizontal' and 'vertical' reversed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Fixed!
… sp-sstore-no-dirty-map
Some test cases: ethereum/tests#483. |
Reentrancy attack returns: https://www.coindesk.com/ethereums-constantinople-upgrade-faces-delay-due-to-security-vulnerability Any ideas on mitigating? |
charge 5000, refund 4800? |
Charge 2300, refund 2100? :) |
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 uses different opetimiazation strategies for storage change
caches.
Rendered