EVM-C: introduce factory -- simpler interface

Replace evm_interface with evm_factory. The factory provides ABI protection and the function for creating EVM instances. After the instance is create you can discard the factory as it is no longer needed.
This commit is contained in:
Paweł Bylica 2016-12-20 16:50:23 +01:00
parent bfd39abfb2
commit 3d2e365661
3 changed files with 62 additions and 59 deletions

View File

@ -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);
}

View File

@ -2,27 +2,15 @@
#include <string.h>
#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;
}

View File

@ -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 `<vm-name>_get_interface(void)`.
/// Each EVM implementation is obligated to provided a function returning
/// an EVM instance.
/// The function has to be named as `<vm-name>_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