mirror of https://github.com/status-im/evmc.git
commit
332d03570c
|
@ -9,6 +9,8 @@ struct examplevm
|
|||
{
|
||||
struct evmc_instance instance;
|
||||
int verbose;
|
||||
evmc_trace_callback trace_callback;
|
||||
struct evmc_tracer_context* tracer_context;
|
||||
};
|
||||
|
||||
static void destroy(struct evmc_instance* evm)
|
||||
|
@ -113,6 +115,15 @@ static struct evmc_result execute(struct evmc_instance* instance,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void set_tracer(struct evmc_instance* instance,
|
||||
evmc_trace_callback callback,
|
||||
struct evmc_tracer_context* context)
|
||||
{
|
||||
struct examplevm* vm = (struct examplevm*)instance;
|
||||
vm->trace_callback = callback;
|
||||
vm->tracer_context = context;
|
||||
}
|
||||
|
||||
struct evmc_instance* evmc_create_examplevm()
|
||||
{
|
||||
struct evmc_instance init = {
|
||||
|
@ -122,6 +133,7 @@ struct evmc_instance* evmc_create_examplevm()
|
|||
.destroy = destroy,
|
||||
.execute = execute,
|
||||
.set_option = set_option,
|
||||
.set_tracer = set_tracer,
|
||||
};
|
||||
struct examplevm* vm = calloc(1, sizeof(struct examplevm));
|
||||
struct evmc_instance* interface = &vm->instance;
|
||||
|
|
|
@ -40,7 +40,7 @@ extern "C" {
|
|||
enum
|
||||
{
|
||||
/** The EVMC ABI version number of the interface declared in this file. */
|
||||
EVMC_ABI_VERSION = 2
|
||||
EVMC_ABI_VERSION = 3
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -675,18 +675,18 @@ enum evmc_revision
|
|||
|
||||
|
||||
/**
|
||||
* Generates and executes machine code for given EVM bytecode.
|
||||
* Executes the given EVM bytecode using the input in the message
|
||||
*
|
||||
* All the fun is here. This function actually does something useful.
|
||||
* This function MAY be invoked multiple times for a single EVM instance.
|
||||
*
|
||||
* @param instance A EVM instance.
|
||||
* @param context The pointer to the Host execution context to be passed
|
||||
* to callback functions. @see ::evmc_context.
|
||||
* @param rev Requested EVM specification revision.
|
||||
* @param msg Call parameters. @see ::evmc_message.
|
||||
* @param code Reference to the bytecode to be executed.
|
||||
* @param code_size The length of the bytecode.
|
||||
* @return All execution results.
|
||||
* @param instance The EVM instance.
|
||||
* @param context The pointer to the Client execution context to be passed
|
||||
* to the callback functions. @see ::evmc_context.
|
||||
* @param rev Requested EVM specification revision.
|
||||
* @param msg Call parameters. @see ::evmc_message.
|
||||
* @param code Reference to the bytecode to be executed.
|
||||
* @param code_size The length of the bytecode.
|
||||
* @return All execution results.
|
||||
*/
|
||||
typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance,
|
||||
struct evmc_context* context,
|
||||
|
@ -696,6 +696,77 @@ typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance,
|
|||
size_t code_size);
|
||||
|
||||
|
||||
/** The opaque type representing a Client-side tracer object. */
|
||||
struct evmc_tracer_context;
|
||||
|
||||
/**
|
||||
* The callback to trace instructions execution in an EVM.
|
||||
*
|
||||
* This function informs the Client what instruction has been executed in the EVM implementation
|
||||
* and what are the results of executing this particular instruction.
|
||||
* The message level information (like call depth, destination address, etc.) are not provided here.
|
||||
* This piece of information can be acquired by inspecting messages being sent to the EVM in
|
||||
* ::evmc_execute_fn and the results of the messages execution.
|
||||
*
|
||||
* @param context The pointer to the Client-side tracing context. This allows to
|
||||
* implement the tracer in OOP manner.
|
||||
* @param code_offset The current instruction position in the code.
|
||||
* @param status_code The status code of the instruction execution.
|
||||
* @param gas_left The amount of the gas left after the instruction execution.
|
||||
* @param stack_num_items The current EVM stack height after the instruction execution.
|
||||
* @param pushed_stack_item The top EVM stack item pushed as the result of the instruction
|
||||
* execution. This value is null when the instruction does not push
|
||||
* anything to the stack.
|
||||
* @param memory_size The size of the EVM memory after the instruction execution.
|
||||
* @param changed_memory_offset The offset in number of bytes of the beginning of the memory area
|
||||
* modified as the result of the instruction execution.
|
||||
* The Client MAY use this information together with
|
||||
* @p changed_memory_size and @p changed_memory to incrementally
|
||||
* update the copy of the full VM's memory.
|
||||
* @param changed_memory_size The size of the memory area modified as the result of
|
||||
* the instruction execution.
|
||||
* @param changed_memory The pointer to the memory area modified as the result of
|
||||
* the instruction execution.
|
||||
* The Client MAY access the pointed memory area
|
||||
* (limited by the @p changed_memory_size) only during the current
|
||||
* execution of the evmc_trace_callback().
|
||||
* The pointer MUST NOT be stored by the Client.
|
||||
* The Client MUST NOT assume that
|
||||
* `changed_memory - changed_memory_offset` is a valid base pointer
|
||||
* of the VM memory.
|
||||
*/
|
||||
typedef void (*evmc_trace_callback)(struct evmc_tracer_context* context,
|
||||
size_t code_offset,
|
||||
enum evmc_status_code status_code,
|
||||
int64_t gas_left,
|
||||
size_t stack_num_items,
|
||||
const struct evmc_uint256be* pushed_stack_item,
|
||||
size_t memory_size,
|
||||
size_t changed_memory_offset,
|
||||
size_t changed_memory_size,
|
||||
const uint8_t* changed_memory);
|
||||
|
||||
/**
|
||||
* Sets the EVM instruction tracer.
|
||||
*
|
||||
* When the tracer is set in the EVM instance, the EVM SHOULD call back the tracer with information
|
||||
* about instructions execution in the EVM.
|
||||
* @see ::evmc_trace_callback.
|
||||
*
|
||||
* This will overwrite the previous settings (the callback and the context).
|
||||
*
|
||||
* @param instance The EVM instance.
|
||||
* @param callback The tracer callback function. This argument MAY be NULL to disable previously
|
||||
* set tracer.
|
||||
* @param context The Client-side tracer context. This argument MAY be NULL in case the tracer
|
||||
* does not require any context. This argument MUST be NULL if the callback
|
||||
* argument is NULL.
|
||||
*/
|
||||
typedef void (*evmc_set_tracer_fn)(struct evmc_instance* instance,
|
||||
evmc_trace_callback callback,
|
||||
struct evmc_tracer_context* context);
|
||||
|
||||
|
||||
/**
|
||||
* The EVM instance.
|
||||
*
|
||||
|
@ -731,6 +802,13 @@ struct evmc_instance
|
|||
/** Pointer to function executing a code by the EVM instance. */
|
||||
evmc_execute_fn execute;
|
||||
|
||||
/**
|
||||
* Optional pointer to function setting the EVM instruction tracer.
|
||||
*
|
||||
* If the EVM does not support this feature the pointer can be NULL.
|
||||
*/
|
||||
evmc_set_tracer_fn set_tracer;
|
||||
|
||||
/**
|
||||
* Optional pointer to function modifying VM's options.
|
||||
*
|
||||
|
|
|
@ -19,6 +19,8 @@ target_link_libraries(
|
|||
CLI11::CLI11
|
||||
)
|
||||
|
||||
set_target_properties(evmc-vmtester PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
|
||||
|
||||
install(TARGETS evmc-vmtester RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
add_test(NAME vmtester-help
|
||||
|
|
|
@ -59,4 +59,13 @@ TEST_F(evmc_vm_test, version)
|
|||
{
|
||||
ASSERT_NE(vm->version, nullptr);
|
||||
EXPECT_GT(std::strlen(vm->version), 0) << "VM name cannot be empty";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(evmc_vm_test, set_tracer)
|
||||
{
|
||||
static const auto tracer_callback = [](evmc_tracer_context*, size_t, evmc_status_code, int64_t,
|
||||
size_t, const evmc_uint256be*, size_t, size_t, size_t,
|
||||
const uint8_t*) noexcept {};
|
||||
if (vm->set_tracer)
|
||||
vm->set_tracer(vm, tracer_callback, nullptr);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue