From 4b142ac52d9cdab658e2120c165618fbe476728b Mon Sep 17 00:00:00 2001 From: jangko Date: Mon, 26 Sep 2022 19:23:54 +0700 Subject: [PATCH] upgrade evmc to v10.0.0 fixes #1172, fixes #950 --- nimbus/forks.nim | 3 + nimbus/p2p/executor/calculate_reward.nim | 5 +- nimbus/transaction/call_common.nim | 21 +- nimbus/transaction/evmc_host_glue.nim | 6 +- nimbus/transaction/evmc_vm_glue.nim | 8 +- nimbus/transaction/host_call_nested.nim | 4 +- nimbus/transaction/host_services.nim | 128 ++++---- nimbus/transaction/host_trace.nim | 5 +- nimbus/vm2/computation.nim | 14 +- nimbus/vm2/evmc_api.nim | 42 ++- nimbus/vm2/evmc_host.nim | 288 ------------------ nimbus/vm2/interpreter/gas_costs.nim | 153 +++++++--- .../vm2/interpreter/op_handlers/oph_call.nim | 104 ++++--- nimbus/vm2/interpreter_dispatch.nim | 3 - nimbus/vm_gas_costs.nim | 4 + 15 files changed, 273 insertions(+), 515 deletions(-) delete mode 100644 nimbus/vm2/evmc_host.nim diff --git a/nimbus/forks.nim b/nimbus/forks.nim index 12ac040f2..b2a202408 100644 --- a/nimbus/forks.nim +++ b/nimbus/forks.nim @@ -18,3 +18,6 @@ type FkIstanbul = "Istanbul" FkBerlin = "Berlin" FkLondon = "London" + FkParis = "Paris" + FkShanghai = "Shanghai" + FkCancun = "Cancun" diff --git a/nimbus/p2p/executor/calculate_reward.nim b/nimbus/p2p/executor/calculate_reward.nim index 3f49954d0..b4e2d365b 100644 --- a/nimbus/p2p/executor/calculate_reward.nim +++ b/nimbus/p2p/executor/calculate_reward.nim @@ -38,7 +38,10 @@ const eth2, # FkPetersburg eth2, # FkIstanbul eth2, # FkBerlin - eth2 # FkLondon + eth2, # FkLondon + eth0, # FkParis + eth0, # FkShanghai + eth0, # FkCancun ] {.push raises: [Defect].} diff --git a/nimbus/transaction/call_common.nim b/nimbus/transaction/call_common.nim index 5ea3e0a26..5f394104e 100644 --- a/nimbus/transaction/call_common.nim +++ b/nimbus/transaction/call_common.nim @@ -53,8 +53,8 @@ proc hostToComputationMessage*(msg: EvmcMessage): Message = depth: msg.depth, gas: msg.gas, sender: msg.sender.fromEvmc, - contractAddress: msg.destination.fromEvmc, - codeAddress: msg.destination.fromEvmc, + contractAddress: msg.recipient.fromEvmc, + codeAddress: msg.code_address.fromEvmc, value: msg.value.fromEvmc, # When input size is zero, input data pointer may be null. data: if msg.input_size <= 0: @[] @@ -122,18 +122,19 @@ proc setupHost(call: CallParams): TransactionHost = let host = TransactionHost( vmState: vmState, msg: EvmcMessage( - kind: if call.isCreate: EVMC_CREATE else: EVMC_CALL, + kind: if call.isCreate: EVMC_CREATE else: EVMC_CALL, # Default: flags: {}, # Default: depth: 0, - gas: call.gasLimit - intrinsicGas, - destination: call.to.toEvmc, - sender: call.sender.toEvmc, - value: call.value.toEvmc, + gas: call.gasLimit - intrinsicGas, + recipient: call.to.toEvmc, + code_address: call.to.toEvmc, + sender: call.sender.toEvmc, + value: call.value.toEvmc, ) # All other defaults in `TransactionHost` are fine. ) - # Generate new contract address, prepare code, and update message `destination` + # Generate new contract address, prepare code, and update message `recipient` # with the contract address. This differs from the previous Nimbus EVM API. # Guarded under `evmc_enabled` for now so it doesn't break vm2. when defined(evmc_enabled): @@ -142,14 +143,14 @@ proc setupHost(call: CallParams): TransactionHost = let sender = call.sender let contractAddress = generateAddress(sender, call.vmState.readOnlyStateDB.getNonce(sender)) - host.msg.destination = contractAddress.toEvmc + host.msg.recipient = contractAddress.toEvmc host.msg.input_size = 0 host.msg.input_data = nil code = call.input else: # TODO: Share the underlying data, but only after checking this does not # cause problems with the database. - code = host.vmState.readOnlyStateDB.getCode(host.msg.destination.fromEvmc) + code = host.vmState.readOnlyStateDB.getCode(host.msg.code_address.fromEvmc) if call.input.len > 0: host.msg.input_size = call.input.len.csize_t # Must copy the data so the `host.msg.input_data` pointer diff --git a/nimbus/transaction/evmc_host_glue.nim b/nimbus/transaction/evmc_host_glue.nim index e2d9cb911..c1256eeda 100644 --- a/nimbus/transaction/evmc_host_glue.nim +++ b/nimbus/transaction/evmc_host_glue.nim @@ -132,8 +132,8 @@ proc evmcExecComputation*(host: TransactionHost): EvmcResult {.inline.} = host.showCallReturn(result) -# This code assumes fields, methods and types of ABI version 9, and must be +# This code assumes fields, methods and types of ABI version 10, and must be # checked for compatibility if the `import evmc/evmc` major version is updated. -when EVMC_ABI_VERSION != 9: - {.error: ("This code assumes EVMC_ABI_VERSION 9;" & +when EVMC_ABI_VERSION != 10: + {.error: ("This code assumes EVMC_ABI_VERSION 10;" & " update the code to use EVMC_ABI_VERSION " & $EVMC_ABI_VERSION).} diff --git a/nimbus/transaction/evmc_vm_glue.nim b/nimbus/transaction/evmc_vm_glue.nim index c5fc0d0cb..339c838ea 100644 --- a/nimbus/transaction/evmc_vm_glue.nim +++ b/nimbus/transaction/evmc_vm_glue.nim @@ -64,6 +64,8 @@ proc evmcExecute(vm: ptr evmc_vm, hostInterface: ptr evmc_host_interface, # Gas left is required to be zero when not `EVMC_SUCCESS` or `EVMC_REVERT`. gas_left: if result.status_code notin {EVMC_SUCCESS, EVMC_REVERT}: 0'i64 else: c.gasMeter.gasRemaining.int64, + gas_refund: if result.status_code == EVMC_SUCCESS: c.gasMeter.gasRefunded.int64 + else: 0'i64, output_data: output_data, output_size: output_size.csize_t, release: if output_data.isNil: nil @@ -100,8 +102,8 @@ proc evmc_create_nimbus_evm(): ptr evmc_vm {.cdecl, exportc.} = GC_ref(vm) return cast[ptr evmc_vm](vm) -# This code assumes fields, methods and types of ABI version 9, and must be +# This code assumes fields, methods and types of ABI version 10, and must be # checked for compatibility if the `import evmc/evmc` major version is updated. -when EVMC_ABI_VERSION != 9: - {.error: ("This code assumes EVMC_ABI_VERSION 9;" & +when EVMC_ABI_VERSION != 10: + {.error: ("This code assumes EVMC_ABI_VERSION 10;" & " update the code to use EVMC_ABI_VERSION " & $EVMC_ABI_VERSION).} diff --git a/nimbus/transaction/host_call_nested.nim b/nimbus/transaction/host_call_nested.nim index 7f877b760..e6f32991b 100644 --- a/nimbus/transaction/host_call_nested.nim +++ b/nimbus/transaction/host_call_nested.nim @@ -56,9 +56,9 @@ proc beforeExecCallEvmcNested(host: TransactionHost, depth: m.depth, gas: m.gas, sender: m.sender.fromEvmc, - codeAddress: m.destination.fromEvmc, + codeAddress: m.code_address.fromEvmc, contractAddress: if m.kind == EVMC_CALL: - m.destination.fromEvmc + m.recipient.fromEvmc else: host.computation.msg.contractAddress, value: m.value.fromEvmc, diff --git a/nimbus/transaction/host_services.nim b/nimbus/transaction/host_services.nim index 2bf5a4c63..7a20cfa79 100644 --- a/nimbus/transaction/host_services.nim +++ b/nimbus/transaction/host_services.nim @@ -11,7 +11,7 @@ import sets, times, stint, chronicles, eth/common/eth_types, ../db/accounts_cache, ../forks, - ".."/[vm_state, vm_computation, vm_internals], + ".."/[vm_state, vm_computation, vm_internals, vm_gas_costs], ./host_types, ./host_trace, ./host_call_nested proc setupTxContext(host: TransactionHost) = @@ -45,7 +45,7 @@ proc setupTxContext(host: TransactionHost) = # [EIP-1985](https://eips.ethereum.org/EIPS/eip-1985) although it's not # officially accepted), and `vmState.gasLimit` is too (`GasInt`). # - # `txContext.block_difficulty` is 256-bit, and this one can genuinely take + # `txContext.block_prev_randao` is 256-bit, and this one can genuinely take # values over much of the 256-bit range. let vmState = host.vmState @@ -73,7 +73,7 @@ proc setupTxContext(host: TransactionHost) = # EIP-4399 # Transfer block randomness to difficulty OPCODE let difficulty = vmState.difficulty.toEvmc - host.txContext.block_difficulty = flip256(difficulty) + host.txContext.block_prev_randao = flip256(difficulty) host.cachedTxContext = true @@ -100,80 +100,66 @@ proc accountExists(host: TransactionHost, address: HostAddress): bool {.show.} = proc getStorage(host: TransactionHost, address: HostAddress, key: HostKey): HostValue {.show.} = host.vmState.readOnlyStateDB.getStorage(address, key) -const - # EIP-1283 - SLOAD_GAS_CONSTANTINOPLE = 200 - # EIP-2200 - SSTORE_SET_GAS = 20000 - SSTORE_RESET_GAS = 5000 - SLOAD_GAS_ISTANBUL = 800 - # EIP-2929 - WARM_STORAGE_READ_COST = 100 - COLD_SLOAD_COST = 2100 - COLD_ACCOUNT_ACCESS_COST = 2600 +proc setStorageStatus(host: TransactionHost, address: HostAddress, + key: HostKey, newVal: HostValue): EvmcStorageStatus {.show.} = + let + db = host.vmState.readOnlyStateDB + currentVal = db.getStorage(address, key) - SSTORE_CLEARS_SCHEDULE_EIP2200 = 15000 - SSTORE_CLEARS_SCHEDULE_EIP3529 = 4800 - -func storageModifiedAgainRefund(originalValue, oldValue, value: HostValue, - fork: Fork): int {.inline.} = - # Calculate `SSTORE` refund according to EIP-2929 (Berlin), - # EIP-2200 (Istanbul) or EIP-1283 (Constantinople only). - result = 0 - if value == originalValue: - result = if value.isZero: SSTORE_SET_GAS - elif fork >= FkBerlin: SSTORE_RESET_GAS - COLD_SLOAD_COST - else: SSTORE_RESET_GAS - let SLOAD_GAS = if fork >= FkBerlin: WARM_STORAGE_READ_COST - elif fork >= FkIstanbul: SLOAD_GAS_ISTANBUL - else: SLOAD_GAS_CONSTANTINOPLE - result -= SLOAD_GAS - - let SSTORE_CLEARS_SCHEDULE = if fork >= FkLondon: - SSTORE_CLEARS_SCHEDULE_EIP3529 - else: - SSTORE_CLEARS_SCHEDULE_EIP2200 - if not originalValue.isZero: - if value.isZero: - result += SSTORE_CLEARS_SCHEDULE - elif oldValue.isZero: - result -= SSTORE_CLEARS_SCHEDULE - -proc setStorage(host: TransactionHost, address: HostAddress, - key: HostKey, value: HostValue): EvmcStorageStatus {.show.} = - let db = host.vmState.readOnlyStateDB - let oldValue = db.getStorage(address, key) - - if oldValue == value: - return EVMC_STORAGE_UNCHANGED + if currentVal == newVal: + return EVMC_STORAGE_ASSIGNED host.vmState.mutateStateDB: - db.setStorage(address, key, value) + db.setStorage(address, key, newVal) - if host.vmState.fork >= FkIstanbul or host.vmState.fork == FkConstantinople: - let originalValue = db.getCommittedStorage(address, key) - if oldValue != originalValue: - # Gas refund for `MODIFIED_AGAIN` (EIP-1283/2200/2929 only). - let refund = storageModifiedAgainRefund(originalValue, oldValue, value, - host.vmState.fork) - # TODO: Refund depends on `Computation` at the moment. - if refund != 0: - host.computation.gasMeter.refundGas(refund) - return EVMC_STORAGE_MODIFIED_AGAIN + # https://eips.ethereum.org/EIPS/eip-1283 + let originalVal = db.getCommittedStorage(address, key) + if originalVal == currentVal: + if originalVal.isZero: + return EVMC_STORAGE_ADDED - if oldValue.isZero: - return EVMC_STORAGE_ADDED - elif value.isZero: - # Gas refund for `DELETED` (all forks). - # TODO: Refund depends on `Computation` at the moment. - let SSTORE_CLEARS_SCHEDULE = if host.vmState.fork >= FkLondon: - SSTORE_CLEARS_SCHEDULE_EIP3529 - else: - SSTORE_CLEARS_SCHEDULE_EIP2200 - host.computation.gasMeter.refundGas(SSTORE_CLEARS_SCHEDULE) - return EVMC_STORAGE_DELETED + # !is_zero(original_val) + if newVal.isZero: + return EVMC_STORAGE_DELETED + else: + return EVMC_STORAGE_MODIFIED + + # originalVal != currentVal + if originalVal.isZero.not: + if currentVal.isZero: + if originalVal == newVal: + return EVMC_STORAGE_DELETED_RESTORED + else: + return EVMC_STORAGE_DELETED_ADDED + + # !is_zero(current_val) + if newVal.isZero: + return EVMC_STORAGE_MODIFIED_DELETED + + # !is_zero(new_val) + if originalVal == newVal: + return EVMC_STORAGE_MODIFIED_RESTORED + else: + return EVMC_STORAGE_ASSIGNED + + # is_zero(original_val) + if originalVal == newVal: + return EVMC_STORAGE_ADDED_DELETED else: - return EVMC_STORAGE_MODIFIED + return EVMC_STORAGE_ASSIGNED + +proc setStorage(host: TransactionHost, address: HostAddress, + key: HostKey, newVal: HostValue): EvmcStorageStatus {.show.} = + let + status = setStorageStatus(host, address, key, newVal) + fork = host.vmState.fork + refund = SstoreCost[fork][status].gasRefund + + if refund != 0: + # TODO: Refund depends on `Computation` at the moment. + host.computation.gasMeter.refundGas(refund) + + status proc getBalance(host: TransactionHost, address: HostAddress): HostBalance {.show.} = host.vmState.readOnlyStateDB.getBalance(address) diff --git a/nimbus/transaction/host_trace.nim b/nimbus/transaction/host_trace.nim index 29dc02efa..880db0045 100644 --- a/nimbus/transaction/host_trace.nim +++ b/nimbus/transaction/host_trace.nim @@ -58,7 +58,8 @@ proc showEvmcMessage(msg: EvmcMessage): string = &" gas={$msg.gas}" & &" value={$msg.value.fromEvmc}" & &" sender={$msg.sender.fromEvmc}" & - &" destination={$msg.destination.fromEvmc}" & + &" recipient={$msg.recipient.fromEvmc}" & + &" code_address={$msg.code_address.fromEvmc}" & &" input_data={inputStr}" if msg.kind == EVMC_CREATE2: result.add &" create2_salt={$msg.create2_salt.fromEvmc}" @@ -88,7 +89,7 @@ proc showEvmcTxContext(txc: EvmcTxContext): string = &" block_number={$txc.block_number}" & &" block_timestamp={$txc.block_timestamp}" & &" block_gas_limit={$txc.block_gas_limit}" & - &" block_difficulty={$txc.block_difficulty.fromEvmc}" & + &" block_prev_randao={$txc.block_prev_randao.fromEvmc}" & &" chain_id={$txc.chain_id.fromEvmc}" & &" block_base_fee={$txc.block_base_fee.fromEvmc}" diff --git a/nimbus/vm2/computation.nim b/nimbus/vm2/computation.nim index 74d01966c..e235ad44a 100644 --- a/nimbus/vm2/computation.nim +++ b/nimbus/vm2/computation.nim @@ -82,7 +82,7 @@ template getBlockNumber*(c: Computation): UInt256 = template getDifficulty*(c: Computation): DifficultyInt = when evmc_enabled: - UInt256.fromEvmc c.host.getTxContext().block_difficulty + UInt256.fromEvmc c.host.getTxContext().block_prev_randao else: c.vmState.difficulty @@ -192,12 +192,6 @@ proc newComputation*(vmState: BaseVMState, message: Message, result.code = newCodeStream( vmState.readOnlyStateDB.getCode(message.codeAddress)) - when evmc_enabled: - result.host.init( - nim_host_get_interface(), - cast[evmc_host_context](result) - ) - proc newComputation*(vmState: BaseVMState, message: Message, code: seq[byte]): Computation = new result result.vmState = vmState @@ -210,12 +204,6 @@ proc newComputation*(vmState: BaseVMState, message: Message, code: seq[byte]): C result.selfDestructs = initHashSet[EthAddress]() result.code = newCodeStream(code) - when evmc_enabled: - result.host.init( - nim_host_get_interface(), - cast[evmc_host_context](result) - ) - template gasCosts*(c: Computation): untyped = c.vmState.gasCosts diff --git a/nimbus/vm2/evmc_api.nim b/nimbus/vm2/evmc_api.nim index 165fd6fae..82a3b3cf6 100644 --- a/nimbus/vm2/evmc_api.nim +++ b/nimbus/vm2/evmc_api.nim @@ -23,30 +23,32 @@ type 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. + block_prev_randao*: evmc_uint256be # The block difficulty. chain_id* : evmc_uint256be # The blockchain's ChainID. block_base_fee* : evmc_uint256be # The block base fee. 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 + kind* : evmc_call_kind + flags* : uint32 + depth* : int32 + gas* : int64 + recipient* : EthAddress + sender* : EthAddress + input_data* : ptr byte + input_size* : uint + value* : evmc_uint256be create2_salt*: evmc_bytes32 + code_address*: EthAddress 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.} + status_code* : evmc_status_code + gas_left* : int64 + gas_refund* : int64 + output_data* : ptr byte + output_size* : uint + release* : proc(result: var nimbus_result) {.cdecl, gcsafe.} create_address*: EthAddress - padding*: array[4, byte] + padding* : array[4, byte] nimbus_host_interface* = object account_exists*: proc(context: evmc_host_context, address: EthAddress): bool {.cdecl, gcsafe.} @@ -151,11 +153,3 @@ proc accessStorage*(ctx: HostContext, address: EthAddress, key: UInt256): evmc_access_status {.inline.} = var key = toEvmc(key) ctx.host.access_storage(ctx.context, address, key) - -#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_host.nim b/nimbus/vm2/evmc_host.nim deleted file mode 100644 index 759a777e5..000000000 --- a/nimbus/vm2/evmc_host.nim +++ /dev/null @@ -1,288 +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.gasLimit) - - # EIP-4399 - # Transfer block randomness to difficulty OPCODE - let difficulty = toEvmc(vmstate.difficulty) - result.block_difficulty = difficulty - - result.chain_id = toEvmc(vmstate.chaindb.config.chainId.uint.u256) - result.block_base_fee = toEvmc(vmstate.baseFee) - -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.stateDB.getStorage(address, UInt256.fromEvmc(key)).toEvmc() - -proc sstoreNetGasMetering(ctx: Computation): bool {.inline.} = - ctx.fork in {FkConstantinople, FkIstanbul, FkBerlin, FkLondon} - -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) - -proc hostAccessAccountImpl(ctx: Computation, address: EthAddress): evmc_access_status {.cdecl.} = - ctx.vmState.mutateStateDB: - if not db.inAccessList(address): - db.accessList(address) - return EVMC_ACCESS_COLD - else: - return EVMC_ACCESS_WARM - -proc hostAccessStorageImpl(ctx: Computation, address: EthAddress, - key: var evmc_bytes32): evmc_access_status {.cdecl.} = - let slot = UInt256.fromEvmc(key) - ctx.vmState.mutateStateDB: - if not db.inAccessList(address, slot): - db.accessList(address, slot) - return EVMC_ACCESS_COLD - else: - return EVMC_ACCESS_WARM - -proc enterCreateImpl(c: Computation, m: nimbus_message): Computation = - # 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)) - ) - return newComputation(c.vmState, childMsg, - ContractSalt.fromEvmc(m.create2_salt)) - -template leaveCreateImpl(c, child: Computation, res: nimbus_result) = - 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 enterCallImpl(c: Computation, m: nimbus_message): Computation = - 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) - ) - newComputation(c.vmState, childMsg) - -template leaveCallImpl(c, child: Computation, res: nimbus_result) = - 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 enterHostCall(c: Computation, msg: var nimbus_message): Computation {.noinline.} = - if msg.kind == EVMC_CREATE or msg.kind == EVMC_CREATE2: - enterCreateImpl(c, msg) - else: - enterCallImpl(c, msg) - -proc leaveHostCall(c, child: Computation, kind: evmc_call_kind): nimbus_result {.noinline.} = - if kind == EVMC_CREATE or kind == EVMC_CREATE2: - leaveCreateImpl(c, child, result) - else: - leaveCallImpl(c, child, result) - -proc hostCallImpl(ctx: Computation, msg: var nimbus_message): nimbus_result {.cdecl.} = - let child = enterHostCall(ctx, msg) - child.execCallOrCreate() - leaveHostCall(ctx, child, msg.kind) - -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) - result.access_account = cast[evmc_access_account_fn](hostAccessAccountImpl) - result.access_storage = cast[evmc_access_storage_fn](hostAccessStorageImpl) - -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 bf0bd155f..7d621749d 100644 --- a/nimbus/vm2/interpreter/gas_costs.nim +++ b/nimbus/vm2/interpreter/gas_costs.nim @@ -125,6 +125,87 @@ const ACCESS_LIST_STORAGE_KEY_COST* = 1900.GasInt ACCESS_LIST_ADDRESS_COST* = 2400.GasInt + +when defined(evmc_enabled): + type + # The gas cost specification for storage instructions. + StorageCostSpec = object + netCost : bool # Is this net gas cost metering schedule? + warmAccess: int16 # Storage warm access cost, YP: G_{warmaccess} + sset : int16 # Storage addition cost, YP: G_{sset} + reset : int16 # Storage modification cost, YP: G_{sreset} + clear : int16 # Storage deletion refund, YP: R_{sclear} + + StorageStoreCost* = object + gasCost* : int16 + gasRefund*: int16 + + # Table of gas cost specification for storage instructions per EVM revision. + func storageCostSpec(): array[Fork, StorageCostSpec] {.compileTime.} = + # Legacy cost schedule. + const revs = [ + FkFrontier, FkHomestead, FkTangerine, + FkSpurious, FkByzantium, FkPetersburg] + + for rev in revs: + result[rev] = StorageCostSpec( + netCost: false, warmAccess: 200, sset: 20000, reset: 5000, clear: 15000) + + # Net cost schedule. + result[FkConstantinople] = StorageCostSpec( + netCost: true, warmAccess: 200, sset: 20000, reset: 5000, clear: 15000) + result[FkIstanbul] = StorageCostSpec( + netCost: true, warmAccess: 800, sset: 20000, reset: 5000, clear: 15000) + result[FkBerlin] = StorageCostSpec( + netCost: true, warmAccess: WarmStorageReadCost, sset: 20000, + reset: 5000 - ColdSloadCost, clear: 15000) + result[FkLondon] = StorageCostSpec( + netCost: true, warmAccess: WarmStorageReadCost, sset: 20000, + reset: 5000 - ColdSloadCost, clear: 4800) + + result[FkParis] = result[FkLondon] + result[FkShanghai] = result[FkLondon] + result[FkCancun] = result[FkLondon] + + proc legacySStoreCost(e: var array[evmc_storage_status, StorageStoreCost], + c: StorageCostSpec) {.compileTime.} = + e[EVMC_STORAGE_ADDED] = StorageStoreCost(gasCost: c.sset , gasRefund: 0) + e[EVMC_STORAGE_DELETED] = StorageStoreCost(gasCost: c.reset, gasRefund: c.clear) + e[EVMC_STORAGE_MODIFIED] = StorageStoreCost(gasCost: c.reset, gasRefund: 0) + e[EVMC_STORAGE_ASSIGNED] = e[EVMC_STORAGE_MODIFIED] + e[EVMC_STORAGE_DELETED_ADDED] = e[EVMC_STORAGE_ADDED] + e[EVMC_STORAGE_MODIFIED_DELETED] = e[EVMC_STORAGE_DELETED] + e[EVMC_STORAGE_DELETED_RESTORED] = e[EVMC_STORAGE_ADDED] + e[EVMC_STORAGE_ADDED_DELETED] = e[EVMC_STORAGE_DELETED] + e[EVMC_STORAGE_MODIFIED_RESTORED] = e[EVMC_STORAGE_MODIFIED] + + proc netSStoreCost(e: var array[evmc_storage_status, StorageStoreCost], + c: StorageCostSpec) {.compileTime.} = + e[EVMC_STORAGE_ASSIGNED] = StorageStoreCost(gasCost: c.warmAccess, gasRefund: 0) + e[EVMC_STORAGE_ADDED] = StorageStoreCost(gasCost: c.sset , gasRefund: 0) + e[EVMC_STORAGE_DELETED] = StorageStoreCost(gasCost: c.reset , gasRefund: c.clear) + e[EVMC_STORAGE_MODIFIED] = StorageStoreCost(gasCost: c.reset , gasRefund: 0) + e[EVMC_STORAGE_DELETED_ADDED] = StorageStoreCost(gasCost: c.warmAccess, gasRefund: -c.clear) + e[EVMC_STORAGE_MODIFIED_DELETED] = StorageStoreCost(gasCost: c.warmAccess, gasRefund: c.clear) + e[EVMC_STORAGE_DELETED_RESTORED] = StorageStoreCost(gasCost: c.warmAccess, + gasRefund: c.reset - c.warmAccess - c.clear) + e[EVMC_STORAGE_ADDED_DELETED] = StorageStoreCost(gasCost: c.warmAccess, + gasRefund: c.sset - c.warmAccess) + e[EVMC_STORAGE_MODIFIED_RESTORED] = StorageStoreCost(gasCost: c.warmAccess, + gasRefund: c.reset - c.warm_access) + + proc storageStoreCost(): array[Fork, array[evmc_storage_status, StorageStoreCost]] {.compileTime.} = + const tbl = storageCostSpec() + for rev in Fork: + let c = tbl[rev] + if not c.netCost: # legacy + legacySStoreCost(result[rev], c) + else: # net cost + netSStoreCost(result[rev], c) + + const + SstoreCost* = storageStoreCost() + template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = ## Generate the gas cost for each forks and store them in a const @@ -224,52 +305,31 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = func `prefix gasSstore`(value: UInt256, gasParams: GasParams): GasResult {.nimcall.} = ## Value is word to save - - when fork >= FkBerlin: - # EIP2929 - const - SLOAD_GAS = WarmStorageReadCost - SSTORE_RESET_GAS = 5000 - ColdSloadCost - else: - const - SLOAD_GAS = FeeSchedule[GasSload] - SSTORE_RESET_GAS = FeeSchedule[GasSreset] - - const - NoopGas = SLOAD_GAS # if the value doesn't change. - DirtyGas = SLOAD_GAS # if a dirty value is changed. - InitGas = FeeSchedule[GasSset] # from clean zero to non-zero - InitRefund = FeeSchedule[GasSset] - SLOAD_GAS # resetting to the original zero value - CleanGas = SSTORE_RESET_GAS # from clean non-zero to something else - 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 + const c = SStoreCost[fork] + let sc = c[gasParams.s_status] + result.gasCost = sc.gasCost + result.gasRefund = sc.gasRefund else: + when fork >= FkBerlin: + # EIP2929 + const + SLOAD_GAS = WarmStorageReadCost + SSTORE_RESET_GAS = 5000 - ColdSloadCost + else: + const + SLOAD_GAS = FeeSchedule[GasSload] + SSTORE_RESET_GAS = FeeSchedule[GasSreset] + + const + NoopGas = SLOAD_GAS # if the value doesn't change. + DirtyGas = SLOAD_GAS # if a dirty value is changed. + InitGas = FeeSchedule[GasSset] # from clean zero to non-zero + InitRefund = FeeSchedule[GasSset] - SLOAD_GAS # resetting to the original zero value + CleanGas = SSTORE_RESET_GAS # from clean non-zero to something else + CleanRefund = SSTORE_RESET_GAS - SLOAD_GAS # resetting to the original non-zero value + ClearRefund = FeeSchedule[RefundsClear]# clearing an originally existing storage slot + when fork < FkConstantinople or fork == FkPetersburg: let isStorageEmpty = gasParams.s_currentValue.isZero @@ -760,7 +820,10 @@ const FkPetersburg: SpuriousGasFees, FkIstanbul: IstanbulGasFees, FkBerlin: BerlinGasFees, - FkLondon: LondonGasFees + FkLondon: LondonGasFees, + FkParis: LondonGasFees, + FkShanghai: LondonGasFees, + FkCancun: LondonGasFees, ] gasCosts(FkFrontier, base, BaseGasCosts) diff --git a/nimbus/vm2/interpreter/op_handlers/oph_call.nim b/nimbus/vm2/interpreter/op_handlers/oph_call.nim index 94a4c1fdd..c0a02ab4c 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_call.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_call.nim @@ -40,7 +40,7 @@ type LocalParams = tuple gas: UInt256 value: UInt256 - destination: EthAddress + codeAddress: EthAddress sender: EthAddress memInPos: int memInLen: int @@ -72,14 +72,14 @@ proc updateStackAndParams(q: var LocalParams; c: Computation) = # and further `childGasLimit` if FkBerlin <= c.fork: when evmc_enabled: - if c.host.accessAccount(q.destination) == EVMC_ACCESS_COLD: + if c.host.accessAccount(q.codeAddress) == EVMC_ACCESS_COLD: c.gasMeter.consumeGas( ColdAccountAccessCost - WarmStorageReadCost, reason = "EIP2929 gasCall") else: c.vmState.mutateStateDB: - if not db.inAccessList(q.destination): - db.accessList(q.destination) + if not db.inAccessList(q.codeAddress): + db.accessList(q.codeAddress) # The WarmStorageReadCostEIP2929 (100) is already deducted in # the form of a constant `gasCall` @@ -91,7 +91,7 @@ proc updateStackAndParams(q: var LocalParams; c: Computation) = proc callParams(c: Computation): LocalParams = ## Helper for callOp() result.gas = c.stack.popInt() - result.destination = c.stack.popAddress() + result.codeAddress = c.stack.popAddress() result.value = c.stack.popInt() result.memInPos = c.stack.popInt().cleanMemRef result.memInLen = c.stack.popInt().cleanMemRef @@ -100,7 +100,7 @@ proc callParams(c: Computation): LocalParams = result.sender = c.msg.contractAddress result.flags = c.msg.flags - result.contractAddress = result.destination + result.contractAddress = result.codeAddress result.updateStackAndParams(c) @@ -114,7 +114,7 @@ proc callCodeParams(c: Computation): LocalParams = proc delegateCallParams(c: Computation): LocalParams = ## Helper for delegateCall() result.gas = c.stack.popInt() - result.destination = c.stack.popAddress() + result.codeAddress = c.stack.popAddress() result.memInPos = c.stack.popInt().cleanMemRef result.memInLen = c.stack.popInt().cleanMemRef result.memOutPos = c.stack.popInt().cleanMemRef @@ -131,7 +131,7 @@ proc delegateCallParams(c: Computation): LocalParams = proc staticCallParams(c: Computation): LocalParams = ## Helper for staticCall() result.gas = c.stack.popInt() - result.destination = c.stack.popAddress() + result.codeAddress = c.stack.popAddress() result.memInPos = c.stack.popInt().cleanMemRef result.memInLen = c.stack.popInt().cleanMemRef result.memOutPos = c.stack.popInt().cleanMemRef @@ -140,7 +140,7 @@ proc staticCallParams(c: Computation): LocalParams = result.value = 0.u256 result.sender = c.msg.contractAddress result.flags = emvcStatic - result.contractAddress = result.destination + result.contractAddress = result.codeAddress result.updateStackAndParams(c) @@ -246,15 +246,16 @@ const msg = new(nimbus_message) c = k.cpt msg[] = nimbus_message( - kind : evmcCall.evmc_call_kind, - depth : (k.cpt.msg.depth + 1).int32, - gas : childGasLimit, - sender : p.sender, - destination: p.destination, - input_data : k.cpt.memory.readPtr(p.memInPos), - input_size : p.memInLen.uint, - value : toEvmc(p.value), - flags : p.flags.uint32 + kind : evmcCall.evmc_call_kind, + depth : (k.cpt.msg.depth + 1).int32, + gas : childGasLimit, + sender : p.sender, + recipient : p.contractAddress, + code_address: p.codeAddress, + input_data : k.cpt.memory.readPtr(p.memInPos), + input_size : p.memInLen.uint, + value : toEvmc(p.value), + flags : p.flags.uint32 ) c.execSubCall(msg, p) else: @@ -267,7 +268,7 @@ const gas: childGasLimit, sender: p.sender, contractAddress: p.contractAddress, - codeAddress: p.destination, + codeAddress: p.codeAddress, value: p.value, data: k.cpt.memory.read(p.memInPos, p.memInLen), flags: p.flags)) @@ -329,15 +330,16 @@ const msg = new(nimbus_message) c = k.cpt msg[] = nimbus_message( - kind : evmcCallCode.evmc_call_kind, - depth : (k.cpt.msg.depth + 1).int32, - gas : childGasLimit, - sender : p.sender, - destination: p.destination, - input_data : k.cpt.memory.readPtr(p.memInPos), - input_size : p.memInLen.uint, - value : toEvmc(p.value), - flags : p.flags.uint32 + kind : evmcCallCode.evmc_call_kind, + depth : (k.cpt.msg.depth + 1).int32, + gas : childGasLimit, + sender : p.sender, + recipient : p.contractAddress, + code_address: p.codeAddress, + input_data : k.cpt.memory.readPtr(p.memInPos), + input_size : p.memInLen.uint, + value : toEvmc(p.value), + flags : p.flags.uint32 ) c.execSubCall(msg, p) else: @@ -350,7 +352,7 @@ const gas: childGasLimit, sender: p.sender, contractAddress: p.contractAddress, - codeAddress: p.destination, + codeAddress: p.codeAddress, value: p.value, data: k.cpt.memory.read(p.memInPos, p.memInLen), flags: p.flags)) @@ -401,15 +403,16 @@ const msg = new(nimbus_message) c = k.cpt msg[] = nimbus_message( - kind : evmcDelegateCall.evmc_call_kind, - depth : (k.cpt.msg.depth + 1).int32, - gas : childGasLimit, - sender : p.sender, - destination: p.destination, - input_data : k.cpt.memory.readPtr(p.memInPos), - input_size : p.memInLen.uint, - value : toEvmc(p.value), - flags : p.flags.uint32 + kind : evmcDelegateCall.evmc_call_kind, + depth : (k.cpt.msg.depth + 1).int32, + gas : childGasLimit, + sender : p.sender, + recipient : p.contractAddress, + code_address: p.codeAddress, + input_data : k.cpt.memory.readPtr(p.memInPos), + input_size : p.memInLen.uint, + value : toEvmc(p.value), + flags : p.flags.uint32 ) c.execSubCall(msg, p) else: @@ -422,7 +425,7 @@ const gas: childGasLimit, sender: p.sender, contractAddress: p.contractAddress, - codeAddress: p.destination, + codeAddress: p.codeAddress, value: p.value, data: k.cpt.memory.read(p.memInPos, p.memInLen), flags: p.flags)) @@ -451,7 +454,7 @@ const # from 700 to 40 # # when opCode == StaticCall: - # if k.cpt.fork >= FkBerlin and destination.toInt <= MaxPrecompilesAddr: + # if k.cpt.fork >= FkBerlin and codeAddress.toInt <= MaxPrecompilesAddr: # gasCost = gasCost - 660.GasInt if gasCost >= 0: k.cpt.gasMeter.consumeGas(gasCost, reason = $StaticCall) @@ -478,15 +481,16 @@ const msg = new(nimbus_message) c = k.cpt msg[] = nimbus_message( - kind : evmcCall.evmc_call_kind, - depth : (k.cpt.msg.depth + 1).int32, - gas : childGasLimit, - sender : p.sender, - destination: p.destination, - input_data : k.cpt.memory.readPtr(p.memInPos), - input_size : p.memInLen.uint, - value : toEvmc(p.value), - flags : p.flags.uint32 + kind : evmcCall.evmc_call_kind, + depth : (k.cpt.msg.depth + 1).int32, + gas : childGasLimit, + sender : p.sender, + recipient : p.contractAddress, + code_address: p.codeAddress, + input_data : k.cpt.memory.readPtr(p.memInPos), + input_size : p.memInLen.uint, + value : toEvmc(p.value), + flags : p.flags.uint32 ) c.execSubCall(msg, p) else: @@ -499,7 +503,7 @@ const gas: childGasLimit, sender: p.sender, contractAddress: p.contractAddress, - codeAddress: p.destination, + codeAddress: p.codeAddress, value: p.value, data: k.cpt.memory.read(p.memInPos, p.memInLen), flags: p.flags)) diff --git a/nimbus/vm2/interpreter_dispatch.nim b/nimbus/vm2/interpreter_dispatch.nim index 9a96b5957..70bb7dff6 100644 --- a/nimbus/vm2/interpreter_dispatch.nim +++ b/nimbus/vm2/interpreter_dispatch.nim @@ -256,6 +256,3 @@ else: # ------------------------------------------------------------------------------ # End # ------------------------------------------------------------------------------ - -when defined(evmc_enabled): - include evmc_host diff --git a/nimbus/vm_gas_costs.nim b/nimbus/vm_gas_costs.nim index 83d34632a..c060dbc9b 100644 --- a/nimbus/vm_gas_costs.nim +++ b/nimbus/vm_gas_costs.nim @@ -48,4 +48,8 @@ export vmg.ACCESS_LIST_STORAGE_KEY_COST, vmg.ACCESS_LIST_ADDRESS_COST +when defined(evmc_enabled): + export + vmg.SstoreCost + # End