diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index d3aed6c76a..d8abba0ca1 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -59,11 +59,6 @@ func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *St return 0, err } - var overflow bool - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - words, overflow := bigUint64(stack.Back(2)) if overflow { return 0, errGasUintOverflow @@ -85,11 +80,6 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack * return 0, err } - var overflow bool - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - words, overflow := bigUint64(stack.Back(2)) if overflow { return 0, errGasUintOverflow @@ -211,10 +201,6 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem return 0, err } - if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow { - return 0, errGasUintOverflow - } - wordGas, overflow := bigUint64(stack.Back(1)) if overflow { return 0, errGasUintOverflow @@ -235,10 +221,6 @@ func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, } var overflow bool - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - wordGas, overflow := bigUint64(stack.Back(2)) if overflow { return 0, errGasUintOverflow @@ -259,9 +241,6 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta } var overflow bool - if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow { - return 0, errGasUintOverflow - } wordGas, overflow := bigUint64(stack.Back(3)) 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) { - var overflow bool - 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 + return memoryGasCost(mem, memorySize) } func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - 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 + return memoryGasCost(mem, memorySize) } func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - 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 + return memoryGasCost(mem, memorySize) } func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - 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 + return memoryGasCost(mem, memorySize) } 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) if err != nil { return 0, err } - if gas, overflow = math.SafeAdd(gas, params.Create2Gas); overflow { - return 0, errGasUintOverflow - } wordGas, overflow := bigUint64(stack.Back(2)) if overflow { return 0, errGasUintOverflow @@ -349,11 +292,24 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, 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) 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 ) if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 6ef27ee28b..793bc74af7 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -96,14 +96,15 @@ func newConstantinopleInstructionSet() [256]operation { valid: true, } instructionSet[CREATE2] = operation{ - execute: opCreate2, - dynamicGas: gasCreate2, - minStack: minStack(4, 1), - maxStack: maxStack(4, 1), - memorySize: memoryCreate2, - valid: true, - writes: true, - returns: true, + execute: opCreate2, + constantGas: params.Create2Gas, + dynamicGas: gasCreate2, + minStack: minStack(4, 1), + maxStack: maxStack(4, 1), + memorySize: memoryCreate2, + valid: true, + writes: true, + returns: true, } return instructionSet } @@ -130,12 +131,13 @@ func newByzantiumInstructionSet() [256]operation { valid: true, } instructionSet[RETURNDATACOPY] = operation{ - execute: opReturnDataCopy, - dynamicGas: gasReturnDataCopy, - minStack: minStack(3, 0), - maxStack: maxStack(3, 0), - memorySize: memoryReturnDataCopy, - valid: true, + execute: opReturnDataCopy, + constantGas: GasFastestStep, + dynamicGas: gasReturnDataCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryReturnDataCopy, + valid: true, } instructionSet[REVERT] = operation{ execute: opRevert, @@ -152,6 +154,7 @@ func newByzantiumInstructionSet() [256]operation { func newSpuriousDragonInstructionSet() [256]operation { instructionSet := newTangerineWhistleInstructionSet() + instructionSet[EXP].dynamicGas = gasExpEip158 return instructionSet } @@ -161,6 +164,7 @@ func newTangerineWhistleInstructionSet() [256]operation { instructionSet[BALANCE].constantGas = params.BalanceGasEip150 instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEip150 instructionSet[SLOAD].constantGas = params.SloadGasEip150 + instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEip150 return instructionSet } @@ -257,7 +261,7 @@ func newFrontierInstructionSet() [256]operation { }, EXP: { execute: opExp, - dynamicGas: gasExp, + dynamicGas: gasExpFrontier, minStack: minStack(2, 1), maxStack: maxStack(2, 1), valid: true, @@ -347,12 +351,13 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, SHA3: { - execute: opSha3, - dynamicGas: gasSha3, - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - memorySize: memorySha3, - valid: true, + execute: opSha3, + constantGas: params.Sha3Gas, + dynamicGas: gasSha3, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + memorySize: memorySha3, + valid: true, }, ADDRESS: { execute: opAddress, @@ -404,12 +409,13 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, CALLDATACOPY: { - execute: opCallDataCopy, - dynamicGas: gasCallDataCopy, - minStack: minStack(3, 0), - maxStack: maxStack(3, 0), - memorySize: memoryCallDataCopy, - valid: true, + execute: opCallDataCopy, + constantGas: GasFastestStep, + dynamicGas: gasCallDataCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryCallDataCopy, + valid: true, }, CODESIZE: { execute: opCodeSize, @@ -419,12 +425,13 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, CODECOPY: { - execute: opCodeCopy, - dynamicGas: gasCodeCopy, - minStack: minStack(3, 0), - maxStack: maxStack(3, 0), - memorySize: memoryCodeCopy, - valid: true, + execute: opCodeCopy, + constantGas: GasFastestStep, + dynamicGas: gasCodeCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryCodeCopy, + valid: true, }, GASPRICE: { execute: opGasprice, @@ -441,12 +448,13 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, EXTCODECOPY: { - execute: opExtCodeCopy, - dynamicGas: gasExtCodeCopy, - minStack: minStack(4, 0), - maxStack: maxStack(4, 0), - memorySize: memoryExtCodeCopy, - valid: true, + execute: opExtCodeCopy, + constantGas: params.ExtcodeCopyBaseFrontier, + dynamicGas: gasExtCodeCopy, + minStack: minStack(4, 0), + maxStack: maxStack(4, 0), + memorySize: memoryExtCodeCopy, + valid: true, }, BLOCKHASH: { execute: opBlockhash, @@ -498,27 +506,30 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, MLOAD: { - execute: opMload, - dynamicGas: gasMLoad, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - memorySize: memoryMLoad, - valid: true, + execute: opMload, + constantGas: GasFastestStep, + dynamicGas: gasMLoad, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + memorySize: memoryMLoad, + valid: true, }, MSTORE: { - execute: opMstore, - dynamicGas: gasMStore, - minStack: minStack(2, 0), - maxStack: maxStack(2, 0), - memorySize: memoryMStore, - valid: true, + execute: opMstore, + constantGas: GasFastestStep, + dynamicGas: gasMStore, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryMStore, + valid: true, }, MSTORE8: { - execute: opMstore8, - dynamicGas: gasMStore8, - memorySize: memoryMStore8, - minStack: minStack(2, 0), - maxStack: maxStack(2, 0), + execute: opMstore8, + constantGas: GasFastestStep, + dynamicGas: gasMStore8, + memorySize: memoryMStore8, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), valid: true, }, @@ -1075,14 +1086,15 @@ func newFrontierInstructionSet() [256]operation { writes: true, }, CREATE: { - execute: opCreate, - dynamicGas: gasCreate, - minStack: minStack(3, 1), - maxStack: maxStack(3, 1), - memorySize: memoryCreate, - valid: true, - writes: true, - returns: true, + execute: opCreate, + constantGas: params.CreateGas, + dynamicGas: gasCreate, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + memorySize: memoryCreate, + valid: true, + writes: true, + returns: true, }, CALL: { execute: opCall, diff --git a/params/gas_table.go b/params/gas_table.go index d549b7e1e7..41b5e8e821 100644 --- a/params/gas_table.go +++ b/params/gas_table.go @@ -18,10 +18,7 @@ package params // GasTable organizes gas prices for different ethereum phases. type GasTable struct { - ExtcodeCopy uint64 - Calls uint64 - - ExpByte uint64 + Calls uint64 } // Variables containing gas prices for different ethereum phases. @@ -29,23 +26,17 @@ var ( // GasTableHomestead contain the gas prices for // the homestead phase. GasTableHomestead = GasTable{ - ExtcodeCopy: 20, - Calls: 40, - ExpByte: 10, + Calls: 40, } // GasTableEIP150 contain the gas re-prices for // the EIP150 phase (a.k.a TangerineWhistle). GasTableEIP150 = GasTable{ - ExtcodeCopy: 700, - Calls: 700, - ExpByte: 10, + Calls: 700, } // GasTableEIP158 contain the gas re-prices for // the EIP155/EIP158 phase (a.k.a Spurious Dragon). GasTableEIP158 = GasTable{ - ExtcodeCopy: 700, - Calls: 700, - ExpByte: 50, + Calls: 700, } ) diff --git a/params/protocol_params.go b/params/protocol_params.go index 133c867aea..42b8c19a97 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -78,6 +78,16 @@ const ( SloadGasEip150 uint64 = 200 ExtcodeHashGas uint64 = 400 // Cost of EXTCODEHASH (introduced in Constantinople) 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 // not exist. This logic is similar to call. // Introduced in Tangerine Whistle (Eip 150)