diff options
Diffstat (limited to 'core/vm/gas.go')
-rw-r--r-- | core/vm/gas.go | 164 |
1 files changed, 94 insertions, 70 deletions
diff --git a/core/vm/gas.go b/core/vm/gas.go index c4d5e4c4e..e64810cd5 100644 --- a/core/vm/gas.go +++ b/core/vm/gas.go @@ -1,11 +1,9 @@ package vm -import "math/big" - -type req struct { - stack int - gas *big.Int -} +import ( + "fmt" + "math/big" +) var ( GasQuickStep = big.NewInt(2) @@ -56,75 +54,30 @@ var ( GasCopyWord = big.NewInt(3) ) -var _baseCheck = map[OpCode]req{ - // Req stack Gas price - ADD: {2, GasFastestStep}, - LT: {2, GasFastestStep}, - GT: {2, GasFastestStep}, - SLT: {2, GasFastestStep}, - SGT: {2, GasFastestStep}, - EQ: {2, GasFastestStep}, - ISZERO: {1, GasFastestStep}, - SUB: {2, GasFastestStep}, - AND: {2, GasFastestStep}, - OR: {2, GasFastestStep}, - XOR: {2, GasFastestStep}, - NOT: {1, GasFastestStep}, - BYTE: {2, GasFastestStep}, - CALLDATALOAD: {1, GasFastestStep}, - CALLDATACOPY: {3, GasFastestStep}, - MLOAD: {1, GasFastestStep}, - MSTORE: {2, GasFastestStep}, - MSTORE8: {2, GasFastestStep}, - CODECOPY: {3, GasFastestStep}, - MUL: {2, GasFastStep}, - DIV: {2, GasFastStep}, - SDIV: {2, GasFastStep}, - MOD: {2, GasFastStep}, - SMOD: {2, GasFastStep}, - SIGNEXTEND: {2, GasFastStep}, - ADDMOD: {3, GasMidStep}, - MULMOD: {3, GasMidStep}, - JUMP: {1, GasMidStep}, - JUMPI: {2, GasSlowStep}, - EXP: {2, GasSlowStep}, - ADDRESS: {0, GasQuickStep}, - ORIGIN: {0, GasQuickStep}, - CALLER: {0, GasQuickStep}, - CALLVALUE: {0, GasQuickStep}, - CODESIZE: {0, GasQuickStep}, - GASPRICE: {0, GasQuickStep}, - COINBASE: {0, GasQuickStep}, - TIMESTAMP: {0, GasQuickStep}, - NUMBER: {0, GasQuickStep}, - CALLDATASIZE: {0, GasQuickStep}, - DIFFICULTY: {0, GasQuickStep}, - GASLIMIT: {0, GasQuickStep}, - POP: {0, GasQuickStep}, - PC: {0, GasQuickStep}, - MSIZE: {0, GasQuickStep}, - GAS: {0, GasQuickStep}, - BLOCKHASH: {1, GasExtStep}, - BALANCE: {0, GasExtStep}, - EXTCODESIZE: {1, GasExtStep}, - EXTCODECOPY: {4, GasExtStep}, - SLOAD: {1, GasStorageGet}, - SSTORE: {2, Zero}, - SHA3: {1, GasSha3Base}, - CREATE: {3, GasCreate}, - CALL: {7, GasCall}, - CALLCODE: {7, GasCall}, - JUMPDEST: {0, GasJumpDest}, - SUICIDE: {1, Zero}, - RETURN: {2, Zero}, -} +func baseCheck(op OpCode, stack *stack, gas *big.Int) error { + // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit + // PUSH is also allowed to calculate the same price for all PUSHes + // DUP requirements are handled elsewhere (except for the stack limit check) + if op >= PUSH1 && op <= PUSH32 { + op = PUSH1 + } + if op >= SWAP1 && op <= SWAP16 { + op = SWAP1 + } -func baseCheck(op OpCode, stack *stack, gas *big.Int) { if r, ok := _baseCheck[op]; ok { - stack.require(r.stack) + err := stack.require(r.stackPop) + if err != nil { + return err + } + + if r.stackPush && len(stack.data)-r.stackPop == 1024 { + return fmt.Errorf("stack limit reached (%d)", maxStack) + } gas.Add(gas, r.gas) } + return nil } func toWordSize(size *big.Int) *big.Int { @@ -133,3 +86,74 @@ func toWordSize(size *big.Int) *big.Int { tmp.Div(tmp, u256(32)) return tmp } + +type req struct { + stackPop int + gas *big.Int + stackPush bool +} + +var _baseCheck = map[OpCode]req{ + // opcode | stack pop | gas price | stack push + ADD: {2, GasFastestStep, true}, + LT: {2, GasFastestStep, true}, + GT: {2, GasFastestStep, true}, + SLT: {2, GasFastestStep, true}, + SGT: {2, GasFastestStep, true}, + EQ: {2, GasFastestStep, true}, + ISZERO: {1, GasFastestStep, true}, + SUB: {2, GasFastestStep, true}, + AND: {2, GasFastestStep, true}, + OR: {2, GasFastestStep, true}, + XOR: {2, GasFastestStep, true}, + NOT: {1, GasFastestStep, true}, + BYTE: {2, GasFastestStep, true}, + CALLDATALOAD: {1, GasFastestStep, true}, + CALLDATACOPY: {3, GasFastestStep, true}, + MLOAD: {1, GasFastestStep, true}, + MSTORE: {2, GasFastestStep, false}, + MSTORE8: {2, GasFastestStep, false}, + CODECOPY: {3, GasFastestStep, false}, + MUL: {2, GasFastStep, true}, + DIV: {2, GasFastStep, true}, + SDIV: {2, GasFastStep, true}, + MOD: {2, GasFastStep, true}, + SMOD: {2, GasFastStep, true}, + SIGNEXTEND: {2, GasFastStep, true}, + ADDMOD: {3, GasMidStep, true}, + MULMOD: {3, GasMidStep, true}, + JUMP: {1, GasMidStep, false}, + JUMPI: {2, GasSlowStep, false}, + EXP: {2, GasSlowStep, true}, + ADDRESS: {0, GasQuickStep, true}, + ORIGIN: {0, GasQuickStep, true}, + CALLER: {0, GasQuickStep, true}, + CALLVALUE: {0, GasQuickStep, true}, + CODESIZE: {0, GasQuickStep, true}, + GASPRICE: {0, GasQuickStep, true}, + COINBASE: {0, GasQuickStep, true}, + TIMESTAMP: {0, GasQuickStep, true}, + NUMBER: {0, GasQuickStep, true}, + CALLDATASIZE: {0, GasQuickStep, true}, + DIFFICULTY: {0, GasQuickStep, true}, + GASLIMIT: {0, GasQuickStep, true}, + POP: {1, GasQuickStep, false}, + PC: {0, GasQuickStep, true}, + MSIZE: {0, GasQuickStep, true}, + GAS: {0, GasQuickStep, true}, + BLOCKHASH: {1, GasExtStep, true}, + BALANCE: {0, GasExtStep, true}, + EXTCODESIZE: {1, GasExtStep, true}, + EXTCODECOPY: {4, GasExtStep, false}, + SLOAD: {1, GasStorageGet, true}, + SSTORE: {2, Zero, false}, + SHA3: {1, GasSha3Base, true}, + CREATE: {3, GasCreate, true}, + CALL: {7, GasCall, true}, + CALLCODE: {7, GasCall, true}, + JUMPDEST: {0, GasJumpDest, false}, + SUICIDE: {1, Zero, false}, + RETURN: {2, Zero, false}, + PUSH1: {0, GasFastStep, true}, + DUP1: {0, Zero, true}, +} |