From 58374e28d95c03d8b0e6d9035c0fb92fad3e865e Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 11 Aug 2018 23:03:54 +0200 Subject: core, state: initial implementation of Eip-1283 --- core/vm/gas_table.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++- core/vm/interface.go | 1 + core/vm/noop.go | 1 + 3 files changed, 60 insertions(+), 1 deletion(-) (limited to 'core/vm') diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index f9eea319e..aee6d6f6d 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -17,9 +17,11 @@ package vm import ( + "bytes" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" + "math/big" ) // memoryGasCosts calculates the quadratic gas for memory expansion. It does so @@ -115,7 +117,7 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack * return gas, nil } -func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSStoreOld(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var ( y, x = stack.Back(1), stack.Back(0) val = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) @@ -137,6 +139,61 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m } } +func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + var ( + y, x = stack.Back(1), stack.Back(0) + current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) + ) + //1. If current value equals new value (this is a no-op), 200 gas is deducted. + //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.1 If original value is 0, 20000 gas is deducted. + // 2.1.2 Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter. + // 2.2 If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + // 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), remove 15000 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 15000 gas to refund counter. + // 2.2.2 If original value equals new value (this storage slot is reset) + // 2.2.2.1 If original value is 0, add 19800 gas to refund counter. + // 2.2.2.2 Otherwise, add 4800 gas to refund counter. + new := common.BigToHash(y) + if current == new { + // 1. current == new + return 200, nil + } + // Todo, get this value + original := common.Hash{} + + // 2 + if original == current { // 2.1 + if original == (common.Hash{}){ // 2.1.1 + return 20000, nil + } + // 2.1.2 + if new == (common.Hash{}){ + evm.StateDB.AddRefund(15000) + } + return 5000, nil + } + // 2.2 + if original != (common.Hash{}){ // 2.2.1 + if current == (common.Hash{}){ // 2.2.1.1 + evm.StateDB.SubRefund(15000) + }else{ + // 2.2.1.2 + evm.StateDB.AddRefund(15000) + } + } + if original == new { // 2.2.2 + if original == (common.Hash{}){ + evm.StateDB.AddRefund(19800) + }else{ + evm.StateDB.AddRefund(4800) + } + } + return 200, nil +} + func makeGasLog(n uint64) gasFunc { return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { requestedSize, overflow := bigUint64(stack.Back(1)) diff --git a/core/vm/interface.go b/core/vm/interface.go index d176f5b39..a5a3ff3e3 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -40,6 +40,7 @@ type StateDB interface { GetCodeSize(common.Address) int AddRefund(uint64) + SubRefund(uint64) GetRefund() uint64 GetState(common.Address, common.Hash) common.Hash diff --git a/core/vm/noop.go b/core/vm/noop.go index b71ead0d7..c7ed2e451 100644 --- a/core/vm/noop.go +++ b/core/vm/noop.go @@ -56,6 +56,7 @@ func (NoopStateDB) GetCode(common.Address) []byte func (NoopStateDB) SetCode(common.Address, []byte) {} func (NoopStateDB) GetCodeSize(common.Address) int { return 0 } func (NoopStateDB) AddRefund(uint64) {} +func (NoopStateDB) SubRefund(uint64) {} func (NoopStateDB) GetRefund() uint64 { return 0 } func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} } func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {} -- cgit v1.2.3