diff --git a/nimbus/vm2/computation.nim b/nimbus/vm2/computation.nim index e603f11be..3e93cdc51 100644 --- a/nimbus/vm2/computation.nim +++ b/nimbus/vm2/computation.nim @@ -23,100 +23,66 @@ import when defined(chronicles_log_level): import stew/byteutils -when defined(evmc_enabled): - import evmc/evmc, evmc_helpers, evmc_api, stew/ranges/ptr_arith - logScope: topics = "vm computation" -const - evmc_enabled* = defined(evmc_enabled) - template getCoinbase*(c: Computation): EthAddress = - when evmc_enabled: - c.host.getTxContext().block_coinbase - else: + block: c.vmState.coinbase template getTimestamp*(c: Computation): int64 = - when evmc_enabled: - c.host.getTxContext().block_timestamp - else: + block: c.vmState.timestamp.toUnix template getBlockNumber*(c: Computation): Uint256 = - when evmc_enabled: - c.host.getTxContext().block_number.u256 - else: + block: c.vmState.blockNumber.blockNumberToVmWord template getDifficulty*(c: Computation): DifficultyInt = - when evmc_enabled: - Uint256.fromEvmc c.host.getTxContext().block_difficulty - else: + block: c.vmState.difficulty template getGasLimit*(c: Computation): GasInt = - when evmc_enabled: - c.host.getTxContext().block_gas_limit.GasInt - else: + block: c.vmState.gasLimit template getChainId*(c: Computation): uint = - when evmc_enabled: - Uint256.fromEvmc(c.host.getTxContext().chain_id).truncate(uint) - else: + block: c.vmState.chaindb.config.chainId.uint template getOrigin*(c: Computation): EthAddress = - when evmc_enabled: - c.host.getTxContext().tx_origin - else: + block: c.vmState.txOrigin template getGasPrice*(c: Computation): GasInt = - when evmc_enabled: - Uint256.fromEvmc(c.host.getTxContext().tx_gas_price).truncate(GasInt) - else: + block: c.vmState.txGasPrice template getBlockHash*(c: Computation, blockNumber: Uint256): Hash256 = - when evmc_enabled: - c.host.getBlockHash(blockNumber) - else: + block: c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber) template accountExists*(c: Computation, address: EthAddress): bool = - when evmc_enabled: - c.host.accountExists(address) - else: + block: if c.fork >= FkSpurious: not c.vmState.readOnlyStateDB.isDeadAccount(address) else: c.vmState.readOnlyStateDB.accountExists(address) template getStorage*(c: Computation, slot: Uint256): Uint256 = - when evmc_enabled: - c.host.getStorage(c.msg.contractAddress, slot) - else: + block: c.vmState.readOnlyStateDB.getStorage(c.msg.contractAddress, slot) template getBalance*(c: Computation, address: EthAddress): Uint256 = - when evmc_enabled: - c.host.getBalance(address) - else: + block: c.vmState.readOnlyStateDB.getBalance(address) template getCodeSize*(c: Computation, address: EthAddress): uint = - when evmc_enabled: - c.host.getCodeSize(address) - else: + block: uint(c.vmState.readOnlyStateDB.getCodeSize(address)) template getCodeHash*(c: Computation, address: EthAddress): Hash256 = - when evmc_enabled: - c.host.getCodeHash(address) - else: + block: let db = c.vmState.readOnlyStateDB if not db.accountExists(address) or db.isEmptyAccount(address): default(Hash256) @@ -124,15 +90,11 @@ template getCodeHash*(c: Computation, address: EthAddress): Hash256 = db.getCodeHash(address) template selfDestruct*(c: Computation, address: EthAddress) = - when evmc_enabled: - c.host.selfDestruct(c.msg.contractAddress, address) - else: + block: c.execSelfDestruct(address) template getCode*(c: Computation, address: EthAddress): seq[byte] = - when evmc_enabled: - c.host.copyCode(address) - else: + block: c.vmState.readOnlyStateDB.getCode(address) proc generateContractAddress(c: Computation, salt: Uint256): EthAddress = @@ -162,11 +124,6 @@ proc newComputation*(vmState: BaseVMState, message: Message, salt= 0.u256): Comp else: result.code = newCodeStream(vmState.readOnlyStateDb.getCode(message.codeAddress)) - when evmc_enabled: - result.host.init( - nim_host_get_interface(), - cast[evmc_host_context](result) - ) template gasCosts*(c: Computation): untyped = c.vmState.gasCosts @@ -401,6 +358,3 @@ proc prepareTracer*(c: Computation) {.inline.} = c.vmState.tracer.prepare(c.msg.depth) include interpreter_dispatch - -when defined(evmc_enabled): - include evmc_host diff --git a/nimbus/vm2/evmc_api.nim b/nimbus/vm2/evmc_api.nim deleted file mode 100644 index 61e2ab687..000000000 --- a/nimbus/vm2/evmc_api.nim +++ /dev/null @@ -1,147 +0,0 @@ -# Nimbus -# Copyright (c) 2019 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 evmc/evmc, ./evmc_helpers, eth/common, ../constants - -type - # we are not using EVMC original signature here - # because we want to trick the compiler - # and reduce unnecessary conversion/typecast - # TODO: move this type definition to nim-evmc - # after we have implemented ABI compatibility test - # TODO: investigate the possibility to use Big Endian VMWord - # directly if it's not involving stint computation - # and we can reduce unecessary conversion further - nimbus_tx_context* = object - tx_gas_price* : evmc_uint256be # The transaction gas price. - tx_origin* : EthAddress # The transaction origin account. - block_coinbase* : EthAddress # The miner of the block. - block_number* : int64 # The block number. - block_timestamp* : int64 # The block timestamp. - block_gas_limit* : int64 # The block gas limit. - block_difficulty*: evmc_uint256be # The block difficulty. - chain_id* : evmc_uint256be # The blockchain's ChainID. - - nimbus_message* = object - kind*: evmc_call_kind - flags*: uint32 - depth*: int32 - gas*: int64 - destination*: EthAddress - sender*: EthAddress - input_data*: ptr byte - input_size*: uint - value*: evmc_uint256be - create2_salt*: evmc_bytes32 - - nimbus_result* = object - status_code*: evmc_status_code - gas_left*: int64 - output_data*: ptr byte - output_size*: uint - release*: proc(result: var nimbus_result) {.cdecl, gcsafe.} - create_address*: EthAddress - padding*: array[4, byte] - - nimbus_host_interface* = object - account_exists*: proc(context: evmc_host_context, address: EthAddress): bool {.cdecl, gcsafe.} - get_storage*: proc(context: evmc_host_context, address: EthAddress, key: ptr evmc_uint256be): evmc_uint256be {.cdecl, gcsafe.} - set_storage*: proc(context: evmc_host_context, address: EthAddress, - key, value: ptr evmc_uint256be): evmc_storage_status {.cdecl, gcsafe.} - get_balance*: proc(context: evmc_host_context, address: EthAddress): evmc_uint256be {.cdecl, gcsafe.} - get_code_size*: proc(context: evmc_host_context, address: EthAddress): uint {.cdecl, gcsafe.} - get_code_hash*: proc(context: evmc_host_context, address: EthAddress): Hash256 {.cdecl, gcsafe.} - copy_code*: proc(context: evmc_host_context, address: EthAddress, - code_offset: int, buffer_data: ptr byte, - buffer_size: int): int {.cdecl, gcsafe.} - selfdestruct*: proc(context: evmc_host_context, address, beneficiary: EthAddress) {.cdecl, gcsafe.} - call*: proc(context: evmc_host_context, msg: ptr nimbus_message): nimbus_result {.cdecl, gcsafe.} - get_tx_context*: proc(context: evmc_host_context): nimbus_tx_context {.cdecl, gcsafe.} - get_block_hash*: proc(context: evmc_host_context, number: int64): Hash256 {.cdecl, gcsafe.} - emit_log*: proc(context: evmc_host_context, address: EthAddress, - data: ptr byte, data_size: uint, - topics: ptr evmc_bytes32, topics_count: uint) {.cdecl, gcsafe.} - -proc nim_host_get_interface*(): ptr nimbus_host_interface {.importc, cdecl.} -proc nim_host_create_context*(vmstate: pointer, msg: ptr evmc_message): evmc_host_context {.importc, cdecl.} -proc nim_host_destroy_context*(ctx: evmc_host_context) {.importc, cdecl.} -proc nim_create_nimbus_vm*(): ptr evmc_vm {.importc, cdecl.} - -type - HostContext* = object - host*: ptr nimbus_host_interface - context*: evmc_host_context - -proc init*(x: var HostContext, host: ptr nimbus_host_interface, context: evmc_host_context) = - x.host = host - x.context = context - -proc init*(x: typedesc[HostContext], host: ptr nimbus_host_interface, context: evmc_host_context): HostContext = - result.init(host, context) - -proc getTxContext*(ctx: HostContext): nimbus_tx_context {.inline.} = - ctx.host.get_tx_context(ctx.context) - -proc getBlockHash*(ctx: HostContext, number: Uint256): Hash256 = - let - blockNumber = ctx.getTxContext().block_number.u256 - ancestorDepth = blockNumber - number - 1 - if ancestorDepth >= constants.MAX_PREV_HEADER_DEPTH: - return - if number >= blockNumber: - return - ctx.host.get_block_hash(ctx.context, number.truncate(int64)) - -proc accountExists*(ctx: HostContext, address: EthAddress): bool {.inline.} = - ctx.host.account_exists(ctx.context, address) - -proc getStorage*(ctx: HostContext, address: EthAddress, key: Uint256): Uint256 = - var key = toEvmc(key) - Uint256.fromEvmc ctx.host.get_storage(ctx.context, address, key.addr) - -proc setStorage*(ctx: HostContext, address: EthAddress, - key, value: Uint256): evmc_storage_status {.inline.} = - var - key = toEvmc(key) - value = toEvmc(value) - ctx.host.set_storage(ctx.context, address, key.addr, value.addr) - -proc getBalance*(ctx: HostContext, address: EthAddress): Uint256 {.inline.} = - Uint256.fromEvmc ctx.host.get_balance(ctx.context, address) - -proc getCodeSize*(ctx: HostContext, address: EthAddress): uint {.inline.} = - ctx.host.get_code_size(ctx.context, address) - -proc getCodeHash*(ctx: HostContext, address: EthAddress): Hash256 {.inline.} = - ctx.host.get_code_hash(ctx.context, address) - -proc copyCode*(ctx: HostContext, address: EthAddress, codeOffset: int = 0): seq[byte] = - let size = ctx.getCodeSize(address).int - if size - codeOffset > 0: - result = newSeq[byte](size - codeOffset) - let read = ctx.host.copy_code(ctx.context, address, - codeOffset, result[0].addr, result.len) - doAssert(read == result.len) - -proc selfdestruct*(ctx: HostContext, address, beneficiary: EthAddress) {.inline.} = - ctx.host.selfdestruct(ctx.context, address, beneficiary) - -proc emitLog*(ctx: HostContext, address: EthAddress, data: openArray[byte], - topics: ptr evmc_bytes32, topicsCount: int) {.inline.} = - ctx.host.emit_log(ctx.context, address, if data.len > 0: data[0].unsafeAddr else: nil, - data.len.uint, topics, topicsCount.uint) - -proc call*(ctx: HostContext, msg: nimbus_message): nimbus_result {.inline.} = - ctx.host.call(ctx.context, msg.unsafeAddr) - -#proc vmHost*(vmState: BaseVMState, gasPrice: GasInt, origin: EthAddress): HostContext = -# let host = nim_host_get_interface() -# let context = nim_host_create_context(cast[pointer](vmState), gasPrice, toEvmc(origin)) -# result.init(host, context) -# -#proc destroy*(hc: HostContext) = -# nim_host_destroy_context(hc.context) diff --git a/nimbus/vm2/evmc_helpers.nim b/nimbus/vm2/evmc_helpers.nim deleted file mode 100644 index c8a7c53d4..000000000 --- a/nimbus/vm2/evmc_helpers.nim +++ /dev/null @@ -1,43 +0,0 @@ -import eth/common, stint, evmc/evmc - -const - evmc_native* {.booldefine.} = false - -func toEvmc*(a: EthAddress): evmc_address {.inline.} = - cast[evmc_address](a) - -func toEvmc*(h: Hash256): evmc_bytes32 {.inline.} = - cast[evmc_bytes32](h) - -func toEvmc*(n: Uint256): evmc_uint256be {.inline.} = - when evmc_native: - cast[evmc_uint256be](n) - else: - cast[evmc_uint256be](n.toByteArrayBE) - -func fromEvmc*(T: type, n: evmc_bytes32): T {.inline.} = - when T is Hash256: - cast[Hash256](n) - elif T is Uint256: - when evmc_native: - cast[Uint256](n) - else: - Uint256.fromBytesBE(n.bytes) - else: - {.error: "cannot convert unsupported evmc type".} - -func fromEvmc*(a: evmc_address): EthAddress {.inline.} = - cast[EthAddress](a) - -when isMainModule: - import constants - var a: evmc_address - a.bytes[19] = 3.byte - var na = fromEvmc(a) - assert(a == toEvmc(na)) - var b = stuint(10, 256) - var eb = b.toEvmc - assert(b == fromEvmc(Uint256, eb)) - var h = EMPTY_SHA3 - var eh = toEvmc(h) - assert(h == fromEvmc(Hash256, eh)) diff --git a/nimbus/vm2/evmc_host.nim b/nimbus/vm2/evmc_host.nim deleted file mode 100644 index 72b66e6f1..000000000 --- a/nimbus/vm2/evmc_host.nim +++ /dev/null @@ -1,252 +0,0 @@ -# Nimbus -# Copyright (c) 2019 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. - -proc hostReleaseResultImpl(res: var nimbus_result) {.cdecl, gcsafe.} = - dealloc(res.output_data) - -proc hostGetTxContextImpl(ctx: Computation): nimbus_tx_context {.cdecl.} = - let vmstate = ctx.vmState - result.tx_gas_price = toEvmc(vmstate.txGasPrice.u256) - result.tx_origin = vmstate.txOrigin - result.block_coinbase = vmstate.coinbase - result.block_number = vmstate.blockNumber.truncate(int64) - result.block_timestamp = vmstate.timestamp.toUnix() - result.block_gas_limit = int64(vmstate.blockHeader.gasLimit) - result.block_difficulty = toEvmc(vmstate.difficulty) - result.chain_id = toEvmc(vmstate.chaindb.config.chainId.uint.u256) - -proc hostGetBlockHashImpl(ctx: Computation, number: int64): Hash256 {.cdecl.} = - ctx.vmState.getAncestorHash(number.u256) - -proc hostAccountExistsImpl(ctx: Computation, address: EthAddress): bool {.cdecl.} = - let db = ctx.vmState.readOnlyStateDB - if ctx.fork >= FkSpurious: - not db.isDeadAccount(address) - else: - db.accountExists(address) - -proc hostGetStorageImpl(ctx: Computation, address: EthAddress, key: var evmc_bytes32): evmc_bytes32 {.cdecl.} = - ctx.vmState.accountDB.getStorage(address, Uint256.fromEvmc(key)).toEvmc() - -proc sstoreNetGasMetering(ctx: Computation): bool {.inline.} = - ctx.fork in {FkConstantinople, FkIstanbul, FkBerlin} - -proc hostSetStorageImpl(ctx: Computation, address: EthAddress, - key, value: var evmc_bytes32): evmc_storage_status {.cdecl.} = - let - slot = Uint256.fromEvmc(key) - newValue = Uint256.fromEvmc(value) - statedb = ctx.vmState.readOnlyStateDb - currValue = statedb.getStorage(address, slot) - - assert address == ctx.msg.contractAddress - - var - status = EVMC_STORAGE_MODIFIED - gasRefund = 0.GasInt - origValue = 0.u256 - - if newValue == currValue: - status = EVMC_STORAGE_UNCHANGED - else: - origValue = statedb.getCommittedStorage(address, slot) - if origValue == currValue or not ctx.sstoreNetGasMetering(): - if currValue == 0: - status = EVMC_STORAGE_ADDED - elif newValue == 0: - status = EVMC_STORAGE_DELETED - else: - status = EVMC_STORAGE_MODIFIED_AGAIN - ctx.vmState.mutateStateDB: - db.setStorage(address, slot, newValue) - - let gasParam = GasParams(kind: Op.Sstore, - s_status: status, - s_currentValue: currValue, - s_originalValue: origValue - ) - gasRefund = ctx.gasCosts[Sstore].c_handler(newValue, gasParam)[1] - - if gasRefund != 0: - ctx.gasMeter.refundGas(gasRefund) - - result = status - -proc hostGetBalanceImpl(ctx: Computation, address: EthAddress): evmc_bytes32 {.cdecl.} = - ctx.vmState.readOnlyStateDB.getBalance(address).toEvmc() - -proc hostGetCodeSizeImpl(ctx: Computation, address: EthAddress): uint {.cdecl.} = - ctx.vmState.readOnlyStateDB.getCode(address).len.uint - -proc hostGetCodeHashImpl(ctx: Computation, address: EthAddress): Hash256 {.cdecl.} = - let db = ctx.vmstate.readOnlyStateDB - if not db.accountExists(address): - return - if db.isEmptyAccount(address): - return - db.getCodeHash(address) - -proc hostCopyCodeImpl(ctx: Computation, address: EthAddress, - codeOffset: int, bufferData: ptr byte, - bufferSize: int): int {.cdecl.} = - - var code = ctx.vmState.readOnlyStateDB.getCode(address) - - # Handle "big offset" edge case. - if codeOffset > code.len: - return 0 - - let maxToCopy = code.len - codeOffset - let numToCopy = min(maxToCopy, bufferSize) - if numToCopy > 0: - copyMem(bufferData, code[codeOffset].addr, numToCopy) - result = numToCopy - -proc hostSelfdestructImpl(ctx: Computation, address, beneficiary: EthAddress) {.cdecl.} = - assert address == ctx.msg.contractAddress - ctx.execSelfDestruct(beneficiary) - -proc hostEmitLogImpl(ctx: Computation, address: EthAddress, - data: ptr byte, dataSize: int, - topics: UncheckedArray[evmc_bytes32], topicsCount: int) {.cdecl.} = - var log: Log - if topicsCount > 0: - log.topics = newSeq[Topic](topicsCount) - for i in 0 ..< topicsCount: - log.topics[i] = topics[i].bytes - - log.data = @(makeOpenArray(data, dataSize)) - log.address = address - ctx.addLogEntry(log) - -template createImpl(c: Computation, m: nimbus_message, res: nimbus_result) = - # TODO: use evmc_message to evoid copy - let childMsg = Message( - kind: CallKind(m.kind), - depth: m.depth, - gas: m.gas, - sender: m.sender, - value: Uint256.fromEvmc(m.value), - data: @(makeOpenArray(m.inputData, m.inputSize.int)) - ) - - let child = newComputation(c.vmState, childMsg, Uint256.fromEvmc(m.create2_salt)) - child.execCallOrCreate() - - if not child.shouldBurnGas: - res.gas_left = child.gasMeter.gasRemaining - - if child.isSuccess: - c.merge(child) - res.status_code = EVMC_SUCCESS - res.create_address = child.msg.contractAddress - else: - res.status_code = if child.shouldBurnGas: EVMC_FAILURE else: EVMC_REVERT - if child.output.len > 0: - # TODO: can we move the ownership of seq to raw pointer? - res.output_size = child.output.len.uint - res.output_data = cast[ptr byte](alloc(child.output.len)) - copyMem(res.output_data, child.output[0].addr, child.output.len) - res.release = hostReleaseResultImpl - -template callImpl(c: Computation, m: nimbus_message, res: nimbus_result) = - let childMsg = Message( - kind: CallKind(m.kind), - depth: m.depth, - gas: m.gas, - sender: m.sender, - codeAddress: m.destination, - contractAddress: if m.kind == EVMC_CALL: m.destination else: c.msg.contractAddress, - value: Uint256.fromEvmc(m.value), - data: @(makeOpenArray(m.inputData, m.inputSize.int)), - flags: MsgFlags(m.flags) - ) - - let child = newComputation(c.vmState, childMsg) - child.execCallOrCreate() - - if not child.shouldBurnGas: - res.gas_left = child.gasMeter.gasRemaining - - if child.isSuccess: - c.merge(child) - res.status_code = EVMC_SUCCESS - else: - res.status_code = if child.shouldBurnGas: EVMC_FAILURE else: EVMC_REVERT - - if child.output.len > 0: - # TODO: can we move the ownership of seq to raw pointer? - res.output_size = child.output.len.uint - res.output_data = cast[ptr byte](alloc(child.output.len)) - copyMem(res.output_data, child.output[0].addr, child.output.len) - res.release = hostReleaseResultImpl - -proc hostCallImpl(ctx: Computation, msg: var nimbus_message): nimbus_result {.cdecl.} = - if msg.kind == EVMC_CREATE or msg.kind == EVMC_CREATE2: - createImpl(ctx, msg, result) - else: - callImpl(ctx, msg, result) - -proc initHostInterface(): evmc_host_interface = - result.account_exists = cast[evmc_account_exists_fn](hostAccountExistsImpl) - result.get_storage = cast[evmc_get_storage_fn](hostGetStorageImpl) - result.set_storage = cast[evmc_set_storage_fn](hostSetStorageImpl) - result.get_balance = cast[evmc_get_balance_fn](hostGetBalanceImpl) - result.get_code_size = cast[evmc_get_code_size_fn](hostGetCodeSizeImpl) - result.get_code_hash = cast[evmc_get_code_hash_fn](hostGetCodeHashImpl) - result.copy_code = cast[evmc_copy_code_fn](hostCopyCodeImpl) - result.selfdestruct = cast[evmc_selfdestruct_fn](hostSelfdestructImpl) - result.call = cast[evmc_call_fn](hostCallImpl) - result.get_tx_context = cast[evmc_get_tx_context_fn](hostGetTxContextImpl) - result.get_block_hash = cast[evmc_get_block_hash_fn](hostGetBlockHashImpl) - result.emit_log = cast[evmc_emit_log_fn](hostEmitLogImpl) - -proc vmSetOptionImpl(vm: ptr evmc_vm, name, value: cstring): evmc_set_option_result {.cdecl.} = - return EVMC_SET_OPTION_INVALID_NAME - -proc vmExecuteImpl(vm: ptr evmc_vm, host: ptr evmc_host_interface, - ctx: Computation, rev: evmc_revision, - msg: evmc_message, code: ptr byte, code_size: uint): evmc_result {.cdecl.} = - discard - -proc vmGetCapabilitiesImpl(vm: ptr evmc_vm): evmc_capabilities {.cdecl.} = - result.incl(EVMC_CAPABILITY_EVM1) - -proc vmDestroyImpl(vm: ptr evmc_vm) {.cdecl.} = - dealloc(vm) - -const - EVMC_HOST_NAME = "nimbus_vm" - EVMC_VM_VERSION = "0.0.1" - -proc init(vm: var evmc_vm) = - vm.abi_version = EVMC_ABI_VERSION - vm.name = EVMC_HOST_NAME - vm.version = EVMC_VM_VERSION - vm.destroy = vmDestroyImpl - vm.execute = cast[evmc_execute_fn](vmExecuteImpl) - vm.get_capabilities = vmGetCapabilitiesImpl - vm.set_option = vmSetOptionImpl - -let gHost = initHostInterface() -proc nim_host_get_interface(): ptr nimbus_host_interface {.exportc, cdecl.} = - result = cast[ptr nimbus_host_interface](gHost.unsafeAddr) - -proc nim_host_create_context(vmstate: BaseVmState, msg: ptr evmc_message): Computation {.exportc, cdecl.} = - #result = HostContext( - # vmState: vmstate, - # gasPrice: GasInt(gasPrice), - # origin: fromEvmc(origin) - #) - GC_ref(result) - -proc nim_host_destroy_context(ctx: Computation) {.exportc, cdecl.} = - GC_unref(ctx) - -proc nim_create_nimbus_vm(): ptr evmc_vm {.exportc, cdecl.} = - result = create(evmc_vm) - init(result[]) diff --git a/nimbus/vm2/interpreter/gas_costs.nim b/nimbus/vm2/interpreter/gas_costs.nim index 283bcf0eb..9f9e1bd12 100644 --- a/nimbus/vm2/interpreter/gas_costs.nim +++ b/nimbus/vm2/interpreter/gas_costs.nim @@ -15,9 +15,6 @@ import ./utils/[macros_gen_opcodes, utils_numeric], ./opcode_values, ./vm_forks, ../../errors -when defined(evmc_enabled): - import evmc/evmc - # Gas Fee Schedule # Yellow Paper Appendix G - https://ethereum.github.io/yellowpaper/paper.pdf type @@ -72,8 +69,6 @@ type case kind*: Op of Sstore: - when defined(evmc_enabled): - s_status*: evmc_storage_status s_currentValue*: Uint256 s_originalValue*: Uint256 of Call, CallCode, DelegateCall, StaticCall: @@ -244,32 +239,7 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = CleanRefund = SSTORE_RESET_GAS - SLOAD_GAS # resetting to the original non-zero value ClearRefund = FeeSchedule[RefundsClear]# clearing an originally existing storage slot - when defined(evmc_enabled): - const - sstoreDirty = when fork < FkConstantinople or fork == FkPetersburg: CleanGas - else: DirtyGas - - case gasParams.s_status - of EVMC_STORAGE_ADDED: result.gasCost = InitGas - of EVMC_STORAGE_MODIFIED: result.gasCost = CleanGas - of EVMC_STORAGE_DELETED: - result.gasCost = CleanGas - result.gasRefund += ClearRefund - of EVMC_STORAGE_UNCHANGED: result.gasCost = sstoreDirty - of EVMC_STORAGE_MODIFIED_AGAIN: - result.gasCost = sstoreDirty - if not gasParams.s_originalValue.isZero: - if gasParams.s_currentValue.isZero: - result.gasRefund -= ClearRefund - if value.isZero: - result.gasRefund += ClearRefund - - if gasParams.s_originalValue == value: - if gasParams.s_originalValue.isZero: - result.gasRefund += InitRefund - else: - result.gasRefund += CleanRefund - else: + block: when fork < FkConstantinople or fork == FkPetersburg: let isStorageEmpty = gasParams.s_currentValue.isZero diff --git a/nimbus/vm2/interpreter/opcodes_impl.nim b/nimbus/vm2/interpreter/opcodes_impl.nim index e8a4b15d3..29b3aa18d 100644 --- a/nimbus/vm2/interpreter/opcodes_impl.nim +++ b/nimbus/vm2/interpreter/opcodes_impl.nim @@ -14,9 +14,6 @@ import ../../errors, ../../constants, ../../db/[db_chain, accounts_cache] -when defined(evmc_enabled): - import ../evmc_api, ../evmc_helpers, evmc/evmc - logScope: topics = "opcode impl" @@ -439,8 +436,7 @@ op sload, inline = true, slot: ## 0x54, Load word from storage. push: c.getStorage(slot) -when not evmc_enabled: - template sstoreImpl(c: Computation, slot, newValue: Uint256) = +template sstoreImpl(c: Computation, slot, newValue: Uint256) = let currentValue {.inject.} = c.getStorage(slot) let @@ -455,27 +451,13 @@ when not evmc_enabled: c.vmState.mutateStateDB: db.setStorage(c.msg.contractAddress, slot, newValue) -when evmc_enabled: - template sstoreEvmc(c: Computation, slot, newValue: Uint256) = - let - currentValue {.inject.} = c.getStorage(slot) - status = c.host.setStorage(c.msg.contractAddress, slot, newValue) - gasParam = GasParams(kind: Op.Sstore, s_status: status) - gasCost = c.gasCosts[Sstore].c_handler(newValue, gasParam)[0] - - c.gasMeter.consumeGas(gasCost, &"SSTORE: {c.msg.contractAddress}[{slot}] -> {newValue} ({currentValue})") - op sstore, inline = false, slot, newValue: ## 0x55, Save word to storage. checkInStaticContext(c) - - when evmc_enabled: - sstoreEvmc(c, slot, newValue) - else: + block: sstoreImpl(c, slot, newValue) -when not evmc_enabled: - template sstoreNetGasMeteringImpl(c: Computation, slot, newValue: Uint256) = +template sstoreNetGasMeteringImpl(c: Computation, slot, newValue: Uint256) = let stateDB = c.vmState.readOnlyStateDB let currentValue {.inject.} = c.getStorage(slot) @@ -500,18 +482,12 @@ op sstoreEIP2200, inline = false, slot, newValue: if c.gasMeter.gasRemaining <= SentryGasEIP2200: raise newException(OutOfGas, "Gas not enough to perform EIP2200 SSTORE") - - when evmc_enabled: - sstoreEvmc(c, slot, newValue) - else: + block: sstoreNetGasMeteringImpl(c, slot, newValue) op sstoreEIP1283, inline = false, slot, newValue: checkInStaticContext(c) - - when evmc_enabled: - sstoreEvmc(c, slot, newValue) - else: + block: sstoreNetGasMeteringImpl(c, slot, newValue) proc jumpImpl(c: Computation, jumpTarget: UInt256) = @@ -645,29 +621,7 @@ template genCreate(callName: untyped, opCode: Op): untyped = createMsgGas -= createMsgGas div 64 c.gasMeter.consumeGas(createMsgGas, reason="CREATE") - when evmc_enabled: - let msg = nimbus_message( - kind: callKind.evmc_call_kind, - depth: (c.msg.depth + 1).int32, - gas: createMsgGas, - sender: c.msg.contractAddress, - input_data: c.memory.readPtr(memPos), - input_size: memLen.uint, - value: toEvmc(endowment), - create2_salt: toEvmc(salt) - ) - - var res = c.host.call(msg) - c.returnData = @(makeOpenArray(res.outputData, res.outputSize.int)) - c.gasMeter.returnGas(res.gas_left) - - if res.status_code == EVMC_SUCCESS: - c.stack.top(res.create_address) - - # TODO: a good candidate for destructor - if not res.release.isNil: - res.release(res) - else: + block: let childMsg = Message( kind: callKind, depth: c.msg.depth + 1, @@ -828,36 +782,7 @@ template genCall(callName: untyped, opCode: Op): untyped = c.gasMeter.returnGas(childGasLimit) return - when evmc_enabled: - let msg = nimbus_message( - kind: callKind.evmc_call_kind, - depth: (c.msg.depth + 1).int32, - gas: childGasLimit, - sender: sender, - destination: destination, - input_data: c.memory.readPtr(memInPos), - input_size: memInLen.uint, - value: toEvmc(value), - flags: flags.uint32 - ) - - var res = c.host.call(msg) - c.returnData = @(makeOpenArray(res.outputData, res.outputSize.int)) - - let actualOutputSize = min(memOutLen, c.returnData.len) - if actualOutputSize > 0: - c.memory.write(memOutPos, - c.returnData.toOpenArray(0, actualOutputSize - 1)) - - c.gasMeter.returnGas(res.gas_left) - - if res.status_code == EVMC_SUCCESS: - c.stack.top(1) - - # TODO: a good candidate for destructor - if not res.release.isNil: - res.release(res) - else: + block: let msg = Message( kind: callKind, depth: c.msg.depth + 1, @@ -1058,7 +983,5 @@ op sstoreEIP2929, inline = false, slot, newValue: db.accessList(c.msg.contractAddress, slot) c.gasMeter.consumeGas(ColdSloadCost, reason = "sstoreEIP2929") - when evmc_enabled: - sstoreEvmc(c, slot, newValue) - else: + block: sstoreNetGasMeteringImpl(c, slot, newValue) diff --git a/nimbus/vm2/interpreter/utils/macros_procs_opcodes.nim b/nimbus/vm2/interpreter/utils/macros_procs_opcodes.nim index f18a7b851..1e76d9cd9 100644 --- a/nimbus/vm2/interpreter/utils/macros_procs_opcodes.nim +++ b/nimbus/vm2/interpreter/utils/macros_procs_opcodes.nim @@ -14,9 +14,6 @@ import ../../types, ../../../errors, ../gas_meter, ../opcode_values, ./utils_numeric -when defined(evmc_enabled): - import ../../evmc_api, evmc/evmc - proc pop(tree: var NimNode): NimNode = ## Returns the last value of a NimNode and remove it result = tree[tree.len-1] @@ -122,15 +119,7 @@ proc logImpl(c: Computation, opcode: Op, topicCount: int) = reason="Memory expansion, Log topic and data gas cost") c.memory.extend(memPos, len) - when evmc_enabled: - var topics: array[4, evmc_bytes32] - for i in 0 ..< topicCount: - topics[i].bytes = c.stack.popTopic() - - c.host.emitLog(c.msg.contractAddress, - c.memory.read(memPos, len), - topics[0].addr, topicCount) - else: + block: var log: Log log.topics = newSeqOfCap[Topic](topicCount) for i in 0 ..< topicCount: diff --git a/nimbus/vm2/memory.nim b/nimbus/vm2/memory.nim index 8ce8bbc2a..b8714a76b 100644 --- a/nimbus/vm2/memory.nim +++ b/nimbus/vm2/memory.nim @@ -47,11 +47,6 @@ proc read*(memory: var Memory, startPos: Natural, size: Natural): seq[byte] = # TODO: use an openarray[byte] result = memory.bytes[startPos ..< (startPos + size)] -when defined(evmc_enabled): - proc readPtr*(memory: var Memory, startPos: Natural): ptr byte = - if memory.bytes.len == 0 or startPos >= memory.bytes.len: return - result = memory.bytes[startPos].addr - proc write*(memory: var Memory, startPos: Natural, value: openarray[byte]) = let size = value.len if size == 0: diff --git a/nimbus/vm2/types.nim b/nimbus/vm2/types.nim index 861e5fe53..e0cf1d8a6 100644 --- a/nimbus/vm2/types.nim +++ b/nimbus/vm2/types.nim @@ -21,10 +21,6 @@ import # TODO - will be hidden at a lower layer ../db/[db_chain, accounts_cache] -when defined(evmc_enabled): - import - ./evmc_api - type VMFlag* = enum ExecutionOK @@ -73,8 +69,6 @@ type Computation* = ref object # The execution computation vmState*: BaseVMState - when defined(evmc_enabled): - host*: HostContext msg*: Message memory*: Memory stack*: Stack