mirror of https://github.com/status-im/evmc.git
commit
799d8b4127
|
@ -4,7 +4,7 @@
|
|||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "EVMJIT"
|
||||
PROJECT_NAME = "EVMC"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <evm.h>
|
||||
#include <evmc.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
@ -6,59 +6,59 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/// Prototype from examplevm.c
|
||||
struct evm_instance* examplevm_create(void);
|
||||
struct evmc_instance* examplevm_create(void);
|
||||
|
||||
struct evm_uint256be balance(struct evm_context* context,
|
||||
const struct evm_address* address)
|
||||
struct evmc_uint256be balance(struct evmc_context* context,
|
||||
const struct evmc_address* address)
|
||||
{
|
||||
struct evm_uint256be ret = {.bytes = {1, 2, 3, 4}};
|
||||
struct evmc_uint256be ret = {.bytes = {1, 2, 3, 4}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct evm_address address(struct evm_context* context)
|
||||
struct evmc_address address(struct evmc_context* context)
|
||||
{
|
||||
struct evm_address ret = {.bytes = {1, 2, 3, 4}};
|
||||
struct evmc_address ret = {.bytes = {1, 2, 3, 4}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void print_address(const struct evm_address* address)
|
||||
static void print_address(const struct evmc_address* address)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < sizeof(address->bytes); ++i)
|
||||
printf("%x", address->bytes[i] & 0xff);
|
||||
}
|
||||
|
||||
static int account_exists(struct evm_context* context,
|
||||
const struct evm_address* address) {
|
||||
static int account_exists(struct evmc_context* context,
|
||||
const struct evmc_address* address) {
|
||||
printf("EVM-C: EXISTS @");
|
||||
print_address(address);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void get_storage(struct evm_uint256be* result,
|
||||
struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const struct evm_uint256be* key)
|
||||
static void get_storage(struct evmc_uint256be* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_uint256be* key)
|
||||
{
|
||||
printf("EVM-C: SLOAD @");
|
||||
print_address(address);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void set_storage(struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const struct evm_uint256be* key,
|
||||
const struct evm_uint256be* value)
|
||||
static void set_storage(struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_uint256be* key,
|
||||
const struct evmc_uint256be* value)
|
||||
{
|
||||
printf("EVM-C: SSTORE @");
|
||||
print_address(address);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void get_balance(struct evm_uint256be* result,
|
||||
struct evm_context* context,
|
||||
const struct evm_address* address)
|
||||
static void get_balance(struct evmc_uint256be* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_address* address)
|
||||
{
|
||||
printf("EVM-C: BALANCE @");
|
||||
print_address(address);
|
||||
|
@ -66,7 +66,7 @@ static void get_balance(struct evm_uint256be* result,
|
|||
*result = balance(context, address);
|
||||
}
|
||||
|
||||
static size_t get_code_size(struct evm_context* context, const struct evm_address* address)
|
||||
static size_t get_code_size(struct evmc_context* context, const struct evmc_address* address)
|
||||
{
|
||||
printf("EVM-C: CODESIZE @");
|
||||
print_address(address);
|
||||
|
@ -74,7 +74,7 @@ static size_t get_code_size(struct evm_context* context, const struct evm_addres
|
|||
return 0;
|
||||
}
|
||||
|
||||
static size_t copy_code(struct evm_context* context, const struct evm_address* address,
|
||||
static size_t copy_code(struct evmc_context* context, const struct evmc_address* address,
|
||||
size_t code_offset, uint8_t* buffer_data, size_t buffer_size)
|
||||
{
|
||||
printf("EVM-C: COPYCODE @");
|
||||
|
@ -83,9 +83,9 @@ static size_t copy_code(struct evm_context* context, const struct evm_address* a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void selfdestruct(struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const struct evm_address* beneficiary)
|
||||
static void selfdestruct(struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_address* beneficiary)
|
||||
{
|
||||
printf("EVM-C: SELFDESTRUCT ");
|
||||
print_address(address);
|
||||
|
@ -94,20 +94,20 @@ static void selfdestruct(struct evm_context* context,
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void call(struct evm_result* result,
|
||||
struct evm_context* context,
|
||||
const struct evm_message* msg)
|
||||
static void call(struct evmc_result* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_message* msg)
|
||||
{
|
||||
printf("EVM-C: CALL (depth: %d)\n", msg->depth);
|
||||
result->status_code = EVM_FAILURE;
|
||||
result->status_code = EVMC_FAILURE;
|
||||
}
|
||||
|
||||
static void get_tx_context(struct evm_tx_context* result, struct evm_context* context)
|
||||
static void get_tx_context(struct evmc_tx_context* result, struct evmc_context* context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void get_block_hash(struct evm_uint256be* result, struct evm_context* context,
|
||||
static void get_block_hash(struct evmc_uint256be* result, struct evmc_context* context,
|
||||
int64_t number)
|
||||
{
|
||||
|
||||
|
@ -116,14 +116,14 @@ static void get_block_hash(struct evm_uint256be* result, struct evm_context* con
|
|||
/// EVM log callback.
|
||||
///
|
||||
/// @note The `evm_log` name is used to avoid conflict with `log()` C function.
|
||||
static void evm_log(struct evm_context* context, const struct evm_address* address,
|
||||
static void evm_log(struct evmc_context* context, const struct evmc_address* address,
|
||||
const uint8_t* data, size_t data_size,
|
||||
const struct evm_uint256be topics[], size_t topics_count)
|
||||
const struct evmc_uint256be topics[], size_t topics_count)
|
||||
{
|
||||
printf("EVM-C: LOG%d\n", (int)topics_count);
|
||||
}
|
||||
|
||||
static const struct evm_context_fn_table ctx_fn_table = {
|
||||
static const struct evmc_context_fn_table ctx_fn_table = {
|
||||
account_exists,
|
||||
get_storage,
|
||||
set_storage,
|
||||
|
@ -139,28 +139,28 @@ static const struct evm_context_fn_table ctx_fn_table = {
|
|||
|
||||
/// Example how the API is supposed to be used.
|
||||
int main(int argc, char *argv[]) {
|
||||
struct evm_instance* jit = examplevm_create();
|
||||
if (jit->abi_version != EVM_ABI_VERSION)
|
||||
struct evmc_instance* jit = examplevm_create();
|
||||
if (jit->abi_version != EVMC_ABI_VERSION)
|
||||
return 1; // Incompatible ABI version.
|
||||
|
||||
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,}};
|
||||
struct evmc_uint256be code_hash = {.bytes = {1, 2, 3,}};
|
||||
uint8_t const input[] = "Hello World!";
|
||||
struct evm_uint256be value = {{1, 0,}};
|
||||
struct evm_address addr = {{0, 1, 2,}};
|
||||
struct evmc_uint256be value = {{1, 0,}};
|
||||
struct evmc_address addr = {{0, 1, 2,}};
|
||||
int64_t gas = 200000;
|
||||
|
||||
struct evm_context ctx = {&ctx_fn_table};
|
||||
struct evmc_context ctx = {&ctx_fn_table};
|
||||
|
||||
struct evm_message msg = {addr, addr, value, input, sizeof(input),
|
||||
struct evmc_message msg = {addr, addr, value, input, sizeof(input),
|
||||
code_hash, gas, 0};
|
||||
|
||||
struct evm_result result =
|
||||
jit->execute(jit, &ctx, EVM_HOMESTEAD, &msg, code, code_size);
|
||||
struct evmc_result result =
|
||||
jit->execute(jit, &ctx, EVMC_HOMESTEAD, &msg, code, code_size);
|
||||
|
||||
printf("Execution result:\n");
|
||||
if (result.status_code != EVM_SUCCESS) {
|
||||
if (result.status_code != EVMC_SUCCESS) {
|
||||
printf(" EVM execution failure: %d\n", result.status_code);
|
||||
} else {
|
||||
printf(" Gas used: %" PRId64 "\n", gas - result.gas_left);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <evm.h>
|
||||
#include <evmc.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
@ -7,11 +7,11 @@
|
|||
|
||||
struct examplevm
|
||||
{
|
||||
struct evm_instance instance;
|
||||
struct evmc_instance instance;
|
||||
int verbose;
|
||||
};
|
||||
|
||||
static void evm_destroy(struct evm_instance* evm)
|
||||
static void evmc_destroy(struct evmc_instance* evm)
|
||||
{
|
||||
free(evm);
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ static void evm_destroy(struct evm_instance* evm)
|
|||
/// Example options.
|
||||
///
|
||||
/// VMs are allowed to omit this function implementation.
|
||||
int evm_set_option(struct evm_instance* instance,
|
||||
char const* name,
|
||||
char const* value)
|
||||
int evmc_set_option(struct evmc_instance* instance,
|
||||
char const* name,
|
||||
char const* value)
|
||||
{
|
||||
struct examplevm* vm = (struct examplevm*)instance;
|
||||
if (strcmp(name, "verbose") == 0) {
|
||||
|
@ -35,31 +35,31 @@ int evm_set_option(struct evm_instance* instance,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void evm_release_result(struct evm_result const* result)
|
||||
static void evmc_release_result(struct evmc_result const* result)
|
||||
{
|
||||
(void)result;
|
||||
}
|
||||
|
||||
static void free_result_output_data(struct evm_result const* result)
|
||||
static void free_result_output_data(struct evmc_result const* result)
|
||||
{
|
||||
free((uint8_t*)result->output_data);
|
||||
}
|
||||
|
||||
static struct evm_result execute(struct evm_instance* instance,
|
||||
struct evm_context* context,
|
||||
enum evm_revision rev,
|
||||
const struct evm_message* msg,
|
||||
const uint8_t* code,
|
||||
size_t code_size)
|
||||
static struct evmc_result execute(struct evmc_instance* instance,
|
||||
struct evmc_context* context,
|
||||
enum evmc_revision rev,
|
||||
const struct evmc_message* msg,
|
||||
const uint8_t* code,
|
||||
size_t code_size)
|
||||
{
|
||||
struct evm_result ret = {};
|
||||
struct evmc_result ret = {};
|
||||
if (code_size == 0) {
|
||||
// In case of empty code return a fancy error message.
|
||||
const char* error = rev == EVM_BYZANTIUM ?
|
||||
const char* error = rev == EVMC_BYZANTIUM ?
|
||||
"Welcome to Byzantium!" : "Hello Ethereum!";
|
||||
ret.output_data = (const uint8_t*)error;
|
||||
ret.output_size = strlen(error);
|
||||
ret.status_code = EVM_FAILURE;
|
||||
ret.status_code = EVMC_FAILURE;
|
||||
ret.release = NULL; // We don't need to release the constant messages.
|
||||
return ret;
|
||||
}
|
||||
|
@ -81,11 +81,11 @@ static struct evm_result execute(struct evm_instance* instance,
|
|||
uint8_t* output_data = (uint8_t*)malloc(address_size);
|
||||
if (!output_data) {
|
||||
// malloc failed, report internal error.
|
||||
ret.status_code = EVM_INTERNAL_ERROR;
|
||||
ret.status_code = EVMC_INTERNAL_ERROR;
|
||||
return ret;
|
||||
}
|
||||
memcpy(output_data, &msg->destination, address_size);
|
||||
ret.status_code = EVM_SUCCESS;
|
||||
ret.status_code = EVMC_SUCCESS;
|
||||
ret.output_data = output_data;
|
||||
ret.output_size = address_size;
|
||||
ret.release = &free_result_output_data;
|
||||
|
@ -93,17 +93,17 @@ static struct evm_result execute(struct evm_instance* instance,
|
|||
}
|
||||
else if (code_size == strlen(counter) &&
|
||||
strncmp((const char*)code, counter, code_size) == 0) {
|
||||
struct evm_uint256be value;
|
||||
const struct evm_uint256be index = {{0,}};
|
||||
struct evmc_uint256be value;
|
||||
const struct evmc_uint256be index = {{0,}};
|
||||
context->fn_table->get_storage(&value, context, &msg->destination, &index);
|
||||
value.bytes[31] += 1;
|
||||
context->fn_table->set_storage(context, &msg->destination, &index, &value);
|
||||
ret.status_code = EVM_SUCCESS;
|
||||
ret.status_code = EVMC_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.release = evm_release_result;
|
||||
ret.status_code = EVM_FAILURE;
|
||||
ret.release = evmc_release_result;
|
||||
ret.status_code = EVMC_FAILURE;
|
||||
ret.gas_left = 0;
|
||||
|
||||
if (vm->verbose)
|
||||
|
@ -112,16 +112,16 @@ static struct evm_result execute(struct evm_instance* instance,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct evm_instance* examplevm_create()
|
||||
struct evmc_instance* examplevm_create()
|
||||
{
|
||||
struct evm_instance init = {
|
||||
.abi_version = EVM_ABI_VERSION,
|
||||
.destroy = evm_destroy,
|
||||
struct evmc_instance init = {
|
||||
.abi_version = EVMC_ABI_VERSION,
|
||||
.destroy = evmc_destroy,
|
||||
.execute = execute,
|
||||
.set_option = evm_set_option
|
||||
.set_option = evmc_set_option
|
||||
};
|
||||
struct examplevm* vm = calloc(1, sizeof(struct examplevm));
|
||||
struct evm_instance* interface = &vm->instance;
|
||||
struct evmc_instance* interface = &vm->instance;
|
||||
memcpy(interface, &init, sizeof(init));
|
||||
return interface;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
///
|
||||
/// @defgroup EVMC EVM-C
|
||||
/// @{
|
||||
#ifndef EVM_H
|
||||
#define EVM_H
|
||||
#ifndef EVMC_H
|
||||
#define EVMC_H
|
||||
|
||||
#include <stdint.h> // Definition of int64_t, uint64_t.
|
||||
#include <stddef.h> // Definition of size_t.
|
||||
|
@ -33,7 +33,7 @@ extern "C" {
|
|||
|
||||
enum {
|
||||
/// The EVM-C ABI version number of the interface declared in this file.
|
||||
EVM_ABI_VERSION = 0
|
||||
EVMC_ABI_VERSION = 0
|
||||
};
|
||||
|
||||
/// Big-endian 256-bit integer.
|
||||
|
@ -42,38 +42,38 @@ enum {
|
|||
/// the most significant byte, bytes[31] is the least significant byte.
|
||||
/// This type is used to transfer to/from the VM values interpreted by the user
|
||||
/// as both 256-bit integers and 256-bit hashes.
|
||||
struct evm_uint256be {
|
||||
struct evmc_uint256be {
|
||||
/// The 32 bytes of the big-endian integer or hash.
|
||||
uint8_t bytes[32];
|
||||
};
|
||||
|
||||
/// Big-endian 160-bit hash suitable for keeping an Ethereum address.
|
||||
struct evm_address {
|
||||
struct evmc_address {
|
||||
/// The 20 bytes of the hash.
|
||||
uint8_t bytes[20];
|
||||
};
|
||||
|
||||
/// The kind of call-like instruction.
|
||||
enum evm_call_kind {
|
||||
EVM_CALL = 0, ///< Request CALL.
|
||||
EVM_DELEGATECALL = 1, ///< Request DELEGATECALL. The value param ignored.
|
||||
EVM_CALLCODE = 2, ///< Request CALLCODE.
|
||||
EVM_CREATE = 3, ///< Request CREATE. Semantic of some params changes.
|
||||
enum evmc_call_kind {
|
||||
EVMC_CALL = 0, ///< Request CALL.
|
||||
EVMC_DELEGATECALL = 1, ///< Request DELEGATECALL. The value param ignored.
|
||||
EVMC_CALLCODE = 2, ///< Request CALLCODE.
|
||||
EVMC_CREATE = 3, ///< Request CREATE. Semantic of some params changes.
|
||||
};
|
||||
|
||||
/// The flags for ::evm_message.
|
||||
enum evm_flags {
|
||||
EVM_STATIC = 1 ///< Static call mode.
|
||||
/// The flags for ::evmc_message.
|
||||
enum evmc_flags {
|
||||
EVMC_STATIC = 1 ///< Static call mode.
|
||||
};
|
||||
|
||||
/// The message describing an EVM call,
|
||||
/// including a zero-depth calls from a transaction origin.
|
||||
struct evm_message {
|
||||
struct evm_address destination; ///< The destination of the message.
|
||||
struct evm_address sender; ///< The sender of the message.
|
||||
struct evmc_message {
|
||||
struct evmc_address destination; ///< The destination of the message.
|
||||
struct evmc_address sender; ///< The sender of the message.
|
||||
|
||||
/// The amount of Ether transferred with the message.
|
||||
struct evm_uint256be value;
|
||||
struct evmc_uint256be value;
|
||||
|
||||
/// The message input data.
|
||||
///
|
||||
|
@ -87,32 +87,32 @@ struct evm_message {
|
|||
|
||||
/// The optional hash of the code of the destination account.
|
||||
/// The null hash MUST be used when not specified.
|
||||
struct evm_uint256be code_hash;
|
||||
struct evmc_uint256be code_hash;
|
||||
|
||||
int64_t gas; ///< The amount of gas for message execution.
|
||||
int32_t depth; ///< The call depth.
|
||||
|
||||
/// The kind of the call. For zero-depth calls ::EVM_CALL SHOULD be used.
|
||||
enum evm_call_kind kind;
|
||||
/// The kind of the call. For zero-depth calls ::EVMC_CALL SHOULD be used.
|
||||
enum evmc_call_kind kind;
|
||||
|
||||
/// Additional flags modifying the call execution behavior.
|
||||
/// In the current version the only valid values are ::EVM_STATIC or 0.
|
||||
/// In the current version the only valid values are ::EVMC_STATIC or 0.
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
|
||||
/// The transaction and block data for execution.
|
||||
struct evm_tx_context {
|
||||
struct evm_uint256be tx_gas_price; ///< The transaction gas price.
|
||||
struct evm_address tx_origin; ///< The transaction origin account.
|
||||
struct evm_address block_coinbase; ///< The miner of the block.
|
||||
struct evmc_tx_context {
|
||||
struct evmc_uint256be tx_gas_price; ///< The transaction gas price.
|
||||
struct evmc_address tx_origin; ///< The transaction origin account.
|
||||
struct evmc_address block_coinbase; ///< The miner of the block.
|
||||
int64_t block_number; ///< The block number.
|
||||
int64_t block_timestamp; ///< The block timestamp.
|
||||
int64_t block_gas_limit; ///< The block gas limit.
|
||||
struct evm_uint256be block_difficulty; ///< The block difficulty.
|
||||
struct evmc_uint256be block_difficulty; ///< The block difficulty.
|
||||
};
|
||||
|
||||
struct evm_context;
|
||||
struct evmc_context;
|
||||
|
||||
/// Get transaction context callback function.
|
||||
///
|
||||
|
@ -120,11 +120,11 @@ struct evm_context;
|
|||
/// block context.
|
||||
///
|
||||
/// @param[out] result The returned transaction context.
|
||||
/// @see ::evm_tx_context.
|
||||
/// @see ::evmc_tx_context.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
typedef void (*evm_get_tx_context_fn)(struct evm_tx_context* result,
|
||||
struct evm_context* context);
|
||||
/// @see ::evmc_context.
|
||||
typedef void (*evmc_get_tx_context_fn)(struct evmc_tx_context* result,
|
||||
struct evmc_context* context);
|
||||
|
||||
/// Get block hash callback function..
|
||||
///
|
||||
|
@ -135,52 +135,52 @@ typedef void (*evm_get_tx_context_fn)(struct evm_tx_context* result,
|
|||
/// @param context The pointer to the Host execution context.
|
||||
/// @param number The block number. Must be a value between
|
||||
// (and including) 0 and 255.
|
||||
typedef void (*evm_get_block_hash_fn)(struct evm_uint256be* result,
|
||||
struct evm_context* context,
|
||||
int64_t number);
|
||||
typedef void (*evmc_get_block_hash_fn)(struct evmc_uint256be* result,
|
||||
struct evmc_context* context,
|
||||
int64_t number);
|
||||
|
||||
/// The execution status code.
|
||||
enum evm_status_code {
|
||||
EVM_SUCCESS = 0, ///< Execution finished with success.
|
||||
EVM_FAILURE = 1, ///< Generic execution failure.
|
||||
EVM_OUT_OF_GAS = 2,
|
||||
EVM_UNDEFINED_INSTRUCTION = 3, ///< Unknown instruction encountered by the VM.
|
||||
EVM_BAD_JUMP_DESTINATION = 4,
|
||||
EVM_STACK_OVERFLOW = 5,
|
||||
EVM_STACK_UNDERFLOW = 6,
|
||||
EVM_REVERT = 7, ///< Execution terminated with REVERT opcode.
|
||||
enum evmc_status_code {
|
||||
EVMC_SUCCESS = 0, ///< Execution finished with success.
|
||||
EVMC_FAILURE = 1, ///< Generic execution failure.
|
||||
EVMC_OUT_OF_GAS = 2,
|
||||
EVMC_UNDEFINED_INSTRUCTION = 3, ///< Unknown instruction encountered by the VM.
|
||||
EVMC_BAD_JUMP_DESTINATION = 4,
|
||||
EVMC_STACK_OVERFLOW = 5,
|
||||
EVMC_STACK_UNDERFLOW = 6,
|
||||
EVMC_REVERT = 7, ///< Execution terminated with REVERT opcode.
|
||||
|
||||
/// Tried to execute an operation which is restricted in static mode.
|
||||
///
|
||||
/// @todo Avoid _ERROR suffix that suggests fatal error.
|
||||
EVM_STATIC_MODE_ERROR = 8,
|
||||
EVMC_STATIC_MODE_ERROR = 8,
|
||||
|
||||
/// The dedicated INVALID instruction was hit.
|
||||
EVM_INVALID_INSTRUCTION = 9,
|
||||
EVMC_INVALID_INSTRUCTION = 9,
|
||||
|
||||
/// Tried to read outside memory bounds.
|
||||
///
|
||||
/// An example is RETURNDATACOPY reading past the available buffer.
|
||||
EVM_INVALID_MEMORY_ACCESS = 10,
|
||||
EVMC_INVALID_MEMORY_ACCESS = 10,
|
||||
|
||||
/// The EVM rejected the execution of the given code or message.
|
||||
///
|
||||
/// This error SHOULD be used to signal that the EVM is not able to or
|
||||
/// willing to execute the given code type or message.
|
||||
/// If an EVM returns the ::EVM_REJECTED status code,
|
||||
/// If an EVM returns the ::EVMC_REJECTED status code,
|
||||
/// the Client MAY try to execute it in other EVM implementation.
|
||||
/// For example, the Client tries running a code in the EVM 1.5. If the
|
||||
/// code is not supported there, the execution falls back to the EVM 1.0.
|
||||
EVM_REJECTED = -1,
|
||||
EVMC_REJECTED = -1,
|
||||
|
||||
/// EVM implementation internal error.
|
||||
///
|
||||
/// @todo We should rethink reporting internal errors. One of the options
|
||||
/// it to allow using any negative value to represent internal errors.
|
||||
EVM_INTERNAL_ERROR = -2,
|
||||
EVMC_INTERNAL_ERROR = -2,
|
||||
};
|
||||
|
||||
struct evm_result; ///< Forward declaration.
|
||||
struct evmc_result; ///< Forward declaration.
|
||||
|
||||
/// Releases resources assigned to an execution result.
|
||||
///
|
||||
|
@ -190,26 +190,26 @@ struct evm_result; ///< Forward declaration.
|
|||
/// @param result The execution result which resource are to be released. The
|
||||
/// result itself it not modified by this function, but becomes
|
||||
/// invalid and user should discard it as well.
|
||||
typedef void (*evm_release_result_fn)(const struct evm_result* result);
|
||||
typedef void (*evmc_release_result_fn)(const struct evmc_result* result);
|
||||
|
||||
/// The EVM code execution result.
|
||||
struct evm_result {
|
||||
struct evmc_result {
|
||||
/// The execution status code.
|
||||
enum evm_status_code status_code;
|
||||
enum evmc_status_code status_code;
|
||||
|
||||
/// The amount of gas left after the execution.
|
||||
///
|
||||
/// If evm_result::code is not ::EVM_SUCCESS nor ::EVM_REVERT
|
||||
/// If evmc_result::code is not ::EVMC_SUCCESS nor ::EVMC_REVERT
|
||||
/// the value MUST be 0.
|
||||
int64_t gas_left;
|
||||
|
||||
/// The reference to output data.
|
||||
///
|
||||
/// The output contains data coming from RETURN opcode (iff evm_result::code
|
||||
/// field is ::EVM_SUCCESS) or from REVERT opcode.
|
||||
/// The output contains data coming from RETURN opcode (iff evmc_result::code
|
||||
/// field is ::EVMC_SUCCESS) or from REVERT opcode.
|
||||
///
|
||||
/// The memory containing the output data is owned by EVM and has to be
|
||||
/// freed with evm_result::release().
|
||||
/// freed with evmc_result::release().
|
||||
///
|
||||
/// This MAY be NULL.
|
||||
const uint8_t* output_data;
|
||||
|
@ -230,7 +230,7 @@ struct evm_result {
|
|||
///
|
||||
/// The suggested code pattern for releasing EVM results:
|
||||
/// @code
|
||||
/// struct evm_result result = ...;
|
||||
/// struct evmc_result result = ...;
|
||||
/// if (result.release)
|
||||
/// result.release(&result);
|
||||
/// @endcode
|
||||
|
@ -238,57 +238,57 @@ struct evm_result {
|
|||
/// @note
|
||||
/// It works similarly to C++ virtual destructor. Attaching the release
|
||||
/// function to the result itself allows EVM composition.
|
||||
evm_release_result_fn release;
|
||||
evmc_release_result_fn release;
|
||||
|
||||
/// The address of the contract created by CREATE opcode.
|
||||
///
|
||||
/// This field has valid value only if the result describes successful
|
||||
/// CREATE (evm_result::status_code is ::EVM_SUCCESS).
|
||||
struct evm_address create_address;
|
||||
/// CREATE (evmc_result::status_code is ::EVMC_SUCCESS).
|
||||
struct evmc_address create_address;
|
||||
|
||||
/// Reserved data that MAY be used by a evm_result object creator.
|
||||
/// Reserved data that MAY be used by a evmc_result object creator.
|
||||
///
|
||||
/// This reserved 4 bytes together with 20 bytes from create_address form
|
||||
/// 24 bytes of memory called "optional data" within evm_result struct
|
||||
/// to be optionally used by the evm_result object creator.
|
||||
/// 24 bytes of memory called "optional data" within evmc_result struct
|
||||
/// to be optionally used by the evmc_result object creator.
|
||||
///
|
||||
/// @see evm_result_optional_data, evm_get_optional_data().
|
||||
/// @see evmc_result_optional_data, evmc_get_optional_data().
|
||||
///
|
||||
/// Also extends the size of the evm_result to 64 bytes (full cache line).
|
||||
/// Also extends the size of the evmc_result to 64 bytes (full cache line).
|
||||
uint8_t padding[4];
|
||||
};
|
||||
|
||||
|
||||
/// The union representing evm_result "optional data".
|
||||
/// The union representing evmc_result "optional data".
|
||||
///
|
||||
/// The evm_result struct contains 24 bytes of optional data that can be
|
||||
/// The evmc_result struct contains 24 bytes of optional data that can be
|
||||
/// reused by the obejct creator if the object does not contain
|
||||
/// evm_result::create_address.
|
||||
/// evmc_result::create_address.
|
||||
///
|
||||
/// An EVM implementation MAY use this memory to keep additional data
|
||||
/// when returning result from ::evm_execute_fn.
|
||||
/// when returning result from ::evmc_execute_fn.
|
||||
/// The host application MAY use this memory to keep additional data
|
||||
/// when returning result of performed calls from ::evm_call_fn.
|
||||
/// when returning result of performed calls from ::evmc_call_fn.
|
||||
///
|
||||
/// @see evm_get_optional_data(), evm_get_const_optional_data().
|
||||
union evm_result_optional_data
|
||||
/// @see evmc_get_optional_data(), evmc_get_const_optional_data().
|
||||
union evmc_result_optional_data
|
||||
{
|
||||
uint8_t bytes[24];
|
||||
void* pointer;
|
||||
};
|
||||
|
||||
/// Provides read-write access to evm_result "optional data".
|
||||
static inline union evm_result_optional_data* evm_get_optional_data(
|
||||
struct evm_result* result)
|
||||
/// Provides read-write access to evmc_result "optional data".
|
||||
static inline union evmc_result_optional_data* evmc_get_optional_data(
|
||||
struct evmc_result* result)
|
||||
{
|
||||
return (union evm_result_optional_data*) &result->create_address;
|
||||
return (union evmc_result_optional_data*) &result->create_address;
|
||||
}
|
||||
|
||||
/// Provides read-only access to evm_result "optional data".
|
||||
static inline const union evm_result_optional_data* evm_get_const_optional_data(
|
||||
const struct evm_result* result)
|
||||
/// Provides read-only access to evmc_result "optional data".
|
||||
static inline const union evmc_result_optional_data* evmc_get_const_optional_data(
|
||||
const struct evmc_result* result)
|
||||
{
|
||||
return (const union evm_result_optional_data*) &result->create_address;
|
||||
return (const union evmc_result_optional_data*) &result->create_address;
|
||||
}
|
||||
|
||||
|
||||
|
@ -297,11 +297,11 @@ static inline const union evm_result_optional_data* evm_get_const_optional_data(
|
|||
/// This callback function is used by the EVM to check if
|
||||
/// there exists an account at given address.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address of the account the query is about.
|
||||
/// @return 1 if exists, 0 otherwise.
|
||||
typedef int (*evm_account_exists_fn)(struct evm_context* context,
|
||||
const struct evm_address* address);
|
||||
typedef int (*evmc_account_exists_fn)(struct evmc_context* context,
|
||||
const struct evmc_address* address);
|
||||
|
||||
/// Get storage callback function.
|
||||
///
|
||||
|
@ -309,27 +309,27 @@ typedef int (*evm_account_exists_fn)(struct evm_context* context,
|
|||
/// storage entry.
|
||||
/// @param[out] result The returned storage value.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address of the contract.
|
||||
/// @param key The index of the storage entry.
|
||||
typedef void (*evm_get_storage_fn)(struct evm_uint256be* result,
|
||||
struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const struct evm_uint256be* key);
|
||||
typedef void (*evmc_get_storage_fn)(struct evmc_uint256be* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_uint256be* key);
|
||||
|
||||
/// Set storage callback function.
|
||||
///
|
||||
/// This callback function is used by an EVM to update the given contract
|
||||
/// storage entry.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address of the contract.
|
||||
/// @param key The index of the storage entry.
|
||||
/// @param value The value to be stored.
|
||||
typedef void (*evm_set_storage_fn)(struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const struct evm_uint256be* key,
|
||||
const struct evm_uint256be* value);
|
||||
typedef void (*evmc_set_storage_fn)(struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_uint256be* key,
|
||||
const struct evmc_uint256be* value);
|
||||
|
||||
/// Get balance callback function.
|
||||
///
|
||||
|
@ -337,19 +337,19 @@ typedef void (*evm_set_storage_fn)(struct evm_context* context,
|
|||
/// address.
|
||||
/// @param[out] result The returned balance value.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address.
|
||||
typedef void (*evm_get_balance_fn)(struct evm_uint256be* result,
|
||||
struct evm_context* context,
|
||||
const struct evm_address* address);
|
||||
typedef void (*evmc_get_balance_fn)(struct evmc_uint256be* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_address* address);
|
||||
|
||||
/// Get code size callback function.
|
||||
///
|
||||
/// This callback function is used by an EVM to get the size of the code stored
|
||||
/// in the account at the given address. For accounts not having a code, this
|
||||
/// function returns 0.
|
||||
typedef size_t (*evm_get_code_size_fn)(struct evm_context* context,
|
||||
const struct evm_address* address);
|
||||
typedef size_t (*evmc_get_code_size_fn)(struct evmc_context* context,
|
||||
const struct evmc_address* address);
|
||||
|
||||
/// Copy code callback function.
|
||||
///
|
||||
|
@ -360,18 +360,18 @@ typedef size_t (*evm_get_code_size_fn)(struct evm_context* context,
|
|||
/// the code, whichever is smaller.
|
||||
///
|
||||
/// @param context The pointer to the Client execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address of the account.
|
||||
/// @param code_offset The offset of the code to copy.
|
||||
/// @param buffer_data The pointer to the memory buffer allocated by the EVM
|
||||
/// to store a copy of the requested code.
|
||||
/// @param buffer_size The size of the memory buffer.
|
||||
/// @return The number of bytes copied to the buffer by the Client.
|
||||
typedef size_t (*evm_copy_code_fn)(struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
size_t code_offset,
|
||||
uint8_t* buffer_data,
|
||||
size_t buffer_size);
|
||||
typedef size_t (*evmc_copy_code_fn)(struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
size_t code_offset,
|
||||
uint8_t* buffer_data,
|
||||
size_t buffer_size);
|
||||
|
||||
/// Selfdestruct callback function.
|
||||
///
|
||||
|
@ -379,32 +379,32 @@ typedef size_t (*evm_copy_code_fn)(struct evm_context* context,
|
|||
/// The execution of the contract will not be stopped, that is up to the EVM.
|
||||
///
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address of the contract to be selfdestructed.
|
||||
/// @param beneficiary The address where the remaining ETH is going to be
|
||||
/// transferred.
|
||||
typedef void (*evm_selfdestruct_fn)(struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const struct evm_address* beneficiary);
|
||||
typedef void (*evmc_selfdestruct_fn)(struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_address* beneficiary);
|
||||
|
||||
/// Log callback function.
|
||||
///
|
||||
/// This callback function is used by an EVM to inform about a LOG that happened
|
||||
/// during an EVM bytecode execution.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @see ::evmc_context.
|
||||
/// @param address The address of the contract that generated the log.
|
||||
/// @param data The pointer to unindexed data attached to the log.
|
||||
/// @param data_size The length of the data.
|
||||
/// @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
|
||||
/// 0 and 4 inclusively.
|
||||
typedef void (*evm_emit_log_fn)(struct evm_context* context,
|
||||
const struct evm_address* address,
|
||||
const uint8_t* data,
|
||||
size_t data_size,
|
||||
const struct evm_uint256be topics[],
|
||||
size_t topics_count);
|
||||
typedef void (*evmc_emit_log_fn)(struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const uint8_t* data,
|
||||
size_t data_size,
|
||||
const struct evmc_uint256be topics[],
|
||||
size_t topics_count);
|
||||
|
||||
/// Pointer to the callback function supporting EVM calls.
|
||||
///
|
||||
|
@ -412,11 +412,11 @@ typedef void (*evm_emit_log_fn)(struct evm_context* context,
|
|||
/// initialized by the EVM, the Client MUST correctly
|
||||
/// initialize all expected fields of the structure.
|
||||
/// @param context The pointer to the Host execution context.
|
||||
/// @see ::evm_context.
|
||||
/// @param msg Call parameters. @see ::evm_message.
|
||||
typedef void (*evm_call_fn)(struct evm_result* result,
|
||||
struct evm_context* context,
|
||||
const struct evm_message* msg);
|
||||
/// @see ::evmc_context.
|
||||
/// @param msg Call parameters. @see ::evmc_message.
|
||||
typedef void (*evmc_call_fn)(struct evmc_result* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_message* msg);
|
||||
|
||||
/// The context interface.
|
||||
///
|
||||
|
@ -424,42 +424,42 @@ typedef void (*evm_call_fn)(struct evm_result* result,
|
|||
/// realisation of vtable for OOP interface (only virtual methods, no data).
|
||||
/// Host implementations SHOULD create constant singletons of this (similarly
|
||||
/// to vtables) to lower the maintenance and memory management cost.
|
||||
struct evm_context_fn_table {
|
||||
evm_account_exists_fn account_exists;
|
||||
evm_get_storage_fn get_storage;
|
||||
evm_set_storage_fn set_storage;
|
||||
evm_get_balance_fn get_balance;
|
||||
evm_get_code_size_fn get_code_size;
|
||||
evm_copy_code_fn copy_code;
|
||||
evm_selfdestruct_fn selfdestruct;
|
||||
evm_call_fn call;
|
||||
evm_get_tx_context_fn get_tx_context;
|
||||
evm_get_block_hash_fn get_block_hash;
|
||||
evm_emit_log_fn emit_log;
|
||||
struct evmc_context_fn_table {
|
||||
evmc_account_exists_fn account_exists;
|
||||
evmc_get_storage_fn get_storage;
|
||||
evmc_set_storage_fn set_storage;
|
||||
evmc_get_balance_fn get_balance;
|
||||
evmc_get_code_size_fn get_code_size;
|
||||
evmc_copy_code_fn copy_code;
|
||||
evmc_selfdestruct_fn selfdestruct;
|
||||
evmc_call_fn call;
|
||||
evmc_get_tx_context_fn get_tx_context;
|
||||
evmc_get_block_hash_fn get_block_hash;
|
||||
evmc_emit_log_fn emit_log;
|
||||
};
|
||||
|
||||
|
||||
/// Execution context managed by the Host.
|
||||
///
|
||||
/// The Host MUST pass the pointer to the execution context to
|
||||
/// ::evm_execute_fn. The EVM MUST pass the same pointer back to the Host in
|
||||
/// ::evmc_execute_fn. The EVM MUST pass the same pointer back to the Host in
|
||||
/// every callback function.
|
||||
/// The context MUST contain at least the function table defining the context
|
||||
/// callback interface.
|
||||
/// Optionally, The Host MAY include in the context additional data.
|
||||
struct evm_context {
|
||||
struct evmc_context {
|
||||
|
||||
/// Function table defining the context interface (vtable).
|
||||
const struct evm_context_fn_table* fn_table;
|
||||
const struct evmc_context_fn_table* fn_table;
|
||||
};
|
||||
|
||||
|
||||
struct evm_instance; ///< Forward declaration.
|
||||
struct evmc_instance; ///< Forward declaration.
|
||||
|
||||
/// Destroys the EVM instance.
|
||||
///
|
||||
/// @param evm The EVM instance to be destroyed.
|
||||
typedef void (*evm_destroy_fn)(struct evm_instance* evm);
|
||||
typedef void (*evmc_destroy_fn)(struct evmc_instance* evm);
|
||||
|
||||
|
||||
/// Configures the EVM instance.
|
||||
|
@ -473,22 +473,22 @@ typedef void (*evm_destroy_fn)(struct evm_instance* evm);
|
|||
/// @param name The option name. NULL-terminated string. Cannot be NULL.
|
||||
/// @param value The new option value. NULL-terminated string. Cannot be NULL.
|
||||
/// @return 1 if the option set successfully, 0 otherwise.
|
||||
typedef int (*evm_set_option_fn)(struct evm_instance* evm,
|
||||
char const* name,
|
||||
char const* value);
|
||||
typedef int (*evmc_set_option_fn)(struct evmc_instance* evm,
|
||||
char const* name,
|
||||
char const* value);
|
||||
|
||||
|
||||
/// EVM revision.
|
||||
///
|
||||
/// The revision of the EVM specification based on the Ethereum
|
||||
/// upgrade / hard fork codenames.
|
||||
enum evm_revision {
|
||||
EVM_FRONTIER = 0,
|
||||
EVM_HOMESTEAD = 1,
|
||||
EVM_TANGERINE_WHISTLE = 2,
|
||||
EVM_SPURIOUS_DRAGON = 3,
|
||||
EVM_BYZANTIUM = 4,
|
||||
EVM_CONSTANTINOPLE = 5,
|
||||
enum evmc_revision {
|
||||
EVMC_FRONTIER = 0,
|
||||
EVMC_HOMESTEAD = 1,
|
||||
EVMC_TANGERINE_WHISTLE = 2,
|
||||
EVMC_SPURIOUS_DRAGON = 3,
|
||||
EVMC_BYZANTIUM = 4,
|
||||
EVMC_CONSTANTINOPLE = 5,
|
||||
};
|
||||
|
||||
|
||||
|
@ -498,43 +498,43 @@ enum evm_revision {
|
|||
///
|
||||
/// @param instance A EVM instance.
|
||||
/// @param context The pointer to the Host execution context to be passed
|
||||
/// to callback functions. @see ::evm_context.
|
||||
/// to callback functions. @see ::evmc_context.
|
||||
/// @param rev Requested EVM specification revision.
|
||||
/// @param msg Call parameters. @see ::evm_message.
|
||||
/// @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 evm_result (*evm_execute_fn)(struct evm_instance* instance,
|
||||
struct evm_context* context,
|
||||
enum evm_revision rev,
|
||||
const struct evm_message* msg,
|
||||
uint8_t const* code,
|
||||
size_t code_size);
|
||||
typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance,
|
||||
struct evmc_context* context,
|
||||
enum evmc_revision rev,
|
||||
const struct evmc_message* msg,
|
||||
uint8_t const* code,
|
||||
size_t code_size);
|
||||
|
||||
|
||||
/// The EVM instance.
|
||||
///
|
||||
/// Defines the base struct of the EVM implementation.
|
||||
struct evm_instance {
|
||||
struct evmc_instance {
|
||||
|
||||
/// EVM-C ABI version implemented by the EVM instance.
|
||||
///
|
||||
/// For future use to detect ABI incompatibilities. The EVM-C ABI version
|
||||
/// represented by this file is in ::EVM_ABI_VERSION.
|
||||
/// represented by this file is in ::EVMC_ABI_VERSION.
|
||||
///
|
||||
/// @todo Consider removing this field.
|
||||
const int abi_version;
|
||||
|
||||
/// Pointer to function destroying the EVM instance.
|
||||
evm_destroy_fn destroy;
|
||||
evmc_destroy_fn destroy;
|
||||
|
||||
/// Pointer to function executing a code by the EVM instance.
|
||||
evm_execute_fn execute;
|
||||
evmc_execute_fn execute;
|
||||
|
||||
/// Optional pointer to function modifying VM's options.
|
||||
///
|
||||
/// If the VM does not support this feature the pointer can be NULL.
|
||||
evm_set_option_fn set_option;
|
||||
evmc_set_option_fn set_option;
|
||||
};
|
||||
|
||||
// END Python CFFI declarations
|
||||
|
@ -546,12 +546,12 @@ struct evm_instance {
|
|||
///
|
||||
/// @return EVM instance or NULL indicating instance creation failure.
|
||||
///
|
||||
/// struct evm_instance* examplevm_create(void);
|
||||
/// struct evmc_instance* examplevm_create(void);
|
||||
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVM_H
|
||||
#endif // EVMC_H
|
||||
/// @}
|
Loading…
Reference in New Issue