diff --git a/examples/capi.c b/examples/capi.c index 1499c36..0afdd43 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -63,19 +63,22 @@ int64_t call( /// Example how the API is supposed to be used. int main(int argc, char *argv[]) { - struct evm_interface intf = examplevm_get_interface(); - struct evm_instance* jit = intf.create(query, update, call); + struct evm_factory factory = examplevm_get_factory(); + if (factory.abi_version != EVM_ABI_VERSION) + return 1; // Incompatible ABI version. - char const code[] = "exec()"; + struct evm_instance* jit = factory.create(query, update, call); + + uint8_t const code[] = "Place some EVM bytecode here"; const size_t code_size = sizeof(code); struct evm_uint256be code_hash = {.bytes = {1, 2, 3,}}; - char const input[] = "Hello World!"; + uint8_t const input[] = "Hello World!"; struct evm_uint256be value = {{1, 0, 0, 0}}; int64_t gas = 200000; struct evm_result result = - intf.execute(jit, NULL, EVM_HOMESTEAD, code_hash, (const uint8_t *)code, code_size, gas, (const uint8_t *)input, - sizeof(input), value); + jit->execute(jit, NULL, EVM_HOMESTEAD, code_hash, code, code_size, gas, + input, sizeof(input), value); printf("Execution result:\n"); if (result.code != EVM_SUCCESS) { @@ -94,5 +97,5 @@ int main(int argc, char *argv[]) { } result.release(&result); - intf.destroy(jit); + jit->destroy(jit); } diff --git a/examples/examplevm.c b/examples/examplevm.c index 7ae86ef..6638d1b 100644 --- a/examples/examplevm.c +++ b/examples/examplevm.c @@ -2,27 +2,15 @@ #include #include "evm.h" -struct evm_instance { + +struct examplevm +{ + struct evm_instance instance; evm_query_fn query_fn; evm_update_fn update_fn; evm_call_fn call_fn; }; -static struct evm_instance* evm_create(evm_query_fn query_fn, - evm_update_fn update_fn, - evm_call_fn call_fn) -{ - struct evm_instance *ret = calloc(1, sizeof(struct evm_instance)); - - if (ret) { - ret->query_fn = query_fn; - ret->update_fn = update_fn; - ret->call_fn = call_fn; - } - - return ret; -} - static void evm_destroy(struct evm_instance* evm) { free(evm); @@ -66,13 +54,23 @@ static struct evm_result evm_execute(struct evm_instance* instance, return ret; } -struct evm_interface examplevm_get_interface() +static struct evm_instance* evm_create(evm_query_fn query_fn, + evm_update_fn update_fn, + evm_call_fn call_fn) { - struct evm_interface intf = {}; - intf.abi_version = EVM_ABI_VERSION; - intf.create = evm_create; - intf.destroy = evm_destroy; - intf.execute = evm_execute; - intf.set_option = evm_set_option; - return intf; + struct examplevm* vm = calloc(1, sizeof(struct examplevm)); + struct evm_instance* interface = &vm->instance; + interface->destroy = evm_destroy; + interface->execute = evm_execute; + interface->set_option = evm_set_option; + vm->query_fn = query_fn; + vm->update_fn = update_fn; + vm->call_fn = call_fn; + return interface; +} + +struct evm_factory examplevm_get_factory() +{ + struct evm_factory factory = {EVM_ABI_VERSION, evm_create}; + return factory; } diff --git a/include/evm.h b/include/evm.h index 794698c..94e123c 100644 --- a/include/evm.h +++ b/include/evm.h @@ -55,7 +55,7 @@ enum evm_result_code { EVM_STACK_UNDERFLOW = 6, }; -struct evm_result; +struct evm_result; ///< Forward declaration. /// Releases resources assigned to an execution result. /// @@ -316,15 +316,12 @@ typedef int64_t (*evm_call_fn)( size_t output_size); -/// Opaque type representing a EVM instance. -struct evm_instance; +struct evm_instance; ///< Forward declaration. -/// Creates new EVM instance. +/// Creates the EVM instance. /// -/// Creates new EVM instance. The instance must be destroyed in evm_destroy(). -/// Single instance is thread-safe and can be shared by many threads. Having -/// **multiple instances is safe but discouraged** as it has not benefits over -/// having the singleton. +/// 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. @@ -425,23 +422,14 @@ typedef void (*evm_prepare_code_fn)(struct evm_instance* instance, uint8_t const* code, size_t code_size); -/// VM interface. +/// The EVM instance. /// -/// Defines the implementation of EVM-C interface for a VM. -struct evm_interface { - /// EVM-C ABI version implemented by the VM. - /// - /// For future use to detect ABI incompatibilities. The EVM-C ABI version - /// represented by this file is in ::EVM_ABI_VERSION. - uint32_t abi_version; - - /// Pointer to function creating a VM's instance. - evm_create_fn create; - - /// Pointer to function destroying a VM's instance. +/// Defines the base struct of the EVM implementation. +struct evm_instance { + /// Pointer to function destroying the EVM instance. evm_destroy_fn destroy; - /// Pointer to function execuing a code in a VM. + /// Pointer to function executing a code by the EVM instance. evm_execute_fn execute; /// Optional pointer to function returning a status of a code. @@ -460,16 +448,30 @@ struct evm_interface { evm_set_option_fn set_option; }; +/// The EVM instance factory. +/// +/// Provides ABI protection and method to create an EVM instance. +struct evm_factory { + /// EVM-C ABI version implemented by the EVM factory and instance. + /// + /// For future use to detect ABI incompatibilities. The EVM-C ABI version + /// represented by this file is in ::EVM_ABI_VERSION. + uint32_t abi_version; + + /// Pointer to function creating and initializing the EVM instance. + evm_create_fn create; +}; + // END Python CFFI declarations -/// Example of a function exporting an interface for an example VM. +/// Example of a function creating uninitialized instance of an example VM. /// -/// Each VM implementation is obligates to provided a function returning -/// VM's interface. -/// The function has to be named as `_get_interface(void)`. +/// Each EVM implementation is obligated to provided a function returning +/// an EVM instance. +/// The function has to be named as `_get_factory(void)`. /// -/// @return VM interface -struct evm_interface examplevm_get_interface(void); +/// @return EVM instance. +struct evm_factory examplevm_get_factory(void); #if __cplusplus