From a54ce7f361bf3300799ef93c529f907c9c67e351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 18 Oct 2018 18:32:19 +0200 Subject: [PATCH] vendor: Upgrade EVMC to version 6.0.0 --- .../ethereum/evmc/bindings/go/evmc/evmc.go | 85 +++-- .../ethereum/evmc/bindings/go/evmc/evmc.h | 337 ++++++++++-------- .../ethereum/evmc/bindings/go/evmc/helpers.h | 21 +- .../ethereum/evmc/bindings/go/evmc/host.c | 86 ++++- .../ethereum/evmc/bindings/go/evmc/host.go | 63 ++-- .../ethereum/evmc/bindings/go/evmc/loader.c | 32 +- .../ethereum/evmc/bindings/go/evmc/loader.h | 15 +- vendor/vendor.json | 10 +- 8 files changed, 401 insertions(+), 248 deletions(-) diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go index 6379c15aba..8039490c17 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go @@ -15,9 +15,9 @@ package evmc #include #include -static inline int set_option(struct evmc_instance* instance, char* name, char* value) +static inline enum evmc_set_option_result set_option(struct evmc_instance* instance, char* name, char* value) { - int ret = evmc_set_option(instance, name, value); + enum evmc_set_option_result ret = evmc_set_option(instance, name, value); free(name); free(value); return ret; @@ -29,29 +29,29 @@ struct extended_context int64_t index; }; -extern const struct evmc_context_fn_table evmc_go_fn_table; +extern const struct evmc_host_interface evmc_go_host; -static struct evmc_result execute_wrapper(struct evmc_instance* instance, int64_t context_index, enum evmc_revision rev, - const struct evmc_address* destination, const struct evmc_address* sender, const struct evmc_uint256be* value, - const uint8_t* input_data, size_t input_size, const struct evmc_uint256be* code_hash, int64_t gas, - int32_t depth, enum evmc_call_kind kind, uint32_t flags, const uint8_t* code, size_t code_size) +static struct evmc_result execute_wrapper(struct evmc_instance* instance, + int64_t context_index, enum evmc_revision rev, + enum evmc_call_kind kind, uint32_t flags, int32_t depth, int64_t gas, + const evmc_address* destination, const evmc_address* sender, + const uint8_t* input_data, size_t input_size, const evmc_uint256be* value, + const uint8_t* code, size_t code_size, const evmc_bytes32* create2_salt) { - struct evmc_uint256be create2_salt = {}; struct evmc_message msg = { - *destination, - *sender, - *value, - input_data, - input_size, - *code_hash, - create2_salt, - gas, - depth, kind, flags, + depth, + gas, + *destination, + *sender, + input_data, + input_size, + *value, + *create2_salt, }; - struct extended_context ctx = {{&evmc_go_fn_table}, context_index}; + struct extended_context ctx = {{&evmc_go_host}, context_index}; return evmc_execute(instance, &ctx.context, rev, &msg, code, code_size); } */ @@ -68,10 +68,10 @@ import ( // Static asserts. const ( - _ = uint(common.HashLength - C.sizeof_struct_evmc_uint256be) // The size of evmc_uint256be equals the size of Hash. - _ = uint(C.sizeof_struct_evmc_uint256be - common.HashLength) - _ = uint(common.AddressLength - C.sizeof_struct_evmc_address) // The size of evmc_address equals the size of Address. - _ = uint(C.sizeof_struct_evmc_address - common.AddressLength) + _ = uint(common.HashLength - C.sizeof_evmc_bytes32) // The size of evmc_bytes32 equals the size of Hash. + _ = uint(C.sizeof_evmc_bytes32 - common.HashLength) + _ = uint(common.AddressLength - C.sizeof_evmc_address) // The size of evmc_address equals the size of Address. + _ = uint(C.sizeof_evmc_address - common.AddressLength) ) type Error int32 @@ -185,18 +185,34 @@ func (instance *Instance) Version() string { return C.GoString(instance.handle.version) } +type Capability uint32 + +const ( + CapabilityEVM1 Capability = C.EVMC_CAPABILITY_EVM1 + CapabilityEWASM Capability = C.EVMC_CAPABILITY_EWASM +) + +func (instance *Instance) HasCapability(capability Capability) bool { + return bool(C.evmc_vm_has_capability(instance.handle, uint32(capability))) +} + func (instance *Instance) SetOption(name string, value string) (err error) { r := C.set_option(instance.handle, C.CString(name), C.CString(value)) - if r != 1 { + switch r { + case C.EVMC_SET_OPTION_INVALID_NAME: err = fmt.Errorf("evmc: option '%s' not accepted", name) + case C.EVMC_SET_OPTION_INVALID_VALUE: + err = fmt.Errorf("evmc: option '%s' has invalid value", name) + case C.EVMC_SET_OPTION_SUCCESS: } return err } func (instance *Instance) Execute(ctx HostContext, rev Revision, - destination common.Address, sender common.Address, value common.Hash, input []byte, codeHash common.Hash, gas int64, - depth int, kind CallKind, static bool, code []byte) (output []byte, gasLeft int64, err error) { + kind CallKind, static bool, depth int, gas int64, + destination common.Address, sender common.Address, input []byte, value common.Hash, + code []byte, create2Salt common.Hash) (output []byte, gasLeft int64, err error) { flags := C.uint32_t(0) if static { @@ -207,11 +223,12 @@ func (instance *Instance) Execute(ctx HostContext, rev Revision, // FIXME: Clarify passing by pointer vs passing by value. evmcDestination := evmcAddress(destination) evmcSender := evmcAddress(sender) - evmcValue := evmcUint256be(value) - evmcCodeHash := evmcUint256be(codeHash) - result := C.execute_wrapper(instance.handle, C.int64_t(ctxId), uint32(rev), &evmcDestination, &evmcSender, &evmcValue, - bytesPtr(input), C.size_t(len(input)), &evmcCodeHash, C.int64_t(gas), C.int32_t(depth), C.enum_evmc_call_kind(kind), - flags, bytesPtr(code), C.size_t(len(code))) + evmcValue := evmcBytes32(value) + evmcCreate2Salt := evmcBytes32(create2Salt) + result := C.execute_wrapper(instance.handle, C.int64_t(ctxId), uint32(rev), + C.enum_evmc_call_kind(kind), flags, C.int32_t(depth), C.int64_t(gas), + &evmcDestination, &evmcSender, bytesPtr(input), C.size_t(len(input)), &evmcValue, + bytesPtr(code), C.size_t(len(code)), &evmcCreate2Salt) removeHostContext(ctxId) output = C.GoBytes(unsafe.Pointer(result.output_data), C.int(result.output_size)) @@ -255,16 +272,16 @@ func getHostContext(idx int) HostContext { return ctx } -func evmcUint256be(in common.Hash) C.struct_evmc_uint256be { - out := C.struct_evmc_uint256be{} +func evmcBytes32(in common.Hash) C.evmc_bytes32 { + out := C.evmc_bytes32{} for i := 0; i < len(in); i++ { out.bytes[i] = C.uint8_t(in[i]) } return out } -func evmcAddress(address common.Address) C.struct_evmc_address { - r := C.struct_evmc_address{} +func evmcAddress(address common.Address) C.evmc_address { + r := C.evmc_address{} for i := 0; i < len(address); i++ { r.bytes[i] = C.uint8_t(address[i]) } diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h index 5ca265dae9..b3a058bb09 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h @@ -11,8 +11,9 @@ #ifndef EVMC_H #define EVMC_H -#include /* Definition of size_t. */ -#include /* Definition of int64_t, uint64_t. */ +#include /* Definition of bool, true and false. */ +#include /* Definition of size_t. */ +#include /* Definition of int64_t, uint64_t. */ #if __cplusplus extern "C" { @@ -22,30 +23,40 @@ extern "C" { enum { - /** The EVMC ABI version number of the interface declared in this file. */ - EVMC_ABI_VERSION = 5 + /** + * The EVMC ABI version number of the interface declared in this file. + * + * The EVMC ABI version always equals the major version number of the EVMC project. + * The Host SHOULD check if the ABI versions match when dynamically loading VMs. + * + * @see @ref versioning + */ + EVMC_ABI_VERSION = 6 }; + /** - * Big-endian 256-bit integer. + * The fixed size array of 32 bytes. * - * 32 bytes of data representing big-endian 256-bit integer. I.e. bytes[0] is - * 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. + * 32 bytes of data capable of storing e.g. 256-bit hashes. */ -struct evmc_uint256be +typedef struct evmc_bytes32 { - /** The 32 bytes of the big-endian integer or hash. */ + /** The 32 bytes. */ uint8_t bytes[32]; -}; +} evmc_bytes32; + +/** + * The alias for evmc_bytes32 to represent a big-endian 256-bit integer. + */ +typedef struct evmc_bytes32 evmc_uint256be; /** Big-endian 160-bit hash suitable for keeping an Ethereum address. */ -struct evmc_address +typedef struct evmc_address { /** The 20 bytes of the hash. */ uint8_t bytes[20]; -}; +} evmc_address; /** The kind of call-like instruction. */ enum evmc_call_kind @@ -70,71 +81,65 @@ enum evmc_flags */ struct evmc_message { - /** The destination of the message. */ - struct evmc_address destination; - - /** The sender of the message. */ - struct evmc_address sender; + /** The kind of the call. For zero-depth calls ::EVMC_CALL SHOULD be used. */ + enum evmc_call_kind kind; /** - * The amount of Ether transferred with the message. + * Additional flags modifying the call execution behavior. + * In the current version the only valid values are ::EVMC_STATIC or 0. */ - struct evmc_uint256be value; + uint32_t flags; + + /** The call depth. */ + int32_t depth; + + /** The amount of gas for message execution. */ + int64_t gas; + + /** The destination of the message. */ + evmc_address destination; + + /** The sender of the message. */ + evmc_address sender; /** * The message input data. * - * This MAY be NULL. + * This MAY be NULL. */ const uint8_t* input_data; /** * The size of the message input data. * - * If input_data is NULL this MUST be 0. + * If input_data is NULL this MUST be 0. */ size_t input_size; /** - * The optional hash of the code of the destination account. - * The null hash MUST be used when not specified. + * The amount of Ether transferred with the message. */ - struct evmc_uint256be code_hash; + evmc_uint256be value; /** * The optional value used in new contract address construction. * - * Ignored unless kind is EVMC_CREATE2. + * Ignored unless kind is EVMC_CREATE2. */ - struct evmc_uint256be create2_salt; - - /** The amount of gas for message execution. */ - int64_t gas; - - /** The call depth. */ - int32_t depth; - - /** 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 ::EVMC_STATIC or 0. - */ - uint32_t flags; + evmc_bytes32 create2_salt; }; /** The transaction and block data for execution. */ 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 evmc_uint256be block_difficulty; /**< The block difficulty. */ + evmc_uint256be tx_gas_price; /**< The transaction gas price. */ + evmc_address tx_origin; /**< The transaction origin account. */ + 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. */ + evmc_uint256be block_difficulty; /**< The block difficulty. */ }; struct evmc_context; @@ -145,28 +150,24 @@ struct evmc_context; * This callback function is used by an EVM to retrieve the transaction and * block context. * - * @param[out] result The returned transaction context. - * @see ::evmc_tx_context. * @param context The pointer to the Host execution context. - * @see ::evmc_context. + * @return The transaction context. */ -typedef void (*evmc_get_tx_context_fn)(struct evmc_tx_context* result, - struct evmc_context* context); +typedef struct evmc_tx_context (*evmc_get_tx_context_fn)(struct evmc_context* context); /** * Get block hash callback function. * - * This callback function is used by an EVM to query the block hash of - * a given block. + * This callback function is used by a VM to query the hash of the header of the given block. + * If the information about the requested block is not available, then this is signalled by + * returning null bytes. * - * @param[out] result The returned block hash value. - * @param context The pointer to the Host execution context. - * @param number The block number. Must be a value between - * (and including) 0 and 255. + * @param context The pointer to the Host execution context. + * @param number The block number. + * @return The block hash or null bytes + * if the information about the block is not available. */ -typedef void (*evmc_get_block_hash_fn)(struct evmc_uint256be* result, - struct evmc_context* context, - int64_t number); +typedef evmc_bytes32 (*evmc_get_block_hash_fn)(struct evmc_context* context, int64_t number); /** * The execution status code. @@ -265,7 +266,7 @@ enum evmc_status_code EVMC_ARGUMENT_OUT_OF_RANGE = 14, /** - * A WebAssembly `unreachable` instruction has been hit during exection. + * A WebAssembly `unreachable` instruction has been hit during execution. */ EVMC_WASM_UNREACHABLE_INSTRUCTION = 15, @@ -376,7 +377,7 @@ struct evmc_result * This field has valid value only if the result describes successful * CREATE (evmc_result::status_code is ::EVMC_SUCCESS). */ - struct evmc_address create_address; + evmc_address create_address; /** * Reserved data that MAY be used by a evmc_result object creator. @@ -394,33 +395,30 @@ struct evmc_result /** - * Check account existence callback function + * Check account existence callback function. * - * 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 ::evmc_context. - * @param address The address of the account the query is about. - * @return 1 if exists, 0 otherwise. + * This callback function is used by the VM to check if + * there exists an account at given address. + * @param context The pointer to the Host execution context. + * @param address The address of the account the query is about. + * @return true if exists, false otherwise. */ -typedef int (*evmc_account_exists_fn)(struct evmc_context* context, - const struct evmc_address* address); +typedef bool (*evmc_account_exists_fn)(struct evmc_context* context, const evmc_address* address); /** * Get storage callback function. * - * This callback function is used by an EVM to query the given contract - * storage entry. - * @param[out] result The returned storage value. - * @param context The pointer to the Host execution context. - * @see ::evmc_context. - * @param address The address of the contract. - * @param key The index of the storage entry. + * This callback function is used by a VM to query the given account storage entry. + * + * @param context The Host execution context. + * @param address The address of the account. + * @param key The index of the account's storage entry. + * @return The storage value at the given storage key or null bytes + * if the account does not exist. */ -typedef void (*evmc_get_storage_fn)(struct evmc_uint256be* result, - struct evmc_context* context, - const struct evmc_address* address, - const struct evmc_uint256be* key); +typedef evmc_bytes32 (*evmc_get_storage_fn)(struct evmc_context* context, + const evmc_address* address, + const evmc_bytes32* key); /** @@ -431,6 +429,7 @@ typedef void (*evmc_get_storage_fn)(struct evmc_uint256be* result, * - 0 is zero value, * - X != 0 (X is any value other than 0), * - Y != X, Y != 0 (Y is any value other than X and 0), + * - Z != Y (Z is any value other than Y), * - the "->" means the change from one value to another. */ enum evmc_storage_status @@ -445,70 +444,79 @@ enum evmc_storage_status */ EVMC_STORAGE_MODIFIED = 1, + /** + * A storage item has been modified after being modified before: X -> Y -> Z. + */ + EVMC_STORAGE_MODIFIED_AGAIN = 2, + /** * A new storage item has been added: 0 -> X. */ - EVMC_STORAGE_ADDED = 2, + EVMC_STORAGE_ADDED = 3, /** * A storage item has been deleted: X -> 0. */ - EVMC_STORAGE_DELETED = 3 + EVMC_STORAGE_DELETED = 4 }; /** * Set storage callback function. * - * This callback function is used by an EVM to update the given contract - * storage entry. + * This callback function is used by a VM to update the given account storage entry. + * The VM MUST make sure that the account exists. This requirement is only a formality because + * VM implementations only modify storage of the account of the current execution context + * (i.e. referenced by evmc_message::destination). + * * @param context The pointer to the Host execution context. - * @see ::evmc_context. - * @param address The address of the contract. + * @param address The address of the account. * @param key The index of the storage entry. * @param value The value to be stored. - * @return The effect on the storage item, @see ::evmc_storage_status. + * @return The effect on the storage item. */ typedef enum evmc_storage_status (*evmc_set_storage_fn)(struct evmc_context* context, - const struct evmc_address* address, - const struct evmc_uint256be* key, - const struct evmc_uint256be* value); + const evmc_address* address, + const evmc_bytes32* key, + const evmc_bytes32* value); /** * Get balance callback function. * - * This callback function is used by an EVM to query the balance of the given - * address. - * @param[out] result The returned balance value. - * @param context The pointer to the Host execution context. - * @see ::evmc_context. - * @param address The address. + * This callback function is used by a VM to query the balance of the given account. + * + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return The balance of the given account or 0 if the account does not exist. */ -typedef void (*evmc_get_balance_fn)(struct evmc_uint256be* result, - struct evmc_context* context, - const struct evmc_address* address); +typedef evmc_uint256be (*evmc_get_balance_fn)(struct evmc_context* context, + const 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. + * This callback function is used by a VM to get the size of the code stored + * in the account at the given address. + * + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return The size of the code in the account or 0 if the account does not exist. */ -typedef size_t (*evmc_get_code_size_fn)(struct evmc_context* context, - const struct evmc_address* address); +typedef size_t (*evmc_get_code_size_fn)(struct evmc_context* context, const evmc_address* address); /** * Get code size callback function. * - * This callback function is used by an EVM to get the keccak256 hash of the code stored - * in the account at the given address. For accounts not having a code, this - * function returns keccak256 hash of empty data. For accounts not existing in the state, - * this function returns 0. + * This callback function is used by a VM to get the keccak256 hash of the code stored + * in the account at the given address. For existing accounts not having a code, this + * function returns keccak256 hash of empty data. + * + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return The hash of the code in the account or null bytes if the account does not exist. */ -typedef void (*evmc_get_code_hash_fn)(struct evmc_uint256be* result, - struct evmc_context* context, - const struct evmc_address* address); +typedef evmc_bytes32 (*evmc_get_code_hash_fn)(struct evmc_context* context, + const evmc_address* address); /** * Copy code callback function. @@ -529,7 +537,7 @@ typedef void (*evmc_get_code_hash_fn)(struct evmc_uint256be* result, * @return The number of bytes copied to the buffer by the Client. */ typedef size_t (*evmc_copy_code_fn)(struct evmc_context* context, - const struct evmc_address* address, + const evmc_address* address, size_t code_offset, uint8_t* buffer_data, size_t buffer_size); @@ -547,8 +555,8 @@ typedef size_t (*evmc_copy_code_fn)(struct evmc_context* context, * transferred. */ typedef void (*evmc_selfdestruct_fn)(struct evmc_context* context, - const struct evmc_address* address, - const struct evmc_address* beneficiary); + const evmc_address* address, + const evmc_address* beneficiary); /** * Log callback function. @@ -565,35 +573,31 @@ typedef void (*evmc_selfdestruct_fn)(struct evmc_context* context, * 0 and 4 inclusively. */ typedef void (*evmc_emit_log_fn)(struct evmc_context* context, - const struct evmc_address* address, + const evmc_address* address, const uint8_t* data, size_t data_size, - const struct evmc_uint256be topics[], + const evmc_bytes32 topics[], size_t topics_count); /** * Pointer to the callback function supporting EVM calls. * - * @param[out] result The result of the call. The result object is not - * 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 ::evmc_context. - * @param msg Call parameters. @see ::evmc_message. + * @param context The pointer to the Host execution context. + * @param msg The call parameters. + * @return The result of the call. */ -typedef void (*evmc_call_fn)(struct evmc_result* result, - struct evmc_context* context, - const struct evmc_message* msg); +typedef struct evmc_result (*evmc_call_fn)(struct evmc_context* context, + const struct evmc_message* msg); /** - * The context interface. + * The Host interface. * - * The set of all callback functions expected by EVM instances. This is C - * 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. + * The set of all callback functions expected by VM instances. This is C + * 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 evmc_context_fn_table +struct evmc_host_interface { /** Check account existence callback function. */ evmc_account_exists_fn account_exists; @@ -645,8 +649,8 @@ struct evmc_context_fn_table */ struct evmc_context { - /** Function table defining the context interface (vtable). */ - const struct evmc_context_fn_table* fn_table; + /** The Host interface. */ + const struct evmc_host_interface* host; }; @@ -660,6 +664,15 @@ struct evmc_instance; */ typedef void (*evmc_destroy_fn)(struct evmc_instance* evm); +/** + * Possible outcomes of evmc_set_option. + */ +enum evmc_set_option_result +{ + EVMC_SET_OPTION_SUCCESS = 0, + EVMC_SET_OPTION_INVALID_NAME = 1, + EVMC_SET_OPTION_INVALID_VALUE = 2 +}; /** * Configures the EVM instance. @@ -672,9 +685,11 @@ typedef void (*evmc_destroy_fn)(struct evmc_instance* evm); * @param evm The EVM instance to be configured. * @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. + * @return The outcome of the operation. */ -typedef int (*evmc_set_option_fn)(struct evmc_instance* evm, char const* name, char const* value); +typedef enum evmc_set_option_result (*evmc_set_option_fn)(struct evmc_instance* evm, + char const* name, + char const* value); /** @@ -717,6 +732,32 @@ typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance, uint8_t const* code, size_t code_size); +/** + * Possible capabilities of a VM. + */ +enum evmc_capabilities +{ + EVMC_CAPABILITY_EVM1 = (1u << 0), /**< The VM is capable of executing EVM1 bytecode. */ + EVMC_CAPABILITY_EWASM = (1u << 1) /**< The VM is capable of execution ewasm bytecode. */ +}; + +/** + * Alias for unsigned integer representing a set of bit flags of EVMC capabilities. + * + * @see evmc_capabilities + */ +typedef uint32_t evmc_capabilities_flagset; + +/** + * Return the supported capabilities of the VM instance. + * + * This function MAY be invoked multiple times for a single VM instance, + * and its value MAY be influenced by calls to evmc_instance::set_option. + * + * @param instance The EVM instance. + * @return The supported capabilities of the VM. @see evmc_capabilities. + */ +typedef evmc_capabilities_flagset (*evmc_get_capabilities_fn)(struct evmc_instance* instance); /** The opaque type representing a Client-side tracer object. */ struct evmc_tracer_context; @@ -762,7 +803,7 @@ typedef void (*evmc_trace_callback)(struct evmc_tracer_context* context, enum evmc_status_code status_code, int64_t gas_left, size_t stack_num_items, - const struct evmc_uint256be* pushed_stack_item, + const evmc_uint256be* pushed_stack_item, size_t memory_size, size_t changed_memory_offset, size_t changed_memory_size, @@ -824,6 +865,16 @@ struct evmc_instance /** Pointer to function executing a code by the EVM instance. */ evmc_execute_fn execute; + /** + * Pointer to function returning capabilities supported by the VM instance. + * + * The value returned might change when different options are requested via set_option. + * + * 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_capabilities; + /** * Optional pointer to function setting the EVM instruction tracer. * @@ -857,7 +908,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 diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h b/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h index 55fa0dc5bc..55868d1b21 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h @@ -10,6 +10,8 @@ * These are convenient for languages where invoking function pointers * is "ugly" or impossible (such as Go). * + * It also contains helpers (overloaded operators) for using EVMC types effectively in C++. + * * @defgroup helpers EVMC Helpers * @{ */ @@ -41,6 +43,17 @@ static inline const char* evmc_vm_version(struct evmc_instance* instance) return instance->version; } +/** + * Checks if the VM instance has the given capability. + * + * @see evmc_get_capabilities_fn + */ +static inline bool evmc_vm_has_capability(struct evmc_instance* vm, + enum evmc_capabilities capability) +{ + return (vm->get_capabilities(vm) & (evmc_capabilities_flagset)capability) != 0; +} + /** * Destroys the VM instance. * @@ -56,13 +69,13 @@ static inline void evmc_destroy(struct evmc_instance* instance) * * @see evmc_set_option_fn */ -static inline int evmc_set_option(struct evmc_instance* instance, - char const* name, - char const* value) +static inline enum evmc_set_option_result evmc_set_option(struct evmc_instance* instance, + char const* name, + char const* value) { if (instance->set_option) return instance->set_option(instance, name, value); - return 0; + return EVMC_SET_OPTION_INVALID_NAME; } /** diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c index 53e3bfbdf2..ac0efd3a39 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c @@ -7,7 +7,20 @@ #include -const struct evmc_context_fn_table evmc_go_fn_table = { + +void evmc_go_free_result_output(const struct evmc_result* result) +{ + free((void*)result->output_data); +} + + +/* Go does not support exporting functions with parameters with const modifiers, + * so we have to cast function pointers to the function types defined in EVMC. + * This disables any type checking of exported Go functions. To mitigate this + * problem the go_exported_functions_type_checks() function simulates usage + * of Go exported functions with expected types to check them during compilation. + */ +const struct evmc_host_interface evmc_go_host = { (evmc_account_exists_fn)accountExists, (evmc_get_storage_fn)getStorage, (evmc_set_storage_fn)setStorage, @@ -22,7 +35,74 @@ const struct evmc_context_fn_table evmc_go_fn_table = { (evmc_emit_log_fn)emitLog, }; -void evmc_go_free_result_output(const struct evmc_result* result) + +#pragma GCC diagnostic error "-Wconversion" +static inline void go_exported_functions_type_checks() { - free((void*)result->output_data); + struct evmc_context* context = NULL; + evmc_address* address = NULL; + evmc_bytes32 bytes32; + uint8_t* data = NULL; + size_t size = 0; + int64_t number = 0; + struct evmc_message* message = NULL; + + evmc_uint256be uint256be; + (void)uint256be; + struct evmc_tx_context tx_context; + (void)tx_context; + struct evmc_result result; + (void)result; + enum evmc_storage_status storage_status; + (void)storage_status; + bool bool_flag; + (void)bool_flag; + + evmc_account_exists_fn account_exists_fn = NULL; + bool_flag = account_exists_fn(context, address); + bool_flag = accountExists(context, address); + + evmc_get_storage_fn get_storage_fn = NULL; + bytes32 = get_storage_fn(context, address, &bytes32); + bytes32 = getStorage(context, address, &bytes32); + + evmc_set_storage_fn set_storage_fn = NULL; + storage_status = set_storage_fn(context, address, &bytes32, &bytes32); + storage_status = setStorage(context, address, &bytes32, &bytes32); + + evmc_get_balance_fn get_balance_fn = NULL; + uint256be = get_balance_fn(context, address); + uint256be = getBalance(context, address); + + evmc_get_code_size_fn get_code_size_fn = NULL; + size = get_code_size_fn(context, address); + size = getCodeSize(context, address); + + evmc_get_code_hash_fn get_code_hash_fn = NULL; + bytes32 = get_code_hash_fn(context, address); + bytes32 = getCodeHash(context, address); + + evmc_copy_code_fn copy_code_fn = NULL; + size = copy_code_fn(context, address, size, data, size); + size = copyCode(context, address, size, data, size); + + evmc_selfdestruct_fn selfdestruct_fn = NULL; + selfdestruct_fn(context, address, address); + selfdestruct(context, address, address); + + evmc_call_fn call_fn = NULL; + result = call_fn(context, message); + result = call(context, message); + + evmc_get_tx_context_fn get_tx_context_fn = NULL; + tx_context = get_tx_context_fn(context); + tx_context = getTxContext(context); + + evmc_get_block_hash_fn get_block_hash_fn = NULL; + bytes32 = get_block_hash_fn(context, number); + bytes32 = getBlockHash(context, number); + + evmc_emit_log_fn emit_log_fn = NULL; + emit_log_fn(context, address, data, size, &bytes32, size); + emitLog(context, address, data, size, &bytes32, size); } diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go index 47f4f638fb..b2346cd373 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go @@ -39,13 +39,14 @@ const ( type StorageStatus int const ( - StorageUnchanged StorageStatus = C.EVMC_STORAGE_UNCHANGED - StorageModified StorageStatus = C.EVMC_STORAGE_MODIFIED - StorageAdded StorageStatus = C.EVMC_STORAGE_ADDED - StorageDeleted StorageStatus = C.EVMC_STORAGE_DELETED + StorageUnchanged StorageStatus = C.EVMC_STORAGE_UNCHANGED + StorageModified StorageStatus = C.EVMC_STORAGE_MODIFIED + StorageModifiedAgain StorageStatus = C.EVMC_STORAGE_MODIFIED_AGAIN + StorageAdded StorageStatus = C.EVMC_STORAGE_ADDED + StorageDeleted StorageStatus = C.EVMC_STORAGE_DELETED ) -func goAddress(in C.struct_evmc_address) common.Address { +func goAddress(in C.evmc_address) common.Address { out := common.Address{} for i := 0; i < len(out); i++ { out[i] = byte(in.bytes[i]) @@ -53,7 +54,7 @@ func goAddress(in C.struct_evmc_address) common.Address { return out } -func goHash(in C.struct_evmc_uint256be) common.Hash { +func goHash(in C.evmc_bytes32) common.Hash { out := common.Hash{} for i := 0; i < len(out); i++ { out[i] = byte(in.bytes[i]) @@ -87,56 +88,49 @@ type HostContext interface { } //export accountExists -func accountExists(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.int { +func accountExists(pCtx unsafe.Pointer, pAddr *C.evmc_address) C.bool { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - exists := ctx.AccountExists(goAddress(*pAddr)) - r := C.int(0) - if exists { - r = 1 - } - return r + return C.bool(ctx.AccountExists(goAddress(*pAddr))) } //export getStorage -func getStorage(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struct_evmc_uint256be) { +func getStorage(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.evmc_bytes32) C.evmc_bytes32 { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - value := ctx.GetStorage(goAddress(*pAddr), goHash(*pKey)) - *pResult = evmcUint256be(value) + return evmcBytes32(ctx.GetStorage(goAddress(*pAddr), goHash(*pKey))) } //export setStorage -func setStorage(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struct_evmc_uint256be, pVal *C.struct_evmc_uint256be) C.enum_evmc_storage_status { +func setStorage(pCtx unsafe.Pointer, pAddr *C.evmc_address, pKey *C.evmc_bytes32, pVal *C.evmc_bytes32) C.enum_evmc_storage_status { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) return C.enum_evmc_storage_status(ctx.SetStorage(goAddress(*pAddr), goHash(*pKey), goHash(*pVal))) } //export getBalance -func getBalance(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) { +func getBalance(pCtx unsafe.Pointer, pAddr *C.evmc_address) C.evmc_uint256be { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - balance := ctx.GetBalance(goAddress(*pAddr)) - *pResult = evmcUint256be(balance) + return evmcBytes32(ctx.GetBalance(goAddress(*pAddr))) } //export getCodeSize -func getCodeSize(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.size_t { +func getCodeSize(pCtx unsafe.Pointer, pAddr *C.evmc_address) C.size_t { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) return C.size_t(ctx.GetCodeSize(goAddress(*pAddr))) } //export getCodeHash -func getCodeHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) { +func getCodeHash(pCtx unsafe.Pointer, pAddr *C.evmc_address) C.evmc_bytes32 { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - *pResult = evmcUint256be(ctx.GetCodeHash(goAddress(*pAddr))) + return evmcBytes32(ctx.GetCodeHash(goAddress(*pAddr))) } //export copyCode -func copyCode(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, offset C.size_t, p *C.uint8_t, size C.size_t) C.size_t { +func copyCode(pCtx unsafe.Pointer, pAddr *C.evmc_address, offset C.size_t, p *C.uint8_t, size C.size_t) C.size_t { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) code := ctx.GetCode(goAddress(*pAddr)) @@ -157,40 +151,39 @@ func copyCode(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, offset C.size_t } //export selfdestruct -func selfdestruct(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pBeneficiary *C.struct_evmc_address) { +func selfdestruct(pCtx unsafe.Pointer, pAddr *C.evmc_address, pBeneficiary *C.evmc_address) { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) ctx.Selfdestruct(goAddress(*pAddr), goAddress(*pBeneficiary)) } //export getTxContext -func getTxContext(pResult unsafe.Pointer, pCtx unsafe.Pointer) { +func getTxContext(pCtx unsafe.Pointer) C.struct_evmc_tx_context { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) gasPrice, origin, coinbase, number, timestamp, gasLimit, difficulty := ctx.GetTxContext() - *(*C.struct_evmc_tx_context)(pResult) = C.struct_evmc_tx_context{ - evmcUint256be(gasPrice), + return C.struct_evmc_tx_context{ + evmcBytes32(gasPrice), evmcAddress(origin), evmcAddress(coinbase), C.int64_t(number), C.int64_t(timestamp), C.int64_t(gasLimit), - evmcUint256be(difficulty), + evmcBytes32(difficulty), } } //export getBlockHash -func getBlockHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, number int64) { +func getBlockHash(pCtx unsafe.Pointer, number int64) C.evmc_bytes32 { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - - *pResult = evmcUint256be(ctx.GetBlockHash(number)) + return evmcBytes32(ctx.GetBlockHash(number)) } //export emitLog -func emitLog(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pData unsafe.Pointer, dataSize C.size_t, pTopics unsafe.Pointer, topicsCount C.size_t) { +func emitLog(pCtx unsafe.Pointer, pAddr *C.evmc_address, pData unsafe.Pointer, dataSize C.size_t, pTopics unsafe.Pointer, topicsCount C.size_t) { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) @@ -208,7 +201,7 @@ func emitLog(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pData unsafe.Poi } //export call -func call(pResult *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc_message) { +func call(pCtx unsafe.Pointer, msg *C.struct_evmc_message) C.struct_evmc_result { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) @@ -234,5 +227,5 @@ func call(pResult *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc result.release = (C.evmc_release_result_fn)(C.evmc_go_free_result_output) } - *pResult = result + return result } diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.c b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.c index 252b6e6d31..12b7407b80 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.c +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.c @@ -16,7 +16,7 @@ #define DLL_HANDLE HMODULE #define DLL_OPEN(filename) LoadLibrary(filename) #define DLL_CLOSE(handle) FreeLibrary(handle) -#define DLL_GET_CREATE_FN(handle, name) (evmc_create_fn) GetProcAddress(handle, name) +#define DLL_GET_CREATE_FN(handle, name) (evmc_create_fn)(uintptr_t) GetProcAddress(handle, name) #define HAVE_STRCPY_S 1 #else #include @@ -69,8 +69,8 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro // Create name buffer with the prefix. const char prefix[] = "evmc_create_"; const size_t prefix_length = strlen(prefix); - char name[sizeof(prefix) + PATH_MAX_LENGTH]; - strcpy_s(name, sizeof(name), prefix); + char prefixed_name[sizeof(prefix) + PATH_MAX_LENGTH]; + strcpy_s(prefixed_name, sizeof(prefixed_name), prefix); // Find filename in the path. const char* sep_pos = strrchr(filename, '/'); @@ -87,30 +87,28 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro if (strncmp(name_pos, lib_prefix, lib_prefix_length) == 0) name_pos += lib_prefix_length; - strcpy_s(name + prefix_length, PATH_MAX_LENGTH, name_pos); + char* base_name = prefixed_name + prefix_length; + strcpy_s(base_name, PATH_MAX_LENGTH, name_pos); // Trim the file extension. - char* ext_pos = strrchr(name, '.'); + char* ext_pos = strrchr(prefixed_name, '.'); if (ext_pos) *ext_pos = 0; // Replace all "-" with "_". - char* dash_pos = name; + char* dash_pos = base_name; while ((dash_pos = strchr(dash_pos, '-')) != NULL) *dash_pos++ = '_'; - // Search for the "full name" based function name. - create_fn = DLL_GET_CREATE_FN(handle, name); - if (!create_fn) + // Search for the built function name. + while ((create_fn = DLL_GET_CREATE_FN(handle, prefixed_name)) == NULL) { - // Try the "short name" based function name. - const char* short_name_pos = strrchr(name, '_'); - if (short_name_pos) - { - short_name_pos += 1; - memmove(name + prefix_length, short_name_pos, strlen(short_name_pos) + 1); - create_fn = DLL_GET_CREATE_FN(handle, name); - } + // Shorten the base name by skipping the `word_` segment. + const char* shorter_name_pos = strchr(base_name, '_'); + if (!shorter_name_pos) + break; + + memmove(base_name, shorter_name_pos + 1, strlen(shorter_name_pos) + 1); } if (!create_fn) diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h index b6492635fc..c9ff5090ce 100644 --- a/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h @@ -60,15 +60,16 @@ enum evmc_loader_error_code * "libexample-interpreter.so", * - the "lib" prefix and file extension are stripped from the name: * "example-interpreter" - * - all "-" are replaced with "_" to construct _full name_: + * - all "-" are replaced with "_" to construct _base name_: * "example_interpreter", - * - the _full name_ is split by "_" char and the last item is taken to form the _short name_: - * "interpreter", - * - the name "evmc_create_" + _full name_ is checked in the library: + * - the function name "evmc_create_" + _base name_ is searched in the library: * "evmc_create_example_interpreter", - * - then, the name "evmc_create_" + _short name_ is checked in the library: - * "evmc_create_interpreter". - * - lastly, the name "evmc_create" is checked in the library + * - if function not found, the _base name_ is shorten by skipping the first word separated by "_": + * "interpreter", + * - then, the function of the shorter name "evmc_create_" + _base name_ is searched in the library: + * "evmc_create_interpreter", + * - the name shortening continues until a function is found or the name cannot be shorten more, + * - lastly, when no function found, the function name "evmc_create" is searched in the library. * * If the create function is found in the library, the pointer to the function is returned. * Otherwise, the ::EVMC_LOADER_SYMBOL_NOT_FOUND error code is signaled and NULL is returned. diff --git a/vendor/vendor.json b/vendor/vendor.json index 2def95088a..4fb4a3e291 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -105,12 +105,12 @@ "revisionTime": "2018-01-22T22:25:45Z" }, { - "checksumSHA1": "gvcZHEaRD0J5Y6QrFTo0GrR2TkE=", + "checksumSHA1": "HxlAMyHDmEEDsOIlULQD2HPoN40=", "path": "github.com/ethereum/evmc/bindings/go/evmc", - "revision": "224080ef8c8d99f5cfe59067a3bd995be23349bf", - "revisionTime": "2018-08-28T21:11:56Z", - "version": "=v5.2.0", - "versionExact": "v5.2.0" + "revision": "3b3aab4f7720f80ba0b989da88b60907c2a8f733", + "revisionTime": "2018-10-18T15:29:18Z", + "version": "v6", + "versionExact": "v6" }, { "checksumSHA1": "7oFpbmDfGobwKsFLIf6wMUvVoKw=",