params, core/vm: deprecating gastable, part 1

This commit is contained in:
Martin Holst Swende 2019-06-18 19:19:33 +02:00
parent d6ccfd92f7
commit 7ef08f1166
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
7 changed files with 77 additions and 107 deletions

View file

@ -18,8 +18,6 @@ package vm
import ( import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/params"
) )
// Gas costs // Gas costs
@ -34,10 +32,10 @@ const (
// calcGas returns the actual gas cost of the call. // 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 // The cost of gas was changed during the homestead price change HF.
// to be implemented. The returned gas is gas - base * 63 / 64. // As part of EIP 150 (TangerineWhistle), the returned gas is gas - base * 63 / 64.
func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.Int) (uint64, error) { func callGas(isEip150 bool, availableGas, base uint64, callCost *big.Int) (uint64, error) {
if gasTable.CreateBySuicide > 0 { if isEip150 {
availableGas = availableGas - base availableGas = availableGas - base
gas := availableGas - availableGas/64 gas := availableGas - availableGas/64
// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150 // If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150

View file

@ -278,10 +278,6 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta
return gas, nil 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) { func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var overflow bool var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
@ -353,18 +349,6 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil 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) { 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) 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 gas = gt.Calls
transfersValue = stack.Back(2).Sign() != 0 transfersValue = stack.Back(2).Sign() != 0
address = common.BigToAddress(stack.Back(1)) address = common.BigToAddress(stack.Back(1))
eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) eip158 = evm.chainRules.IsEIP158
eip150 = evm.chainRules.IsEIP150
) )
if eip158 { if eip158 {
if transfersValue && evm.StateDB.Empty(address) { 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 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 { if err != nil {
return 0, err return 0, err
} }
@ -428,7 +413,7 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return 0, errGasUintOverflow 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 { if err != nil {
return 0, err 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) { func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var gas uint64 var gas uint64
// EIP150 homestead gas reprice fork: // EIP150 homestead gas reprice fork:
if evm.ChainConfig().IsEIP150(evm.BlockNumber) { if evm.chainRules.IsEIP150 {
gas = gt.Suicide gas = params.SuicideGasEip150
var ( var address = common.BigToAddress(stack.Back(0))
address = common.BigToAddress(stack.Back(0))
eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber)
)
if eip158 { if evm.chainRules.IsEIP158 {
// if empty and transfers value // if empty and transfers value
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
gas += gt.CreateBySuicide gas += params.CreateBySuicideGas
} }
} else if !evm.StateDB.Exist(address) { } 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 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 { if err != nil {
return 0, err return 0, err
} }
@ -502,7 +484,7 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac
return 0, errGasUintOverflow 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 { if err != nil {
return 0, err return 0, err
} }

View file

@ -95,6 +95,10 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
cfg.JumpTable = constantinopleInstructionSet cfg.JumpTable = constantinopleInstructionSet
case evm.ChainConfig().IsByzantium(evm.BlockNumber): case evm.ChainConfig().IsByzantium(evm.BlockNumber):
cfg.JumpTable = byzantiumInstructionSet 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): case evm.ChainConfig().IsHomestead(evm.BlockNumber):
cfg.JumpTable = homesteadInstructionSet cfg.JumpTable = homesteadInstructionSet
default: default:

View file

@ -56,6 +56,8 @@ type operation struct {
var ( var (
frontierInstructionSet = newFrontierInstructionSet() frontierInstructionSet = newFrontierInstructionSet()
homesteadInstructionSet = newHomesteadInstructionSet() homesteadInstructionSet = newHomesteadInstructionSet()
tangerineWhistleInstructionSet = newTangerineWhistleInstructionSet()
spuriousDragonInstructionSet = newSpuriousDragonInstructionSet()
byzantiumInstructionSet = newByzantiumInstructionSet() byzantiumInstructionSet = newByzantiumInstructionSet()
constantinopleInstructionSet = newConstantinopleInstructionSet() constantinopleInstructionSet = newConstantinopleInstructionSet()
) )
@ -88,7 +90,7 @@ func newConstantinopleInstructionSet() [256]operation {
} }
instructionSet[EXTCODEHASH] = operation{ instructionSet[EXTCODEHASH] = operation{
execute: opExtCodeHash, execute: opExtCodeHash,
dynamicGas: gasExtCodeHash, constantGas: params.ExtcodeHashGas,
minStack: minStack(1, 1), minStack: minStack(1, 1),
maxStack: maxStack(1, 1), maxStack: maxStack(1, 1),
valid: true, valid: true,
@ -110,7 +112,7 @@ func newConstantinopleInstructionSet() [256]operation {
// byzantium instructions. // byzantium instructions.
func newByzantiumInstructionSet() [256]operation { func newByzantiumInstructionSet() [256]operation {
// instructions that can be executed during the homestead phase. // instructions that can be executed during the homestead phase.
instructionSet := newHomesteadInstructionSet() instructionSet := newSpuriousDragonInstructionSet()
instructionSet[STATICCALL] = operation{ instructionSet[STATICCALL] = operation{
execute: opStaticCall, execute: opStaticCall,
dynamicGas: gasStaticCall, dynamicGas: gasStaticCall,
@ -148,6 +150,20 @@ func newByzantiumInstructionSet() [256]operation {
return instructionSet 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 // NewHomesteadInstructionSet returns the frontier and homestead
// instructions that can be executed during the homestead phase. // instructions that can be executed during the homestead phase.
func newHomesteadInstructionSet() [256]operation { func newHomesteadInstructionSet() [256]operation {
@ -347,7 +363,7 @@ func newFrontierInstructionSet() [256]operation {
}, },
BALANCE: { BALANCE: {
execute: opBalance, execute: opBalance,
dynamicGas: gasBalance, constantGas: params.BalanceGasFrontier,
minStack: minStack(1, 1), minStack: minStack(1, 1),
maxStack: maxStack(1, 1), maxStack: maxStack(1, 1),
valid: true, valid: true,
@ -419,7 +435,7 @@ func newFrontierInstructionSet() [256]operation {
}, },
EXTCODESIZE: { EXTCODESIZE: {
execute: opExtCodeSize, execute: opExtCodeSize,
dynamicGas: gasExtCodeSize, constantGas: params.ExtcodeSizeGasFrontier,
minStack: minStack(1, 1), minStack: minStack(1, 1),
maxStack: maxStack(1, 1), maxStack: maxStack(1, 1),
valid: true, valid: true,
@ -508,7 +524,7 @@ func newFrontierInstructionSet() [256]operation {
}, },
SLOAD: { SLOAD: {
execute: opSload, execute: opSload,
dynamicGas: gasSLoad, constantGas: params.SloadGasFrontier,
minStack: minStack(1, 1), minStack: minStack(1, 1),
maxStack: maxStack(1, 1), maxStack: maxStack(1, 1),
valid: true, valid: true,

View file

@ -306,8 +306,6 @@ func (c *ChainConfig) GasTable(num *big.Int) GasTable {
return GasTableHomestead return GasTableHomestead
} }
switch { switch {
case c.IsConstantinople(num):
return GasTableConstantinople
case c.IsEIP158(num): case c.IsEIP158(num):
return GasTableEIP158 return GasTableEIP158
case c.IsEIP150(num): case c.IsEIP150(num):

View file

@ -18,22 +18,10 @@ package params
// GasTable organizes gas prices for different ethereum phases. // GasTable organizes gas prices for different ethereum phases.
type GasTable struct { type GasTable struct {
ExtcodeSize uint64
ExtcodeCopy uint64 ExtcodeCopy uint64
ExtcodeHash uint64
Balance uint64
SLoad uint64
Calls uint64 Calls uint64
Suicide uint64
ExpByte 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. // Variables containing gas prices for different ethereum phases.
@ -41,53 +29,23 @@ var (
// GasTableHomestead contain the gas prices for // GasTableHomestead contain the gas prices for
// the homestead phase. // the homestead phase.
GasTableHomestead = GasTable{ GasTableHomestead = GasTable{
ExtcodeSize: 20,
ExtcodeCopy: 20, ExtcodeCopy: 20,
Balance: 20,
SLoad: 50,
Calls: 40, Calls: 40,
Suicide: 0,
ExpByte: 10, ExpByte: 10,
} }
// GasTableEIP150 contain the gas re-prices for // GasTableEIP150 contain the gas re-prices for
// the EIP150 phase. // the EIP150 phase (a.k.a TangerineWhistle).
GasTableEIP150 = GasTable{ GasTableEIP150 = GasTable{
ExtcodeSize: 700,
ExtcodeCopy: 700, ExtcodeCopy: 700,
Balance: 400,
SLoad: 200,
Calls: 700, Calls: 700,
Suicide: 5000,
ExpByte: 10, ExpByte: 10,
CreateBySuicide: 25000,
} }
// GasTableEIP158 contain the gas re-prices for // GasTableEIP158 contain the gas re-prices for
// the EIP155/EIP158 phase. // the EIP155/EIP158 phase (a.k.a Spurious Dragon).
GasTableEIP158 = GasTable{ GasTableEIP158 = GasTable{
ExtcodeSize: 700,
ExtcodeCopy: 700, ExtcodeCopy: 700,
Balance: 400,
SLoad: 200,
Calls: 700, Calls: 700,
Suicide: 5000,
ExpByte: 50, 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,
} }
) )

View file

@ -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. 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. 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 MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
// Precompiled contract gas prices // Precompiled contract gas prices