diff --git a/examples/capi.c b/examples/capi.c index 5c07a6d..dad8e34 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -108,19 +108,24 @@ static void evm_log(struct evm_env* env, const struct evm_uint160be* address, printf("EVM-C: LOG%d\n", (int)topics_count); } +static const struct evm_host example_host = { + query, + get_storage, + set_storage, + selfdestruct, + call, + get_tx_context, + get_block_hash, + evm_log +}; + /// Example how the API is supposed to be used. int main(int argc, char *argv[]) { struct evm_factory factory = examplevm_get_factory(); if (factory.abi_version != EVM_ABI_VERSION) return 1; // Incompatible ABI version. - struct evm_instance* jit = factory.create(query, - get_storage, - set_storage, - selfdestruct, - call, - get_tx_context, get_block_hash, - evm_log); + struct evm_instance* jit = factory.create(&example_host); uint8_t const code[] = "Place some EVM bytecode here"; const size_t code_size = sizeof(code); diff --git a/examples/examplevm.c b/examples/examplevm.c index 6869f34..3783b56 100644 --- a/examples/examplevm.c +++ b/examples/examplevm.c @@ -7,14 +7,7 @@ struct examplevm { struct evm_instance instance; - evm_query_state_fn query_fn; - evm_get_storage_fn get_storage_fn; - evm_set_storage_fn set_storage_fn; - evm_selfdestruct_fn selfdestruct_fn; - evm_call_fn call_fn; - evm_get_tx_context_fn get_tx_context_fn; - evm_get_block_hash_fn get_block_hash_fn; - evm_log_fn log_fn; + const struct evm_host* host; int example_option; }; @@ -103,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->get_storage_fn(&value, env, &msg->address, &index); + vm->host->get_storage(&value, env, &msg->address, &index); value.bytes[31] += 1; - vm->set_storage_fn(env, &msg->address, &index, &value); + vm->host->set_storage(env, &msg->address, &index, &value); ret.code = EVM_SUCCESS; return ret; } @@ -117,28 +110,14 @@ static struct evm_result execute(struct evm_instance* instance, return ret; } -static struct evm_instance* evm_create(evm_query_state_fn query_fn, - evm_get_storage_fn get_storage_fn, - evm_set_storage_fn set_storage_fn, - evm_selfdestruct_fn selfdestruct_fn, - evm_call_fn call_fn, - evm_get_tx_context_fn get_tx_context_fn, - evm_get_block_hash_fn get_block_hash_fn, - evm_log_fn log_fn) +static struct evm_instance* evm_create(const struct evm_host* host) { struct examplevm* vm = calloc(1, sizeof(struct examplevm)); struct evm_instance* interface = &vm->instance; interface->destroy = evm_destroy; interface->execute = execute; interface->set_option = evm_set_option; - vm->query_fn = query_fn; - vm->get_storage_fn = get_storage_fn; - vm->set_storage_fn = set_storage_fn; - vm->selfdestruct_fn = selfdestruct_fn; - vm->call_fn = call_fn; - vm->get_tx_context_fn = get_tx_context_fn; - vm->get_block_hash_fn = get_block_hash_fn; - vm->log_fn = log_fn; + vm->host = host; return interface; } diff --git a/include/evm.h b/include/evm.h index 5cf302c..d3c4ee7 100644 --- a/include/evm.h +++ b/include/evm.h @@ -328,6 +328,23 @@ typedef void (*evm_call_fn)( struct evm_env* env, const struct evm_message* msg); +/// EVM 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 +/// to vtables) to lower the maintenance and memory management cost. +struct evm_host { + evm_query_state_fn query; + evm_get_storage_fn get_storage; + evm_set_storage_fn set_storage; + evm_selfdestruct_fn selfdestruct; + evm_call_fn call; + evm_get_tx_context_fn get_tx_context; + evm_get_block_hash_fn get_block_hash; + evm_log_fn log; +}; + struct evm_instance; ///< Forward declaration. @@ -336,20 +353,10 @@ struct evm_instance; ///< Forward declaration. /// Creates and initializes an EVM instance by providing the information /// about runtime callback functions. /// -/// @param query_fn Pointer to query callback function. Nonnull. -/// @param update_fn Pointer to update callback function. Nonnull. -/// @param call_fn Pointer to call callback function. Nonnull. -/// @param get_tx_context_fn Pointer to get tx context function. Nonnull. -/// @param get_block_hash_fn Pointer to get block hash function. Nonnull. -/// @return Pointer to the created EVM instance. -typedef struct evm_instance* (*evm_create_fn)(evm_query_state_fn query_fn, - evm_get_storage_fn get_storage_fn, - evm_set_storage_fn set_storage_fn, - evm_selfdestruct_fn selfdestruct_fn, - evm_call_fn call_fn, - evm_get_tx_context_fn get_tx_context_fn, - evm_get_block_hash_fn get_block_hash_fn, - evm_log_fn log_fn); +/// @param host Pointer to an EVM Host controlling the created EVM +/// instance. MUST NOT be null. +/// @return Pointer to the created EVM instance. +typedef struct evm_instance* (*evm_create_fn)(const struct evm_host* host); /// Destroys the EVM instance. ///