From 33bf2f9da276cb1b75c26c155002946586f1a3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 11 Sep 2018 14:34:59 +0200 Subject: [PATCH] vendor: Add EVMC 5.2.0 govendor fetch github.com/ethereum/evmc/bindings/go/evmc@=v5.2.0 --- vendor/github.com/ethereum/evmc/LICENSE | 202 ++++ .../ethereum/evmc/bindings/go/evmc/evmc.go | 279 ++++++ .../ethereum/evmc/bindings/go/evmc/evmc.h | 868 ++++++++++++++++++ .../ethereum/evmc/bindings/go/evmc/helpers.h | 155 ++++ .../ethereum/evmc/bindings/go/evmc/host.c | 28 + .../ethereum/evmc/bindings/go/evmc/host.go | 238 +++++ .../ethereum/evmc/bindings/go/evmc/loader.c | 153 +++ .../ethereum/evmc/bindings/go/evmc/loader.h | 109 +++ vendor/vendor.json | 8 + 9 files changed, 2040 insertions(+) create mode 100644 vendor/github.com/ethereum/evmc/LICENSE create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.c create mode 100644 vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h diff --git a/vendor/github.com/ethereum/evmc/LICENSE b/vendor/github.com/ethereum/evmc/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/ethereum/evmc/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go new file mode 100644 index 0000000000..6379c15aba --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.go @@ -0,0 +1,279 @@ +// EVMC: Ethereum Client-VM Connector API. +// Copyright 2018 The EVMC Authors. +// Licensed under the Apache License, Version 2.0. See the LICENSE file. + +package evmc + +/* +#cgo CFLAGS: -I${SRCDIR}/.. -Wall -Wextra +#cgo !windows LDFLAGS: -ldl + +#include +#include +#include + +#include +#include + +static inline int set_option(struct evmc_instance* instance, char* name, char* value) +{ + int ret = evmc_set_option(instance, name, value); + free(name); + free(value); + return ret; +} + +struct extended_context +{ + struct evmc_context context; + int64_t index; +}; + +extern const struct evmc_context_fn_table evmc_go_fn_table; + +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) +{ + struct evmc_uint256be create2_salt = {}; + struct evmc_message msg = { + *destination, + *sender, + *value, + input_data, + input_size, + *code_hash, + create2_salt, + gas, + depth, + kind, + flags, + }; + + struct extended_context ctx = {{&evmc_go_fn_table}, context_index}; + return evmc_execute(instance, &ctx.context, rev, &msg, code, code_size); +} +*/ +import "C" + +import ( + "errors" + "fmt" + "sync" + "unsafe" + + "github.com/ethereum/go-ethereum/common" +) + +// 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) +) + +type Error int32 + +func (err Error) IsInternalError() bool { + return err < 0 +} + +func (err Error) Error() string { + code := C.enum_evmc_status_code(err) + + switch code { + case C.EVMC_FAILURE: + return "evmc: failure" + case C.EVMC_REVERT: + return "evmc: revert" + case C.EVMC_OUT_OF_GAS: + return "evmc: out of gas" + case C.EVMC_INVALID_INSTRUCTION: + return "evmc: invalid instruction" + case C.EVMC_UNDEFINED_INSTRUCTION: + return "evmc: undefined instruction" + case C.EVMC_STACK_OVERFLOW: + return "evmc: stack overflow" + case C.EVMC_STACK_UNDERFLOW: + return "evmc: stack underflow" + case C.EVMC_BAD_JUMP_DESTINATION: + return "evmc: bad jump destination" + case C.EVMC_INVALID_MEMORY_ACCESS: + return "evmc: invalid memory access" + case C.EVMC_CALL_DEPTH_EXCEEDED: + return "evmc: call depth exceeded" + case C.EVMC_STATIC_MODE_VIOLATION: + return "evmc: static mode violation" + case C.EVMC_PRECOMPILE_FAILURE: + return "evmc: precompile failure" + case C.EVMC_CONTRACT_VALIDATION_FAILURE: + return "evmc: contract validation failure" + case C.EVMC_ARGUMENT_OUT_OF_RANGE: + return "evmc: argument out of range" + case C.EVMC_WASM_UNREACHABLE_INSTRUCTION: + return "evmc: the WebAssembly unreachable instruction has been hit during execution" + case C.EVMC_WASM_TRAP: + return "evmc: a WebAssembly trap has been hit during execution" + case C.EVMC_REJECTED: + return "evmc: rejected" + } + + if code < 0 { + return fmt.Sprintf("evmc: internal error (%d)", int32(code)) + } + + return fmt.Sprintf("evmc: unknown non-fatal status code %d", int32(code)) +} + +const ( + Failure = Error(C.EVMC_FAILURE) + Revert = Error(C.EVMC_REVERT) +) + +type Revision int32 + +const ( + Frontier Revision = C.EVMC_FRONTIER + Homestead Revision = C.EVMC_HOMESTEAD + TangerineWhistle Revision = C.EVMC_TANGERINE_WHISTLE + SpuriousDragon Revision = C.EVMC_SPURIOUS_DRAGON + Byzantium Revision = C.EVMC_BYZANTIUM + Constantinople Revision = C.EVMC_CONSTANTINOPLE +) + +type Instance struct { + handle *C.struct_evmc_instance +} + +func Load(filename string) (instance *Instance, err error) { + cfilename := C.CString(filename) + var loaderErr C.enum_evmc_loader_error_code + handle := C.evmc_load_and_create(cfilename, &loaderErr) + C.free(unsafe.Pointer(cfilename)) + switch loaderErr { + case C.EVMC_LOADER_SUCCESS: + instance = &Instance{handle} + case C.EVMC_LOADER_CANNOT_OPEN: + err = fmt.Errorf("evmc loader: cannot open %s", filename) + case C.EVMC_LOADER_SYMBOL_NOT_FOUND: + err = fmt.Errorf("evmc loader: the EVMC create function not found in %s", filename) + case C.EVMC_LOADER_INVALID_ARGUMENT: + panic("evmc loader: filename argument is invalid") + case C.EVMC_LOADER_INSTANCE_CREATION_FAILURE: + err = errors.New("evmc loader: VM instance creation failure") + case C.EVMC_LOADER_ABI_VERSION_MISMATCH: + err = errors.New("evmc loader: ABI version mismatch") + default: + panic(fmt.Sprintf("evmc loader: unexpected error (%d)", int(loaderErr))) + } + return instance, err +} + +func (instance *Instance) Destroy() { + C.evmc_destroy(instance.handle) +} + +func (instance *Instance) Name() string { + // TODO: consider using C.evmc_vm_name(instance.handle) + return C.GoString(instance.handle.name) +} + +func (instance *Instance) Version() string { + // TODO: consider using C.evmc_vm_version(instance.handle) + return C.GoString(instance.handle.version) +} + +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 { + err = fmt.Errorf("evmc: option '%s' not accepted", name) + } + 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) { + + flags := C.uint32_t(0) + if static { + flags |= C.EVMC_STATIC + } + + ctxId := addHostContext(ctx) + // 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))) + removeHostContext(ctxId) + + output = C.GoBytes(unsafe.Pointer(result.output_data), C.int(result.output_size)) + gasLeft = int64(result.gas_left) + if result.status_code != C.EVMC_SUCCESS { + err = Error(result.status_code) + } + + if result.release != nil { + C.evmc_release_result(&result) + } + + return output, gasLeft, err +} + +var ( + hostContextCounter int + hostContextMap = map[int]HostContext{} + hostContextMapMu sync.Mutex +) + +func addHostContext(ctx HostContext) int { + hostContextMapMu.Lock() + id := hostContextCounter + hostContextCounter++ + hostContextMap[id] = ctx + hostContextMapMu.Unlock() + return id +} + +func removeHostContext(id int) { + hostContextMapMu.Lock() + delete(hostContextMap, id) + hostContextMapMu.Unlock() +} + +func getHostContext(idx int) HostContext { + hostContextMapMu.Lock() + ctx := hostContextMap[idx] + hostContextMapMu.Unlock() + return ctx +} + +func evmcUint256be(in common.Hash) C.struct_evmc_uint256be { + out := C.struct_evmc_uint256be{} + 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{} + for i := 0; i < len(address); i++ { + r.bytes[i] = C.uint8_t(address[i]) + } + return r +} + +func bytesPtr(bytes []byte) *C.uint8_t { + if len(bytes) == 0 { + return nil + } + return (*C.uint8_t)(unsafe.Pointer(&bytes[0])) +} diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h new file mode 100644 index 0000000000..5ca265dae9 --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h @@ -0,0 +1,868 @@ +/** + * EVMC: Ethereum Client-VM Connector API + * + * @copyright + * Copyright 2018 The EVMC Authors. + * Licensed under the Apache License, Version 2.0. See the LICENSE file. + * + * @defgroup EVMC EVMC + * @{ + */ +#ifndef EVMC_H +#define EVMC_H + +#include /* Definition of size_t. */ +#include /* Definition of int64_t, uint64_t. */ + +#if __cplusplus +extern "C" { +#endif + +/* BEGIN Python CFFI declarations */ + +enum +{ + /** The EVMC ABI version number of the interface declared in this file. */ + EVMC_ABI_VERSION = 5 +}; + +/** + * Big-endian 256-bit integer. + * + * 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. + */ +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 evmc_address +{ + /** The 20 bytes of the hash. */ + uint8_t bytes[20]; +}; + +/** The kind of call-like instruction. */ +enum evmc_call_kind +{ + EVMC_CALL = 0, /**< Request CALL. */ + EVMC_DELEGATECALL = 1, /**< Request DELEGATECALL. Valid since Homestead. + The value param ignored. */ + EVMC_CALLCODE = 2, /**< Request CALLCODE. */ + EVMC_CREATE = 3, /**< Request CREATE. */ + EVMC_CREATE2 = 4 /**< Request CREATE2. Valid since Constantinople.*/ +}; + +/** 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 evmc_message +{ + /** The destination of the message. */ + struct evmc_address destination; + + /** The sender of the message. */ + struct evmc_address sender; + + /** + * The amount of Ether transferred with the message. + */ + struct evmc_uint256be value; + + /** + * The message input data. + * + * 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. + */ + size_t input_size; + + /** + * The optional hash of the code of the destination account. + * The null hash MUST be used when not specified. + */ + struct evmc_uint256be code_hash; + + /** + * The optional value used in new contract address construction. + * + * 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; +}; + + +/** 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. */ +}; + +struct evmc_context; + +/** + * Get transaction context callback function. + * + * 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. + */ +typedef void (*evmc_get_tx_context_fn)(struct evmc_tx_context* result, + 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. + * + * @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. + */ +typedef void (*evmc_get_block_hash_fn)(struct evmc_uint256be* result, + struct evmc_context* context, + int64_t number); + +/** + * The execution status code. + * + * Successful execution is represented by ::EVMC_SUCCESS having value 0. + * + * Positive values represent failures defined by VM specifications with generic + * ::EVMC_FAILURE code of value 1. + * + * Status codes with negative values represent VM internal errors + * not provided by EVM specifications. These errors MUST not be passed back + * to the caller. They MAY be handled by the Client in predefined manner + * (see e.g. ::EVMC_REJECTED), otherwise internal errors are not recoverable. + * The generic representant of errors is ::EVMC_INTERNAL_ERROR but + * an EVM implementation MAY return negative status codes that are not defined + * in the EVMC documentation. + * + * @note + * In case new status codes are needed, please create an issue or pull request + * in the EVMC repository (https://github.com/ethereum/evmc). + */ +enum evmc_status_code +{ + /** Execution finished with success. */ + EVMC_SUCCESS = 0, + + /** Generic execution failure. */ + EVMC_FAILURE = 1, + + /** + * Execution terminated with REVERT opcode. + * + * In this case the amount of gas left MAY be non-zero and additional output + * data MAY be provided in ::evmc_result. + */ + EVMC_REVERT = 2, + + /** The execution has run out of gas. */ + EVMC_OUT_OF_GAS = 3, + + /** + * The designated INVALID instruction has been hit during execution. + * + * The EIP-141 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-141.md) + * defines the instruction 0xfe as INVALID instruction to indicate execution + * abortion coming from high-level languages. This status code is reported + * in case this INVALID instruction has been encountered. + */ + EVMC_INVALID_INSTRUCTION = 4, + + /** An undefined instruction has been encountered. */ + EVMC_UNDEFINED_INSTRUCTION = 5, + + /** + * The execution has attempted to put more items on the EVM stack + * than the specified limit. + */ + EVMC_STACK_OVERFLOW = 6, + + /** Execution of an opcode has required more items on the EVM stack. */ + EVMC_STACK_UNDERFLOW = 7, + + /** Execution has violated the jump destination restrictions. */ + EVMC_BAD_JUMP_DESTINATION = 8, + + /** + * Tried to read outside memory bounds. + * + * An example is RETURNDATACOPY reading past the available buffer. + */ + EVMC_INVALID_MEMORY_ACCESS = 9, + + /** Call depth has exceeded the limit (if any) */ + EVMC_CALL_DEPTH_EXCEEDED = 10, + + /** Tried to execute an operation which is restricted in static mode. */ + EVMC_STATIC_MODE_VIOLATION = 11, + + /** + * A call to a precompiled or system contract has ended with a failure. + * + * An example: elliptic curve functions handed invalid EC points. + */ + EVMC_PRECOMPILE_FAILURE = 12, + + /** + * Contract validation has failed (e.g. due to EVM 1.5 jump validity, + * Casper's purity checker or ewasm contract rules). + */ + EVMC_CONTRACT_VALIDATION_FAILURE = 13, + + /** + * An argument to a state accessing method has a value outside of the + * accepted range of values. + */ + EVMC_ARGUMENT_OUT_OF_RANGE = 14, + + /** + * A WebAssembly `unreachable` instruction has been hit during exection. + */ + EVMC_WASM_UNREACHABLE_INSTRUCTION = 15, + + /** + * A WebAssembly trap has been hit during execution. This can be for many + * reasons, including division by zero, validation errors, etc. + */ + EVMC_WASM_TRAP = 16, + + /** EVM implementation generic internal error. */ + EVMC_INTERNAL_ERROR = -1, + + /** + * The execution of the given code and/or message has been rejected + * by the EVM implementation. + * + * 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 ::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. + */ + EVMC_REJECTED = -2 +}; + +/* Forward declaration. */ +struct evmc_result; + +/** + * Releases resources assigned to an execution result. + * + * This function releases memory (and other resources, if any) assigned to the + * specified execution result making the result object invalid. + * + * @param result The execution result which resources are to be released. The + * result itself it not modified by this function, but becomes + * invalid and user MUST discard it as well. + * This MUST NOT be NULL. + * + * @note + * The result is passed by pointer to avoid (shallow) copy of the ::evmc_result + * struct. Think of this as the best possible C language approximation to + * passing objects by reference. + */ +typedef void (*evmc_release_result_fn)(const struct evmc_result* result); + +/** The EVM code execution result. */ +struct evmc_result +{ + /** The execution status code. */ + enum evmc_status_code status_code; + + /** + * The amount of gas left after the execution. + * + * 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 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 evmc_result::release(). + * + * This MAY be NULL. + */ + const uint8_t* output_data; + + /** + * The size of the output data. + * + * If output_data is NULL this MUST be 0. + */ + size_t output_size; + + /** + * The pointer to a function releasing all resources associated with + * the result object. + * + * This function pointer is optional (MAY be NULL) and MAY be set by + * the EVM implementation. If set it MUST be used by the user to + * release memory and other resources associated with the result object. + * After the result resources are released the result object + * MUST NOT be used any more. + * + * The suggested code pattern for releasing EVM results: + * @code + * struct evmc_result result = ...; + * if (result.release) + * result.release(&result); + * @endcode + * + * @note + * It works similarly to C++ virtual destructor. Attaching the release + * function to the result itself allows EVM composition. + */ + 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 (evmc_result::status_code is ::EVMC_SUCCESS). + */ + struct evmc_address create_address; + + /** + * 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 evmc_result struct + * to be optionally used by the evmc_result object creator. + * + * @see evmc_result_optional_data, evmc_get_optional_data(). + * + * Also extends the size of the evmc_result to 64 bytes (full cache line). + */ + uint8_t padding[4]; +}; + + +/** + * 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. + */ +typedef int (*evmc_account_exists_fn)(struct evmc_context* context, + const struct 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. + */ +typedef void (*evmc_get_storage_fn)(struct evmc_uint256be* result, + struct evmc_context* context, + const struct evmc_address* address, + const struct evmc_uint256be* key); + + +/** + * The effect of an attempt to modify a contract storage item. + * + * For the purpose of explaining the meaning of each element, the following + * notation is used: + * - 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), + * - the "->" means the change from one value to another. + */ +enum evmc_storage_status +{ + /** + * The value of a storage item has been left unchanged: 0 -> 0 and X -> X. + */ + EVMC_STORAGE_UNCHANGED = 0, + + /** + * The value of a storage item has been modified: X -> Y. + */ + EVMC_STORAGE_MODIFIED = 1, + + /** + * A new storage item has been added: 0 -> X. + */ + EVMC_STORAGE_ADDED = 2, + + /** + * A storage item has been deleted: X -> 0. + */ + EVMC_STORAGE_DELETED = 3 +}; + + +/** + * 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 ::evmc_context. + * @param address The address of the contract. + * @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. + */ +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); + +/** + * 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. + */ +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 (*evmc_get_code_size_fn)(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 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. + */ +typedef void (*evmc_get_code_hash_fn)(struct evmc_uint256be* result, + struct evmc_context* context, + const struct evmc_address* address); + +/** + * Copy code callback function. + * + * This callback function is used by an EVM to request a copy of the code + * of the given account to the memory buffer provided by the EVM. + * The Client MUST copy the requested code, starting with the given offset, + * to the provided memory buffer up to the size of the buffer or the size of + * the code, whichever is smaller. + * + * @param context The pointer to the Client execution 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 (*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. + * + * This callback function is used by an EVM to SELFDESTRUCT given contract. + * 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 ::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 (*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 ::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 (*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. + * + * @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. + */ +typedef void (*evmc_call_fn)(struct evmc_result* result, + struct evmc_context* context, + const struct evmc_message* msg); + +/** + * The context 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. + */ +struct evmc_context_fn_table +{ + /** Check account existence callback function. */ + evmc_account_exists_fn account_exists; + + /** Get storage callback function. */ + evmc_get_storage_fn get_storage; + + /** Set storage callback function. */ + evmc_set_storage_fn set_storage; + + /** Get balance callback function. */ + evmc_get_balance_fn get_balance; + + /** Get code size callback function. */ + evmc_get_code_size_fn get_code_size; + + /** Get code hash callback function. */ + evmc_get_code_hash_fn get_code_hash; + + /** Copy code callback function. */ + evmc_copy_code_fn copy_code; + + /** Selfdestruct callback function. */ + evmc_selfdestruct_fn selfdestruct; + + /** Call callback function. */ + evmc_call_fn call; + + /** Get transaction context callback function. */ + evmc_get_tx_context_fn get_tx_context; + + /** Get block hash callback function. */ + evmc_get_block_hash_fn get_block_hash; + + /** Emit log callback function. */ + evmc_emit_log_fn emit_log; +}; + + +/** + * Execution context managed by the Host. + * + * The Host MUST pass the pointer to the execution context to + * ::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 evmc_context +{ + /** Function table defining the context interface (vtable). */ + const struct evmc_context_fn_table* fn_table; +}; + + +/* Forward declaration. */ +struct evmc_instance; + +/** + * Destroys the EVM instance. + * + * @param evm The EVM instance to be destroyed. + */ +typedef void (*evmc_destroy_fn)(struct evmc_instance* evm); + + +/** + * Configures the EVM instance. + * + * Allows modifying options of the EVM instance. + * Options: + * - code cache behavior: on, off, read-only, ... + * - optimizations, + * + * @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. + */ +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 evmc_revision +{ + EVMC_FRONTIER = 0, + EVMC_HOMESTEAD = 1, + EVMC_TANGERINE_WHISTLE = 2, + EVMC_SPURIOUS_DRAGON = 3, + EVMC_BYZANTIUM = 4, + EVMC_CONSTANTINOPLE = 5, + + EVMC_LATEST_REVISION = EVMC_CONSTANTINOPLE +}; + + +/** + * Executes the given EVM bytecode using the input in the message + * + * This function MAY be invoked multiple times for a single EVM instance. + * + * @param instance The EVM instance. + * @param context The pointer to the Client execution context to be passed + * to the callback functions. @see ::evmc_context. + * @param rev Requested EVM specification revision. + * @param msg Call parameters. @see ::evmc_message. + * @param code Reference to the bytecode to be executed. + * @param code_size The length of the bytecode. + * @return All execution results. + */ +typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance, + struct evmc_context* context, + enum evmc_revision rev, + const struct evmc_message* msg, + uint8_t const* code, + size_t code_size); + + +/** The opaque type representing a Client-side tracer object. */ +struct evmc_tracer_context; + +/** + * The callback to trace instructions execution in an EVM. + * + * This function informs the Client what instruction has been executed in the EVM implementation + * and what are the results of executing this particular instruction. + * The message level information (like call depth, destination address, etc.) are not provided here. + * This piece of information can be acquired by inspecting messages being sent to the EVM in + * ::evmc_execute_fn and the results of the messages execution. + * + * @param context The pointer to the Client-side tracing context. This allows to + * implement the tracer in OOP manner. + * @param code_offset The current instruction position in the code. + * @param status_code The status code of the instruction execution. + * @param gas_left The amount of the gas left after the instruction execution. + * @param stack_num_items The current EVM stack height after the instruction execution. + * @param pushed_stack_item The top EVM stack item pushed as the result of the instruction + * execution. This value is null when the instruction does not push + * anything to the stack. + * @param memory_size The size of the EVM memory after the instruction execution. + * @param changed_memory_offset The offset in number of bytes of the beginning of the memory area + * modified as the result of the instruction execution. + * The Client MAY use this information together with + * @p changed_memory_size and @p changed_memory to incrementally + * update the copy of the full VM's memory. + * @param changed_memory_size The size of the memory area modified as the result of + * the instruction execution. + * @param changed_memory The pointer to the memory area modified as the result of + * the instruction execution. + * The Client MAY access the pointed memory area + * (limited by the @p changed_memory_size) only during the current + * execution of the evmc_trace_callback(). + * The pointer MUST NOT be stored by the Client. + * The Client MUST NOT assume that + * `changed_memory - changed_memory_offset` is a valid base pointer + * of the VM memory. + */ +typedef void (*evmc_trace_callback)(struct evmc_tracer_context* context, + size_t code_offset, + enum evmc_status_code status_code, + int64_t gas_left, + size_t stack_num_items, + const struct evmc_uint256be* pushed_stack_item, + size_t memory_size, + size_t changed_memory_offset, + size_t changed_memory_size, + const uint8_t* changed_memory); + +/** + * Sets the EVM instruction tracer. + * + * When the tracer is set in the EVM instance, the EVM SHOULD call back the tracer with information + * about instructions execution in the EVM. + * @see ::evmc_trace_callback. + * + * This will overwrite the previous settings (the callback and the context). + * + * @param instance The EVM instance. + * @param callback The tracer callback function. This argument MAY be NULL to disable previously + * set tracer. + * @param context The Client-side tracer context. This argument MAY be NULL in case the tracer + * does not require any context. This argument MUST be NULL if the callback + * argument is NULL. + */ +typedef void (*evmc_set_tracer_fn)(struct evmc_instance* instance, + evmc_trace_callback callback, + struct evmc_tracer_context* context); + + +/** + * The EVM instance. + * + * Defines the base struct of the EVM implementation. + */ +struct evmc_instance +{ + /** + * EVMC ABI version implemented by the EVM instance. + * + * Used to detect ABI incompatibilities. The EVMC ABI version + * represented by this file is in ::EVMC_ABI_VERSION. + */ + const int abi_version; + + /** + * The name of the EVMC VM implementation. + * + * It MUST be a NULL-terminated not empty string. + */ + const char* name; + + /** + * The version of the EVMC VM implementation, e.g. "1.2.3b4". + * + * It MUST be a NULL-terminated not empty string. + */ + const char* version; + + /** Pointer to function destroying the EVM instance. */ + evmc_destroy_fn destroy; + + /** Pointer to function executing a code by the EVM instance. */ + evmc_execute_fn execute; + + /** + * Optional pointer to function setting the EVM instruction tracer. + * + * If the EVM does not support this feature the pointer can be NULL. + */ + evmc_set_tracer_fn set_tracer; + + /** + * Optional pointer to function modifying VM's options. + * + * If the VM does not support this feature the pointer can be NULL. + */ + evmc_set_option_fn set_option; +}; + +/* END Python CFFI declarations */ + +#if EVMC_DOCUMENTATION +/** + * Example of a function creating an instance of an example EVM implementation. + * + * Each EVM implementation MUST provide a function returning an EVM instance. + * The function SHOULD be named `evmc_create_(void)`. If the VM name contains hyphens + * replaces them with underscores in the function names. + * + * @par Binaries naming convention + * For VMs distributed as shared libraries, the name of the library SHOULD match the VM name. + * The convetional library filename prefixes and extensions SHOULD be ignored by the Client. + * For example, the shared library with the "beta-interpreter" implementation may be named + * `libbeta-interpreter.so`. + * + * @return EVM instance or NULL indicating instance creation failure. + */ +struct evmc_instance* evmc_create_examplevm(void); +#endif + +#if __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h b/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h new file mode 100644 index 0000000000..55fa0dc5bc --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/helpers.h @@ -0,0 +1,155 @@ +/* EVMC: Ethereum Client-VM Connector API. + * Copyright 2018 The EVMC Authors. + * Licensed under the Apache License, Version 2.0. See the LICENSE file. + */ + +/** + * EVMC Helpers + * + * A collection of helper functions for invoking a VM instance methods. + * These are convenient for languages where invoking function pointers + * is "ugly" or impossible (such as Go). + * + * @defgroup helpers EVMC Helpers + * @{ + */ +#pragma once + +#include + +/** + * Returns true if the VM instance has a compatible ABI version. + */ +static inline int evmc_is_abi_compatible(struct evmc_instance* instance) +{ + return instance->abi_version == EVMC_ABI_VERSION; +} + +/** + * Returns the name of the VM instance. + */ +static inline const char* evmc_vm_name(struct evmc_instance* instance) +{ + return instance->name; +} + +/** + * Returns the version of the VM instance. + */ +static inline const char* evmc_vm_version(struct evmc_instance* instance) +{ + return instance->version; +} + +/** + * Destroys the VM instance. + * + * @see evmc_destroy_fn + */ +static inline void evmc_destroy(struct evmc_instance* instance) +{ + instance->destroy(instance); +} + +/** + * Sets the option for the VM instance, if the feature is supported by the VM. + * + * @see evmc_set_option_fn + */ +static inline int 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; +} + +/** + * Sets the tracer callback for the VM instance, if the feature is supported by the VM. + * + * @see evmc_set_tracer_fn + */ +static inline void evmc_set_tracer(struct evmc_instance* instance, + evmc_trace_callback callback, + struct evmc_tracer_context* context) +{ + if (instance->set_tracer) + instance->set_tracer(instance, callback, context); +} + +/** + * Executes code in the VM instance. + * + * @see evmc_execute_fn. + */ +static inline struct evmc_result evmc_execute(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) +{ + return instance->execute(instance, context, rev, msg, code, code_size); +} + +/** + * Releases the resources allocated to the execution result. + * + * @see evmc_release_result_fn + */ +static inline void evmc_release_result(struct evmc_result* result) +{ + result->release(result); +} + + +/** + * Helpers for optional storage of evmc_result. + * + * In some contexts (i.e. evmc_result::create_address is unused) objects of + * type evmc_result contains a memory storage that MAY be used by the object + * owner. This group defines helper types and functions for accessing + * the optional storage. + * + * @defgroup result_optional_storage Result Optional Storage + * @{ + */ + +/** + * The union representing evmc_result "optional storage". + * + * The evmc_result struct contains 24 bytes of optional storage that can be + * reused by the object creator if the object does not contain + * evmc_result::create_address. + * + * A VM implementation MAY use this memory to keep additional data + * 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 evmc_call_fn(). + * + * @see evmc_get_optional_storage(), evmc_get_const_optional_storage(). + */ +union evmc_result_optional_storage +{ + uint8_t bytes[24]; /**< 24 bytes of optional storage. */ + void* pointer; /**< Optional pointer. */ +}; + +/** Provides read-write access to evmc_result "optional storage". */ +static inline union evmc_result_optional_storage* evmc_get_optional_storage( + struct evmc_result* result) +{ + return (union evmc_result_optional_storage*)&result->create_address; +} + +/** Provides read-only access to evmc_result "optional storage". */ +static inline const union evmc_result_optional_storage* evmc_get_const_optional_storage( + const struct evmc_result* result) +{ + return (const union evmc_result_optional_storage*)&result->create_address; +} + +/** @} */ + +/** @} */ diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c new file mode 100644 index 0000000000..53e3bfbdf2 --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c @@ -0,0 +1,28 @@ +/* EVMC: Ethereum Client-VM Connector API. + * Copyright 2018 The EVMC Authors. + * Licensed under the Apache License, Version 2.0. See the LICENSE file. + */ + +#include "_cgo_export.h" + +#include + +const struct evmc_context_fn_table evmc_go_fn_table = { + (evmc_account_exists_fn)accountExists, + (evmc_get_storage_fn)getStorage, + (evmc_set_storage_fn)setStorage, + (evmc_get_balance_fn)getBalance, + (evmc_get_code_size_fn)getCodeSize, + (evmc_get_code_hash_fn)getCodeHash, + (evmc_copy_code_fn)copyCode, + (evmc_selfdestruct_fn)selfdestruct, + (evmc_call_fn)call, + (evmc_get_tx_context_fn)getTxContext, + (evmc_get_block_hash_fn)getBlockHash, + (evmc_emit_log_fn)emitLog, +}; + +void evmc_go_free_result_output(const struct evmc_result* result) +{ + free((void*)result->output_data); +} diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go new file mode 100644 index 0000000000..47f4f638fb --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/host.go @@ -0,0 +1,238 @@ +// EVMC: Ethereum Client-VM Connector API. +// Copyright 2018 The EVMC Authors. +// Licensed under the Apache License, Version 2.0. See the LICENSE file. + +package evmc + +/* +#cgo CFLAGS: -I${SRCDIR}/.. -Wall -Wextra -Wno-unused-parameter + +#include + +struct extended_context +{ + struct evmc_context context; + int64_t index; +}; + +void evmc_go_free_result_output(const struct evmc_result* result); + +*/ +import "C" +import ( + "math/big" + "unsafe" + + "github.com/ethereum/go-ethereum/common" +) + +type CallKind int + +const ( + Call CallKind = C.EVMC_CALL + DelegateCall CallKind = C.EVMC_DELEGATECALL + CallCode CallKind = C.EVMC_CALLCODE + Create CallKind = C.EVMC_CREATE + Create2 CallKind = C.EVMC_CREATE2 +) + +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 +) + +func goAddress(in C.struct_evmc_address) common.Address { + out := common.Address{} + for i := 0; i < len(out); i++ { + out[i] = byte(in.bytes[i]) + } + return out +} + +func goHash(in C.struct_evmc_uint256be) common.Hash { + out := common.Hash{} + for i := 0; i < len(out); i++ { + out[i] = byte(in.bytes[i]) + } + return out +} + +func goByteSlice(data *C.uint8_t, size C.size_t) []byte { + if size == 0 { + return []byte{} + } + return (*[1 << 30]byte)(unsafe.Pointer(data))[:size:size] +} + +type HostContext interface { + AccountExists(addr common.Address) bool + GetStorage(addr common.Address, key common.Hash) common.Hash + SetStorage(addr common.Address, key common.Hash, value common.Hash) StorageStatus + GetBalance(addr common.Address) common.Hash + GetCodeSize(addr common.Address) int + GetCodeHash(addr common.Address) common.Hash + GetCode(addr common.Address) []byte + Selfdestruct(addr common.Address, beneficiary common.Address) + GetTxContext() (gasPrice common.Hash, origin common.Address, coinbase common.Address, number int64, timestamp int64, + gasLimit int64, difficulty common.Hash) + GetBlockHash(number int64) common.Hash + EmitLog(addr common.Address, topics []common.Hash, data []byte) + Call(kind CallKind, + destination common.Address, sender common.Address, value *big.Int, input []byte, gas int64, depth int, + static bool) (output []byte, gasLeft int64, createAddr common.Address, err error) +} + +//export accountExists +func accountExists(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.int { + 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 +} + +//export getStorage +func getStorage(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struct_evmc_uint256be) { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + value := ctx.GetStorage(goAddress(*pAddr), goHash(*pKey)) + *pResult = evmcUint256be(value) +} + +//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 { + 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) { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + balance := ctx.GetBalance(goAddress(*pAddr)) + *pResult = evmcUint256be(balance) +} + +//export getCodeSize +func getCodeSize(pCtx unsafe.Pointer, pAddr *C.struct_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) { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + *pResult = evmcUint256be(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 { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + code := ctx.GetCode(goAddress(*pAddr)) + length := C.size_t(len(code)) + + if offset >= length { + return 0 + } + + toCopy := length - offset + if toCopy > size { + toCopy = size + } + + out := goByteSlice(p, size) + copy(out, code[offset:]) + return toCopy +} + +//export selfdestruct +func selfdestruct(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pBeneficiary *C.struct_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) { + 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), + evmcAddress(origin), + evmcAddress(coinbase), + C.int64_t(number), + C.int64_t(timestamp), + C.int64_t(gasLimit), + evmcUint256be(difficulty), + } +} + +//export getBlockHash +func getBlockHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, number int64) { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + + *pResult = evmcUint256be(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) { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + + // FIXME: Optimize memory copy + data := C.GoBytes(pData, C.int(dataSize)) + tData := C.GoBytes(pTopics, C.int(topicsCount*32)) + + nTopics := int(topicsCount) + topics := make([]common.Hash, nTopics) + for i := 0; i < nTopics; i++ { + copy(topics[i][:], tData[i*32:(i+1)*32]) + } + + ctx.EmitLog(goAddress(*pAddr), topics, data) +} + +//export call +func call(pResult *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc_message) { + idx := int((*C.struct_extended_context)(pCtx).index) + ctx := getHostContext(idx) + + kind := CallKind(msg.kind) + output, gasLeft, createAddr, err := ctx.Call(kind, goAddress(msg.destination), goAddress(msg.sender), goHash(msg.value).Big(), + goByteSlice(msg.input_data, msg.input_size), int64(msg.gas), int(msg.depth), msg.flags != 0) + + statusCode := C.enum_evmc_status_code(0) + if err != nil { + statusCode = C.enum_evmc_status_code(err.(Error)) + } + + result := C.struct_evmc_result{} + result.status_code = statusCode + result.gas_left = C.int64_t(gasLeft) + result.create_address = evmcAddress(createAddr) + + if len(output) > 0 { + // TODO: We could pass it directly to the caller without a copy. The caller should release it. Check depth. + cOutput := C.CBytes(output) + result.output_data = (*C.uint8_t)(cOutput) + result.output_size = C.size_t(len(output)) + result.release = (C.evmc_release_result_fn)(C.evmc_go_free_result_output) + } + + *pResult = 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 new file mode 100644 index 0000000000..252b6e6d31 --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.c @@ -0,0 +1,153 @@ +/* EVMC: Ethereum Client-VM Connector API. + * Copyright 2018 The EVMC Authors. + * Licensed under the Apache License, Version 2.0. See the LICENSE file. + */ + +#include + +#include +#include + +#include +#include + +#if _WIN32 +#include +#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 HAVE_STRCPY_S 1 +#else +#include +#define DLL_HANDLE void* +#define DLL_OPEN(filename) dlopen(filename, RTLD_LAZY) +#define DLL_CLOSE(handle) dlclose(handle) +#define DLL_GET_CREATE_FN(handle, name) (evmc_create_fn)(uintptr_t) dlsym(handle, name) +#define HAVE_STRCPY_S 0 +#endif + +#define PATH_MAX_LENGTH 4096 + +#if !HAVE_STRCPY_S +static void strcpy_s(char* dest, size_t destsz, const char* src) +{ + size_t len = strlen(src); + if (len > destsz - 1) + len = destsz - 1; + memcpy(dest, src, len); + dest[len] = 0; +} +#endif + + +evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* error_code) +{ + enum evmc_loader_error_code ec = EVMC_LOADER_SUCCESS; + evmc_create_fn create_fn = NULL; + + if (!filename) + { + ec = EVMC_LOADER_INVALID_ARGUMENT; + goto exit; + } + + const size_t length = strlen(filename); + if (length == 0 || length > PATH_MAX_LENGTH) + { + ec = EVMC_LOADER_INVALID_ARGUMENT; + goto exit; + } + + DLL_HANDLE handle = DLL_OPEN(filename); + if (!handle) + { + ec = EVMC_LOADER_CANNOT_OPEN; + goto exit; + } + + // 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); + + // Find filename in the path. + const char* sep_pos = strrchr(filename, '/'); +#if _WIN32 + // On Windows check also Windows classic path separator. + const char* sep_pos_windows = strrchr(filename, '\\'); + sep_pos = sep_pos_windows > sep_pos ? sep_pos_windows : sep_pos; +#endif + const char* name_pos = sep_pos ? sep_pos + 1 : filename; + + // Skip "lib" prefix if present. + const char lib_prefix[] = "lib"; + const size_t lib_prefix_length = strlen(lib_prefix); + 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); + + // Trim the file extension. + char* ext_pos = strrchr(name, '.'); + if (ext_pos) + *ext_pos = 0; + + // Replace all "-" with "_". + char* dash_pos = 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) + { + // 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); + } + } + + if (!create_fn) + create_fn = DLL_GET_CREATE_FN(handle, "evmc_create"); + + if (!create_fn) + { + DLL_CLOSE(handle); + ec = EVMC_LOADER_SYMBOL_NOT_FOUND; + } + +exit: + if (error_code) + *error_code = ec; + return create_fn; +} + +struct evmc_instance* evmc_load_and_create(const char* filename, + enum evmc_loader_error_code* error_code) +{ + evmc_create_fn create_fn = evmc_load(filename, error_code); + + if (!create_fn) + return NULL; + + struct evmc_instance* instance = create_fn(); + if (!instance) + { + *error_code = EVMC_LOADER_INSTANCE_CREATION_FAILURE; + return NULL; + } + + if (!evmc_is_abi_compatible(instance)) + { + *error_code = EVMC_LOADER_ABI_VERSION_MISMATCH; + return NULL; + } + + return instance; +} diff --git a/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h new file mode 100644 index 0000000000..b6492635fc --- /dev/null +++ b/vendor/github.com/ethereum/evmc/bindings/go/evmc/loader.h @@ -0,0 +1,109 @@ +/* EVMC: Ethereum Client-VM Connector API. + * Copyright 2018 The EVMC Authors. + * Licensed under the Apache License, Version 2.0. See the LICENSE file. + */ + +/** + * EVMC Loader Library + * + * The EVMC Loader Library supports loading VMs implemented as Dynamically Loaded Libraries + * (DLLs, shared objects). + * + * @defgroup loader EVMC Loader + * @{ + */ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +/** The function pointer type for EVMC create functions. */ +typedef struct evmc_instance* (*evmc_create_fn)(void); + +/** Error codes for the EVMC loader. */ +enum evmc_loader_error_code +{ + /** The loader succeeded. */ + EVMC_LOADER_SUCCESS = 0, + + /** The loader cannot open the given file name. */ + EVMC_LOADER_CANNOT_OPEN = 1, + + /** The VM create function not found. */ + EVMC_LOADER_SYMBOL_NOT_FOUND = 2, + + /** The invalid argument value provided. */ + EVMC_LOADER_INVALID_ARGUMENT = 3, + + /** The creation of a VM instance has failed. */ + EVMC_LOADER_INSTANCE_CREATION_FAILURE = 4, + + /** The ABI version of the VM instance has mismatched. */ + EVMC_LOADER_ABI_VERSION_MISMATCH = 5, +}; + +/** + * Dynamically loads the shared object (DLL) with an EVM implementation. + * + * This function tries to open a DLL at the given `filename`. On UNIX-like systems dlopen() function + * is used. On Windows LoadLibrary() function is used. + * + * If the file does not exist or is not a valid shared library the ::EVMC_LOADER_CANNOT_OPEN error + * code is signaled and NULL is returned. + * + * After the DLL is successfully loaded the function tries to find the EVM create function in the + * library. The `filename` is used to guess the EVM name and the name of the create function. + * The create function name is constructed by the following rules. Consider example path: + * "/ethereum/libexample-interpreter.so". + * - the filename is taken from the path: + * "libexample-interpreter.so", + * - the "lib" prefix and file extension are stripped from the name: + * "example-interpreter" + * - all "-" are replaced with "_" to construct _full 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: + * "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 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. + * + * It is safe to call this function with the same filename argument multiple times + * (the DLL is not going to be loaded multiple times). + * + * @param filename The null terminated path (absolute or relative) to the shared library + * containing the EVM implementation. If the value is NULL, an empty C-string + * or longer than the path maximum length the ::EVMC_LOADER_INVALID_ARGUMENT is + * signaled. + * @param error_code The pointer to the error code. If not NULL the value is set to + * ::EVMC_LOADER_SUCCESS on success or any other error code as described above. + * @return The pointer to the EVM create function or NULL. + */ +evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* error_code); + +/** + * Dynamically loads the VM DLL and creates the VM instance. + * + * This is a macro for creating the VM instance with the function returned from evmc_load(). + * The function signals the same errors as evmc_load() and additionally: + * - ::EVMC_LOADER_INSTANCE_CREATION_FAILURE when the create function returns NULL, + * - ::EVMC_LOADER_ABI_VERSION_MISMATCH when the created VM instance has ABI version different + * from the ABI version of this library (::EVMC_ABI_VERSION). + * + * It is safe to call this function with the same filename argument multiple times: + * the DLL is not going to be loaded multiple times, but the function will return new VM instance + * each time. + */ +struct evmc_instance* evmc_load_and_create(const char* filename, + enum evmc_loader_error_code* error_code); + +#if __cplusplus +} +#endif + +/** @} */ diff --git a/vendor/vendor.json b/vendor/vendor.json index 06268535e9..2def95088a 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -104,6 +104,14 @@ "revision": "a3814ce5008e612a0c6d027608b54e1d0d9a5613", "revisionTime": "2018-01-22T22:25:45Z" }, + { + "checksumSHA1": "gvcZHEaRD0J5Y6QrFTo0GrR2TkE=", + "path": "github.com/ethereum/evmc/bindings/go/evmc", + "revision": "224080ef8c8d99f5cfe59067a3bd995be23349bf", + "revisionTime": "2018-08-28T21:11:56Z", + "version": "=v5.2.0", + "versionExact": "v5.2.0" + }, { "checksumSHA1": "7oFpbmDfGobwKsFLIf6wMUvVoKw=", "path": "github.com/fatih/color",