diff --git a/examples/capi.c b/examples/capi.c index 6252a57..7a67c45 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -4,14 +4,14 @@ #include "evm.h" -struct evm_uint256be balance(struct evm_env* env, +struct evm_uint256be balance(struct evm_context* context, const struct evm_uint160be* address) { struct evm_uint256be ret = {.bytes = {1, 2, 3, 4}}; return ret; } -struct evm_uint160be address(struct evm_env* env) +struct evm_uint160be address(struct evm_context* context) { struct evm_uint160be ret = {.bytes = {1, 2, 3, 4}}; return ret; @@ -24,7 +24,7 @@ static void print_address(const struct evm_uint160be* address) printf("%x", address->bytes[i] & 0xff); } -static int account_exists(struct evm_env* env, +static int account_exists(struct evm_context* context, const struct evm_uint160be* address) { printf("EVM-C: EXISTS @"); print_address(address); @@ -33,7 +33,7 @@ static int account_exists(struct evm_env* env, } static void get_storage(struct evm_uint256be* result, - struct evm_env* env, + struct evm_context* context, const struct evm_uint160be* address, const struct evm_uint256be* key) { @@ -42,7 +42,7 @@ static void get_storage(struct evm_uint256be* result, printf("\n"); } -static void set_storage(struct evm_env* env, +static void set_storage(struct evm_context* context, const struct evm_uint160be* address, const struct evm_uint256be* key, const struct evm_uint256be* value) @@ -53,17 +53,17 @@ static void set_storage(struct evm_env* env, } static void get_balance(struct evm_uint256be* result, - struct evm_env* env, + struct evm_context* context, const struct evm_uint160be* address) { printf("EVM-C: BALANCE @"); print_address(address); printf("\n"); - *result = balance(env, address); + *result = balance(context, address); } static size_t get_code(const uint8_t** code, - struct evm_env* env, + struct evm_context* context, const struct evm_uint160be* address) { printf("EVM-C: CODE @"); @@ -72,7 +72,7 @@ static size_t get_code(const uint8_t** code, return 0; } -static void selfdestruct(struct evm_env* env, +static void selfdestruct(struct evm_context* context, const struct evm_uint160be* address, const struct evm_uint160be* beneficiary) { @@ -84,19 +84,19 @@ static void selfdestruct(struct evm_env* env, } static void call(struct evm_result* result, - struct evm_env* env, + struct evm_context* context, const struct evm_message* msg) { printf("EVM-C: CALL (depth: %d)\n", msg->depth); result->code = EVM_FAILURE; } -static void get_tx_context(struct evm_tx_context* result, struct evm_env* env) +static void get_tx_context(struct evm_tx_context* result, struct evm_context* context) { } -static void get_block_hash(struct evm_uint256be* result, struct evm_env* env, +static void get_block_hash(struct evm_uint256be* result, struct evm_context* context, int64_t number) { @@ -105,7 +105,7 @@ static void get_block_hash(struct evm_uint256be* result, struct evm_env* env, /// EVM log callback. /// /// @note The `evm_log` name is used to avoid conflict with `log()` C function. -static void evm_log(struct evm_env* env, const struct evm_uint160be* address, +static void evm_log(struct evm_context* context, const struct evm_uint160be* address, const uint8_t* data, size_t data_size, const struct evm_uint256be topics[], size_t topics_count) { diff --git a/examples/examplevm.c b/examples/examplevm.c index 0e5c74a..3836e11 100644 --- a/examples/examplevm.c +++ b/examples/examplevm.c @@ -47,7 +47,7 @@ static void free_result_output_data(struct evm_result const* result) } static struct evm_result execute(struct evm_instance* instance, - struct evm_env* env, + struct evm_context* context, enum evm_mode mode, const struct evm_message* msg, const uint8_t* code, @@ -96,9 +96,9 @@ static struct evm_result execute(struct evm_instance* instance, strncmp((const char*)code, counter, code_size)) { struct evm_uint256be value; const struct evm_uint256be index = {{0,}}; - vm->host->get_storage(&value, env, &msg->address, &index); + vm->host->get_storage(&value, context, &msg->address, &index); value.bytes[31] += 1; - vm->host->set_storage(env, &msg->address, &index, &value); + vm->host->set_storage(context, &msg->address, &index, &value); ret.code = EVM_SUCCESS; return ret; } diff --git a/include/evm.h b/include/evm.h index b80f6ad..51fc40b 100644 --- a/include/evm.h +++ b/include/evm.h @@ -1,6 +1,7 @@ /// EVM-C -- C interface to Ethereum Virtual Machine /// /// ## High level design rules +/// /// 1. Pass function arguments and results by value. /// This rule comes from modern C++ and tries to avoid costly alias analysis /// needed for optimization. As the result we have a lots of complex structs @@ -10,6 +11,12 @@ /// The interface also tries to match host application "natural" endianess. /// I would like to know what endianess you use and where. /// +/// ## Terms +/// +/// 1. EVM -- an Ethereum Virtual Machine instance/implementation. +/// 2. Host -- an entity controlling the EVM. The Host requests code execution +/// and responses to EVM queries by callback functions. +/// /// @defgroup EVMC EVM-C /// @{ #ifndef EVM_H @@ -29,9 +36,12 @@ enum { EVM_ABI_VERSION = 0 }; -/// Opaque struct representing execution environment managed by the host -/// application. -struct evm_env; +/// Opaque structure representing execution context managed by the Host. +/// +/// The Host MAY pass the pointer to the Host execution context to +/// ::evm_execute_fn. The EVM MUST pass the same pointer back to the Host in +/// every callback function. +struct evm_context {}; /// Big-endian 256-bit integer. /// @@ -87,10 +97,10 @@ struct evm_tx_context { }; typedef void (*evm_get_tx_context_fn)(struct evm_tx_context* result, - struct evm_env* env); + struct evm_context* context); typedef void (*evm_get_block_hash_fn)(struct evm_uint256be* result, - struct evm_env* env, + struct evm_context* context, int64_t number); /// The execution result code. @@ -187,11 +197,11 @@ struct evm_result { /// /// This callback function is used by the EVM to check if /// there exists an account at given address. -/// @param env Pointer to execution environment managed by the host -/// application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address of the account the query is about. /// @return 1 if exists, 0 otherwise. -typedef int (*evm_account_exists_fn)(struct evm_env* env, +typedef int (*evm_account_exists_fn)(struct evm_context* context, const struct evm_uint160be* address); /// Get storage callback function. @@ -199,12 +209,12 @@ typedef int (*evm_account_exists_fn)(struct evm_env* env, /// This callback function is used by an EVM to query the given contract /// storage entry. /// @param[out] result The returned storage value. -/// @param env Pointer to execution environment managed by the host -/// application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address of the contract. /// @param key The index of the storage entry. typedef void (*evm_get_storage_fn)(struct evm_uint256be* result, - struct evm_env* env, + struct evm_context* context, const struct evm_uint160be* address, const struct evm_uint256be* key); @@ -212,12 +222,12 @@ typedef void (*evm_get_storage_fn)(struct evm_uint256be* result, /// /// This callback function is used by an EVM to update the given contract /// storage entry. -/// @param env Pointer to execution environment managed by the host -/// application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address of the contract. /// @param key The index of the storage entry. /// @param value The value to be stored. -typedef void (*evm_set_storage_fn)(struct evm_env* env, +typedef void (*evm_set_storage_fn)(struct evm_context* context, const struct evm_uint160be* address, const struct evm_uint256be* key, const struct evm_uint256be* value); @@ -227,11 +237,11 @@ typedef void (*evm_set_storage_fn)(struct evm_env* env, /// This callback function is used by an EVM to query the balance of the given /// address. /// @param[out] result The returned balance value. -/// @param env Pointer to execution environment managed by the host -/// application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address. typedef void (*evm_get_balance_fn)(struct evm_uint256be* result, - struct evm_env* env, + struct evm_context* context, const struct evm_uint160be* address); /// Get code callback function. @@ -241,22 +251,23 @@ typedef void (*evm_get_balance_fn)(struct evm_uint256be* result, /// @param[out] result_code The pointer to the contract code. This argument is /// optional. If NULL is provided, the host MUST only /// return the code size. -/// @param env Pointer to execution context managed by the Host. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address of the contract. /// @return The size of the code. typedef size_t (*evm_get_code_fn)(const uint8_t** result_code, - struct evm_env* env, + struct evm_context* context, const struct evm_uint160be* address); /// Selfdestruct callback function. /// /// This callback function is used by an EVM to SELFDESTRUCT given contract. -/// @param env The pointer to the execution environment managed by -/// the host application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address of the contract to be selfdestructed. /// @param beneficiary The address where the remaining ETH is going to be /// transferred. -typedef void (*evm_selfdestruct_fn)(struct evm_env* env, +typedef void (*evm_selfdestruct_fn)(struct evm_context* context, const struct evm_uint160be* address, const struct evm_uint160be* beneficiary); @@ -264,15 +275,15 @@ typedef void (*evm_selfdestruct_fn)(struct evm_env* env, /// /// This callback function is used by an EVM to inform about a LOG that happened /// during an EVM bytecode execution. -/// @param env The pointer to execution environment managed by -/// the host application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param address The address of the contract that generated the log. /// @param data The pointer to unindexed data attached to the log. /// @param data_size The length of the data. /// @param topics The pointer to the array of topics attached to the log. /// @param topics_count The number of the topics. Valid values are between /// 0 and 4 inclusively. -typedef void (*evm_log_fn)(struct evm_env* env, +typedef void (*evm_log_fn)(struct evm_context* context, const struct evm_uint160be* address, const uint8_t* data, size_t data_size, @@ -282,22 +293,19 @@ typedef void (*evm_log_fn)(struct evm_env* env, /// Pointer to the callback function supporting EVM calls. /// /// @param[out] result Call result. -/// @param env Pointer to execution environment managed by the host -/// application. +/// @param context The pointer to the Host execution context. +/// @see ::evm_context. /// @param msg Call parameters. -typedef void (*evm_call_fn)( - struct evm_result* result, - struct evm_env* env, - const struct evm_message* msg); +typedef void (*evm_call_fn)(struct evm_result* result, + struct evm_context* context, + const struct evm_message* msg); -/// EVM Host interface. +/// The Host interface. /// /// The set of all callback functions expected by EVM instances. This is C /// realisation of OOP interface (only virtual methods, no data). -/// Host implementations SHOULD create constant singletons of this (similar +/// Host implementations SHOULD create constant singletons of this (similarly /// to vtables) to lower the maintenance and memory management cost. -/// -/// @todo Merge evm_host with evm_env? struct evm_host { evm_account_exists_fn account_exists; evm_get_storage_fn get_storage; @@ -363,8 +371,8 @@ enum evm_mode { /// All the fun is here. This function actually does something useful. /// /// @param instance A EVM instance. -/// @param env A pointer to the execution environment provided by the -/// user and passed to callback functions. +/// @param context The pointer to the Host execution context to be passed +/// to callback functions. @see ::evm_context. /// @param mode EVM compatibility mode. /// @param code_hash A hash of the bytecode, usually Keccak. The EVM uses it /// as the code identifier. A EVM implementation is able to @@ -378,7 +386,7 @@ enum evm_mode { /// @param value Call value. /// @return All execution results. typedef struct evm_result (*evm_execute_fn)(struct evm_instance* instance, - struct evm_env* env, + struct evm_context* context, enum evm_mode mode, const struct evm_message* msg, uint8_t const* code,