Transaction: Map `evmc_result` back to `Computation` result

This missing part of EVMC processing allows third-party EVMs to work.

It fixes EVMC result processing (at the top-level of calls, not nested calls)
to use the EVMC result object, instead of reading so much internal state of the
Nimbus `Computation` object.

It has been tested by calling [`evmone`](https://github.com/ethereum/evmone)
and getting useful results with tracing enabled (`showTxCalls = true`).  It's
even able to run parts of the fixtures test suite.

There are other issues with account balances, etc that need to be worked on to
get the correct _final_ results, but the EVM execution is correct with this.

Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
Jamie Lokier 2021-12-10 13:57:03 +00:00
parent 6ef9bfd21b
commit 072934272b
No known key found for this signature in database
GPG Key ID: CBC25C68435C30A2
1 changed files with 23 additions and 1 deletions

View File

@ -174,6 +174,28 @@ proc setupHost(call: CallParams): TransactionHost =
return host
when defined(evmc_enabled):
import ./host_services
proc doExecEvmc(host: TransactionHost, call: CallParams) =
var callResult = evmcExecComputation(host)
let c = host.computation
if callResult.status_code == EVMC_SUCCESS:
c.error = nil
elif callResult.status_code == EVMC_REVERT:
c.setError("EVMC_REVERT", false)
else:
c.setError($callResult.status_code, true)
c.gasMeter.gasRemaining = callResult.gas_left
c.msg.contractAddress = callResult.create_address.fromEvmc
c.output = if callResult.output_size <= 0: @[]
else: @(makeOpenArray(callResult.output_data,
callResult.output_size.int))
if not callResult.release.isNil:
{.gcsafe.}:
callResult.release(callResult)
proc runComputation*(call: CallParams): CallResult =
let host = setupHost(call)
let c = host.computation
@ -188,7 +210,7 @@ proc runComputation*(call: CallParams): CallResult =
db.subBalance(call.sender, call.gasLimit.u256 * call.gasPrice.u256)
when defined(evmc_enabled):
discard evmcExecComputation(host)
doExecEvmc(host, call)
else:
execComputation(host.computation)