From 7ef08f1166a80197f8367c9df89b34e6116b104a Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 18 Jun 2019 19:19:33 +0200 Subject: [PATCH] params, core/vm: deprecating gastable, part 1 --- core/vm/gas.go | 10 +++--- core/vm/gas_table.go | 42 +++++++------------------ core/vm/interpreter.go | 4 +++ core/vm/jump_table.go | 66 ++++++++++++++++++++++++--------------- params/config.go | 2 -- params/gas_table.go | 46 ++------------------------- params/protocol_params.go | 14 +++++++++ 7 files changed, 77 insertions(+), 107 deletions(-) diff --git a/core/vm/gas.go b/core/vm/gas.go index 022a84f243..bd8b4f1042 100644 --- a/core/vm/gas.go +++ b/core/vm/gas.go @@ -18,8 +18,6 @@ package vm import ( "math/big" - - "github.com/ethereum/go-ethereum/params" ) // Gas costs @@ -34,10 +32,10 @@ const ( // calcGas returns the actual gas cost of the call. // -// The cost of gas was changed during the homestead price change HF. To allow for EIP150 -// to be implemented. The returned gas is gas - base * 63 / 64. -func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.Int) (uint64, error) { - if gasTable.CreateBySuicide > 0 { +// The cost of gas was changed during the homestead price change HF. +// As part of EIP 150 (TangerineWhistle), the returned gas is gas - base * 63 / 64. +func callGas(isEip150 bool, availableGas, base uint64, callCost *big.Int) (uint64, error) { + if isEip150 { availableGas = availableGas - base gas := availableGas - availableGas/64 // If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150 diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 8270300ba7..d3aed6c76a 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -278,10 +278,6 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta return gas, nil } -func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.ExtcodeHash, nil -} - func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var overflow bool gas, err := memoryGasCost(mem, memorySize) @@ -353,18 +349,6 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, return gas, nil } -func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.Balance, nil -} - -func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.ExtcodeSize, nil -} - -func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.SLoad, nil -} - func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) @@ -383,7 +367,8 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem gas = gt.Calls transfersValue = stack.Back(2).Sign() != 0 address = common.BigToAddress(stack.Back(1)) - eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) + eip158 = evm.chainRules.IsEIP158 + eip150 = evm.chainRules.IsEIP150 ) if eip158 { if transfersValue && evm.StateDB.Empty(address) { @@ -404,7 +389,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.callGasTemp, err = callGas(eip150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } @@ -428,7 +413,7 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } @@ -449,20 +434,17 @@ func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var gas uint64 // EIP150 homestead gas reprice fork: - if evm.ChainConfig().IsEIP150(evm.BlockNumber) { - gas = gt.Suicide - var ( - address = common.BigToAddress(stack.Back(0)) - eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) - ) + if evm.chainRules.IsEIP150 { + gas = params.SuicideGasEip150 + var address = common.BigToAddress(stack.Back(0)) - if eip158 { + if evm.chainRules.IsEIP158 { // if empty and transfers value if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { - gas += gt.CreateBySuicide + gas += params.CreateBySuicideGas } } else if !evm.StateDB.Exist(address) { - gas += gt.CreateBySuicide + gas += params.CreateBySuicideGas } } @@ -482,7 +464,7 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } @@ -502,7 +484,7 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 989f85f5d3..bb67de176e 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -95,6 +95,10 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { cfg.JumpTable = constantinopleInstructionSet case evm.ChainConfig().IsByzantium(evm.BlockNumber): cfg.JumpTable = byzantiumInstructionSet + case evm.ChainConfig().IsEIP158(evm.BlockNumber): + cfg.JumpTable = spuriousDragonInstructionSet + case evm.ChainConfig().IsEIP150(evm.BlockNumber): + cfg.JumpTable = tangerineWhistleInstructionSet case evm.ChainConfig().IsHomestead(evm.BlockNumber): cfg.JumpTable = homesteadInstructionSet default: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 425436f9e5..6ef27ee28b 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -54,10 +54,12 @@ type operation struct { } var ( - frontierInstructionSet = newFrontierInstructionSet() - homesteadInstructionSet = newHomesteadInstructionSet() - byzantiumInstructionSet = newByzantiumInstructionSet() - constantinopleInstructionSet = newConstantinopleInstructionSet() + frontierInstructionSet = newFrontierInstructionSet() + homesteadInstructionSet = newHomesteadInstructionSet() + tangerineWhistleInstructionSet = newTangerineWhistleInstructionSet() + spuriousDragonInstructionSet = newSpuriousDragonInstructionSet() + byzantiumInstructionSet = newByzantiumInstructionSet() + constantinopleInstructionSet = newConstantinopleInstructionSet() ) // NewConstantinopleInstructionSet returns the frontier, homestead @@ -87,11 +89,11 @@ func newConstantinopleInstructionSet() [256]operation { valid: true, } instructionSet[EXTCODEHASH] = operation{ - execute: opExtCodeHash, - dynamicGas: gasExtCodeHash, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opExtCodeHash, + constantGas: params.ExtcodeHashGas, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, } instructionSet[CREATE2] = operation{ execute: opCreate2, @@ -110,7 +112,7 @@ func newConstantinopleInstructionSet() [256]operation { // byzantium instructions. func newByzantiumInstructionSet() [256]operation { // instructions that can be executed during the homestead phase. - instructionSet := newHomesteadInstructionSet() + instructionSet := newSpuriousDragonInstructionSet() instructionSet[STATICCALL] = operation{ execute: opStaticCall, dynamicGas: gasStaticCall, @@ -148,6 +150,20 @@ func newByzantiumInstructionSet() [256]operation { return instructionSet } +func newSpuriousDragonInstructionSet() [256]operation { + instructionSet := newTangerineWhistleInstructionSet() + return instructionSet + +} + +func newTangerineWhistleInstructionSet() [256]operation { + instructionSet := newHomesteadInstructionSet() + instructionSet[BALANCE].constantGas = params.BalanceGasEip150 + instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEip150 + instructionSet[SLOAD].constantGas = params.SloadGasEip150 + return instructionSet +} + // NewHomesteadInstructionSet returns the frontier and homestead // instructions that can be executed during the homestead phase. func newHomesteadInstructionSet() [256]operation { @@ -346,11 +362,11 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, BALANCE: { - execute: opBalance, - dynamicGas: gasBalance, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opBalance, + constantGas: params.BalanceGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, ORIGIN: { execute: opOrigin, @@ -418,11 +434,11 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, EXTCODESIZE: { - execute: opExtCodeSize, - dynamicGas: gasExtCodeSize, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opExtCodeSize, + constantGas: params.ExtcodeSizeGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, EXTCODECOPY: { execute: opExtCodeCopy, @@ -507,11 +523,11 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, SLOAD: { - execute: opSload, - dynamicGas: gasSLoad, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opSload, + constantGas: params.SloadGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, SSTORE: { execute: opSstore, diff --git a/params/config.go b/params/config.go index c59c748ac2..6f75562d6b 100644 --- a/params/config.go +++ b/params/config.go @@ -306,8 +306,6 @@ func (c *ChainConfig) GasTable(num *big.Int) GasTable { return GasTableHomestead } switch { - case c.IsConstantinople(num): - return GasTableConstantinople case c.IsEIP158(num): return GasTableEIP158 case c.IsEIP150(num): diff --git a/params/gas_table.go b/params/gas_table.go index 6c4a38269c..d549b7e1e7 100644 --- a/params/gas_table.go +++ b/params/gas_table.go @@ -18,22 +18,10 @@ package params // GasTable organizes gas prices for different ethereum phases. type GasTable struct { - ExtcodeSize uint64 ExtcodeCopy uint64 - ExtcodeHash uint64 - Balance uint64 - SLoad uint64 Calls uint64 - Suicide uint64 ExpByte uint64 - - // CreateBySuicide occurs when the - // refunded account is one that does - // not exist. This logic is similar - // to call. May be left nil. Nil means - // not charged. - CreateBySuicide uint64 } // Variables containing gas prices for different ethereum phases. @@ -41,53 +29,23 @@ var ( // GasTableHomestead contain the gas prices for // the homestead phase. GasTableHomestead = GasTable{ - ExtcodeSize: 20, ExtcodeCopy: 20, - Balance: 20, - SLoad: 50, Calls: 40, - Suicide: 0, ExpByte: 10, } // GasTableEIP150 contain the gas re-prices for - // the EIP150 phase. + // the EIP150 phase (a.k.a TangerineWhistle). GasTableEIP150 = GasTable{ - ExtcodeSize: 700, ExtcodeCopy: 700, - Balance: 400, - SLoad: 200, Calls: 700, - Suicide: 5000, ExpByte: 10, - - CreateBySuicide: 25000, } // GasTableEIP158 contain the gas re-prices for - // the EIP155/EIP158 phase. + // the EIP155/EIP158 phase (a.k.a Spurious Dragon). GasTableEIP158 = GasTable{ - ExtcodeSize: 700, ExtcodeCopy: 700, - Balance: 400, - SLoad: 200, Calls: 700, - Suicide: 5000, ExpByte: 50, - - CreateBySuicide: 25000, - } - // GasTableConstantinople contain the gas re-prices for - // the constantinople phase. - GasTableConstantinople = GasTable{ - ExtcodeSize: 700, - ExtcodeCopy: 700, - ExtcodeHash: 400, - Balance: 400, - SLoad: 200, - Calls: 700, - Suicide: 5000, - ExpByte: 50, - - CreateBySuicide: 25000, } ) diff --git a/params/protocol_params.go b/params/protocol_params.go index 14750f6a1a..133c867aea 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -69,6 +69,20 @@ const ( MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. TxDataNonZeroGas uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + // These have been changed during the course of the chain + BalanceGasFrontier uint64 = 20 // The cost of a BALANCE operation + BalanceGasEip150 uint64 = 400 // The cost of a BALANCE operation after Tangerine Whistle + ExtcodeSizeGasFrontier uint64 = 20 // Cost of EXTCODESIZE before EIP 150 (T.W) + ExtcodeSizeGasEip150 uint64 = 700 // Cost of EXTCODESIZE after EIP 150 (T.W) + SloadGasFrontier uint64 = 50 + SloadGasEip150 uint64 = 200 + ExtcodeHashGas uint64 = 400 // Cost of EXTCODEHASH (introduced in Constantinople) + SuicideGasEip150 uint64 = 5000 // Cost of SELFDESTRUCT post T.W + // CreateBySuicide occurs when the refunded account is one that does + // not exist. This logic is similar to call. + // Introduced in Tangerine Whistle (Eip 150) + CreateBySuicideGas uint64 = 25000 + MaxCodeSize = 24576 // Maximum bytecode to permit for a contract // Precompiled contract gas prices