mirror of https://github.com/status-im/evmc.git
commit
7ae0021859
3
Doxyfile
3
Doxyfile
|
@ -101,7 +101,8 @@ WARN_LOGFILE =
|
|||
#---------------------------------------------------------------------------
|
||||
INPUT = \
|
||||
include/evmc/evmc.h include/evmc/helpers.h include/evmc/helpers.hpp include/evmc/loader.h include/evmc/utils.h include/evmc/instructions.h \
|
||||
docs/
|
||||
docs/ \
|
||||
examples/example_vm.c
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
|
|
|
@ -9,6 +9,7 @@ to access Ethereum environment and state.
|
|||
# Guides
|
||||
|
||||
- [Host Implementation Guide](@ref hostguide)
|
||||
- [VM Implementation Guide](@ref vmguide)
|
||||
|
||||
|
||||
# Versioning {#versioning}
|
||||
|
|
|
@ -20,7 +20,7 @@ When Host implementation is ready it's time to start using EVMC VMs.
|
|||
|
||||
1. Firstly, create a VM instance. You need to know what is the name of the "create"
|
||||
function in particular VM implementation. The EVMC recommends to name the
|
||||
function by the VM codename, e.g. ::evmc_create_examplevm().
|
||||
function by the VM codename, e.g. ::evmc_create_example_vm().
|
||||
Invoking the create function will give you the VM instance (::evmc_instance).
|
||||
It is recommended to create the VM instance once.
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# EVMC VM Implementation Guide {#vmguide}
|
||||
|
||||
> How to add EVMC interface to Your Ethereum VM implementation.
|
||||
|
||||
## An example
|
||||
|
||||
You can start with [the example implementation of EVMC VM interface in C](@ref example_vm.c).
|
||||
|
||||
## VM instance
|
||||
|
||||
The VM instance is described by the ::evmc_instance struct. It contains the
|
||||
basic static information about the VM like name and version. The struct also
|
||||
includes the VM methods (in form of function pointers) to allow the Host
|
||||
to interact with the VM.
|
||||
|
||||
Some methods are optional. The VM must implement at least all mandatory ones.
|
||||
|
||||
The instance struct must also include the EVMC ABI version (::EVMC_ABI_VERSION)
|
||||
it was build with. This allows the Host to check the ABI compatibility when
|
||||
loading VMs dynamically.
|
||||
|
||||
The VM instance is created and returned as a pointer from a special "create"
|
||||
function. The EVMC recommends to name the function by the VM codename,
|
||||
e.g. ::evmc_create_example_vm().
|
||||
|
||||
## VM methods implementation
|
||||
|
||||
Each VM methods takes the pointer to the ::evmc_instance as the first argument.
|
||||
The VM implementation can extend the ::evmc_instance struct for storing internal
|
||||
data. This allow implementing the VM in object-oriented manner.
|
||||
|
||||
The most important method is ::evmc_instance::execute() because it executes EVM code.
|
||||
Remember that the Host is allowed to invoke the execute method concurrently
|
||||
so do not store data related to a particular execution context in the VM instance.
|
||||
|
||||
## Resource management
|
||||
|
||||
All additional resources allocated when the VM instance is created must be
|
||||
freed when the destroy method is invoked.
|
||||
|
||||
The VM implementation can also attach additional resources to the ::evmc_result
|
||||
of an execution. These resource must be freed when the ::evmc_result::release()
|
||||
method is invoked.
|
||||
|
||||
|
||||
*Have fun!*
|
|
@ -2,6 +2,15 @@
|
|||
* Copyright 2018 The EVMC Authors.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
*/
|
||||
|
||||
/// @file
|
||||
/// Example implementation of the EVMC VM interface.
|
||||
///
|
||||
/// This VM does not do anything useful except for showing
|
||||
/// how EVMC VM API should be implemented.
|
||||
/// The inplementation is done in C only, but could be done in C++ in very
|
||||
/// similar way.
|
||||
|
||||
#include "example_vm.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
@ -9,34 +18,33 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define STR(x) #x
|
||||
|
||||
#if !defined(PROJECT_VERSION)
|
||||
#define PROJECT_VERSION 0.0.0
|
||||
#endif
|
||||
|
||||
/// The example VM instance struct extending the evmc_instance.
|
||||
struct example_vm
|
||||
{
|
||||
struct evmc_instance instance;
|
||||
int verbose;
|
||||
evmc_trace_callback trace_callback;
|
||||
struct evmc_tracer_context* tracer_context;
|
||||
struct evmc_instance instance; ///< The base struct.
|
||||
int verbose; ///< The verbosity level.
|
||||
evmc_trace_callback trace_callback; ///< The trace callback.
|
||||
struct evmc_tracer_context* tracer_context; ///< The tracer context.
|
||||
};
|
||||
|
||||
static void destroy(struct evmc_instance* evm)
|
||||
/// The implementation of the evmc_instance::destroy() method.
|
||||
static void destroy(struct evmc_instance* vm)
|
||||
{
|
||||
free(evm);
|
||||
free(vm);
|
||||
}
|
||||
|
||||
/// The example implementation of the evmc_instance::get_capabilities() method.
|
||||
static evmc_capabilities_flagset get_capabilities(struct evmc_instance* vm)
|
||||
{
|
||||
(void)vm;
|
||||
return EVMC_CAPABILITY_EVM1 | EVMC_CAPABILITY_EWASM;
|
||||
}
|
||||
|
||||
/// Example options.
|
||||
/// Example VM options.
|
||||
///
|
||||
/// VMs are allowed to omit this function implementation.
|
||||
/// The implementation of the evmc_instance::set_option() method.
|
||||
/// VMs are allowed to omit this method implementation.
|
||||
static enum evmc_set_option_result set_option(struct evmc_instance* instance,
|
||||
const char* name,
|
||||
const char* value)
|
||||
|
@ -60,16 +68,14 @@ static enum evmc_set_option_result set_option(struct evmc_instance* instance,
|
|||
return EVMC_SET_OPTION_INVALID_NAME;
|
||||
}
|
||||
|
||||
static void release_result(struct evmc_result const* result)
|
||||
{
|
||||
(void)result;
|
||||
}
|
||||
|
||||
static void free_result_output_data(struct evmc_result const* result)
|
||||
/// The implementation of the evmc_result::release() method that frees
|
||||
/// the output buffer attached to the result object.
|
||||
static void free_result_output_data(const struct evmc_result* result)
|
||||
{
|
||||
free((uint8_t*)result->output_data);
|
||||
}
|
||||
|
||||
/// The example implementation of the evmc_instance::execute() method.
|
||||
static struct evmc_result execute(struct evmc_instance* instance,
|
||||
struct evmc_context* context,
|
||||
enum evmc_revision rev,
|
||||
|
@ -128,7 +134,6 @@ static struct evmc_result execute(struct evmc_instance* instance,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret.release = release_result;
|
||||
ret.status_code = EVMC_FAILURE;
|
||||
ret.gas_left = 0;
|
||||
|
||||
|
@ -138,6 +143,7 @@ static struct evmc_result execute(struct evmc_instance* instance,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/// The implementation of the optional evmc_instance::set_tracer() method.
|
||||
static void set_tracer(struct evmc_instance* instance,
|
||||
evmc_trace_callback callback,
|
||||
struct evmc_tracer_context* context)
|
||||
|
@ -147,6 +153,19 @@ static void set_tracer(struct evmc_instance* instance,
|
|||
vm->tracer_context = context;
|
||||
}
|
||||
|
||||
|
||||
/// @cond internal
|
||||
|
||||
/// Stringify the argument.
|
||||
#define STR(x) #x
|
||||
|
||||
#if !defined(PROJECT_VERSION)
|
||||
/// The dummy project version if not provided by the build system.
|
||||
#define PROJECT_VERSION 0.0.0
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
struct evmc_instance* evmc_create_example_vm()
|
||||
{
|
||||
struct evmc_instance init = {
|
||||
|
@ -155,7 +174,7 @@ struct evmc_instance* evmc_create_example_vm()
|
|||
.version = STR(PROJECT_VERSION),
|
||||
.destroy = destroy,
|
||||
.execute = execute,
|
||||
.get_capabilites = get_capabilities,
|
||||
.get_capabilities = get_capabilities,
|
||||
.set_option = set_option,
|
||||
.set_tracer = set_tracer,
|
||||
};
|
||||
|
|
|
@ -876,7 +876,7 @@ struct evmc_instance
|
|||
* A Client SHOULD only rely on the value returned here if it has queried it after
|
||||
* it has called set_option.
|
||||
*/
|
||||
evmc_get_capabilities_fn get_capabilites;
|
||||
evmc_get_capabilities_fn get_capabilities;
|
||||
|
||||
/**
|
||||
* Optional pointer to function setting the EVM instruction tracer.
|
||||
|
@ -911,7 +911,7 @@ struct evmc_instance
|
|||
*
|
||||
* @return EVM instance or NULL indicating instance creation failure.
|
||||
*/
|
||||
struct evmc_instance* evmc_create_examplevm(void);
|
||||
struct evmc_instance* evmc_create_example_vm(void);
|
||||
#endif
|
||||
|
||||
#if __cplusplus
|
||||
|
|
|
@ -51,7 +51,7 @@ static inline const char* evmc_vm_version(struct evmc_instance* instance)
|
|||
static inline bool evmc_vm_has_capability(struct evmc_instance* vm,
|
||||
enum evmc_capabilities capability)
|
||||
{
|
||||
return (vm->get_capabilites(vm) & (evmc_capabilities_flagset)capability) != 0;
|
||||
return (vm->get_capabilities(vm) & (evmc_capabilities_flagset)capability) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue