From e60ad129a246c4aaf2598ca6dbd172e8b19a7214 Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Mon, 17 May 2021 10:23:59 +0100 Subject: [PATCH] Transaction: New object `TransactionHost` for "EVMC host services" `TransactionHost` represents the interface to the EVM from the application once we've fully transitioned to EVMC. It represents a managed EVM call, and the "EVMC host" side of the host<->EVM boundary. This holds transaction state which sits outside the EVM, but a pointer to this is passed around by the EVM as _opaque_ type `evmc_host_context`. To the EVM, this offers "host services", which manage account state that the EVM cannot do, such as balance transfers, call costs, storage, logs, gas refunds, nested calls and new contract addresses. The EVM has no direct access to the account state database or network; it's all via "host services". To the application (host side), this object represents a managed EVM call, with inputs, a method to run, outputs, hidden transaction state, and later async scheduling. It is to replace `Computation` on the application side, while `Computation` will remain but just be for the EVM side. Signed-off-by: Jamie Lokier --- nimbus/transaction/host_types.nim | 97 +++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 nimbus/transaction/host_types.nim diff --git a/nimbus/transaction/host_types.nim b/nimbus/transaction/host_types.nim new file mode 100644 index 000000000..15c5df8f2 --- /dev/null +++ b/nimbus/transaction/host_types.nim @@ -0,0 +1,97 @@ +# Nimbus - Types and helpers used at the boundary of transactions/RPC and EVMC/EVM +# +# Copyright (c) 2019-2021 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + sets, stint, evmc/evmc, eth/common/eth_types, ../vm_types + +# Object `TransactionHost` represents "EVMC host" to the EVM. "Host services" +# manage account state outside EVM such as balance transfers, storage, logs and +# gas refunds. This object holds transaction state hidden from the EVM, and +# the EVM passes this around as opaque `evmc_host_context`. To the application +# outside the EVM, this object represents a computation for a transaction. +# +# `Host..` types are like EVMC types, but used in `TransactionHost` code. They +# occupy the same positions in EVMC functions and objects as the type they map +# to/from. But `Host..` types match internal APIs in the rest of Nimbus, to +# minimise the amount of explicit conversions when using them. We could just +# use the Nimbus types, but these names document their use and also role. +# +# `Evmc..` types named here are actual EVMC types. They play a similar role to +# `Host..` types, except the `Evmc` prefix indicates they are the actual EVMC +# types and more care applies. Byte order (big/little-endian) may need to be +# swapped in object fields of these types, and enums respected. +# +# When crossing the EVMC API boundary, between internal APIs and EVMC binary +# interface there have to be type-conversions and some big/little-endian byte +# swapping. Those conversions are mostly kept out of `TransactionHost` logic +# and delegated to glue code. + +type + HostAddress* = EthAddress # Mapped to/from evmc_address. + HostKey* = UInt256 # Mapped to/from evmc_bytes32. + HostValue* = UInt256 # Mapped to/from evmc_bytes32. + HostBalance* = UInt256 # Mapped to/from evmc_uint256be. + HostSize* = uint # Mapped to/from csize_t - unsigned! + HostHash* = Hash256 # Mapped to/from evmc_bytes32. + HostTopic* = Topic # Mapped to/from evmc_bytes32. + HostBlockNumber* = BlockNumber # Mapped to/from int64. + HostGasInt* = GasInt # Mapped to/from int64. + HostGasPrice* = GasInt # Mapped to/from evmc_uint256be. + + EvmcStatusCode* = evmc_status_code + EvmcCallKind* = evmc_call_kind + EvmcStorageStatus* = evmc_storage_status + EvmcTxContext* = evmc_tx_context + EvmcMessage* = evmc_message + EvmcResult* = evmc_result + + TransactionHost* = ref object + vmState*: BaseVMState + computation*: Computation + msg*: EvmcMessage + input*: seq[byte] + cachedTxContext*: bool + txContext*: EvmcTxContext + logEntries*: seq[Log] + touchedAccounts*: HashSet[EthAddress] + selfDestructs*: HashSet[EthAddress] + +# 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_ +# calls to `flip256` where it is wanted. + +template toEvmc*(n: Uint256): evmc_uint256be = + cast[evmc_uint256be](n) + +template toEvmc*(n: Hash256): evmc_bytes32 = + cast[evmc_bytes32](n) + +template toEvmc*(address: EthAddress): evmc_address = + cast[evmc_address](address) + +template fromEvmc*(n: evmc_uint256be): UInt256 = + cast[UInt256](n) + +template fromEvmc*(address: evmc_address): EthAddress = + cast[EthAddress](address) + +template flip256*(word256: evmc_uint256be): evmc_uint256be = + cast[evmc_uint256be](Uint256.fromBytesBe(word256.bytes).toBytes) + +template isCreate*(kind: EvmcCallKind): bool = + kind in {EVMC_CREATE, EVMC_CREATE2} + +template isStatic*(msg: EvmcMessage): bool = + EVMC_STATIC in msg.flags + +# Nim quirks: Exporting `evmc_status_code` (etc) are needed to access the enum +# values, even though alias `EnumStatusCode` is already exported. Exporting +# `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