From 0e2bc8408dc8e203de50ffcfc69b29ffb147f28f Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Tue, 18 May 2021 23:53:14 +0100 Subject: [PATCH] Transaction: Run all computations via EVMC `execute` 1. Send all EVM executions through the EVMC `execute` function. It leads to the same place in the end as calling `Computation` before, but `execute` is the API function used by all EVMC implementations, and it is very explicit what data is passed back and forth. 2. As a consequence this starts using the new `host_services` code from EVM, so this is a significant change to the paths used for account state processing. 3. Because we will have to remove the `newComputation` call on the host side, anticipating that the contract code is now saved in `host` instead of being copied around. As it's saved in `host`, there is no need to pass it separately to `evmcExecComputation`. Signed-off-by: Jamie Lokier --- nimbus/transaction/call_common.nim | 33 ++++++++++++++++++++------- nimbus/transaction/evmc_host_glue.nim | 6 ++--- nimbus/transaction/host_types.nim | 1 + 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/nimbus/transaction/call_common.nim b/nimbus/transaction/call_common.nim index d42c23a28..d804484f8 100644 --- a/nimbus/transaction/call_common.nim +++ b/nimbus/transaction/call_common.nim @@ -45,7 +45,7 @@ type memory*: Memory # EVM memory on return (for test only). error*: Error # Error if `isError` (for test only). -proc hostToComputationMessage(msg: EvmcMessage): Message = +proc hostToComputationMessage*(msg: EvmcMessage): Message = Message( kind: CallKind(msg.kind), depth: msg.depth, @@ -162,6 +162,7 @@ proc setupHost(call: CallParams): TransactionHost = let cMsg = hostToComputationMessage(host.msg) host.computation = newComputation(vmState, cMsg, code) + shallowCopy(host.code, code) else: if call.input.len > 0: @@ -176,6 +177,26 @@ proc setupHost(call: CallParams): TransactionHost = return host +proc doExec(host: TransactionHost, call: CallParams) = + let c = host.computation + if call.noTransfer: + # TODO: This isn't doing `noTransfer` properly yet, just enough for + # fixtures tests. + executeOpcodes(c) + doAssert c.continuation.isNil + doAssert c.child.isNil + else: + execComputation(c) + +when defined(evmc_enabled): + import ./host_services + proc doExecEvmc(host: TransactionHost, call: CallParams) = + if call.noTransfer: + let c = host.computation + c.setError("Unable to perform noTransfer computations in EVMC mode", true) + else: + let callResult = evmcExecComputation(host) + proc runComputation*(call: CallParams): CallResult = let host = setupHost(call) let c = host.computation @@ -189,14 +210,10 @@ proc runComputation*(call: CallParams): CallResult = host.vmState.mutateStateDB: db.subBalance(call.sender, call.gasLimit.u256 * call.gasPrice.u256) - if call.noTransfer: - # TODO: This isn't doing `noTransfer` properly yet, just enough for - # fixtures tests. - executeOpcodes(c) - doAssert c.continuation.isNil - doAssert c.child.isNil + when defined(evmc_enabled): + doExecEvmc(host, call) else: - execComputation(c) + doExec(host, call) # Calculated gas used, taking into account refund rules. var gasRemaining: GasInt = 0 diff --git a/nimbus/transaction/evmc_host_glue.nim b/nimbus/transaction/evmc_host_glue.nim index 4cc632ad5..e57da94cd 100644 --- a/nimbus/transaction/evmc_host_glue.nim +++ b/nimbus/transaction/evmc_host_glue.nim @@ -90,7 +90,7 @@ proc evmc_create_nimbus_evm(): ptr evmc_vm {.cdecl, importc.} # a separate library yet. import ./evmc_vm_glue -proc evmcExecComputation*(host: TransactionHost, code: seq[byte]): EvmcResult = +proc evmcExecComputation*(host: TransactionHost): EvmcResult = let vm = evmc_create_nimbus_evm() if vm.isNil: echo "Warning: No EVM" @@ -119,5 +119,5 @@ proc evmcExecComputation*(host: TransactionHost, code: seq[byte]): EvmcResult = {.gcsafe.}: vm.execute(vm, hostInterface[].addr, hostContext, evmc_revision(host.vmState.fork), host.msg, - if code.len > 0: code[0].unsafeAddr else: nil, - code.len.csize_t) + if host.code.len > 0: host.code[0].unsafeAddr else: nil, + host.code.len.csize_t) diff --git a/nimbus/transaction/host_types.nim b/nimbus/transaction/host_types.nim index 15c5df8f2..73eca3dd9 100644 --- a/nimbus/transaction/host_types.nim +++ b/nimbus/transaction/host_types.nim @@ -55,6 +55,7 @@ type computation*: Computation msg*: EvmcMessage input*: seq[byte] + code*: seq[byte] cachedTxContext*: bool txContext*: EvmcTxContext logEntries*: seq[Log]