Merge pull request #128 from ethereum/evmc-context

EVM-C renames
This commit is contained in:
Paweł Bylica 2017-08-21 07:46:42 +02:00 committed by GitHub
commit 861a610af1
3 changed files with 75 additions and 65 deletions

View File

@ -4,14 +4,14 @@
#include "evm.h" #include "evm.h"
struct evm_uint256be balance(struct evm_env* env, struct evm_uint256be balance(struct evm_context* context,
const struct evm_uint160be* address) const struct evm_uint160be* address)
{ {
struct evm_uint256be ret = {.bytes = {1, 2, 3, 4}}; struct evm_uint256be ret = {.bytes = {1, 2, 3, 4}};
return ret; return ret;
} }
struct evm_uint160be address(struct evm_env* env) struct evm_uint160be address(struct evm_context* context)
{ {
struct evm_uint160be ret = {.bytes = {1, 2, 3, 4}}; struct evm_uint160be ret = {.bytes = {1, 2, 3, 4}};
return ret; return ret;
@ -24,7 +24,7 @@ static void print_address(const struct evm_uint160be* address)
printf("%x", address->bytes[i] & 0xff); printf("%x", address->bytes[i] & 0xff);
} }
static int account_exists(struct evm_env* env, static int account_exists(struct evm_context* context,
const struct evm_uint160be* address) { const struct evm_uint160be* address) {
printf("EVM-C: EXISTS @"); printf("EVM-C: EXISTS @");
print_address(address); print_address(address);
@ -33,7 +33,7 @@ static int account_exists(struct evm_env* env,
} }
static void get_storage(struct evm_uint256be* result, static void get_storage(struct evm_uint256be* result,
struct evm_env* env, struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const struct evm_uint256be* key) const struct evm_uint256be* key)
{ {
@ -42,7 +42,7 @@ static void get_storage(struct evm_uint256be* result,
printf("\n"); printf("\n");
} }
static void set_storage(struct evm_env* env, static void set_storage(struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const struct evm_uint256be* key, const struct evm_uint256be* key,
const struct evm_uint256be* value) const struct evm_uint256be* value)
@ -53,17 +53,17 @@ static void set_storage(struct evm_env* env,
} }
static void get_balance(struct evm_uint256be* result, static void get_balance(struct evm_uint256be* result,
struct evm_env* env, struct evm_context* context,
const struct evm_uint160be* address) const struct evm_uint160be* address)
{ {
printf("EVM-C: BALANCE @"); printf("EVM-C: BALANCE @");
print_address(address); print_address(address);
printf("\n"); printf("\n");
*result = balance(env, address); *result = balance(context, address);
} }
static size_t get_code(const uint8_t** code, static size_t get_code(const uint8_t** code,
struct evm_env* env, struct evm_context* context,
const struct evm_uint160be* address) const struct evm_uint160be* address)
{ {
printf("EVM-C: CODE @"); printf("EVM-C: CODE @");
@ -72,7 +72,7 @@ static size_t get_code(const uint8_t** code,
return 0; return 0;
} }
static void selfdestruct(struct evm_env* env, static void selfdestruct(struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const struct evm_uint160be* beneficiary) const struct evm_uint160be* beneficiary)
{ {
@ -84,19 +84,19 @@ static void selfdestruct(struct evm_env* env,
} }
static void call(struct evm_result* result, static void call(struct evm_result* result,
struct evm_env* env, struct evm_context* context,
const struct evm_message* msg) const struct evm_message* msg)
{ {
printf("EVM-C: CALL (depth: %d)\n", msg->depth); printf("EVM-C: CALL (depth: %d)\n", msg->depth);
result->code = EVM_FAILURE; result->code = EVM_FAILURE;
} }
static void get_tx_context(struct evm_tx_context* result, struct evm_env* env) static void get_tx_context(struct evm_tx_context* result, struct evm_context* context)
{ {
} }
static void get_block_hash(struct evm_uint256be* result, struct evm_env* env, static void get_block_hash(struct evm_uint256be* result, struct evm_context* context,
int64_t number) int64_t number)
{ {
@ -105,7 +105,7 @@ static void get_block_hash(struct evm_uint256be* result, struct evm_env* env,
/// EVM log callback. /// EVM log callback.
/// ///
/// @note The `evm_log` name is used to avoid conflict with `log()` C function. /// @note The `evm_log` name is used to avoid conflict with `log()` C function.
static void evm_log(struct evm_env* env, const struct evm_uint160be* address, static void evm_log(struct evm_context* context, const struct evm_uint160be* address,
const uint8_t* data, size_t data_size, const uint8_t* data, size_t data_size,
const struct evm_uint256be topics[], size_t topics_count) const struct evm_uint256be topics[], size_t topics_count)
{ {

View File

@ -47,8 +47,8 @@ static void free_result_output_data(struct evm_result const* result)
} }
static struct evm_result execute(struct evm_instance* instance, static struct evm_result execute(struct evm_instance* instance,
struct evm_env* env, struct evm_context* context,
enum evm_mode mode, enum evm_revision rev,
const struct evm_message* msg, const struct evm_message* msg,
const uint8_t* code, const uint8_t* code,
size_t code_size) size_t code_size)
@ -56,7 +56,7 @@ static struct evm_result execute(struct evm_instance* instance,
struct evm_result ret = {}; struct evm_result ret = {};
if (code_size == 0) { if (code_size == 0) {
// In case of empty code return a fancy error message. // In case of empty code return a fancy error message.
const char* error = mode == EVM_BYZANTIUM ? const char* error = rev == EVM_BYZANTIUM ?
"Welcome to Byzantium!" : "Hello Ethereum!"; "Welcome to Byzantium!" : "Hello Ethereum!";
ret.output_data = (const uint8_t*)error; ret.output_data = (const uint8_t*)error;
ret.output_size = strlen(error); ret.output_size = strlen(error);
@ -96,9 +96,9 @@ static struct evm_result execute(struct evm_instance* instance,
strncmp((const char*)code, counter, code_size)) { strncmp((const char*)code, counter, code_size)) {
struct evm_uint256be value; struct evm_uint256be value;
const struct evm_uint256be index = {{0,}}; const struct evm_uint256be index = {{0,}};
vm->host->get_storage(&value, env, &msg->address, &index); vm->host->get_storage(&value, context, &msg->address, &index);
value.bytes[31] += 1; value.bytes[31] += 1;
vm->host->set_storage(env, &msg->address, &index, &value); vm->host->set_storage(context, &msg->address, &index, &value);
ret.code = EVM_SUCCESS; ret.code = EVM_SUCCESS;
return ret; return ret;
} }

View File

@ -1,6 +1,7 @@
/// EVM-C -- C interface to Ethereum Virtual Machine /// EVM-C -- C interface to Ethereum Virtual Machine
/// ///
/// ## High level design rules /// ## High level design rules
///
/// 1. Pass function arguments and results by value. /// 1. Pass function arguments and results by value.
/// This rule comes from modern C++ and tries to avoid costly alias analysis /// This rule comes from modern C++ and tries to avoid costly alias analysis
/// needed for optimization. As the result we have a lots of complex structs /// needed for optimization. As the result we have a lots of complex structs
@ -10,6 +11,12 @@
/// The interface also tries to match host application "natural" endianess. /// The interface also tries to match host application "natural" endianess.
/// I would like to know what endianess you use and where. /// I would like to know what endianess you use and where.
/// ///
/// ## Terms
///
/// 1. EVM -- an Ethereum Virtual Machine instance/implementation.
/// 2. Host -- an entity controlling the EVM. The Host requests code execution
/// and responses to EVM queries by callback functions.
///
/// @defgroup EVMC EVM-C /// @defgroup EVMC EVM-C
/// @{ /// @{
#ifndef EVM_H #ifndef EVM_H
@ -29,9 +36,12 @@ enum {
EVM_ABI_VERSION = 0 EVM_ABI_VERSION = 0
}; };
/// Opaque struct representing execution environment managed by the host /// Opaque structure representing execution context managed by the Host.
/// application. ///
struct evm_env; /// The Host MAY pass the pointer to the Host execution context to
/// ::evm_execute_fn. The EVM MUST pass the same pointer back to the Host in
/// every callback function.
struct evm_context {};
/// Big-endian 256-bit integer. /// Big-endian 256-bit integer.
/// ///
@ -87,10 +97,10 @@ struct evm_tx_context {
}; };
typedef void (*evm_get_tx_context_fn)(struct evm_tx_context* result, typedef void (*evm_get_tx_context_fn)(struct evm_tx_context* result,
struct evm_env* env); struct evm_context* context);
typedef void (*evm_get_block_hash_fn)(struct evm_uint256be* result, typedef void (*evm_get_block_hash_fn)(struct evm_uint256be* result,
struct evm_env* env, struct evm_context* context,
int64_t number); int64_t number);
/// The execution result code. /// The execution result code.
@ -187,11 +197,11 @@ struct evm_result {
/// ///
/// This callback function is used by the EVM to check if /// This callback function is used by the EVM to check if
/// there exists an account at given address. /// there exists an account at given address.
/// @param env Pointer to execution environment managed by the host /// @param context The pointer to the Host execution context.
/// application. /// @see ::evm_context.
/// @param address The address of the account the query is about. /// @param address The address of the account the query is about.
/// @return 1 if exists, 0 otherwise. /// @return 1 if exists, 0 otherwise.
typedef int (*evm_account_exists_fn)(struct evm_env* env, typedef int (*evm_account_exists_fn)(struct evm_context* context,
const struct evm_uint160be* address); const struct evm_uint160be* address);
/// Get storage callback function. /// Get storage callback function.
@ -199,12 +209,12 @@ typedef int (*evm_account_exists_fn)(struct evm_env* env,
/// This callback function is used by an EVM to query the given contract /// This callback function is used by an EVM to query the given contract
/// storage entry. /// storage entry.
/// @param[out] result The returned storage value. /// @param[out] result The returned storage value.
/// @param env Pointer to execution environment managed by the host /// @param context The pointer to the Host execution context.
/// application. /// @see ::evm_context.
/// @param address The address of the contract. /// @param address The address of the contract.
/// @param key The index of the storage entry. /// @param key The index of the storage entry.
typedef void (*evm_get_storage_fn)(struct evm_uint256be* result, typedef void (*evm_get_storage_fn)(struct evm_uint256be* result,
struct evm_env* env, struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const struct evm_uint256be* key); const struct evm_uint256be* key);
@ -212,12 +222,12 @@ typedef void (*evm_get_storage_fn)(struct evm_uint256be* result,
/// ///
/// This callback function is used by an EVM to update the given contract /// This callback function is used by an EVM to update the given contract
/// storage entry. /// storage entry.
/// @param env Pointer to execution environment managed by the host /// @param context The pointer to the Host execution context.
/// application. /// @see ::evm_context.
/// @param address The address of the contract. /// @param address The address of the contract.
/// @param key The index of the storage entry. /// @param key The index of the storage entry.
/// @param value The value to be stored. /// @param value The value to be stored.
typedef void (*evm_set_storage_fn)(struct evm_env* env, typedef void (*evm_set_storage_fn)(struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const struct evm_uint256be* key, const struct evm_uint256be* key,
const struct evm_uint256be* value); const struct evm_uint256be* value);
@ -227,11 +237,11 @@ typedef void (*evm_set_storage_fn)(struct evm_env* env,
/// This callback function is used by an EVM to query the balance of the given /// This callback function is used by an EVM to query the balance of the given
/// address. /// address.
/// @param[out] result The returned balance value. /// @param[out] result The returned balance value.
/// @param env Pointer to execution environment managed by the host /// @param context The pointer to the Host execution context.
/// application. /// @see ::evm_context.
/// @param address The address. /// @param address The address.
typedef void (*evm_get_balance_fn)(struct evm_uint256be* result, typedef void (*evm_get_balance_fn)(struct evm_uint256be* result,
struct evm_env* env, struct evm_context* context,
const struct evm_uint160be* address); const struct evm_uint160be* address);
/// Get code callback function. /// Get code callback function.
@ -241,22 +251,23 @@ typedef void (*evm_get_balance_fn)(struct evm_uint256be* result,
/// @param[out] result_code The pointer to the contract code. This argument is /// @param[out] result_code The pointer to the contract code. This argument is
/// optional. If NULL is provided, the host MUST only /// optional. If NULL is provided, the host MUST only
/// return the code size. /// return the code size.
/// @param env Pointer to execution context managed by the Host. /// @param context The pointer to the Host execution context.
/// @see ::evm_context.
/// @param address The address of the contract. /// @param address The address of the contract.
/// @return The size of the code. /// @return The size of the code.
typedef size_t (*evm_get_code_fn)(const uint8_t** result_code, typedef size_t (*evm_get_code_fn)(const uint8_t** result_code,
struct evm_env* env, struct evm_context* context,
const struct evm_uint160be* address); const struct evm_uint160be* address);
/// Selfdestruct callback function. /// Selfdestruct callback function.
/// ///
/// This callback function is used by an EVM to SELFDESTRUCT given contract. /// This callback function is used by an EVM to SELFDESTRUCT given contract.
/// @param env The pointer to the execution environment managed by /// @param context The pointer to the Host execution context.
/// the host application. /// @see ::evm_context.
/// @param address The address of the contract to be selfdestructed. /// @param address The address of the contract to be selfdestructed.
/// @param beneficiary The address where the remaining ETH is going to be /// @param beneficiary The address where the remaining ETH is going to be
/// transferred. /// transferred.
typedef void (*evm_selfdestruct_fn)(struct evm_env* env, typedef void (*evm_selfdestruct_fn)(struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const struct evm_uint160be* beneficiary); const struct evm_uint160be* beneficiary);
@ -264,15 +275,15 @@ typedef void (*evm_selfdestruct_fn)(struct evm_env* env,
/// ///
/// This callback function is used by an EVM to inform about a LOG that happened /// This callback function is used by an EVM to inform about a LOG that happened
/// during an EVM bytecode execution. /// during an EVM bytecode execution.
/// @param env The pointer to execution environment managed by /// @param context The pointer to the Host execution context.
/// the host application. /// @see ::evm_context.
/// @param address The address of the contract that generated the log. /// @param address The address of the contract that generated the log.
/// @param data The pointer to unindexed data attached to the log. /// @param data The pointer to unindexed data attached to the log.
/// @param data_size The length of the data. /// @param data_size The length of the data.
/// @param topics The pointer to the array of topics attached to the log. /// @param topics The pointer to the array of topics attached to the log.
/// @param topics_count The number of the topics. Valid values are between /// @param topics_count The number of the topics. Valid values are between
/// 0 and 4 inclusively. /// 0 and 4 inclusively.
typedef void (*evm_log_fn)(struct evm_env* env, typedef void (*evm_log_fn)(struct evm_context* context,
const struct evm_uint160be* address, const struct evm_uint160be* address,
const uint8_t* data, const uint8_t* data,
size_t data_size, size_t data_size,
@ -282,22 +293,19 @@ typedef void (*evm_log_fn)(struct evm_env* env,
/// Pointer to the callback function supporting EVM calls. /// Pointer to the callback function supporting EVM calls.
/// ///
/// @param[out] result Call result. /// @param[out] result Call result.
/// @param env Pointer to execution environment managed by the host /// @param context The pointer to the Host execution context.
/// application. /// @see ::evm_context.
/// @param msg Call parameters. /// @param msg Call parameters.
typedef void (*evm_call_fn)( typedef void (*evm_call_fn)(struct evm_result* result,
struct evm_result* result, struct evm_context* context,
struct evm_env* env, const struct evm_message* msg);
const struct evm_message* msg);
/// EVM Host interface. /// The Host interface.
/// ///
/// The set of all callback functions expected by EVM instances. This is C /// The set of all callback functions expected by EVM instances. This is C
/// realisation of OOP interface (only virtual methods, no data). /// realisation of OOP interface (only virtual methods, no data).
/// Host implementations SHOULD create constant singletons of this (similar /// Host implementations SHOULD create constant singletons of this (similarly
/// to vtables) to lower the maintenance and memory management cost. /// to vtables) to lower the maintenance and memory management cost.
///
/// @todo Merge evm_host with evm_env?
struct evm_host { struct evm_host {
evm_account_exists_fn account_exists; evm_account_exists_fn account_exists;
evm_get_storage_fn get_storage; evm_get_storage_fn get_storage;
@ -346,13 +354,15 @@ typedef int (*evm_set_option_fn)(struct evm_instance* evm,
char const* value); char const* value);
/// EVM compatibility mode aka chain mode. /// EVM revision.
/// The names for the last two hard forks come from Python implementation. ///
enum evm_mode { /// The revision of the EVM specification based on the Ethereum
/// upgrade / hard fork codenames.
enum evm_revision {
EVM_FRONTIER = 0, EVM_FRONTIER = 0,
EVM_HOMESTEAD = 1, EVM_HOMESTEAD = 1,
EVM_ANTI_DOS = 2, EVM_TANGERINE_WHISTLE = 2,
EVM_CLEARING = 3, EVM_SPURIOUS_DRAGON = 3,
EVM_BYZANTIUM = 4, EVM_BYZANTIUM = 4,
EVM_CONSTANTINOPLE = 5, EVM_CONSTANTINOPLE = 5,
}; };
@ -363,9 +373,9 @@ enum evm_mode {
/// All the fun is here. This function actually does something useful. /// All the fun is here. This function actually does something useful.
/// ///
/// @param instance A EVM instance. /// @param instance A EVM instance.
/// @param env A pointer to the execution environment provided by the /// @param context The pointer to the Host execution context to be passed
/// user and passed to callback functions. /// to callback functions. @see ::evm_context.
/// @param mode EVM compatibility mode. /// @param rev Requested EVM specification revision.
/// @param code_hash A hash of the bytecode, usually Keccak. The EVM uses it /// @param code_hash A hash of the bytecode, usually Keccak. The EVM uses it
/// as the code identifier. A EVM implementation is able to /// as the code identifier. A EVM implementation is able to
/// hash the code itself if it requires it, but the host /// hash the code itself if it requires it, but the host
@ -378,8 +388,8 @@ enum evm_mode {
/// @param value Call value. /// @param value Call value.
/// @return All execution results. /// @return All execution results.
typedef struct evm_result (*evm_execute_fn)(struct evm_instance* instance, typedef struct evm_result (*evm_execute_fn)(struct evm_instance* instance,
struct evm_env* env, struct evm_context* context,
enum evm_mode mode, enum evm_revision rev,
const struct evm_message* msg, const struct evm_message* msg,
uint8_t const* code, uint8_t const* code,
size_t code_size); size_t code_size);
@ -401,7 +411,7 @@ enum evm_code_status {
/// Get information the status of the code in the VM. /// Get information the status of the code in the VM.
typedef enum evm_code_status typedef enum evm_code_status
(*evm_get_code_status_fn)(struct evm_instance* instance, (*evm_get_code_status_fn)(struct evm_instance* instance,
enum evm_mode mode, enum evm_revision rev,
uint32_t flags, uint32_t flags,
struct evm_uint256be code_hash); struct evm_uint256be code_hash);
@ -409,7 +419,7 @@ typedef enum evm_code_status
/// to execute the code but allows compilation of the code ahead of time in /// to execute the code but allows compilation of the code ahead of time in
/// JIT-like VMs. /// JIT-like VMs.
typedef void (*evm_prepare_code_fn)(struct evm_instance* instance, typedef void (*evm_prepare_code_fn)(struct evm_instance* instance,
enum evm_mode mode, enum evm_revision rev,
uint32_t flags, uint32_t flags,
struct evm_uint256be code_hash, struct evm_uint256be code_hash,
uint8_t const* code, uint8_t const* code,