diff --git a/nimbus/vm/computation.nim b/nimbus/vm/computation.nim index 73eee2ae2..a972104bb 100644 --- a/nimbus/vm/computation.nim +++ b/nimbus/vm/computation.nim @@ -17,6 +17,64 @@ import logScope: topics = "vm computation" +const + evmc_enabled* {.booldefine.} = true + +template getCoinbase*(c: Computation): EthAddress = + when evmc_enabled: + fromEvmc c.host.getTxContext().block_coinbase + else: + c.vmState.coinbase + +template getTimestamp*(c: Computation): int64 = + when evmc_enabled: + c.host.getTxContext().block_timestamp + else: + c.vmState.timestamp.toUnix + +template getBlockNumber*(c: Computation): Uint256 = + when evmc_enabled: + c.host.getTxContext().block_number.u256 + else: + c.vmState.blockNumber.blockNumberToVmWord + +template getDifficulty*(c: Computation): DifficultyInt = + when evmc_enabled: + Uint256.fromEvmc c.host.getTxContext().block_difficulty + else: + c.vmState.difficulty + +template getGasLimit*(c: Computation): GasInt = + when evmc_enabled: + c.host.getTxContext().block_gas_limit.GasInt + else: + c.vmState.gasLimit + +template getChainId*(c: Computation): uint = + when evmc_enabled: + Uint256.fromEvmc(c.host.getTxContext().chain_id).truncate(uint) + else: + c.vmState.chaindb.config.chainId + +template getOrigin*(c: Computation): EthAddress = + when evmc_enabled: + fromEvmc c.host.getTxContext().tx_origin + else: + c.vmState.txOrigin + +template getGasPrice*(c: Computation): GasInt = + when evmc_enabled: + Uint256.fromEvmc(c.host.getTxContext().tx_gas_price).truncate(GasInt) + else: + c.vmState.txGasPrice + +template getBlockHash*(c: Computation, blockNumber: Uint256): Hash256 = + #when evmc_enabled: + # c.host.getBlockHash(blockNumber.truncate(int64)) + #else: + #randomStatetest7.json + c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber) + proc newComputation*(vmState: BaseVMState, message: Message): Computation = new result result.vmState = vmState @@ -27,6 +85,13 @@ proc newComputation*(vmState: BaseVMState, message: Message): Computation = result.touchedAccounts = initHashSet[EthAddress]() result.suicides = initHashSet[EthAddress]() result.code = newCodeStream(message.code) + + when evmc_enabled: + result.host.init( + nim_host_get_interface(), + cast[evmc_host_context](result) + ) + # a dummy/terminus continuation proc result.nextProc = proc() = discard diff --git a/nimbus/vm/evmc_api.nim b/nimbus/vm/evmc_api.nim index 6adabf59b..f11fda4c6 100644 --- a/nimbus/vm/evmc_api.nim +++ b/nimbus/vm/evmc_api.nim @@ -7,14 +7,14 @@ import evmc/evmc, evmc_helpers, eth/common -proc nim_host_get_interface(): ptr evmc_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.} +proc nim_host_get_interface*(): ptr evmc_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 evmc_host_interface + host*: ptr evmc_host_interface context*: evmc_host_context proc init*(x: var HostContext, host: ptr evmc_host_interface, context: evmc_host_context) = @@ -25,10 +25,12 @@ proc init*(x: typedesc[HostContext], host: ptr evmc_host_interface, context: evm result.init(host, context) proc getTxContext*(ctx: HostContext): evmc_tx_context = - ctx.host.get_tx_context(ctx.context) + {.gcsafe.}: + ctx.host.get_tx_context(ctx.context) proc getBlockHash*(ctx: HostContext, number: int64): Hash256 = - Hash256.fromEvmc ctx.host.get_block_hash(ctx.context, number) + {.gcsafe.}: + Hash256.fromEvmc ctx.host.get_block_hash(ctx.context, number) proc accountExists*(ctx: HostContext, address: EthAddress): bool = var address = toEvmc(address) diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index ed19dc8c4..d5c753323 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -12,7 +12,7 @@ import ./gas_meter, ./gas_costs, ./opcode_values, ./vm_forks, ../memory, ../message, ../stack, ../code_stream, ../computation, ../../vm_state, ../../errors, ../../constants, ../../vm_types, - ../../db/[db_chain, state_db], ../../utils + ../../db/[db_chain, state_db], ../../utils, ../evmc_api, ../evmc_helpers logScope: topics = "opcode impl" @@ -240,7 +240,7 @@ op balance, inline = true: op origin, inline = true: ## 0x32, Get execution origination address. - push: c.vmState.txOrigin + push: c.getOrigin() op caller, inline = true: ## 0x33, Get caller address. @@ -301,7 +301,7 @@ op codeCopy, inline = false, memStartPos, copyStartPos, size: op gasprice, inline = true: ## 0x3A, Get price of gas in current environment. - push: c.vmState.txGasPrice + push: c.getGasPrice() op extCodeSize, inline = true: ## 0x3b, Get size of an account's code @@ -350,32 +350,31 @@ op returnDataCopy, inline = false, memStartPos, copyStartPos, size: op blockhash, inline = true, blockNumber: ## 0x40, Get the hash of one of the 256 most recent complete blocks. - push: c.vmState.getAncestorHash(blockNumber.vmWordToBlockNumber) + push: c.getBlockHash(blockNumber) op coinbase, inline = true: ## 0x41, Get the block's beneficiary address. - push: c.vmState.coinbase + push: c.getCoinbase() op timestamp, inline = true: ## 0x42, Get the block's timestamp. - push: c.vmState.timestamp.toUnix + push: c.getTimestamp() op blocknumber, inline = true: ## 0x43, Get the block's number. - push: c.vmState.blockNumber.blockNumberToVmWord + push: c.getBlockNumber() op difficulty, inline = true: ## 0x44, Get the block's difficulty - push: c.vmState.difficulty + push: c.getDifficulty() op gasLimit, inline = true: ## 0x45, Get the block's gas limit - push: c.vmState.gasLimit + push: c.getGasLimit() op chainId, inline = true: ## 0x46, Get current chain’s EIP-155 unique identifier. - # TODO: this is a stub - push: c.vmState.chaindb.config.chainId + push: c.getChainId() op selfBalance, inline = true: ## 0x47, Get current contract's balance. diff --git a/nimbus/vm_types.nim b/nimbus/vm_types.nim index dbb6c6066..d9a82e1b7 100644 --- a/nimbus/vm_types.nim +++ b/nimbus/vm_types.nim @@ -8,7 +8,7 @@ import tables, eth/common, eth/trie/db, options, json, sets, - ./vm/[memory, stack, code_stream], + ./vm/[memory, stack, code_stream, evmc_api], ./vm/interpreter/[gas_costs, opcode_values, vm_forks], # TODO - will be hidden at a lower layer ./db/[db_chain, state_db] @@ -59,6 +59,7 @@ type Computation* = ref object # The execution computation vmState*: BaseVMState + host*: HostContext msg*: Message memory*: Memory stack*: Stack