core/vm, params: switch EIP2200 to Wei's version

This commit is contained in:
Péter Szilágyi 2019-08-16 15:55:15 +03:00
parent 5734445548
commit f95fd45898
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
3 changed files with 36 additions and 25 deletions

View file

@ -17,6 +17,8 @@
package vm package vm
import ( import (
"errors"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -160,12 +162,13 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi
return params.NetSstoreDirtyGas, nil return params.NetSstoreDirtyGas, nil
} }
// 0. If *gasleft* is less than or equal to 2300, fail the current call.
// 1. If current value equals new value (this is a no-op), SSTORE_NOOP_GAS gas is deducted. // 1. If current value equals new value (this is a no-op), SSTORE_NOOP_GAS gas is deducted.
// 2. If current value does not equal new value: // 2. If current value does not equal new value:
// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context): // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context):
// 2.1.1. If original value is 0, SSTORE_INIT_GAS gas is deducted. // 2.1.1. If original value is 0, SSTORE_INIT_GAS gas is deducted.
// 2.1.2. Otherwise, SSTORE_CLEAN_GAS gas is deducted. If new value is 0, add SSTORE_CLEAR_REFUND to refund counter. // 2.1.2. Otherwise, SSTORE_CLEAN_GAS gas is deducted. If new value is 0, add SSTORE_CLEAR_REFUND to refund counter.
// 2.2. If original value does not equal current value (this storage slot is dirty), SSTORE_DIRTY_GAS gas is deducted, SSTORE_DIRTY_REFUND is refunded. Apply both of the following clauses: // 2.2. If original value does not equal current value (this storage slot is dirty), SSTORE_DIRTY_GAS gas is deducted. Apply both of the following clauses:
// 2.2.1. If original value is not 0: // 2.2.1. If original value is not 0:
// 2.2.1.1. If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEAR_REFUND gas from refund counter. We can prove that refund counter will never go below 0. // 2.2.1.1. If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEAR_REFUND gas from refund counter. We can prove that refund counter will never go below 0.
// 2.2.1.2. If new value is 0 (also means that current value is not 0), add SSTORE_CLEAR_REFUND gas to refund counter. // 2.2.1.2. If new value is 0 (also means that current value is not 0), add SSTORE_CLEAR_REFUND gas to refund counter.
@ -173,6 +176,11 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi
// 2.2.2.1. If original value is 0, add SSTORE_INIT_REFUND to refund counter. // 2.2.2.1. If original value is 0, add SSTORE_INIT_REFUND to refund counter.
// 2.2.2.2. Otherwise, add SSTORE_CLEAN_REFUND gas to refund counter. // 2.2.2.2. Otherwise, add SSTORE_CLEAN_REFUND gas to refund counter.
func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// If we fail the minimum gas availability invariant, fail (0)
if contract.Gas <= params.SstoreSentryGasEIP2200 {
return 0, errors.New("not enough gas for reentrancy sentry")
}
// Gas sentry honoured, do the actual gas calculation based on the stored value
var ( var (
y, x = stack.Back(1), stack.Back(0) y, x = stack.Back(1), stack.Back(0)
current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
@ -206,7 +214,6 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
evm.StateDB.AddRefund(params.SstoreCleanRefundEIP2200) evm.StateDB.AddRefund(params.SstoreCleanRefundEIP2200)
} }
} }
evm.StateDB.AddRefund(params.SstoreDirtyRefundEIP2200)
return params.SstoreDirtyGasEIP2200, nil // dirty update (2.2) return params.SstoreDirtyGasEIP2200, nil // dirty update (2.2)
} }

View file

@ -50,27 +50,31 @@ func TestMemoryGasCost(t *testing.T) {
var eip2200Tests = []struct { var eip2200Tests = []struct {
original byte original byte
gaspool uint64
input string input string
used uint64 used uint64
refund uint64 refund uint64
failure error
}{ }{
{0, "0x60006000556000600055", 1612, 0}, // 0 -> 0 -> 0 {0, math.MaxUint64, "0x60006000556000600055", 1612, 0, nil}, // 0 -> 0 -> 0
{0, "0x60006000556001600055", 20812, 0}, // 0 -> 0 -> 1 {0, math.MaxUint64, "0x60006000556001600055", 20812, 0, nil}, // 0 -> 0 -> 1
{0, "0x60016000556000600055", 22312, 20700}, // 0 -> 1 -> 0 {0, math.MaxUint64, "0x60016000556000600055", 20812, 19200, nil}, // 0 -> 1 -> 0
{0, "0x60016000556002600055", 22312, 1500}, // 0 -> 1 -> 2 {0, math.MaxUint64, "0x60016000556002600055", 20812, 0, nil}, // 0 -> 1 -> 2
{0, "0x60016000556001600055", 20812, 0}, // 0 -> 1 -> 1 {0, math.MaxUint64, "0x60016000556001600055", 20812, 0, nil}, // 0 -> 1 -> 1
{1, "0x60006000556000600055", 5812, 15000}, // 1 -> 0 -> 0 {1, math.MaxUint64, "0x60006000556000600055", 5812, 15000, nil}, // 1 -> 0 -> 0
{1, "0x60006000556001600055", 7312, 5700}, // 1 -> 0 -> 1 {1, math.MaxUint64, "0x60006000556001600055", 5812, 4200, nil}, // 1 -> 0 -> 1
{1, "0x60006000556002600055", 7312, 1500}, // 1 -> 0 -> 2 {1, math.MaxUint64, "0x60006000556002600055", 5812, 0, nil}, // 1 -> 0 -> 2
{1, "0x60026000556000600055", 7312, 16500}, // 1 -> 2 -> 0 {1, math.MaxUint64, "0x60026000556000600055", 5812, 15000, nil}, // 1 -> 2 -> 0
{1, "0x60026000556003600055", 7312, 1500}, // 1 -> 2 -> 3 {1, math.MaxUint64, "0x60026000556003600055", 5812, 0, nil}, // 1 -> 2 -> 3
{1, "0x60026000556001600055", 7312, 5700}, // 1 -> 2 -> 1 {1, math.MaxUint64, "0x60026000556001600055", 5812, 4200, nil}, // 1 -> 2 -> 1
{1, "0x60026000556002600055", 5812, 0}, // 1 -> 2 -> 2 {1, math.MaxUint64, "0x60026000556002600055", 5812, 0, nil}, // 1 -> 2 -> 2
{1, "0x60016000556000600055", 5812, 15000}, // 1 -> 1 -> 0 {1, math.MaxUint64, "0x60016000556000600055", 5812, 15000, nil}, // 1 -> 1 -> 0
{1, "0x60016000556002600055", 5812, 0}, // 1 -> 1 -> 2 {1, math.MaxUint64, "0x60016000556002600055", 5812, 0, nil}, // 1 -> 1 -> 2
{1, "0x60016000556001600055", 1612, 0}, // 1 -> 1 -> 1 {1, math.MaxUint64, "0x60016000556001600055", 1612, 0, nil}, // 1 -> 1 -> 1
{0, "0x600160005560006000556001600055", 42318, 20700}, // 0 -> 1 -> 0 -> 1 {0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1
{1, "0x600060005560016000556000600055", 12318, 20700}, // 1 -> 0 -> 1 -> 0 {1, math.MaxUint64, "0x600060005560016000556000600055", 10818, 19200, nil}, // 1 -> 0 -> 1 -> 0
{1, 2306, "0x6001600055", 2306, 0, ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH)
{1, 2307, "0x6001600055", 806, 0, nil}, // 1 -> 1 (2301 sentry + 2xPUSH)
} }
func TestEIP2200(t *testing.T) { func TestEIP2200(t *testing.T) {
@ -89,11 +93,11 @@ func TestEIP2200(t *testing.T) {
} }
vmenv := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}}) vmenv := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int)) _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
if err != nil { if err != tt.failure {
t.Errorf("test %d: failed to run test: %v", i, err) t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
} }
if used := math.MaxUint64 - gas; used != tt.used { if used := tt.gaspool - gas; used != tt.used {
t.Errorf("test %d: gas used mismatch: have %v, want %v", i, used, tt.used) t.Errorf("test %d: gas used mismatch: have %v, want %v", i, used, tt.used)
} }
if refund := vmenv.StateDB.GetRefund(); refund != tt.refund { if refund := vmenv.StateDB.GetRefund(); refund != tt.refund {

View file

@ -52,9 +52,9 @@ const (
NetSstoreResetRefund uint64 = 4800 // Once per SSTORE operation for resetting to the original non-zero value NetSstoreResetRefund uint64 = 4800 // Once per SSTORE operation for resetting to the original non-zero value
NetSstoreResetClearRefund uint64 = 19800 // Once per SSTORE operation for resetting to the original zero value NetSstoreResetClearRefund uint64 = 19800 // Once per SSTORE operation for resetting to the original zero value
SstoreSentryGasEIP2200 uint64 = 2300 // Minimum gas required to be present for an SSTORE call, not consumed
SstoreNoopGasEIP2200 uint64 = 800 // Once per SSTORE operation if the value doesn't change. SstoreNoopGasEIP2200 uint64 = 800 // Once per SSTORE operation if the value doesn't change.
SstoreDirtyGasEIP2200 uint64 = 2300 // Once per SSTORE operation if the slot is already dirty SstoreDirtyGasEIP2200 uint64 = 800 // Once per SSTORE operation if a dirty value is changed.
SstoreDirtyRefundEIP2200 uint64 = 1500 // Once per SSTORE operation if the slot is already dirty
SstoreInitGasEIP2200 uint64 = 20000 // Once per SSTORE operation from clean zero to non-zero SstoreInitGasEIP2200 uint64 = 20000 // Once per SSTORE operation from clean zero to non-zero
SstoreInitRefundEIP2200 uint64 = 19200 // Once per SSTORE operation for resetting to the original zero value SstoreInitRefundEIP2200 uint64 = 19200 // Once per SSTORE operation for resetting to the original zero value
SstoreCleanGasEIP2200 uint64 = 5000 // Once per SSTORE operation from clean non-zero to something else SstoreCleanGasEIP2200 uint64 = 5000 // Once per SSTORE operation from clean non-zero to something else