Merge pull request #32 from ethereum/tracing

Tracing API
This commit is contained in:
Alex Beregszaszi 2018-07-25 18:00:35 +01:00 committed by GitHub
commit 332d03570c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 12 deletions

View File

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

View File

@ -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.
*

View File

@ -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

View File

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