EVMC: Use the same host interface for nested calls as top-level

Prior to this patch, top-level EVM executions and nested EVM executions did
their `getStorage` and other requests using a completely different set of host
functions.  It was just unfinished, to get top-level "new" EVMC working.

This finishes the job - it stops using the old methods.  Effect:

- Functionality added at the EVMC host level will be used by all EVM calls.
  (The target here is Beam Sync).

- The old set of functions are no longer used, so they can be removed.

- When EVMC host call tracing is enabled (`showTxCalls = true`), it traces
  the calls from nested EVM executions as well as top-level.

Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
Jamie Lokier 2021-08-17 17:18:07 +01:00
parent b783756ff3
commit 8fcd8354b1
No known key found for this signature in database
GPG Key ID: CBC25C68435C30A2
3 changed files with 16 additions and 4 deletions

View File

@ -108,6 +108,7 @@ proc evmcExecComputation*(host: TransactionHost): EvmcResult {.inline.} =
return return
let hostContext = cast[evmc_host_context](host) let hostContext = cast[evmc_host_context](host)
host.hostInterface = hostInterface.unsafeAddr
# Without `{.gcsafe.}:` here, the call via `vm.execute` results in a Nim # Without `{.gcsafe.}:` here, the call via `vm.execute` results in a Nim
# compile-time error in a far away function. Starting here, a cascade of # compile-time error in a far away function. Starting here, a cascade of

View File

@ -112,16 +112,25 @@ proc beforeExecEvmcNested(host: TransactionHost, msg: EvmcMessage): Computation
# contribute to the stack frame of `callEvmcNested` below. # contribute to the stack frame of `callEvmcNested` below.
{.noinline.} = {.noinline.} =
host.showCallEntry(msg) host.showCallEntry(msg)
if msg.kind == EVMC_CREATE or msg.kind == EVMC_CREATE2: let c = if msg.kind == EVMC_CREATE or msg.kind == EVMC_CREATE2:
return beforeExecCreateEvmcNested(host, msg) beforeExecCreateEvmcNested(host, msg)
else: else:
return beforeExecCallEvmcNested(host, msg) beforeExecCallEvmcNested(host, msg)
when defined(evmc_enabled):
c.host.init(cast[ptr nimbus_host_interface](host.hostInterface),
cast[typeof(c.host.context)](host))
host.saveComputation.add(host.computation)
host.computation = c
return c
proc afterExecEvmcNested(host: TransactionHost, child: Computation, proc afterExecEvmcNested(host: TransactionHost, child: Computation,
kind: EvmcCallKind): EvmcResult kind: EvmcCallKind): EvmcResult
# This function must be declared with `{.noinline.}` to make sure it doesn't # This function must be declared with `{.noinline.}` to make sure it doesn't
# contribute to the stack frame of `callEvmcNested` below. # contribute to the stack frame of `callEvmcNested` below.
{.noinline.} = {.noinline.} =
host.computation = host.saveComputation[^1]
host.saveComputation[^1] = nil
host.saveComputation.setLen(host.saveComputation.len - 1)
if kind == EVMC_CREATE or kind == EVMC_CREATE2: if kind == EVMC_CREATE or kind == EVMC_CREATE2:
afterExecCreateEvmcNested(host, child, result) afterExecCreateEvmcNested(host, child, result)
else: else:

View File

@ -63,6 +63,8 @@ type
touchedAccounts*: HashSet[EthAddress] touchedAccounts*: HashSet[EthAddress]
selfDestructs*: HashSet[EthAddress] selfDestructs*: HashSet[EthAddress]
depth*: int depth*: int
saveComputation*: seq[Computation]
hostInterface*: ptr evmc_host_interface
# These versions of `toEvmc` and `fromEvmc` don't flip big/little-endian like # These versions of `toEvmc` and `fromEvmc` don't flip big/little-endian like
# the older functions in `evmc_helpers`. New code only flips with _explicit_ # the older functions in `evmc_helpers`. New code only flips with _explicit_