From fb94aa8a35253871dd0cee7907bf58cce9555505 Mon Sep 17 00:00:00 2001 From: Jordan Hrycaj Date: Tue, 13 Apr 2021 18:12:47 +0100 Subject: [PATCH] re-integrated 0x3# op handlers --- nimbus/vm2/interpreter/op_handlers.nim | 7 +- .../vm2/interpreter/op_handlers/oph_defs.nim | 23 +- .../interpreter/op_handlers/oph_envinfo.nim | 370 ++++++++++++++++++ nimbus/vm2/interpreter/opcodes_impl.nim | 227 +++-------- 4 files changed, 453 insertions(+), 174 deletions(-) create mode 100644 nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim diff --git a/nimbus/vm2/interpreter/op_handlers.nim b/nimbus/vm2/interpreter/op_handlers.nim index 70bd113a5..aee0288a2 100644 --- a/nimbus/vm2/interpreter/op_handlers.nim +++ b/nimbus/vm2/interpreter/op_handlers.nim @@ -20,7 +20,7 @@ import strformat, ./op_codes, ./op_handlers/[oph_defs, - oph_arithmetic, oph_hash, + oph_arithmetic, oph_hash, oph_envinfo, oph_sysops] # ------------------------------------------------------------------------------ @@ -50,6 +50,11 @@ const doAssert rc[w.opCode].info == "" rc[w.opCode] = w + for w in vm2OpExecEnvInfo: + if w.complain("EnvInfo"): + doAssert rc[w.opCode].info == "" + rc[w.opCode] = w + for w in vm2OpExecSysOP: if w.complain("SysOp"): doAssert rc[w.opCode].info == "" diff --git a/nimbus/vm2/interpreter/op_handlers/oph_defs.nim b/nimbus/vm2/interpreter/op_handlers/oph_defs.nim index 11b70203a..1c41b9005 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_defs.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_defs.nim @@ -8,8 +8,8 @@ # at your option. This file may not be copied, modified, or distributed except # according to those terms. -## EVM Opcodes, Definitons -## ======================= +## EVM Opcodes, Definitions +## ======================== ## const @@ -36,17 +36,32 @@ else: {.fatal: "Flag \"vm2_enabled\" must be unset "& "while circular dependency breaker kludge is activated".} type + GasMeter* = object + whatever: int + + CodeStream* = ref object + bytes*: seq[byte] + + Message* = ref object + contractAddress*: UInt256 + sender*: UInt256 + value*: UInt256 + data*: seq[byte] + Computation* = ref object + gasMeter*: GasMeter stack*: Stack memory*: Memory - code: int + msg*: Message + code*: CodeStream + returnData*: seq[byte] # ------------------------------------------------------------------------------ # Kludge END # ------------------------------------------------------------------------------ export - Op, Fork, Computation, Memory, Stack, UInt256 + Op, Fork, Computation, Memory, Stack, UInt256, Message type Vm2Ctx* = object of RootObj diff --git a/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim b/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim new file mode 100644 index 000000000..6753ae78d --- /dev/null +++ b/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim @@ -0,0 +1,370 @@ +# Nimbus +# Copyright (c) 2018 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or +# http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or +# http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or distributed except +# according to those terms. + +## EVM Opcode Handlers: Environmental Information +## ============================================== +## + +const + kludge {.intdefine.}: int = 0 + breakCircularDependency {.used.} = kludge > 0 + +import + ../../../errors, + ./oph_defs, + sequtils, + strformat, + stint + +# ------------------------------------------------------------------------------ +# Kludge BEGIN +# ------------------------------------------------------------------------------ + +when not breakCircularDependency: + import + ../../code_stream, + ../../stack, + ../../v2computation, + ../../v2memory, + ../../v2state, + ../gas_meter, + ../utils/v2utils_numeric, + eth/common + +else: + import macros + + # copied from stack.nim + macro genTupleType(len: static[int], elemType: untyped): untyped = + result = nnkTupleConstr.newNimNode() + for i in 0 ..< len: result.add(elemType) + + # function stubs from stack.nim (to satisfy compiler logic) + proc push[T](x: Stack; n: T) = discard + proc popAddress(x: var Stack): UInt256 = 0.u256 + proc popInt(x: var Stack, n: static[int]): auto = + var rc: genTupleType(n, UInt256) + return rc + + # function stubs from v2computation.nim (to satisfy compiler logic) + proc getBalance[T](c: Computation, address: T): Uint256 = 0.u256 + proc getOrigin(c: Computation): Uint256 = 0.u256 + proc getGasPrice(c: Computation): Uint256 = 0.u256 + proc getCodeSize[T](c: Computation, address: T): uint = 0 + proc getCode[T](c: Computation, address: T): seq[byte] = @[] + + # function stubs from v2utils_numeric.nim + func cleanMemRef(x: UInt256): int = 0 + + # function stubs from v2memory.nim + proc len(mem: Memory): int = 0 + proc extend(mem: var Memory; startPos: Natural; size: Natural) = discard + proc write(mem: var Memory, startPos: Natural, val: openarray[byte]) = discard + + # function stubs from code_stream.nim + proc len(c: CodeStream): int = len(c.bytes) + +# ------------------------------------------------------------------------------ +# Kludge END +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +# Private helpers +# ------------------------------------------------------------------------------ + +proc writePaddedResult(mem: var Memory, + data: openarray[byte], + memPos, dataPos, len: Natural, + paddingValue = 0.byte) = + + mem.extend(memPos, len) + let dataEndPosition = dataPos.int64 + len - 1 + let sourceBytes = + data[min(dataPos, data.len) .. min(data.len - 1, dataEndPosition)] + + mem.write(memPos, sourceBytes) + + # Don't duplicate zero-padding of mem.extend + let paddingOffset = min(memPos + sourceBytes.len, mem.len) + let numPaddingBytes = min(mem.len - paddingOffset, len - sourceBytes.len) + if numPaddingBytes > 0: + # TODO: avoid unnecessary memory allocation + mem.write(paddingOffset, repeat(paddingValue, numPaddingBytes)) + +# ------------------------------------------------------------------------------ +# Private, op handlers implementation +# ------------------------------------------------------------------------------ + +const + addressOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x30, Get address of currently executing account. + k.cpt.stack.push: + k.cpt.msg.contractAddress + + balanceOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x31, Get balance of the given account. + let address = k.cpt.stack.popAddress + k.cpt.stack.push: + k.cpt.getBalance(address) + + originOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x32, Get execution origination address. + k.cpt.stack.push: + k.cpt.getOrigin() + + callerOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x33, Get caller address. + k.cpt.stack.push: + k.cpt.msg.sender + + callValueOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x34, Get deposited value by the instruction/transaction + ## responsible for this execution + k.cpt.stack.push: + k.cpt.msg.value + + callDataLoadOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x35, Get input data of current environment + let (startPos) = k.cpt.stack.popInt(1) + let start = startPos.cleanMemRef + if start >= k.cpt.msg.data.len: + k.cpt.stack.push: + 0 + return + + # If the data does not take 32 bytes, pad with zeros + let endRange = min(k.cpt.msg.data.len - 1, start + 31) + let presentBytes = endRange - start + + # We rely on value being initialized with 0 by default + var value: array[32, byte] + value[0 .. presentBytes] = k.cpt.msg.data.toOpenArray(start, endRange) + k.cpt.stack.push: + value + + + callDataSizeOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x36, Get size of input data in current environment. + k.cpt.stack.push: + k.cpt.msg.data.len.u256 + + + callDataCopyOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x37, Copy input data in current environment to memory. + let (memStartPos, copyStartPos, size) = k.cpt.stack.popInt(3) + + # TODO tests: https://github.com/status-im/nimbus/issues/67 + let (memPos, copyPos, len) = + (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) + + when not breakCircularDependency: + k.cpt.gasMeter.consumeGas( + k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len), + reason = "CallDataCopy fee") + + k.cpt.memory.writePaddedResult(k.cpt.msg.data, memPos, copyPos, len) + + + codeSizeOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x38, Get size of code running in current environment. + k.cpt.stack.push: + k.cpt.code.len + + + codeCopyOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x39, Copy code running in current environment to memory. + let (memStartPos, copyStartPos, size) = k.cpt.stack.popInt(3) + + # TODO tests: https://github.com/status-im/nimbus/issues/67 + let (memPos, copyPos, len) = + (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) + + when not breakCircularDependency: + k.cpt.gasMeter.consumeGas( + k.cpt.gasCosts[CodeCopy].m_handler(k.cpt.memory.len, memPos, len), + reason = "CodeCopy fee") + + k.cpt.memory.writePaddedResult(k.cpt.code.bytes, memPos, copyPos, len) + + + gasPriceOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x3A, Get price of gas in current environment. + k.cpt.stack.push: + k.cpt.getGasPrice + + extCodeSizeOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x3b, Get size of an account's code + let address = k.cpt.stack.popAddress() + k.cpt.stack.push: + k.cpt.getCodeSize(address) + + + extCodeCopyOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x3c, Copy an account's code to memory. + let address = k.cpt.stack.popAddress() + + let (memStartPos, codeStartPos, size) = k.cpt.stack.popInt(3) + let (memPos, codePos, len) = + (memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef) + + when not breakCircularDependency: + k.cpt.gasMeter.consumeGas( + k.cpt.gasCosts[ExtCodeCopy].m_handler(k.cpt.memory.len, memPos, len), + reason = "ExtCodeCopy fee") + + let codeBytes = k.cpt.getCode(address) + k.cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len) + + + returnDataSizeOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x3d, Get size of output data from the previous call from the + ## current environment. + k.cpt.stack.push: + k.cpt.returnData.len + + + returnDataCopyOp: Vm2OpFn = proc (k: Vm2Ctx) = + ## 0x3e, Copy output data from the previous call to memory. + let (memStartPos, copyStartPos, size) = k.cpt.stack.popInt(3) + + let (memPos, copyPos, len) = + (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) + + when not breakCircularDependency: + let gasCost = k.cpt.gasCosts[ReturnDataCopy].m_handler( + k.cpt.memory.len, memPos, len) + k.cpt.gasMeter.consumeGas(gasCost, reason = "returnDataCopy fee") + + if copyPos + len > k.cpt.returnData.len: + raise newException( + OutOfBoundsRead, + "Return data length is not sufficient to satisfy request. Asked\n"& + &"for data from index {copyStartPos} to {copyStartPos + size}. "& + &"Return data is {k.cpt.returnData.len} in \n" & + "length") + k.cpt.memory.writePaddedResult(k.cpt.returnData, memPos, copyPos, len) + +# ------------------------------------------------------------------------------ +# Public, op exec table entries +# ------------------------------------------------------------------------------ + +const + vm2OpExecEnvInfo*: seq[Vm2OpExec] = @[ + + (opCode: Address, ## 0x20, Address + forks: Vm2OpAllForks, + info: "Get address of currently executing account", + exec: (prep: vm2OpIgnore, + run: addressOp, + post: vm2OpIgnore)), + + (opCode: Balance, ## 0x31, Balance + forks: Vm2OpAllForks, + info: "Get balance of the given account", + exec: (prep: vm2OpIgnore, + run: balanceOp, + post: vm2OpIgnore)), + + (opCode: Origin, ## 0x32, Origination address + forks: Vm2OpAllForks, + info: "Get execution origination address", + exec: (prep: vm2OpIgnore, + run: originOp, + post: vm2OpIgnore)), + + (opCode: Caller, ## 0x33, Caller address + forks: Vm2OpAllForks, + info: "Get caller address", + exec: (prep: vm2OpIgnore, + run: callerOp, + post: vm2OpIgnore)), + + (opCode: CallValue, ## 0x34, Execution deposited value + forks: Vm2OpAllForks, + info: "Get deposited value by the instruction/transaction " & + "responsible for this execution", + exec: (prep: vm2OpIgnore, + run: callValueOp, + post: vm2OpIgnore)), + + (opCode: CallDataLoad, ## 0x35, Input data + forks: Vm2OpAllForks, + info: "Get input data of current environment", + exec: (prep: vm2OpIgnore, + run: callDataLoadOp, + post: vm2OpIgnore)), + + (opCode: CallDataSize, ## 0x36, Size of input data + forks: Vm2OpAllForks, + info: "Get size of input data in current environment", + exec: (prep: vm2OpIgnore, + run: callDataSizeOp, + post: vm2OpIgnore)), + + (opCode: CallDataCopy, ## 0x37, Copy input data to memory. + forks: Vm2OpAllForks, + info: "Copy input data in current environment to memory", + exec: (prep: vm2OpIgnore, + run: callDataCopyOp, + post: vm2OpIgnore)), + + (opCode: CodeSize, ## 0x38, Size of code + forks: Vm2OpAllForks, + info: "Get size of code running in current environment", + exec: (prep: vm2OpIgnore, + run: codeSizeOp, + post: vm2OpIgnore)), + + (opCode: CodeCopy, ## 0x39, Copy code to memory. + forks: Vm2OpAllForks, + info: "Copy code running in current environment to memory", + exec: (prep: vm2OpIgnore, + run: codeCopyOp, + post: vm2OpIgnore)), + + (opCode: GasPrice, ## 0x3a, Gas price + forks: Vm2OpAllForks, + info: "Get price of gas in current environment", + exec: (prep: vm2OpIgnore, + run: gasPriceOp, + post: vm2OpIgnore)), + + (opCode: ExtCodeSize, ## 0x3b, Account code size + forks: Vm2OpAllForks, + info: "Get size of an account's code", + exec: (prep: vm2OpIgnore, + run: extCodeSizeOp, + post: vm2OpIgnore)), + + (opCode: ExtCodeCopy, ## 0x3c, Account code copy to memory. + forks: Vm2OpAllForks, + info: "Copy an account's code to memory", + exec: (prep: vm2OpIgnore, + run: extCodeCopyOp, + post: vm2OpIgnore)), + + (opCode: ReturnDataSize, ## 0x3d, Previous call output data size + forks: Vm2OpAllForks, + info: "Get size of output data from the previous call " & + "from the current environment", + exec: (prep: vm2OpIgnore, + run: returnDataSizeOp, + post: vm2OpIgnore)), + + (opCode: ReturnDataCopy, ## 0x3e, Previous call output data copy to memory + forks: Vm2OpAllForks, + info: "Copy output data from the previous call to memory", + exec: (prep: vm2OpIgnore, + run: returnDataCopyOp, + post: vm2OpIgnore))] + +# ------------------------------------------------------------------------------ +# End +# ------------------------------------------------------------------------------ diff --git a/nimbus/vm2/interpreter/opcodes_impl.nim b/nimbus/vm2/interpreter/opcodes_impl.nim index 76f69c96e..195decf2c 100644 --- a/nimbus/vm2/interpreter/opcodes_impl.nim +++ b/nimbus/vm2/interpreter/opcodes_impl.nim @@ -38,6 +38,26 @@ template push(x: typed) {.dirty.} = ## Push an expression on the computation stack c.stack.push x +proc writePaddedResult(mem: var Memory, + data: openarray[byte], + memPos, dataPos, len: Natural, + paddingValue = 0.byte) = + + mem.extend(memPos, len) + let dataEndPosition = dataPos.int64 + len - 1 + let sourceBytes = data[min(dataPos, data.len) .. min(data.len - 1, dataEndPosition)] + mem.write(memPos, sourceBytes) + + # Don't duplicate zero-padding of mem.extend + let paddingOffset = min(memPos + sourceBytes.len, mem.len) + let numPaddingBytes = min(mem.len - paddingOffset, len - sourceBytes.len) + if numPaddingBytes > 0: + # TODO: avoid unnecessary memory allocation + mem.write(paddingOffset, repeat(paddingValue, numPaddingBytes)) + +# ################################## +# re-implemented OP handlers + var gdbBPHook_counter = 0 proc gdbBPHook*() = gdbBPHook_counter.inc @@ -57,175 +77,44 @@ template opHandler(callName: untyped; opCode: Op) = desc.cpt = c vm2OpTabBerlin[opCode].exec.run(desc) -# ################################## -# 0s: Stop and Arithmetic Operations - -opHandler add, Op.Add -opHandler mul, Op.Mul -opHandler sub, Op.Sub -opHandler divide, Op.Div -opHandler sdiv, Op.Sdiv -opHandler modulo, Op.Mod -opHandler smod, Op.Smod -opHandler addmod, Op.AddMod -opHandler mulmod, Op.MulMod -opHandler exp, Op.Exp -opHandler signExtend, Op.SignExtend - -# ########################################## -# 10s: Comparison & Bitwise Logic Operations - -opHandler lt, Op.Lt -opHandler gt, Op.Gt -opHandler slt, Op.Slt -opHandler sgt, Op.Sgt -opHandler eq, Op.Eq -opHandler isZero, Op.IsZero -opHandler andOp, Op.And -opHandler orOp, Op.Or -opHandler xorOp, Op.Xor -opHandler notOp, Op.Not -opHandler byteOp, Op.Byte - -# ########################################## -# 20s: SHA3 - -opHandler sha3, Op.Sha3 - -# ########################################## -# 30s: Environmental Information - -proc writePaddedResult(mem: var Memory, - data: openarray[byte], - memPos, dataPos, len: Natural, - paddingValue = 0.byte) = - - mem.extend(memPos, len) - let dataEndPosition = dataPos.int64 + len - 1 - let sourceBytes = data[min(dataPos, data.len) .. min(data.len - 1, dataEndPosition)] - mem.write(memPos, sourceBytes) - - # Don't duplicate zero-padding of mem.extend - let paddingOffset = min(memPos + sourceBytes.len, mem.len) - let numPaddingBytes = min(mem.len - paddingOffset, len - sourceBytes.len) - if numPaddingBytes > 0: - # TODO: avoid unnecessary memory allocation - mem.write(paddingOffset, repeat(paddingValue, numPaddingBytes)) - -op address, inline = true: - ## 0x30, Get address of currently executing account. - push: c.msg.contractAddress - -op balance, inline = true: - ## 0x31, Get balance of the given account. - let address = c.stack.popAddress() - push: c.getBalance(address) - -op origin, inline = true: - ## 0x32, Get execution origination address. - push: c.getOrigin() - -op caller, inline = true: - ## 0x33, Get caller address. - push: c.msg.sender - -op callValue, inline = true: - ## 0x34, Get deposited value by the instruction/transaction - ## responsible for this execution - push: c.msg.value - -op callDataLoad, inline = false, startPos: - ## 0x35, Get input data of current environment - let start = startPos.cleanMemRef - if start >= c.msg.data.len: - push: 0 - return - - # If the data does not take 32 bytes, pad with zeros - let endRange = min(c.msg.data.len - 1, start + 31) - let presentBytes = endRange - start - # We rely on value being initialized with 0 by default - var value: array[32, byte] - value[0 .. presentBytes] = c.msg.data.toOpenArray(start, endRange) - - push: value - -op callDataSize, inline = true: - ## 0x36, Get size of input data in current environment. - push: c.msg.data.len.u256 - -op callDataCopy, inline = false, memStartPos, copyStartPos, size: - ## 0x37, Copy input data in current environment to memory. - # TODO tests: https://github.com/status-im/nimbus/issues/67 - - let (memPos, copyPos, len) = (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) - - c.gasMeter.consumeGas( - c.gasCosts[CallDataCopy].m_handler(c.memory.len, memPos, len), - reason="CallDataCopy fee") - - c.memory.writePaddedResult(c.msg.data, memPos, copyPos, len) - -op codeSize, inline = true: - ## 0x38, Get size of code running in current environment. - push: c.code.len - -op codeCopy, inline = false, memStartPos, copyStartPos, size: - ## 0x39, Copy code running in current environment to memory. - # TODO tests: https://github.com/status-im/nimbus/issues/67 - - let (memPos, copyPos, len) = (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) - - c.gasMeter.consumeGas( - c.gasCosts[CodeCopy].m_handler(c.memory.len, memPos, len), - reason="CodeCopy fee") - - c.memory.writePaddedResult(c.code.bytes, memPos, copyPos, len) - -op gasprice, inline = true: - ## 0x3A, Get price of gas in current environment. - push: c.getGasPrice() - -op extCodeSize, inline = true: - ## 0x3b, Get size of an account's code - let address = c.stack.popAddress() - push: c.getCodeSize(address) - -op extCodeCopy, inline = true: - ## 0x3c, Copy an account's code to memory. - let address = c.stack.popAddress() - let (memStartPos, codeStartPos, size) = c.stack.popInt(3) - let (memPos, codePos, len) = (memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef) - - c.gasMeter.consumeGas( - c.gasCosts[ExtCodeCopy].m_handler(c.memory.len, memPos, len), - reason="ExtCodeCopy fee") - - let codeBytes = c.getCode(address) - c.memory.writePaddedResult(codeBytes, memPos, codePos, len) - -op returnDataSize, inline = true: - ## 0x3d, Get size of output data from the previous call from the current environment. - push: c.returnData.len - -op returnDataCopy, inline = false, memStartPos, copyStartPos, size: - ## 0x3e, Copy output data from the previous call to memory. - let (memPos, copyPos, len) = (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) - let gasCost = c.gasCosts[ReturnDataCopy].m_handler(c.memory.len, memPos, len) - c.gasMeter.consumeGas( - gasCost, - reason="returnDataCopy fee") - - if copyPos + len > c.returnData.len: - # TODO Geth additionally checks copyPos + len < 64 - # Parity uses a saturating addition - # Yellow paper mentions μs[1] + i are not subject to the 2^256 modulo. - raise newException(OutOfBoundsRead, - "Return data length is not sufficient to satisfy request. Asked \n" & - &"for data from index {copyStartPos} to {copyStartPos + size}. Return data is {c.returnData.len} in \n" & - "length") - - c.memory.writePaddedResult(c.returnData, memPos, copyPos, len) +opHandler add, Op.Add +opHandler mul, Op.Mul +opHandler sub, Op.Sub +opHandler divide, Op.Div +opHandler sdiv, Op.Sdiv +opHandler modulo, Op.Mod +opHandler smod, Op.Smod +opHandler addmod, Op.AddMod +opHandler mulmod, Op.MulMod +opHandler exp, Op.Exp +opHandler signExtend, Op.SignExtend +opHandler lt, Op.Lt +opHandler gt, Op.Gt +opHandler slt, Op.Slt +opHandler sgt, Op.Sgt +opHandler eq, Op.Eq +opHandler isZero, Op.IsZero +opHandler andOp, Op.And +opHandler orOp, Op.Or +opHandler xorOp, Op.Xor +opHandler notOp, Op.Not +opHandler byteOp, Op.Byte +opHandler sha3, Op.Sha3 +opHandler address, Op.Address +opHandler balance, Op.Balance +opHandler origin, Op.Origin +opHandler caller, Op.Caller +opHandler callValue, Op.CallValue +opHandler callDataLoad, Op.CallDataLoad +opHandler callDataSize, Op.CallDataSize +opHandler callDataCopy, Op.CallDataCopy +opHandler codeSize, Op.CodeSize +opHandler codeCopy, Op.CodeCopy +opHandler gasprice, Op.GasPrice +opHandler extCodeSize, Op.ExtCodeSize +opHandler extCodeCopy, Op.ExtCodeCopy +opHandler returnDataSize, Op.ReturnDataSize +opHandler returnDataCopy, Op.ReturnDataCopy # ########################################## # 40s: Block Information