core/vm, params: deprecate gastable, use both constant and dynamic gas

This commit is contained in:
Martin Holst Swende 2019-06-18 21:55:30 +02:00
parent 7ef08f1166
commit be2827213a
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
4 changed files with 109 additions and 140 deletions

View file

@ -59,11 +59,6 @@ func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *St
return 0, err return 0, err
} }
var overflow bool
if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
return 0, errGasUintOverflow
}
words, overflow := bigUint64(stack.Back(2)) words, overflow := bigUint64(stack.Back(2))
if overflow { if overflow {
return 0, errGasUintOverflow return 0, errGasUintOverflow
@ -85,11 +80,6 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *
return 0, err return 0, err
} }
var overflow bool
if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
return 0, errGasUintOverflow
}
words, overflow := bigUint64(stack.Back(2)) words, overflow := bigUint64(stack.Back(2))
if overflow { if overflow {
return 0, errGasUintOverflow return 0, errGasUintOverflow
@ -211,10 +201,6 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
return 0, err return 0, err
} }
if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow {
return 0, errGasUintOverflow
}
wordGas, overflow := bigUint64(stack.Back(1)) wordGas, overflow := bigUint64(stack.Back(1))
if overflow { if overflow {
return 0, errGasUintOverflow return 0, errGasUintOverflow
@ -235,10 +221,6 @@ func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
} }
var overflow bool var overflow bool
if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
return 0, errGasUintOverflow
}
wordGas, overflow := bigUint64(stack.Back(2)) wordGas, overflow := bigUint64(stack.Back(2))
if overflow { if overflow {
return 0, errGasUintOverflow return 0, errGasUintOverflow
@ -259,9 +241,6 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta
} }
var overflow bool var overflow bool
if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow {
return 0, errGasUintOverflow
}
wordGas, overflow := bigUint64(stack.Back(3)) wordGas, overflow := bigUint64(stack.Back(3))
if overflow { if overflow {
@ -279,62 +258,26 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta
} }
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 return memoryGasCost(mem, memorySize)
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, errGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
return 0, errGasUintOverflow
}
return gas, nil
} }
func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var overflow bool return memoryGasCost(mem, memorySize)
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, errGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
return 0, errGasUintOverflow
}
return gas, nil
} }
func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var overflow bool return memoryGasCost(mem, memorySize)
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, errGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
return 0, errGasUintOverflow
}
return gas, nil
} }
func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var overflow bool return memoryGasCost(mem, memorySize)
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow {
return 0, errGasUintOverflow
}
return gas, nil
} }
func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
} }
if gas, overflow = math.SafeAdd(gas, params.Create2Gas); overflow {
return 0, errGasUintOverflow
}
wordGas, overflow := bigUint64(stack.Back(2)) wordGas, overflow := bigUint64(stack.Back(2))
if overflow { if overflow {
return 0, errGasUintOverflow return 0, errGasUintOverflow
@ -349,11 +292,24 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil return gas, nil
} }
func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasExpFrontier(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)
var ( var (
gas = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas gas = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas
overflow bool
)
if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
return 0, errGasUintOverflow
}
return gas, nil
}
func gasExpEip158(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)
var (
gas = expByteLen * params.ExpByteEip158 // no overflow check required. Max is 256 * ExpByte gas
overflow bool overflow bool
) )
if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {

View file

@ -96,14 +96,15 @@ func newConstantinopleInstructionSet() [256]operation {
valid: true, valid: true,
} }
instructionSet[CREATE2] = operation{ instructionSet[CREATE2] = operation{
execute: opCreate2, execute: opCreate2,
dynamicGas: gasCreate2, constantGas: params.Create2Gas,
minStack: minStack(4, 1), dynamicGas: gasCreate2,
maxStack: maxStack(4, 1), minStack: minStack(4, 1),
memorySize: memoryCreate2, maxStack: maxStack(4, 1),
valid: true, memorySize: memoryCreate2,
writes: true, valid: true,
returns: true, writes: true,
returns: true,
} }
return instructionSet return instructionSet
} }
@ -130,12 +131,13 @@ func newByzantiumInstructionSet() [256]operation {
valid: true, valid: true,
} }
instructionSet[RETURNDATACOPY] = operation{ instructionSet[RETURNDATACOPY] = operation{
execute: opReturnDataCopy, execute: opReturnDataCopy,
dynamicGas: gasReturnDataCopy, constantGas: GasFastestStep,
minStack: minStack(3, 0), dynamicGas: gasReturnDataCopy,
maxStack: maxStack(3, 0), minStack: minStack(3, 0),
memorySize: memoryReturnDataCopy, maxStack: maxStack(3, 0),
valid: true, memorySize: memoryReturnDataCopy,
valid: true,
} }
instructionSet[REVERT] = operation{ instructionSet[REVERT] = operation{
execute: opRevert, execute: opRevert,
@ -152,6 +154,7 @@ func newByzantiumInstructionSet() [256]operation {
func newSpuriousDragonInstructionSet() [256]operation { func newSpuriousDragonInstructionSet() [256]operation {
instructionSet := newTangerineWhistleInstructionSet() instructionSet := newTangerineWhistleInstructionSet()
instructionSet[EXP].dynamicGas = gasExpEip158
return instructionSet return instructionSet
} }
@ -161,6 +164,7 @@ func newTangerineWhistleInstructionSet() [256]operation {
instructionSet[BALANCE].constantGas = params.BalanceGasEip150 instructionSet[BALANCE].constantGas = params.BalanceGasEip150
instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEip150 instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEip150
instructionSet[SLOAD].constantGas = params.SloadGasEip150 instructionSet[SLOAD].constantGas = params.SloadGasEip150
instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEip150
return instructionSet return instructionSet
} }
@ -257,7 +261,7 @@ func newFrontierInstructionSet() [256]operation {
}, },
EXP: { EXP: {
execute: opExp, execute: opExp,
dynamicGas: gasExp, dynamicGas: gasExpFrontier,
minStack: minStack(2, 1), minStack: minStack(2, 1),
maxStack: maxStack(2, 1), maxStack: maxStack(2, 1),
valid: true, valid: true,
@ -347,12 +351,13 @@ func newFrontierInstructionSet() [256]operation {
valid: true, valid: true,
}, },
SHA3: { SHA3: {
execute: opSha3, execute: opSha3,
dynamicGas: gasSha3, constantGas: params.Sha3Gas,
minStack: minStack(2, 1), dynamicGas: gasSha3,
maxStack: maxStack(2, 1), minStack: minStack(2, 1),
memorySize: memorySha3, maxStack: maxStack(2, 1),
valid: true, memorySize: memorySha3,
valid: true,
}, },
ADDRESS: { ADDRESS: {
execute: opAddress, execute: opAddress,
@ -404,12 +409,13 @@ func newFrontierInstructionSet() [256]operation {
valid: true, valid: true,
}, },
CALLDATACOPY: { CALLDATACOPY: {
execute: opCallDataCopy, execute: opCallDataCopy,
dynamicGas: gasCallDataCopy, constantGas: GasFastestStep,
minStack: minStack(3, 0), dynamicGas: gasCallDataCopy,
maxStack: maxStack(3, 0), minStack: minStack(3, 0),
memorySize: memoryCallDataCopy, maxStack: maxStack(3, 0),
valid: true, memorySize: memoryCallDataCopy,
valid: true,
}, },
CODESIZE: { CODESIZE: {
execute: opCodeSize, execute: opCodeSize,
@ -419,12 +425,13 @@ func newFrontierInstructionSet() [256]operation {
valid: true, valid: true,
}, },
CODECOPY: { CODECOPY: {
execute: opCodeCopy, execute: opCodeCopy,
dynamicGas: gasCodeCopy, constantGas: GasFastestStep,
minStack: minStack(3, 0), dynamicGas: gasCodeCopy,
maxStack: maxStack(3, 0), minStack: minStack(3, 0),
memorySize: memoryCodeCopy, maxStack: maxStack(3, 0),
valid: true, memorySize: memoryCodeCopy,
valid: true,
}, },
GASPRICE: { GASPRICE: {
execute: opGasprice, execute: opGasprice,
@ -441,12 +448,13 @@ func newFrontierInstructionSet() [256]operation {
valid: true, valid: true,
}, },
EXTCODECOPY: { EXTCODECOPY: {
execute: opExtCodeCopy, execute: opExtCodeCopy,
dynamicGas: gasExtCodeCopy, constantGas: params.ExtcodeCopyBaseFrontier,
minStack: minStack(4, 0), dynamicGas: gasExtCodeCopy,
maxStack: maxStack(4, 0), minStack: minStack(4, 0),
memorySize: memoryExtCodeCopy, maxStack: maxStack(4, 0),
valid: true, memorySize: memoryExtCodeCopy,
valid: true,
}, },
BLOCKHASH: { BLOCKHASH: {
execute: opBlockhash, execute: opBlockhash,
@ -498,27 +506,30 @@ func newFrontierInstructionSet() [256]operation {
valid: true, valid: true,
}, },
MLOAD: { MLOAD: {
execute: opMload, execute: opMload,
dynamicGas: gasMLoad, constantGas: GasFastestStep,
minStack: minStack(1, 1), dynamicGas: gasMLoad,
maxStack: maxStack(1, 1), minStack: minStack(1, 1),
memorySize: memoryMLoad, maxStack: maxStack(1, 1),
valid: true, memorySize: memoryMLoad,
valid: true,
}, },
MSTORE: { MSTORE: {
execute: opMstore, execute: opMstore,
dynamicGas: gasMStore, constantGas: GasFastestStep,
minStack: minStack(2, 0), dynamicGas: gasMStore,
maxStack: maxStack(2, 0), minStack: minStack(2, 0),
memorySize: memoryMStore, maxStack: maxStack(2, 0),
valid: true, memorySize: memoryMStore,
valid: true,
}, },
MSTORE8: { MSTORE8: {
execute: opMstore8, execute: opMstore8,
dynamicGas: gasMStore8, constantGas: GasFastestStep,
memorySize: memoryMStore8, dynamicGas: gasMStore8,
minStack: minStack(2, 0), memorySize: memoryMStore8,
maxStack: maxStack(2, 0), minStack: minStack(2, 0),
maxStack: maxStack(2, 0),
valid: true, valid: true,
}, },
@ -1075,14 +1086,15 @@ func newFrontierInstructionSet() [256]operation {
writes: true, writes: true,
}, },
CREATE: { CREATE: {
execute: opCreate, execute: opCreate,
dynamicGas: gasCreate, constantGas: params.CreateGas,
minStack: minStack(3, 1), dynamicGas: gasCreate,
maxStack: maxStack(3, 1), minStack: minStack(3, 1),
memorySize: memoryCreate, maxStack: maxStack(3, 1),
valid: true, memorySize: memoryCreate,
writes: true, valid: true,
returns: true, writes: true,
returns: true,
}, },
CALL: { CALL: {
execute: opCall, execute: opCall,

View file

@ -18,10 +18,7 @@ package params
// GasTable organizes gas prices for different ethereum phases. // GasTable organizes gas prices for different ethereum phases.
type GasTable struct { type GasTable struct {
ExtcodeCopy uint64 Calls uint64
Calls uint64
ExpByte uint64
} }
// Variables containing gas prices for different ethereum phases. // Variables containing gas prices for different ethereum phases.
@ -29,23 +26,17 @@ var (
// GasTableHomestead contain the gas prices for // GasTableHomestead contain the gas prices for
// the homestead phase. // the homestead phase.
GasTableHomestead = GasTable{ GasTableHomestead = GasTable{
ExtcodeCopy: 20, Calls: 40,
Calls: 40,
ExpByte: 10,
} }
// GasTableEIP150 contain the gas re-prices for // GasTableEIP150 contain the gas re-prices for
// the EIP150 phase (a.k.a TangerineWhistle). // the EIP150 phase (a.k.a TangerineWhistle).
GasTableEIP150 = GasTable{ GasTableEIP150 = GasTable{
ExtcodeCopy: 700, Calls: 700,
Calls: 700,
ExpByte: 10,
} }
// GasTableEIP158 contain the gas re-prices for // GasTableEIP158 contain the gas re-prices for
// the EIP155/EIP158 phase (a.k.a Spurious Dragon). // the EIP155/EIP158 phase (a.k.a Spurious Dragon).
GasTableEIP158 = GasTable{ GasTableEIP158 = GasTable{
ExtcodeCopy: 700, Calls: 700,
Calls: 700,
ExpByte: 50,
} }
) )

View file

@ -78,6 +78,16 @@ const (
SloadGasEip150 uint64 = 200 SloadGasEip150 uint64 = 200
ExtcodeHashGas uint64 = 400 // Cost of EXTCODEHASH (introduced in Constantinople) ExtcodeHashGas uint64 = 400 // Cost of EXTCODEHASH (introduced in Constantinople)
SuicideGasEip150 uint64 = 5000 // Cost of SELFDESTRUCT post T.W SuicideGasEip150 uint64 = 5000 // Cost of SELFDESTRUCT post T.W
// EXP has a dynamic portion depending on the size of the exponent
ExpByteFrontier uint64 = 10 // was set to 10 in Frontier
ExpByteEip158 uint64 = 50 // was raised to 50 during Eip158 (Spurious Dragon)
// Extcodecopy has a dynamic AND a static cost. This represents only the
// static portion of the gas. It was changed during EIP 150 (Tangerine Whistle)
ExtcodeCopyBaseFrontier uint64 = 20
ExtcodeCopyBaseEip150 uint64 = 700
// CreateBySuicide occurs when the refunded account is one that does // CreateBySuicide occurs when the refunded account is one that does
// not exist. This logic is similar to call. // not exist. This logic is similar to call.
// Introduced in Tangerine Whistle (Eip 150) // Introduced in Tangerine Whistle (Eip 150)