EVMC: Add missing EIP-2929 (Berlin) functions to EVMC host

The update for London (EIP-1559) in 1cdb30df ("bump nim-emvc with evmc revision
8.0.0 to 9.0.0") really bumped EVMC ABI version from 7.5 up to 9.

In other words, it skipped Berlin, going direct from Istanbul to London.

That was accompanied by EVMC changes in 05e9b891 ("EIP-3198: add baseFee op
code in nim-evm"), which added the API changes needed for London.

But the missing Berlin functions weren't added in the move to London.

As a result, our EVMC host became incompatible with Berlin, London, and really
all revisions of the ABI, and if a third party EVM was loaded, it crashed.

This commit adds the missing Berlin host support, and makes our ABI
binary-compatible with real EVMC again.

Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
Jamie Lokier 2021-08-05 02:52:40 +01:00 committed by jangko
parent 7972e7a55c
commit 74f53c7761
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
5 changed files with 62 additions and 1 deletions

View File

@ -64,6 +64,14 @@ proc emitLog(p: evmc_host_context, address: var evmc_address,
toHost(p).emitLog(address.fromEvmc, data, data_size,
cast[ptr HostTopic](topics), topics_count)
proc accessAccount(p: evmc_host_context,
address: var evmc_address): evmc_access_status {.cdecl.} =
toHost(p).accessAccount(address.fromEvmc)
proc accessStorage(p: evmc_host_context, address: var evmc_address,
key: var evmc_bytes32): evmc_access_status {.cdecl.} =
toHost(p).accessStorage(address.fromEvmc, key.fromEvmc)
proc evmcGetHostInterface(): ref evmc_host_interface =
var theHostInterface {.global, threadvar.}: ref evmc_host_interface
if theHostInterface.isNil:
@ -80,6 +88,8 @@ proc evmcGetHostInterface(): ref evmc_host_interface =
get_tx_context: getTxContext,
get_block_hash: getBlockHash,
emit_log: emitLog,
access_account: accessAccount,
access_storage: accessStorage,
)
return theHostInterface

View File

@ -272,6 +272,23 @@ proc emitLog(host: TransactionHost, address: HostAddress,
host.computation.logEntries.add(log)
#host.logEntries.add(log)
proc accessAccount(host: TransactionHost, address: HostAddress): EvmcAccessStatus {.show.} =
host.vmState.mutateStateDB:
if not db.inAccessList(address):
db.accessList(address)
return EVMC_ACCESS_COLD
else:
return EVMC_ACCESS_WARM
proc accessStorage(host: TransactionHost, address: HostAddress,
key: HostKey): EvmcAccessStatus {.show.} =
host.vmState.mutateStateDB:
if not db.inAccessList(address, key):
db.accessList(address, key)
return EVMC_ACCESS_COLD
else:
return EVMC_ACCESS_WARM
when use_evmc_glue:
{.pop: inline.}
const included_from_host_services = true

View File

@ -46,6 +46,7 @@ type
EvmcStatusCode* = evmc_status_code
EvmcCallKind* = evmc_call_kind
EvmcStorageStatus* = evmc_storage_status
EvmcAccessStatus* = evmc_access_status
EvmcTxContext* = evmc_tx_context
EvmcMessage* = evmc_message
EvmcResult* = evmc_result
@ -95,4 +96,4 @@ template isStatic*(msg: EvmcMessage): bool =
# `evmc_flags` won't export the flags, `evmc_flag_bit_shifts` must be used.
export
evmc_status_code, evmc_call_kind,
evmc_flag_bit_shifts, evmc_storage_status
evmc_flag_bit_shifts, evmc_storage_status, evmc_access_status

View File

@ -66,6 +66,10 @@ type
emit_log*: proc(context: evmc_host_context, address: EthAddress,
data: ptr byte, data_size: uint,
topics: ptr evmc_bytes32, topics_count: uint) {.cdecl, gcsafe.}
access_account*: proc(context: evmc_host_context,
address: EthAddress): evmc_access_status {.cdecl, gcsafe.}
access_storage*: proc(context: evmc_host_context, address: EthAddress,
key: var evmc_bytes32): evmc_access_status {.cdecl, gcsafe.}
proc nim_host_get_interface*(): ptr nimbus_host_interface {.importc, cdecl.}
proc nim_host_create_context*(vmstate: pointer, msg: ptr evmc_message): evmc_host_context {.importc, cdecl.}
@ -139,6 +143,15 @@ proc emitLog*(ctx: HostContext, address: EthAddress, data: openArray[byte],
proc call*(ctx: HostContext, msg: nimbus_message): nimbus_result {.inline.} =
ctx.host.call(ctx.context, msg.unsafeAddr)
proc accessAccount*(ctx: HostContext,
address: EthAddress): evmc_access_status {.inline.} =
ctx.host.access_account(ctx.context, address)
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))

View File

@ -124,6 +124,24 @@ proc hostEmitLogImpl(ctx: Computation, address: EthAddress,
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(
@ -215,6 +233,8 @@ proc initHostInterface(): evmc_host_interface =
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