re-named compu_helper.nim => computation.nim

why:
  exports all except one of the original computation.nim functional
  objects
This commit is contained in:
Jordan Hrycaj 2021-04-26 17:00:46 +01:00 committed by zah
parent a86308c079
commit 5d0d44c38f
16 changed files with 307 additions and 359 deletions

View File

@ -1,252 +0,0 @@
# 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,
../utils,
./code_stream,
./interpreter/[forks_list, gas_meter, gas_costs, op_codes],
./memory,
./message,
./stack,
./state,
./transaction_tracer,
./types,
chronicles,
eth/[common, keys],
options,
sets
logScope:
topics = "vm compu helper"
when defined(chronicles_log_level):
import stew/byteutils
# ------------------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------------------
proc generateContractAddress(c: Computation, salt: Uint256): EthAddress =
if c.msg.kind == evmcCreate:
let creationNonce = c.vmState.readOnlyStateDb().getNonce(c.msg.sender)
result = generateAddress(c.msg.sender, creationNonce)
else:
result = generateSafeAddress(c.msg.sender, salt, c.msg.data)
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
template getCoinbase*(c: Computation): EthAddress =
c.vmState.coinbase
template getTimestamp*(c: Computation): int64 =
c.vmState.timestamp.toUnix
template getBlockNumber*(c: Computation): Uint256 =
c.vmState.blockNumber.blockNumberToVmWord
template getDifficulty*(c: Computation): DifficultyInt =
c.vmState.difficulty
template getGasLimit*(c: Computation): GasInt =
c.vmState.gasLimit
template getChainId*(c: Computation): uint =
c.vmState.chaindb.config.chainId.uint
template getOrigin*(c: Computation): EthAddress =
c.vmState.txOrigin
template getGasPrice*(c: Computation): GasInt =
c.vmState.txGasPrice
template getBlockHash*(c: Computation, blockNumber: Uint256): Hash256 =
c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber)
template accountExists*(c: Computation, address: EthAddress): bool =
if c.fork >= FkSpurious:
not c.vmState.readOnlyStateDB.isDeadAccount(address)
else:
c.vmState.readOnlyStateDB.accountExists(address)
template getStorage*(c: Computation, slot: Uint256): Uint256 =
c.vmState.readOnlyStateDB.getStorage(c.msg.contractAddress, slot)
template getBalance*(c: Computation, address: EthAddress): Uint256 =
c.vmState.readOnlyStateDB.getBalance(address)
template getCodeSize*(c: Computation, address: EthAddress): uint =
uint(c.vmState.readOnlyStateDB.getCodeSize(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 selfDestruct*(c: Computation, address: EthAddress) =
c.execSelfDestruct(address)
template getCode*(c: Computation, address: EthAddress): seq[byte] =
c.vmState.readOnlyStateDB.getCode(address)
proc newComputation*(vmState: BaseVMState,
message: Message, salt= 0.u256): Computation =
new result
result.vmState = vmState
result.msg = message
result.memory = Memory()
result.stack = newStack()
result.returnStack = @[]
result.gasMeter.init(message.gas)
result.touchedAccounts = initHashSet[EthAddress]()
result.suicides = initHashSet[EthAddress]()
if result.msg.isCreate():
result.msg.contractAddress = result.generateContractAddress(salt)
result.code = newCodeStream(message.data)
message.data = @[]
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
template isSuccess*(c: Computation): bool =
c.error.isNil
template isError*(c: Computation): bool =
not c.isSuccess
func shouldBurnGas*(c: Computation): bool =
c.isError and c.error.burnsGas
proc isSuicided*(c: Computation, address: EthAddress): bool =
result = address in c.suicides
proc snapshot*(c: Computation) =
c.savePoint = c.vmState.accountDb.beginSavePoint()
proc commit*(c: Computation) =
c.vmState.accountDb.commit(c.savePoint)
proc dispose*(c: Computation) {.inline.} =
c.vmState.accountDb.safeDispose(c.savePoint)
c.savePoint = nil
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
let contractCode = c.output
if contractCode.len == 0: return
if fork >= FkSpurious and contractCode.len >= EIP170_CODE_SIZE_LIMIT:
debug "Contract code size exceeds EIP170",
limit = EIP170_CODE_SIZE_LIMIT,
actual = contractCode.len
return false
let storageAddr = c.msg.contractAddress
if c.isSuicided(storageAddr): return
let gasParams = GasParams(kind: Create, cr_memLength: contractCode.len)
let codeCost = c.gasCosts[Create].c_handler(0.u256, gasParams).gasCost
if c.gasMeter.gasRemaining >= codeCost:
c.gasMeter.consumeGas(codeCost, reason = "Write contract code for CREATE")
c.vmState.mutateStateDb:
db.setCode(storageAddr, contractCode)
result = true
else:
if fork < FkHomestead or FkByzantium <= fork:
c.output = @[]
result = false
template chainTo*(c, toChild: Computation, after: untyped) =
c.child = toChild
c.continuation = proc() =
after
proc merge*(c, child: Computation) =
c.logEntries.add child.logEntries
c.gasMeter.refundGas(child.gasMeter.gasRefunded)
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
proc refundSelfDestruct*(c: Computation) =
let cost = gasFees[c.fork][RefundSelfDestruct]
c.gasMeter.refundGas(cost * c.suicides.len)
proc tracingEnabled*(c: Computation): bool {.inline.} =
TracerFlags.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)
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -1,12 +1,252 @@
# 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
./interpreter_dispatch
../constants,
../db/accounts_cache,
../utils,
./code_stream,
./interpreter/[forks_list, gas_meter, gas_costs, op_codes],
./memory,
./message,
./stack,
./state,
./transaction_tracer,
./types,
chronicles,
eth/[common, keys],
options,
sets
export
interpreter_dispatch
logScope:
topics = "vm computation"
when defined(chronicles_log_level):
import stew/byteutils
# ------------------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------------------
proc generateContractAddress(c: Computation, salt: Uint256): EthAddress =
if c.msg.kind == evmcCreate:
let creationNonce = c.vmState.readOnlyStateDb().getNonce(c.msg.sender)
result = generateAddress(c.msg.sender, creationNonce)
else:
result = generateSafeAddress(c.msg.sender, salt, c.msg.data)
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
template getCoinbase*(c: Computation): EthAddress =
c.vmState.coinbase
template getTimestamp*(c: Computation): int64 =
c.vmState.timestamp.toUnix
template getBlockNumber*(c: Computation): Uint256 =
c.vmState.blockNumber.blockNumberToVmWord
template getDifficulty*(c: Computation): DifficultyInt =
c.vmState.difficulty
template getGasLimit*(c: Computation): GasInt =
c.vmState.gasLimit
template getChainId*(c: Computation): uint =
c.vmState.chaindb.config.chainId.uint
template getOrigin*(c: Computation): EthAddress =
c.vmState.txOrigin
template getGasPrice*(c: Computation): GasInt =
c.vmState.txGasPrice
template getBlockHash*(c: Computation, blockNumber: Uint256): Hash256 =
c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber)
template accountExists*(c: Computation, address: EthAddress): bool =
if c.fork >= FkSpurious:
not c.vmState.readOnlyStateDB.isDeadAccount(address)
else:
c.vmState.readOnlyStateDB.accountExists(address)
template getStorage*(c: Computation, slot: Uint256): Uint256 =
c.vmState.readOnlyStateDB.getStorage(c.msg.contractAddress, slot)
template getBalance*(c: Computation, address: EthAddress): Uint256 =
c.vmState.readOnlyStateDB.getBalance(address)
template getCodeSize*(c: Computation, address: EthAddress): uint =
uint(c.vmState.readOnlyStateDB.getCodeSize(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 selfDestruct*(c: Computation, address: EthAddress) =
c.execSelfDestruct(address)
template getCode*(c: Computation, address: EthAddress): seq[byte] =
c.vmState.readOnlyStateDB.getCode(address)
proc newComputation*(vmState: BaseVMState,
message: Message, salt= 0.u256): Computation =
new result
result.vmState = vmState
result.msg = message
result.memory = Memory()
result.stack = newStack()
result.returnStack = @[]
result.gasMeter.init(message.gas)
result.touchedAccounts = initHashSet[EthAddress]()
result.suicides = initHashSet[EthAddress]()
if result.msg.isCreate():
result.msg.contractAddress = result.generateContractAddress(salt)
result.code = newCodeStream(message.data)
message.data = @[]
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
template isSuccess*(c: Computation): bool =
c.error.isNil
template isError*(c: Computation): bool =
not c.isSuccess
func shouldBurnGas*(c: Computation): bool =
c.isError and c.error.burnsGas
proc isSuicided*(c: Computation, address: EthAddress): bool =
result = address in c.suicides
proc snapshot*(c: Computation) =
c.savePoint = c.vmState.accountDb.beginSavePoint()
proc commit*(c: Computation) =
c.vmState.accountDb.commit(c.savePoint)
proc dispose*(c: Computation) {.inline.} =
c.vmState.accountDb.safeDispose(c.savePoint)
c.savePoint = nil
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
let contractCode = c.output
if contractCode.len == 0: return
if fork >= FkSpurious and contractCode.len >= EIP170_CODE_SIZE_LIMIT:
debug "Contract code size exceeds EIP170",
limit = EIP170_CODE_SIZE_LIMIT,
actual = contractCode.len
return false
let storageAddr = c.msg.contractAddress
if c.isSuicided(storageAddr): return
let gasParams = GasParams(kind: Create, cr_memLength: contractCode.len)
let codeCost = c.gasCosts[Create].c_handler(0.u256, gasParams).gasCost
if c.gasMeter.gasRemaining >= codeCost:
c.gasMeter.consumeGas(codeCost, reason = "Write contract code for CREATE")
c.vmState.mutateStateDb:
db.setCode(storageAddr, contractCode)
result = true
else:
if fork < FkHomestead or FkByzantium <= fork:
c.output = @[]
result = false
template chainTo*(c, toChild: Computation, after: untyped) =
c.child = toChild
c.continuation = proc() =
after
proc merge*(c, child: Computation) =
c.logEntries.add child.logEntries
c.gasMeter.refundGas(child.gasMeter.gasRefunded)
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
proc refundSelfDestruct*(c: Computation) =
let cost = gasFees[c.fork][RefundSelfDestruct]
c.gasMeter.refundGas(cost * c.suicides.len)
proc tracingEnabled*(c: Computation): bool {.inline.} =
TracerFlags.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)
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -16,7 +16,7 @@ const
import
../code_stream,
../compu_helper,
../computation,
./forks_list,
./gas_costs,
./gas_meter,

View File

@ -14,7 +14,7 @@
import
../../../constants,
../../compu_helper,
../../computation,
../../stack,
../../types,
../op_codes,

View File

@ -13,7 +13,7 @@
##
import
../../compu_helper,
../../computation,
../../stack,
../../state,
../op_codes,

View File

@ -16,7 +16,7 @@ import
../../../constants,
../../../db/accounts_cache,
../../../errors,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../../state,

View File

@ -15,7 +15,7 @@
import
../../../constants,
../../../errors,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../../state,

View File

@ -15,7 +15,7 @@
import
../../../errors,
../../code_stream,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../../state,

View File

@ -15,7 +15,7 @@
import
../../../constants,
../../../errors,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../gas_costs,

View File

@ -15,7 +15,7 @@
import
../../../constants,
../../../errors,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../../types,

View File

@ -16,7 +16,7 @@ import
../../../db/accounts_cache,
../../../errors,
../../code_stream,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../../state,

View File

@ -15,7 +15,7 @@
import
../../../db/accounts_cache,
../../../errors,
../../compu_helper,
../../computation,
../../memory,
../../stack,
../../state,

View File

@ -17,7 +17,7 @@ import
../constants,
../db/accounts_cache,
./code_stream,
./compu_helper,
./computation,
./interpreter/op_dispatcher,
./message,
./precompiles,

View File

@ -23,8 +23,8 @@ import
../constants,
../db/accounts_cache,
../transaction,
./compu_helper,
./computation,
./interpreter_dispatch,
./interpreter/[forks_list, gas_costs, gas_meter],
./message,
./state,

View File

@ -9,103 +9,63 @@
# according to those terms.
# The computation module suffers from a circular include/import dependency.
# The VM computation module suffers from a circular include/import dependency.
# After fixing this wrapper should be re-factored.
when defined(evmc_enabled) or not defined(vm2_enabled):
import
./vm/computation as vmc
export
vmc.accountExists,
vmc.addLogEntry,
vmc.chainTo,
vmc.commit,
vmc.dispose,
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.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
vmc.execCallOrCreate,
vmc.executeOpcodes
else:
import
./vm2/compu_helper as xmc,
./vm2/computation as vmc
./vm2/computation as vmc,
./vm2/interpreter_dispatch as vmi
export
xmc.accountExists,
xmc.addLogEntry,
xmc.chainTo,
xmc.commit,
xmc.dispose,
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.getGasRefund,
xmc.getOrigin,
xmc.getStorage,
xmc.getTimestamp,
xmc.isError,
xmc.isOriginComputation,
xmc.isSuccess,
xmc.isSuicided,
xmc.merge,
xmc.newComputation,
xmc.prepareTracer,
xmc.refundSelfDestruct,
xmc.rollback,
xmc.selfDestruct,
xmc.setError,
xmc.shouldBurnGas,
xmc.snapshot,
xmc.traceError,
xmc.traceOpCodeEnded,
xmc.traceOpCodeStarted,
xmc.tracingEnabled,
xmc.writeContract
vmi.execCallOrCreate,
vmi.executeOpcodes
export
vmc.execCallOrCreate,
vmc.executeOpcodes
vmc.accountExists,
vmc.addLogEntry,
vmc.chainTo,
vmc.commit,
vmc.dispose,
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.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

View File

@ -63,8 +63,8 @@ when defined(evmc_enabled) or not defined(vm2_enabled):
else:
import
./vm2/code_stream as aCst,
./vm2/compu_helper as bChp,
./vm2/computation as cVmc,
./vm2/computation as bChp,
./vm2/interpreter_dispatch as cVmc,
./vm2/interpreter/forks_list as dVmf,
./vm2/interpreter/gas_meter as eGmt,
./vm2/interpreter/op_codes as fVmo,