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 <import> rather than <include> the interpreter_dispatch.nim source.
This commit is contained in:
parent
9b70ab5f8f
commit
b2ce6d9e70
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue