From b2ce6d9e70abb5281b498de2ad1f9b1ae41cc275 Mon Sep 17 00:00:00 2001 From: Jordan Hrycaj Date: Tue, 20 Apr 2021 16:39:32 +0100 Subject: [PATCH] re-arrange functions from v2computation.nim and interpreter_dispatch.nim why: step towards breaking circular dependency details: some functions from v2computation.nim have been extracted into compu_helper.nim which does not explicitly back-import v2computation.nim. all non recursive op handlers now import this source file rather than v2computation.nim. recursive call/create op handler still need to import v2computation.nim. the executeOpcodes() function from interpreter_dispatch.nim has been moved to v2computation.nim which allows for rather than the interpreter_dispatch.nim source. --- nimbus/vm2/compu_helper.nim | 132 +++++++++++++++ .../op_handlers/oph_arithmetic.nim | 4 +- .../interpreter/op_handlers/oph_blockdata.nim | 4 +- .../vm2/interpreter/op_handlers/oph_call.nim | 11 +- .../interpreter/op_handlers/oph_create.nim | 5 +- .../interpreter/op_handlers/oph_envinfo.nim | 25 ++- .../vm2/interpreter/op_handlers/oph_hash.nim | 8 +- .../vm2/interpreter/op_handlers/oph_log.nim | 4 +- .../interpreter/op_handlers/oph_memory.nim | 18 +-- .../interpreter/op_handlers/oph_sysops.nim | 4 +- nimbus/vm2/interpreter_dispatch.nim | 36 ++--- nimbus/vm2/v2computation.nim | 153 +++--------------- nimbus/vm2/v2interpreter.nim | 51 +++--- nimbus/vm_computation.nim | 78 ++++++--- 14 files changed, 292 insertions(+), 241 deletions(-) create mode 100644 nimbus/vm2/compu_helper.nim diff --git a/nimbus/vm2/compu_helper.nim b/nimbus/vm2/compu_helper.nim new file mode 100644 index 000000000..889157737 --- /dev/null +++ b/nimbus/vm2/compu_helper.nim @@ -0,0 +1,132 @@ +# 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. + +import + ../constants, + ../db/accounts_cache, + ./interpreter/op_codes, + ./transaction_tracer, + ./v2state, + ./v2types, + chronicles, + eth/[common, keys], + options, + sets + +logScope: + topics = "vm compu helper" + +when defined(chronicles_log_level): + import stew/byteutils + +template accountExists*(c: Computation, address: EthAddress): bool = + if c.fork >= FkSpurious: + not c.vmState.readOnlyStateDB.isDeadAccount(address) + else: + c.vmState.readOnlyStateDB.accountExists(address) + +proc addLogEntry*(c: Computation, log: Log) {.inline.} = + c.logEntries.add(log) + +template fork*(c: Computation): untyped = + c.vmState.fork + +template gasCosts*(c: Computation): untyped = + c.vmState.gasCosts + +template getBalance*(c: Computation, address: EthAddress): Uint256 = + c.vmState.readOnlyStateDB.getBalance(address) + +template getBlockHash*(c: Computation, blockNumber: Uint256): Hash256 = + c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber) + +template getBlockNumber*(c: Computation): Uint256 = + c.vmState.blockNumber.blockNumberToVmWord + +template getChainId*(c: Computation): uint = + c.vmState.chaindb.config.chainId.uint + +template getCode*(c: Computation, address: EthAddress): seq[byte] = + c.vmState.readOnlyStateDB.getCode(address) + +template getCodeHash*(c: Computation, address: EthAddress): Hash256 = + let + db = c.vmState.readOnlyStateDB + if not db.accountExists(address) or db.isEmptyAccount(address): + default(Hash256) + else: + db.getCodeHash(address) + +template getCodeSize*(c: Computation, address: EthAddress): uint = + uint(c.vmState.readOnlyStateDB.getCodeSize(address)) + +template getCoinbase*(c: Computation): EthAddress = + c.vmState.coinbase + +template getDifficulty*(c: Computation): DifficultyInt = + c.vmState.difficulty + +template getGasLimit*(c: Computation): GasInt = + c.vmState.gasLimit + +template getGasPrice*(c: Computation): GasInt = + c.vmState.txGasPrice + +template getOrigin*(c: Computation): EthAddress = + c.vmState.txOrigin + +template getStorage*(c: Computation, slot: Uint256): Uint256 = + c.vmState.readOnlyStateDB.getStorage(c.msg.contractAddress, slot) + +template getTimestamp*(c: Computation): int64 = + c.vmState.timestamp.toUnix + +proc prepareTracer*(c: Computation) {.inline.} = + c.vmState.tracer.prepare(c.msg.depth) + +proc selfDestruct*(c: Computation, beneficiary: EthAddress) = + c.vmState.mutateStateDB: + let + localBalance = c.getBalance(c.msg.contractAddress) + beneficiaryBalance = c.getBalance(beneficiary) + + # Transfer to beneficiary + db.setBalance(beneficiary, localBalance + beneficiaryBalance) + + # Zero the balance of the address being deleted. + # This must come after sending to beneficiary in case the + # contract named itself as the beneficiary. + db.setBalance(c.msg.contractAddress, 0.u256) + + trace "SELFDESTRUCT", + contractAddress = c.msg.contractAddress.toHex, + localBalance = localBalance.toString, + beneficiary = beneficiary.toHex + + c.touchedAccounts.incl beneficiary + # Register the account to be deleted + c.suicides.incl(c.msg.contractAddress) + +proc setError*(c: Computation, msg: string, burnsGas = false) {.inline.} = + c.error = Error(info: msg, burnsGas: burnsGas) + +proc traceOpCodeStarted*(c: Computation, op: Op): int {.inline.} = + c.vmState.tracer.traceOpCodeStarted(c, op) + +proc traceOpCodeEnded*(c: Computation, op: Op, lastIndex: int) {.inline.} = + c.vmState.tracer.traceOpCodeEnded(c, op, lastIndex) + +proc tracingEnabled*(c: Computation): bool {.inline.} = + TracerFlags.EnableTracing in c.vmState.tracer.flags + + +# deprecated, related to nimvm/evmc implementation +proc execSelfDestruct*(c: Computation, address: EthAddress) {.deprecated.} = + c.selfDestruct(address) diff --git a/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim b/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim index 9acf7434e..bb709e2f6 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim @@ -27,8 +27,8 @@ import when not breakCircularDependency: import ../../../constants, + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2types, ../gas_meter, ../utils/v2utils_numeric, @@ -53,7 +53,7 @@ else: var rc: genTupleType(n, UInt256) return rc - # function stubs from v2computation.nim (to satisfy compiler logic) + # function stubs from compu_helper.nim (to satisfy compiler logic) proc gasCosts(c: Computation): array[Op,int] = result # function stubs from v2utils_numeric.nim diff --git a/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim b/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim index e65c7a7fa..2af000e64 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim @@ -26,8 +26,8 @@ import when not breakCircularDependency: import + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2state, eth/common, times @@ -46,7 +46,7 @@ else: var rc: genTupleType(n, UInt256) return rc - # function stubs from v2computation.nim (to satisfy compiler logic) + # function stubs from compu_helper.nim (to satisfy compiler logic) proc getBalance[T](c: Computation, address: T): Uint256 = 0.u256 proc getBlockHash(c: Computation, blockNumber: Uint256): Uint256 = 0.u256 proc getCoinbase(c: Computation): Uint256 = 0.u256 diff --git a/nimbus/vm2/interpreter/op_handlers/oph_call.nim b/nimbus/vm2/interpreter/op_handlers/oph_call.nim index 643daef8f..703bd12d8 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_call.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_call.nim @@ -28,8 +28,9 @@ import when not breakCircularDependency: import - ../../../db/accounts_cache, ../../../constants, + ../../../db/accounts_cache, + ../../compu_helper, ../../stack, ../../v2computation, ../../v2memory, @@ -62,12 +63,14 @@ else: proc popAddress(x: var Stack): EthAddress = result proc popInt(x: var Stack): UInt256 = result - # function stubs from v2computation.nim (to satisfy compiler logic) + # function stubs from compu_helper.nim (to satisfy compiler logic) proc gasCosts(c: Computation): array[Op,int] = result proc getBalance[T](c: Computation, address: T): Uint256 = result - proc newComputation[A,B](v:A, m:B, salt = 0.u256): Computation = new result - func shouldBurnGas(c: Computation): bool = result proc accountExists(c: Computation, address: EthAddress): bool = result + + # function stubs from v2computation.nim (to satisfy compiler logic) + func shouldBurnGas(c: Computation): bool = result + proc newComputation[A,B](v:A, m:B, salt = 0.u256): Computation = new result proc isSuccess(c: Computation): bool = result proc merge(c, child: Computation) = discard template chainTo(c, d: Computation, e: untyped) = diff --git a/nimbus/vm2/interpreter/op_handlers/oph_create.nim b/nimbus/vm2/interpreter/op_handlers/oph_create.nim index 876b3967c..2549ab4c5 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_create.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_create.nim @@ -31,6 +31,7 @@ import when not breakCircularDependency: import ../../../constants, + ../../compu_helper, ../../stack, ../../v2computation, ../../v2memory, @@ -56,9 +57,11 @@ else: proc peekInt(x: Stack): UInt256 = result proc popInt(x: var Stack): UInt256 = result - # function stubs from v2computation.nim (to satisfy compiler logic) + # function stubs from compu_helper.nim (to satisfy compiler logic) proc gasCosts(c: Computation): array[Op,int] = result proc getBalance[T](c: Computation, address: T): Uint256 = result + + # function stubs from v2computation.nim (to satisfy compiler logic) proc newComputation[A,B](v:A, m:B, salt = 0.u256): Computation = new result func shouldBurnGas(c: Computation): bool = result proc isSuccess(c: Computation): bool = result diff --git a/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim b/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim index 0a8bae40a..82a6b8ebf 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim @@ -31,24 +31,23 @@ import when not breakCircularDependency: import ../../code_stream, + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2memory, ../../v2state, ../gas_meter, - ../v2gas_costs, ../utils/v2utils_numeric, + ../v2gas_costs, eth/common else: import macros - var + const GasBalance = 0 GasExtCode = 42 GasExtCodeHash = 7 - blindGasCosts: array[Op,int] - blindAddress: EthAddress + var gasFees: array[Fork,array[0..123,int]] # copied from stack.nim @@ -58,19 +57,19 @@ else: # function stubs from stack.nim (to satisfy compiler logic) proc push[T](x: Stack; n: T) = discard - proc popAddress(x: var Stack): EthAddress = blindAddress + proc popAddress(x: var Stack): EthAddress = result 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 gasCosts(c: Computation): array[Op,int] = blindGasCosts - proc getBalance[T](c: Computation, address: T): Uint256 = 0.u256 - proc getCodeSize[T](c: Computation, address: T): uint = 0 + # function stubs from compu_helper.nim (to satisfy compiler logic) + proc gasCosts(c: Computation): array[Op,int] = result + proc getBalance[T](c: Computation, address: T): Uint256 = result + proc getCodeSize[T](c: Computation, address: T): uint = result proc getCode[T](c: Computation, address: T): seq[byte] = @[] - proc getGasPrice(c: Computation): Uint256 = 0.u256 - proc getOrigin(c: Computation): Uint256 = 0.u256 - proc getCodeHash[T](c: Computation, address: T): Uint256 = 0.u256 + proc getGasPrice(c: Computation): Uint256 = result + proc getOrigin(c: Computation): Uint256 = result + proc getCodeHash[T](c: Computation, address: T): Uint256 = result # function stubs from v2utils_numeric.nim func cleanMemRef(x: UInt256): int = 0 diff --git a/nimbus/vm2/interpreter/op_handlers/oph_hash.nim b/nimbus/vm2/interpreter/op_handlers/oph_hash.nim index 51abb37ce..947e8581a 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_hash.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_hash.nim @@ -28,8 +28,8 @@ import when not breakCircularDependency: import ../../../constants, + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2memory, ../gas_meter, ../utils/v2utils_numeric, @@ -40,8 +40,6 @@ when not breakCircularDependency: else: import macros - var blindGasCosts: array[Op,int] - # copied from stack.nim macro genTupleType(len: static[int], elemType: untyped): untyped = result = nnkTupleConstr.newNimNode() @@ -60,8 +58,8 @@ else: proc len(mem: Memory): int = 0 proc extend(mem: var Memory; startPos: Natural; size: Natural) = discard - # function stubs from v2computation.nim (to satisfy compiler logic) - proc gasCosts(c: Computation): array[Op,int] = blindGasCosts + # function stubs from compu_helper.nim (to satisfy compiler logic) + proc gasCosts(c: Computation): array[Op,int] = result # function stubs from gas_meter.nim proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard diff --git a/nimbus/vm2/interpreter/op_handlers/oph_log.nim b/nimbus/vm2/interpreter/op_handlers/oph_log.nim index 39c091f2c..b4a82df5e 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_log.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_log.nim @@ -33,8 +33,8 @@ import when not breakCircularDependency: import ../../../constants, + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2memory, ../../v2types, ../gas_meter, @@ -60,7 +60,7 @@ else: var rc: genTupleType(n, UInt256) return rc - # function stubs from v2computation.nim (to satisfy compiler logic) + # function stubs from compu_helper.nim (to satisfy compiler logic) proc gasCosts(c: Computation): array[Op,int] = blindGasCosts proc addLogEntry(c: Computation, log: Log) = discard diff --git a/nimbus/vm2/interpreter/op_handlers/oph_memory.nim b/nimbus/vm2/interpreter/op_handlers/oph_memory.nim index 50af641fd..f1b6c0ae0 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_memory.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_memory.nim @@ -31,8 +31,8 @@ when not breakCircularDependency: import ../../../db/accounts_cache, ../../code_stream, + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2memory, ../../v2state, ../../v2types, @@ -47,8 +47,6 @@ else: const ColdSloadCost = 42 WarmStorageReadCost = 43 - var - blindGasCosts: array[Op,int] # copied from stack.nim macro genTupleType(len: static[int], elemType: untyped): untyped = @@ -62,9 +60,9 @@ else: var rc: genTupleType(n, UInt256) return rc - # function stubs from v2computation.nim (to satisfy compiler logic) - proc getStorage(c: Computation, slot: Uint256): Uint256 = 0.u256 - proc gasCosts(c: Computation): array[Op,int] = blindGasCosts + # function stubs from compu_helper.nim (to satisfy compiler logic) + proc getStorage(c: Computation, slot: Uint256): Uint256 = result + proc gasCosts(c: Computation): array[Op,int] = result # function stubs from v2utils_numeric.nim func cleanMemRef(x: UInt256): int = 0 @@ -81,7 +79,7 @@ else: proc isValidOpcode(c: CodeStream, position: int): bool = false # function stubs from v2state.nim - proc readOnlyStateDB(x: BaseVMState): ReadOnlyStateDB = x.accountDb + proc readOnlyStateDB(x: BaseVMState): ReadOnlyStateDB = result template mutateStateDB(vmState: BaseVMState, body: untyped) = block: var db {.inject.} = vmState.accountDb @@ -99,14 +97,14 @@ else: s_originalValue: Uint256 else: discard - proc c_handler(x: int; y: Uint256, z: GasParams): (int,int) = (0,0) + proc c_handler(x: int; y: Uint256, z: GasParams): (int,int) = result proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = 0 # function stubs from state_db.nim - proc getCommittedStorage[A,B](x: A; y: B; z: Uint256): Uint256 = 0.u256 + proc getCommittedStorage[A,B](x: A; y: B; z: Uint256): Uint256 = result # function stubs from accounts_cache.nim: - func inAccessList[A,B](ac: A; address: B; slot: UInt256): bool = false + func inAccessList[A,B](ac: A; address: B; slot: UInt256): bool = result proc accessList[A,B](ac: var A; address: B; slot: UInt256) = discard proc setStorage[A,B](ac: var A; address: B, slot, value: UInt256) = discard diff --git a/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim b/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim index 2f472e1e3..5b6686772 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim @@ -29,8 +29,8 @@ import when not breakCircularDependency: import ../../../db/accounts_cache, + ../../compu_helper, ../../stack, - ../../v2computation, ../../v2memory, ../../v2state, ../../v2types, @@ -58,7 +58,7 @@ else: var rc: genTupleType(n, UInt256) return rc - # function stubs from v2computation.nim (to satisfy compiler logic) + # function stubs from compu_helper.nim (to satisfy compiler logic) proc gasCosts(c: Computation): array[Op,int] = result proc setError(c: Computation, msg: string, burnsGas = false) = discard proc selfDestruct(c: Computation, address: EthAddress) = discard diff --git a/nimbus/vm2/interpreter_dispatch.nim b/nimbus/vm2/interpreter_dispatch.nim index a9b25db7b..d41e6a560 100644 --- a/nimbus/vm2/interpreter_dispatch.nim +++ b/nimbus/vm2/interpreter_dispatch.nim @@ -1,20 +1,24 @@ # 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. +# * 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. import - chronicles, + ./compu_helper, ./interpreter/[gas_meter, op_handlers, op_handlers/oph_defs, v2gas_costs], - ./code_stream, ./v2types, ./v2precompiles + ./code_stream, + ./v2types, + chronicles logScope: topics = "vm opcode" - -proc selectVM(c: Computation, fork: Fork) {.gcsafe.} = +proc selectVM*(c: Computation, fork: Fork) {.gcsafe.} = var desc: Vm2Ctx if c.tracingEnabled: @@ -51,21 +55,3 @@ proc selectVM(c: Computation, fork: Fork) {.gcsafe.} = else: discard - -proc executeOpcodes(c: Computation) = - let fork = c.fork - - block: - if not c.continuation.isNil: - c.continuation = nil - elif c.execPrecompiles(fork): - break - - try: - c.selectVM(fork) - except CatchableError as e: - c.setError(&"Opcode Dispatch Error msg={e.msg}, depth={c.msg.depth}", true) - - if c.isError() and c.continuation.isNil: - if c.tracingEnabled: c.traceError() - debug "executeOpcodes error", msg=c.error.info diff --git a/nimbus/vm2/v2computation.nim b/nimbus/vm2/v2computation.nim index dcbc6fd89..46d2775fe 100644 --- a/nimbus/vm2/v2computation.nim +++ b/nimbus/vm2/v2computation.nim @@ -9,92 +9,19 @@ when defined(evmc_enabled): {.fatal: "Flags \"evmc_enabled\" and \"vm2_enabled\" are mutually exclusive"} import - chronicles, strformat, macros, options, times, + chronicles, strformat, macros, options, sets, eth/[common, keys], - ../constants, ../errors, - ./interpreter/[v2opcode_values, gas_meter, v2gas_costs, v2forks], + ../constants, + ./compu_helper, + ./interpreter/[op_codes, gas_meter, v2gas_costs, v2forks], ./code_stream, ./memory_defs, ./v2message, ./stack, ./v2types, ./v2state, - ../db/[accounts_cache, db_chain], - ../utils/header, ./v2precompiles, + ../db/accounts_cache, + ./v2precompiles, ./transaction_tracer, ../utils -when defined(chronicles_log_level): - import stew/byteutils - logScope: topics = "vm computation" -template getCoinbase*(c: Computation): EthAddress = - block: - c.vmState.coinbase - -template getTimestamp*(c: Computation): int64 = - block: - c.vmState.timestamp.toUnix - -template getBlockNumber*(c: Computation): Uint256 = - block: - c.vmState.blockNumber.blockNumberToVmWord - -template getDifficulty*(c: Computation): DifficultyInt = - block: - c.vmState.difficulty - -template getGasLimit*(c: Computation): GasInt = - block: - c.vmState.gasLimit - -template getChainId*(c: Computation): uint = - block: - c.vmState.chaindb.config.chainId.uint - -template getOrigin*(c: Computation): EthAddress = - block: - c.vmState.txOrigin - -template getGasPrice*(c: Computation): GasInt = - block: - c.vmState.txGasPrice - -template getBlockHash*(c: Computation, blockNumber: Uint256): Hash256 = - block: - c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber) - -template accountExists*(c: Computation, address: EthAddress): bool = - block: - if c.fork >= FkSpurious: - not c.vmState.readOnlyStateDB.isDeadAccount(address) - else: - c.vmState.readOnlyStateDB.accountExists(address) - -template getStorage*(c: Computation, slot: Uint256): Uint256 = - block: - c.vmState.readOnlyStateDB.getStorage(c.msg.contractAddress, slot) - -template getBalance*(c: Computation, address: EthAddress): Uint256 = - block: - c.vmState.readOnlyStateDB.getBalance(address) - -template getCodeSize*(c: Computation, address: EthAddress): uint = - block: - uint(c.vmState.readOnlyStateDB.getCodeSize(address)) - -template getCodeHash*(c: Computation, address: EthAddress): Hash256 = - block: - let db = c.vmState.readOnlyStateDB - if not db.accountExists(address) or db.isEmptyAccount(address): - default(Hash256) - else: - db.getCodeHash(address) - -template selfDestruct*(c: Computation, address: EthAddress) = - block: - c.execSelfDestruct(address) - -template getCode*(c: Computation, address: EthAddress): seq[byte] = - block: - c.vmState.readOnlyStateDB.getCode(address) - proc generateContractAddress(c: Computation, salt: Uint256): EthAddress = if c.msg.kind == evmcCreate: let creationNonce = c.vmState.readOnlyStateDb().getNonce(c.msg.sender) @@ -102,7 +29,6 @@ proc generateContractAddress(c: Computation, salt: Uint256): EthAddress = else: result = generateSafeAddress(c.msg.sender, salt, c.msg.data) -import stew/byteutils proc newComputation*(vmState: BaseVMState, message: Message, salt= 0.u256): Computation = new result @@ -122,13 +48,6 @@ proc newComputation*(vmState: BaseVMState, message: Message, salt= 0.u256): Comp else: result.code = newCodeStream(vmState.readOnlyStateDb.getCode(message.codeAddress)) - -template gasCosts*(c: Computation): untyped = - c.vmState.gasCosts - -template fork*(c: Computation): untyped = - c.vmState.fork - proc isOriginComputation*(c: Computation): bool = # Is this computation the computation initiated by a transaction c.msg.sender == c.vmState.txOrigin @@ -158,9 +77,6 @@ proc dispose*(c: Computation) {.inline.} = proc rollback*(c: Computation) = c.vmState.accountDb.rollback(c.savePoint) -proc setError*(c: Computation, msg: string, burnsGas = false) {.inline.} = - c.error = Error(info: msg, burnsGas: burnsGas) - proc writeContract*(c: Computation, fork: Fork): bool {.gcsafe.} = result = true @@ -306,32 +222,6 @@ proc merge*(c, child: Computation) = c.suicides.incl child.suicides c.touchedAccounts.incl child.touchedAccounts -proc execSelfDestruct*(c: Computation, beneficiary: EthAddress) = - c.vmState.mutateStateDB: - let - localBalance = c.getBalance(c.msg.contractAddress) - beneficiaryBalance = c.getBalance(beneficiary) - - # Transfer to beneficiary - db.setBalance(beneficiary, localBalance + beneficiaryBalance) - - # Zero the balance of the address being deleted. - # This must come after sending to beneficiary in case the - # contract named itself as the beneficiary. - db.setBalance(c.msg.contractAddress, 0.u256) - - trace "SELFDESTRUCT", - contractAddress = c.msg.contractAddress.toHex, - localBalance = localBalance.toString, - beneficiary = beneficiary.toHex - - c.touchedAccounts.incl beneficiary - # Register the account to be deleted - c.suicides.incl(c.msg.contractAddress) - -proc addLogEntry*(c: Computation, log: Log) {.inline.} = - c.logEntries.add(log) - proc getGasRefund*(c: Computation): GasInt = if c.isSuccess: result = c.gasMeter.gasRefunded @@ -340,19 +230,28 @@ proc refundSelfDestruct*(c: Computation) = let cost = gasFees[c.fork][RefundSelfDestruct] c.gasMeter.refundGas(cost * c.suicides.len) -proc tracingEnabled*(c: Computation): bool {.inline.} = - EnableTracing in c.vmState.tracer.flags - -proc traceOpCodeStarted*(c: Computation, op: Op): int {.inline.} = - c.vmState.tracer.traceOpCodeStarted(c, op) - -proc traceOpCodeEnded*(c: Computation, op: Op, lastIndex: int) {.inline.} = - c.vmState.tracer.traceOpCodeEnded(c, op, lastIndex) proc traceError*(c: Computation) {.inline.} = c.vmState.tracer.traceError(c) -proc prepareTracer*(c: Computation) {.inline.} = - c.vmState.tracer.prepare(c.msg.depth) -include interpreter_dispatch +import interpreter_dispatch + +proc executeOpcodes(c: Computation) = + let fork = c.fork + + block: + if not c.continuation.isNil: + c.continuation = nil + elif c.execPrecompiles(fork): + break + + try: + c.selectVM(fork) + except CatchableError as e: + c.setError( + &"Opcode Dispatch Error msg={e.msg}, depth={c.msg.depth}", true) + + if c.isError() and c.continuation.isNil: + if c.tracingEnabled: c.traceError() + debug "executeOpcodes error", msg=c.error.info diff --git a/nimbus/vm2/v2interpreter.nim b/nimbus/vm2/v2interpreter.nim index edaff9765..b889aecf7 100644 --- a/nimbus/vm2/v2interpreter.nim +++ b/nimbus/vm2/v2interpreter.nim @@ -35,50 +35,53 @@ export # Used in vm_types. Beware of recursive dependencies # see vm_computation +import + ./compu_helper as xmc +export + xmc.accountExists, + xmc.addLogEntry, + xmc.fork, + xmc.getBalance, + xmc.getBlockHash, + xmc.getBlockNumber, + xmc.getChainId, + xmc.getCode, + xmc.getCodeHash, + xmc.getCodeSize, + xmc.getCoinbase, + xmc.getDifficulty, + xmc.getGasLimit, + xmc.getGasPrice, + xmc.getOrigin, + xmc.getStorage, + xmc.getTimestamp, + xmc.prepareTracer, + xmc.selfDestruct, + xmc.setError, + xmc.traceOpCodeEnded, + xmc.traceOpCodeStarted, + xmc.tracingEnabled + import ./v2computation as vmc export - vmc.accountExists, - vmc.addLogEntry, vmc.commit, vmc.dispose, vmc.execCallOrCreate, vmc.chainTo, - vmc.execSelfDestruct, vmc.executeOpcodes, - vmc.fork, - vmc.getBalance, - vmc.getBlockHash, - vmc.getBlockNumber, - vmc.getChainId, - vmc.getCode, - vmc.getCodeHash, - vmc.getCodeSize, - vmc.getCoinbase, - vmc.getDifficulty, - vmc.getGasLimit, - vmc.getGasPrice, vmc.getGasRefund, - vmc.getOrigin, - vmc.getStorage, - vmc.getTimestamp, vmc.isError, vmc.isOriginComputation, vmc.isSuccess, vmc.isSuicided, vmc.merge, vmc.newComputation, - vmc.prepareTracer, vmc.refundSelfDestruct, vmc.rollback, - vmc.selfDestruct, - vmc.setError, vmc.shouldBurnGas, vmc.snapshot, vmc.traceError, - vmc.traceOpCodeEnded, - vmc.traceOpCodeStarted, - vmc.tracingEnabled, vmc.writeContract diff --git a/nimbus/vm_computation.nim b/nimbus/vm_computation.nim index 64c13553d..55dc7f009 100644 --- a/nimbus/vm_computation.nim +++ b/nimbus/vm_computation.nim @@ -14,52 +14,82 @@ when defined(evmc_enabled) or not defined(vm2_enabled): import ./vm/computation as vmc + + export + vmc.accountExists, + vmc.addLogEntry, + vmc.execSelfDestruct, + vmc.fork, + vmc.getBalance, + vmc.getBlockHash, + vmc.getBlockNumber, + vmc.getChainId, + vmc.getCode, + vmc.getCodeHash, + vmc.getCodeSize, + vmc.getCoinbase, + vmc.getDifficulty, + vmc.getGasLimit, + vmc.getGasPrice, + vmc.getOrigin, + vmc.getStorage, + vmc.getTimestamp, + vmc.selfDestruct, + vmc.setError, + vmc.prepareTracer, + vmc.traceOpCodeEnded, + vmc.traceOpCodeStarted, + vmc.tracingEnabled + else: import + ./vm2/compu_helper as xmc, ./vm2/v2computation as vmc + export + xmc.accountExists, + xmc.addLogEntry, + xmc.execSelfDestruct, + xmc.fork, + xmc.getBalance, + xmc.getBlockHash, + xmc.getBlockNumber, + xmc.getChainId, + xmc.getCode, + xmc.getCodeHash, + xmc.getCodeSize, + xmc.getCoinbase, + xmc.getDifficulty, + xmc.getGasLimit, + xmc.getGasPrice, + xmc.getOrigin, + xmc.getStorage, + xmc.getTimestamp, + xmc.prepareTracer, + xmc.selfDestruct, + xmc.setError, + xmc.traceOpCodeEnded, + xmc.traceOpCodeStarted, + xmc.tracingEnabled + export - vmc.accountExists, - vmc.addLogEntry, vmc.commit, vmc.dispose, vmc.execCallOrCreate, vmc.chainTo, - vmc.execSelfDestruct, vmc.executeOpcodes, - vmc.fork, - vmc.getBalance, - vmc.getBlockHash, - vmc.getBlockNumber, - vmc.getChainId, - vmc.getCode, - vmc.getCodeHash, - vmc.getCodeSize, - vmc.getCoinbase, - vmc.getDifficulty, - vmc.getGasLimit, - vmc.getGasPrice, vmc.getGasRefund, - vmc.getOrigin, - vmc.getStorage, - vmc.getTimestamp, vmc.isError, vmc.isOriginComputation, vmc.isSuccess, vmc.isSuicided, vmc.merge, vmc.newComputation, - vmc.prepareTracer, vmc.refundSelfDestruct, vmc.rollback, - vmc.selfDestruct, - vmc.setError, vmc.shouldBurnGas, vmc.snapshot, vmc.traceError, - vmc.traceOpCodeEnded, - vmc.traceOpCodeStarted, - vmc.tracingEnabled, vmc.writeContract # End