Merge remote-tracking branch 'ewasm/evmc-v6' into release/1.8-evmc6

This commit is contained in:
Paweł Bylica 2018-11-29 10:48:27 +01:00
commit 4983d55fbb
No known key found for this signature in database
GPG key ID: 7A0C037434FE77EF
18 changed files with 3290 additions and 15 deletions

View file

@ -140,24 +140,21 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
} }
if chainConfig.IsEWASM(ctx.BlockNumber) { if chainConfig.IsEWASM(ctx.BlockNumber) {
// to be implemented by EVM-C and Wagon PRs. if vmConfig.EWASMInterpreter != "" {
// if vmConfig.EWASMInterpreter != "" { evm.interpreters = append(evm.interpreters, NewEVMC(vmConfig.EWASMInterpreter, evm))
// extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":") } else {
// path := extIntOpts[0] panic("The default ewasm interpreter not supported yet.")
// options := []string{} }
// if len(extIntOpts) > 1 {
// options = extIntOpts[1..]
// }
// evm.interpreters = append(evm.interpreters, NewEVMVCInterpreter(evm, vmConfig, options))
// } else {
// evm.interpreters = append(evm.interpreters, NewEWASMInterpreter(evm, vmConfig))
// }
panic("No supported ewasm interpreter yet.")
} }
// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here if vmConfig.EVMInterpreter != "" {
// as we always want to have the built-in EVM as the failover option. // Create custom EVM.
evm.interpreters = append(evm.interpreters, NewEVMC(vmConfig.EVMInterpreter, evm))
}
// Keep the built-in EVM as the failover option.
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig)) evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))
evm.interpreter = evm.interpreters[0] evm.interpreter = evm.interpreters[0]
return evm return evm

325
core/vm/evmc.go Normal file
View file

@ -0,0 +1,325 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package vm
import (
"bytes"
"fmt"
"math/big"
"strings"
"sync"
"github.com/ethereum/evmc/bindings/go/evmc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
type EVMC struct {
instance *evmc.Instance
env *EVM
readOnly bool // TODO: The readOnly flag should not be here.
}
var (
createMu sync.Mutex
evmcConfig string // The configuration the instance was created with.
evmcInstance *evmc.Instance
)
func createVM(config string) *evmc.Instance {
createMu.Lock()
defer createMu.Unlock()
if evmcInstance == nil {
options := strings.Split(config, ",")
path := options[0]
if path == "" {
panic("EVMC VM path not provided, set --vm.(evm|ewasm)=/path/to/vm")
}
var err error
evmcInstance, err = evmc.Load(path)
if err != nil {
panic(err.Error())
}
log.Info("EVMC VM loaded", "name", evmcInstance.Name(), "version", evmcInstance.Version(), "path", path)
for _, option := range options[1:] {
if idx := strings.Index(option, "="); idx >= 0 {
name := option[:idx]
value := option[idx+1:]
err := evmcInstance.SetOption(name, value)
if err == nil {
log.Info("EVMC VM option set", "name", name, "value", value)
} else {
log.Warn("EVMC VM option setting failed", "name", name, "error", err)
}
}
}
evm1Cap := evmcInstance.HasCapability(evmc.CapabilityEVM1)
ewasmCap := evmcInstance.HasCapability(evmc.CapabilityEWASM)
log.Info("EVMC VM capabilities", "evm1", evm1Cap, "ewasm", ewasmCap)
evmcConfig = config // Remember the config.
} else if evmcConfig != config {
log.Error("New EVMC VM requested", "newconfig", config, "oldconfig", evmcConfig)
}
return evmcInstance
}
func NewEVMC(options string, env *EVM) *EVMC {
return &EVMC{createVM(options), env, false}
}
// Implements evmc.HostContext interface.
type HostContext struct {
env *EVM
contract *Contract
}
func (host *HostContext) AccountExists(addr common.Address) bool {
env := host.env
eip158 := env.ChainConfig().IsEIP158(env.BlockNumber)
if eip158 {
if !env.StateDB.Empty(addr) {
return true
}
} else if env.StateDB.Exist(addr) {
return true
}
return false
}
func (host *HostContext) GetStorage(addr common.Address, key common.Hash) common.Hash {
env := host.env
return env.StateDB.GetState(addr, key)
}
func (host *HostContext) SetStorage(addr common.Address, key common.Hash, value common.Hash) (status evmc.StorageStatus) {
env := host.env
oldValue := env.StateDB.GetState(addr, key)
if oldValue == value {
return evmc.StorageUnchanged
}
env.StateDB.SetState(addr, key, value)
zero := common.Hash{}
status = evmc.StorageModified
if oldValue == zero {
return evmc.StorageAdded
} else if value == zero {
env.StateDB.AddRefund(params.SstoreRefundGas)
return evmc.StorageDeleted
}
return evmc.StorageModified
}
func (host *HostContext) GetBalance(addr common.Address) common.Hash {
env := host.env
balance := env.StateDB.GetBalance(addr)
return common.BigToHash(balance)
}
func (host *HostContext) GetCodeSize(addr common.Address) int {
env := host.env
return env.StateDB.GetCodeSize(addr)
}
func (host *HostContext) GetCodeHash(addr common.Address) common.Hash {
env := host.env
return env.StateDB.GetCodeHash(addr)
}
func (host *HostContext) GetCode(addr common.Address) []byte {
env := host.env
return env.StateDB.GetCode(addr)
}
func (host *HostContext) Selfdestruct(addr common.Address, beneficiary common.Address) {
env := host.env
db := env.StateDB
if !db.HasSuicided(addr) {
db.AddRefund(params.SuicideRefundGas)
}
balance := db.GetBalance(addr)
db.AddBalance(beneficiary, balance)
db.Suicide(addr)
}
func (host *HostContext) GetTxContext() (gasPrice common.Hash, origin common.Address, coinbase common.Address,
number int64, timestamp int64, gasLimit int64, difficulty common.Hash) {
env := host.env
gasPrice = common.BigToHash(env.GasPrice)
origin = env.Origin
coinbase = env.Coinbase
number = env.BlockNumber.Int64()
timestamp = env.Time.Int64()
gasLimit = int64(env.GasLimit)
difficulty = common.BigToHash(env.Difficulty)
return gasPrice, origin, coinbase, number, timestamp, gasLimit, difficulty
}
func (host *HostContext) GetBlockHash(number int64) common.Hash {
env := host.env
b := env.BlockNumber.Int64()
if number >= (b-256) && number < b {
return env.GetHash(uint64(number))
}
return common.Hash{}
}
func (host *HostContext) EmitLog(addr common.Address, topics []common.Hash, data []byte) {
env := host.env
env.StateDB.AddLog(&types.Log{
Address: addr,
Topics: topics,
Data: data,
BlockNumber: env.BlockNumber.Uint64(),
})
}
func (host *HostContext) Call(kind evmc.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) {
env := host.env
gasU := uint64(gas)
var gasLeftU uint64
switch kind {
case evmc.Call:
if static {
output, gasLeftU, err = env.StaticCall(host.contract, destination, input, gasU)
} else {
output, gasLeftU, err = env.Call(host.contract, destination, input, gasU, value)
}
case evmc.DelegateCall:
output, gasLeftU, err = env.DelegateCall(host.contract, destination, input, gasU)
case evmc.CallCode:
output, gasLeftU, err = env.CallCode(host.contract, destination, input, gasU, value)
case evmc.Create:
var createOutput []byte
createOutput, createAddr, gasLeftU, err = env.Create(host.contract, input, gasU, value)
isHomestead := env.ChainConfig().IsHomestead(env.BlockNumber)
if !isHomestead && err == ErrCodeStoreOutOfGas {
err = nil
}
if err == errExecutionReverted {
// Assign return buffer from REVERT.
// TODO: Bad API design: return data buffer and the code is returned in the same place. In worst case
// the code is returned also when there is not enough funds to deploy the code.
output = createOutput
}
}
// Map errors.
if err == errExecutionReverted {
err = evmc.Revert
} else if err != nil {
err = evmc.Failure
}
gasLeft = int64(gasLeftU)
return output, gasLeft, createAddr, err
}
func getRevision(env *EVM) evmc.Revision {
n := env.BlockNumber
conf := env.ChainConfig()
if conf.IsConstantinople(n) {
return evmc.Constantinople
}
if conf.IsByzantium(n) {
return evmc.Byzantium
}
if conf.IsEIP158(n) {
return evmc.SpuriousDragon
}
if conf.IsEIP150(n) {
return evmc.TangerineWhistle
}
if conf.IsHomestead(n) {
return evmc.Homestead
}
return evmc.Frontier
}
func (evm *EVMC) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
evm.env.depth++
defer func() { evm.env.depth-- }()
// Don't bother with the execution if there's no code.
if len(contract.Code) == 0 {
return nil, nil
}
kind := evmc.Call
if evm.env.StateDB.GetCodeSize(contract.Address()) == 0 {
// Guess if this is a CREATE.
kind = evmc.Create
}
// Make sure the readOnly is only set if we aren't in readOnly yet.
// This makes also sure that the readOnly flag isn't removed for child calls.
if readOnly && !evm.readOnly {
evm.readOnly = true
defer func() { evm.readOnly = false }()
}
output, gasLeft, err := evm.instance.Execute(
&HostContext{evm.env, contract},
getRevision(evm.env),
kind,
evm.readOnly,
evm.env.depth-1,
int64(contract.Gas),
contract.Address(),
contract.Caller(),
input,
common.BigToHash(contract.value),
contract.Code,
common.Hash{})
contract.Gas = uint64(gasLeft)
if err == evmc.Revert {
err = errExecutionReverted
} else if evmcError, ok := err.(evmc.Error); ok && evmcError.IsInternalError() {
panic(fmt.Sprintf("EVMC VM internal error: %s", evmcError.Error()))
}
return output, err
}
func (evm *EVMC) CanRun(code []byte) bool {
cap := evmc.CapabilityEVM1
wasmPreamble := []byte("\x00asm\x01\x00\x00\x00")
if bytes.HasPrefix(code, wasmPreamble) {
cap = evmc.CapabilityEWASM
}
// FIXME: Optimize. Access capabilities once.
return evm.instance.HasCapability(cap)
}

6
vendor/github.com/ethereum/evmc/AUTHORS.md generated vendored Normal file
View file

@ -0,0 +1,6 @@
# EVMC Authors
> The sorted list of EVMC authors for copyright purposes.
- Alex Beregszaszi
- Pawel Bylica [@chfast](https://github.com/chfast) <pawel@ethereum.org>

85
vendor/github.com/ethereum/evmc/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,85 @@
# Changelog
## [6.0.0] - 2018-10-24
- Added: [[#116](https://github.com/ethereum/evmc/pull/116)]
[EVMC Host implementation example](https://github.com/ethereum/evmc/blob/master/examples/example_host.cpp).
- Added: [[#127](https://github.com/ethereum/evmc/pull/127)]
Support for Constantinople SSTORE net gas metering.
- Added: [[#133](https://github.com/ethereum/evmc/pull/133)]
Support for Constantinople CREATE2 salt in Go bindings.
- Added: [[#144](https://github.com/ethereum/evmc/pull/144)]
A VM can now report its **capabilities** (i.e. EVM and/or ewasm).
- Added: [[#159](https://github.com/ethereum/evmc/pull/159)]
[EVMC Host implementation guide](https://ethereum.github.io/evmc/hostguide.html).
- Added: [[#160](https://github.com/ethereum/evmc/pull/160)]
[EVMC VM implementation guide](https://ethereum.github.io/evmc/vmguide.html).
- Changed: [[#119](https://github.com/ethereum/evmc/pull/119)]
EVMC loader symbol searching has been generalized.
- Changed: [[#125](https://github.com/ethereum/evmc/pull/125)]
The `evmc_context_fn_table` renamed to `evmc_host_interface`.
- Changed: [[#128](https://github.com/ethereum/evmc/pull/128)]
The `evmc_message` fields reordered.
- Changed: [[#136](https://github.com/ethereum/evmc/pull/136)]
The `evmc_set_option()` now returns more information about the failure cause.
- Changed: [[#138](https://github.com/ethereum/evmc/pull/138)], [[#140](https://github.com/ethereum/evmc/pull/140)]
In C the `bool` type is used instead of `int` for true/false flags.
- Changed: [[#152](https://github.com/ethereum/evmc/pull/152)]
Introduction of the `evmc_bytes32` type.
- Changed: [[#154](https://github.com/ethereum/evmc/pull/154)]
Simplification of signatures of Host methods.
## [5.2.0] - 2018-08-28
- Feature: [[#81](https://github.com/ethereum/evmc/pull/81)]
Use also "evmc_create" function name for loading EVMC DLLs.
- Fix: [[#92](https://github.com/ethereum/evmc/pull/92)]
The evmc.h header compatibility with C++98 fixed.
- Fix: [[#93](https://github.com/ethereum/evmc/pull/93)], [[#103](https://github.com/ethereum/evmc/pull/103)]
Compilation and build configuration fixes.
- Improved: [[#97](https://github.com/ethereum/evmc/pull/97)], [[#107](https://github.com/ethereum/evmc/pull/107)]
Documentation improvements, including documentation for the VM Tester.
## [5.1.0] - 2018-08-23
- Feature: [[#41](https://github.com/ethereum/evmc/pull/41)]
Go language bindings for EVMC.
- Feature: [[#56](https://github.com/ethereum/evmc/pull/56), [#62](https://github.com/ethereum/evmc/pull/62)]
New error codes.
- Feature: [[#67](https://github.com/ethereum/evmc/pull/67), [#68](https://github.com/ethereum/evmc/pull/68), [#70](https://github.com/ethereum/evmc/pull/70)]
More helper functions.
- Fix: [[#72](https://github.com/ethereum/evmc/pull/72)]
Go bindings: Properly handle unknown error codes.
- Improved: [[#58](https://github.com/ethereum/evmc/pull/58)]
Documentation has been extended.
- Improved: [[#59](https://github.com/ethereum/evmc/pull/59)]
Optional Result Storage helper module has been separated.
- Improved: [[#75](https://github.com/ethereum/evmc/pull/75)]
Cable upgraded to 0.2.11.
- Improved: [[#77](https://github.com/ethereum/evmc/pull/77)]
The license changed from MIT to Apache 2.0.
## [5.0.0] - 2018-08-10
- Feature: [[#23](https://github.com/ethereum/evmc/pull/23), [#24](https://github.com/ethereum/evmc/pull/24)]
List of status codes extended and reordered.
- Feature: [[#32](https://github.com/ethereum/evmc/pull/32)]
VM Tracing API.
- Feature: [[#33](https://github.com/ethereum/evmc/pull/33), [#34](https://github.com/ethereum/evmc/pull/34)]
The support library with metrics tables for EVM1 instructions.
- Feature: [[#35](https://github.com/ethereum/evmc/pull/35)]
Ability to create EVMC CMake package.
- Feature: [[#40](https://github.com/ethereum/evmc/pull/40)]
The loader support library for VM dynamic loading.
- Feature: [[#45](https://github.com/ethereum/evmc/pull/45)]
Constantinople: Support for `CREATE2` instruction.
- Feature: [[#49](https://github.com/ethereum/evmc/pull/49)]
Constantinople: Support for `EXTCODEHASH` instruction.
- Feature: [[#52](https://github.com/ethereum/evmc/pull/52)]
Constantinople: Storage status is reported back from `evmc_set_storage()`.
[6.0.0]: https://github.com/ethereum/evmc/releases/tag/v6.0.0
[5.2.0]: https://github.com/ethereum/evmc/releases/tag/v5.2.0
[5.1.0]: https://github.com/ethereum/evmc/releases/tag/v5.1.0
[5.0.0]: https://github.com/ethereum/evmc/releases/tag/v5.0.0

82
vendor/github.com/ethereum/evmc/CMakeLists.txt generated vendored Normal file
View file

@ -0,0 +1,82 @@
# EVMC: Ethereum Client-VM Connector API.
# Copyright 2018 The EVMC Authors.
# Licensed under the Apache License, Version 2.0. See the LICENSE file.
cmake_minimum_required(VERSION 3.5)
if(TARGET evmc)
# The evmc library has been already created (probably by other submodule).
return()
endif()
option(EVMC_TESTING "Build EVMC tests and test tools" OFF)
option(EVMC_EXAMPLES "Build EVMC examples" ${EVMC_TESTING})
option(HUNTER_ENABLED "Enable Hunter package manager support" "${EVMC_TESTING}")
include(cmake/cable/bootstrap.cmake)
include(CableBuildType)
include(CableCompilerSettings)
include(CMakePackageConfigHelpers)
include(HunterGate)
include(GNUInstallDirs)
include(defaults/HunterCacheServers)
include(HunterConfig)
project(evmc)
set(PROJECT_VERSION 6.0.0)
cable_set_build_type(DEFAULT Release CONFIGURATION_TYPES Debug Release)
cable_configure_compiler(NO_STACK_PROTECTION)
set(include_dir ${PROJECT_SOURCE_DIR}/include)
add_library(evmc INTERFACE)
add_library(evmc::evmc ALIAS evmc)
target_include_directories(evmc INTERFACE $<BUILD_INTERFACE:${include_dir}>$<INSTALL_INTERFACE:include>)
install(TARGETS evmc EXPORT evmcTargets)
install(DIRECTORY include/evmc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
add_subdirectory(lib)
if(EVMC_TESTING)
enable_testing()
add_subdirectory(test)
endif()
if(EVMC_EXAMPLES OR EVMC_TESTING)
add_subdirectory(examples)
endif()
write_basic_package_version_file(evmcConfigVersion.cmake COMPATIBILITY ExactVersion)
configure_package_config_file(
cmake/Config.cmake.in
evmcConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/evmc
)
install(
EXPORT evmcTargets
NAMESPACE evmc::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/evmc
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/evmcConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/evmcConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/evmc
)
if(WIN32)
set(CPACK_GENERATOR ZIP)
else()
set(CPACK_GENERATOR TGZ)
endif()
string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME}-${PROJECT_VERSION}-${system_name})
set(CPACK_PACKAGE_CHECKSUM SHA256)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY FALSE)
include(CPack)

319
vendor/github.com/ethereum/evmc/Doxyfile generated vendored Normal file
View file

@ -0,0 +1,319 @@
# Doxyfile 1.8.9.1
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "EVMC"
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = YES
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = \
include/evmc/evmc.h include/evmc/helpers.h include/evmc/helpers.hpp include/evmc/loader.h include/evmc/utils.h include/evmc/instructions.h \
docs/ \
examples/example_vm.c
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = YES
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = .
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = YES
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = NO
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = EVMC_DOCUMENTATION=1
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

202
vendor/github.com/ethereum/evmc/LICENSE generated vendored Normal file
View file

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

67
vendor/github.com/ethereum/evmc/README.md generated vendored Normal file
View file

@ -0,0 +1,67 @@
# EVMC
[![chat: on gitter][gitter badge]][Gitter]
[![readme style: standard][readme style standard badge]][standard readme]
> Ethereum Client-VM Connector API
The EVMC is the low-level ABI between Ethereum Virtual Machines (EVMs) and
Ethereum Clients. On the EVM side it supports classic EVM1 and [ewasm].
On the Client-side it defines the interface for EVM implementations
to access Ethereum environment and state.
## Usage
Please visit the [documentation].
## Related projects
### EVMs
- [aleth-interpreter]
- [evmjit]
- [Hera]
### Clients
- [aleth]
- [nim-evmc]
- [go-ethereum] (in progress)
- [pyevm] (in progress)
- [pyethereum] (abandoned)
## Contribute
[![chat: on gitter][gitter badge]][Gitter]
Talk with us on the [EVMC Gitter chat][Gitter].
## Maintainers
- Alex Beregszaszi [@axic]
- Paweł Bylica [@chfast]
See also the list of [EVMC Authors](AUTHORS.md).
## License
Licensed under the [MIT License](LICENSE).
[@axic]: https://github.com/axic
[@chfast]: https://github.com/chfast
[documentation]: https://ethereum.github.io/evmc
[ewasm]: https://github.com/ewasm/design
[evmjit]: https://github.com/ethereum/evmjit
[Hera]: https://github.com/ewasm/hera
[Gitter]: https://gitter.im/ethereum/evmc
[aleth-interpreter]: https://github.com/ethereum/aleth/tree/master/libaleth-interpreter
[aleth]: https://github.com/ethereum/aleth
[nim-evmc]: https://github.com/status-im/nim-evmc
[go-ethereum]: https://github.com/ethereum/go-ethereum/pull/17050
[pyevm]: https://github.com/ethereum/py-evm
[pyethereum]: https://github.com/ethereum/pyethereum/pull/406
[standard readme]: https://github.com/RichardLitt/standard-readme
[gitter badge]: https://img.shields.io/gitter/room/ethereum/evmc.svg?style=flat-square
[readme style standard badge]: https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square

58
vendor/github.com/ethereum/evmc/appveyor.yml generated vendored Normal file
View file

@ -0,0 +1,58 @@
version: "{build}"
branches:
only:
- master
- /release\/.*/
- appveyor
- hunter
configuration:
- Release
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
GENERATOR: "Visual Studio 15 2017 Win64"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015 Win64"
- GO: true
cache:
- C:\.hunter\_Base\Cache -> cmake\HunterConfig.cmake
before_build:
- ps: >-
if ($env:GENERATOR) {
if (!(test-path build)) { mkdir build }
cd build
cmake -Wno-dev -G "$env:GENERATOR" .. -DBUILD_SHARED_LIBS=ON -DEVMC_EXAMPLES=ON -DEVMC_TESTING=ON -DCMAKE_INSTALL_PREFIX=C:\install
}
build_script:
- ps: >-
if ($env:GENERATOR) {
cmake --build . --config $env:CONFIGURATION --target install
}
elseif ($env:GO) {
$env:PATH = "C:\msys64\mingw64\bin;$env:PATH"
$env:GOPATH = "C:\Users\appveyor\go"
mkdir $env:GOPATH
gcc --version
go env
go get github.com/ethereum/go-ethereum/common
copy include/evmc/evmc.h bindings/go/evmc
copy include/evmc/helpers.h bindings/go/evmc
copy include/evmc/loader.h bindings/go/evmc
copy lib/loader/loader.c bindings/go/evmc
go build ./bindings/go/evmc
}
after_build:
- ps: >-
if ($env:GENERATOR) {
cd C:\projects\evmc\build\test
Release\evmc-test.exe
C:\install\bin\evmc-vmtester.exe C:\install\bin\evmc-example-vm.dll
}

View file

@ -0,0 +1,296 @@
// 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 <evmc/evmc.h>
#include <evmc/helpers.h>
#include <evmc/loader.h>
#include <stdlib.h>
#include <string.h>
static inline enum evmc_set_option_result set_option(struct evmc_instance* instance, char* name, char* value)
{
enum evmc_set_option_result 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_host_interface evmc_go_host;
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_message msg = {
kind,
flags,
depth,
gas,
*destination,
*sender,
input_data,
input_size,
*value,
*create2_salt,
};
struct extended_context ctx = {{&evmc_go_host}, 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_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
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)
}
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))
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,
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 {
flags |= C.EVMC_STATIC
}
ctxId := addHostContext(ctx)
// FIXME: Clarify passing by pointer vs passing by value.
evmcDestination := evmcAddress(destination)
evmcSender := evmcAddress(sender)
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))
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 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.evmc_address {
r := C.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]))
}

919
vendor/github.com/ethereum/evmc/bindings/go/evmc/evmc.h generated vendored Normal file
View file

@ -0,0 +1,919 @@
/**
* 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 <stdbool.h> /* Definition of bool, true and false. */
#include <stddef.h> /* Definition of size_t. */
#include <stdint.h> /* 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.
*
* 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
};
/**
* The fixed size array of 32 bytes.
*
* 32 bytes of data capable of storing e.g. 256-bit hashes.
*/
typedef struct evmc_bytes32
{
/** 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. */
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
{
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 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 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.
*/
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 amount of Ether transferred with the message.
*/
evmc_uint256be value;
/**
* The optional value used in new contract address construction.
*
* Ignored unless kind is EVMC_CREATE2.
*/
evmc_bytes32 create2_salt;
};
/** The transaction and block data for execution. */
struct evmc_tx_context
{
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;
/**
* Get transaction context callback function.
*
* This callback function is used by an EVM to retrieve the transaction and
* block context.
*
* @param context The pointer to the Host execution context.
* @return The transaction 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 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 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 evmc_bytes32 (*evmc_get_block_hash_fn)(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 execution.
*/
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).
*/
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 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 bool (*evmc_account_exists_fn)(struct evmc_context* context, const evmc_address* address);
/**
* Get storage callback function.
*
* 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 evmc_bytes32 (*evmc_get_storage_fn)(struct evmc_context* context,
const evmc_address* address,
const evmc_bytes32* 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),
* - Z != Y (Z is any value other than Y),
* - 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 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 = 3,
/**
* A storage item has been deleted: X -> 0.
*/
EVMC_STORAGE_DELETED = 4
};
/**
* Set storage callback function.
*
* 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.
* @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.
*/
typedef enum evmc_storage_status (*evmc_set_storage_fn)(struct evmc_context* context,
const evmc_address* address,
const evmc_bytes32* key,
const evmc_bytes32* value);
/**
* Get balance callback function.
*
* 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 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 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 evmc_address* address);
/**
* Get code size callback function.
*
* 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 evmc_bytes32 (*evmc_get_code_hash_fn)(struct evmc_context* context,
const 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 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 evmc_address* address,
const 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 evmc_address* address,
const uint8_t* data,
size_t data_size,
const evmc_bytes32 topics[],
size_t topics_count);
/**
* Pointer to the callback function supporting EVM calls.
*
* @param context The pointer to the Host execution context.
* @param msg The call parameters.
* @return The result of the call.
*/
typedef struct evmc_result (*evmc_call_fn)(struct evmc_context* context,
const struct evmc_message* msg);
/**
* The Host interface.
*
* 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_host_interface
{
/** 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
{
/** The Host interface. */
const struct evmc_host_interface* host;
};
/* 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);
/**
* 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.
*
* 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 The outcome of the operation.
*/
typedef enum evmc_set_option_result (*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);
/**
* 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;
/**
* 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 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;
/**
* 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.
*
* 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_<vm-name>(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_example_vm(void);
#endif
#if __cplusplus
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,168 @@
/* 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).
*
* It also contains helpers (overloaded operators) for using EVMC types effectively in C++.
*
* @defgroup helpers EVMC Helpers
* @{
*/
#pragma once
#include <evmc/evmc.h>
/**
* 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;
}
/**
* 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.
*
* @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 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 EVMC_SET_OPTION_INVALID_NAME;
}
/**
* 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;
}
/** @} */
/** @} */

108
vendor/github.com/ethereum/evmc/bindings/go/evmc/host.c generated vendored Normal file
View file

@ -0,0 +1,108 @@
/* 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 <stdlib.h>
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,
(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,
};
#pragma GCC diagnostic error "-Wconversion"
static inline void go_exported_functions_type_checks()
{
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);
}

View file

@ -0,0 +1,231 @@
// 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 <evmc/evmc.h>
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
StorageModifiedAgain StorageStatus = C.EVMC_STORAGE_MODIFIED_AGAIN
StorageAdded StorageStatus = C.EVMC_STORAGE_ADDED
StorageDeleted StorageStatus = C.EVMC_STORAGE_DELETED
)
func goAddress(in C.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.evmc_bytes32) 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.evmc_address) C.bool {
idx := int((*C.struct_extended_context)(pCtx).index)
ctx := getHostContext(idx)
return C.bool(ctx.AccountExists(goAddress(*pAddr)))
}
//export getStorage
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)
return evmcBytes32(ctx.GetStorage(goAddress(*pAddr), goHash(*pKey)))
}
//export setStorage
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(pCtx unsafe.Pointer, pAddr *C.evmc_address) C.evmc_uint256be {
idx := int((*C.struct_extended_context)(pCtx).index)
ctx := getHostContext(idx)
return evmcBytes32(ctx.GetBalance(goAddress(*pAddr)))
}
//export getCodeSize
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(pCtx unsafe.Pointer, pAddr *C.evmc_address) C.evmc_bytes32 {
idx := int((*C.struct_extended_context)(pCtx).index)
ctx := getHostContext(idx)
return evmcBytes32(ctx.GetCodeHash(goAddress(*pAddr)))
}
//export copyCode
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))
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.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(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()
return C.struct_evmc_tx_context{
evmcBytes32(gasPrice),
evmcAddress(origin),
evmcAddress(coinbase),
C.int64_t(number),
C.int64_t(timestamp),
C.int64_t(gasLimit),
evmcBytes32(difficulty),
}
}
//export getBlockHash
func getBlockHash(pCtx unsafe.Pointer, number int64) C.evmc_bytes32 {
idx := int((*C.struct_extended_context)(pCtx).index)
ctx := getHostContext(idx)
return evmcBytes32(ctx.GetBlockHash(number))
}
//export emitLog
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)
// 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(pCtx unsafe.Pointer, msg *C.struct_evmc_message) C.struct_evmc_result {
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)
}
return result
}

View file

@ -0,0 +1,151 @@
/* EVMC: Ethereum Client-VM Connector API.
* Copyright 2018 The EVMC Authors.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#include <evmc/loader.h>
#include <evmc/evmc.h>
#include <evmc/helpers.h>
#include <stdint.h>
#include <string.h>
#if _WIN32
#include <Windows.h>
#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)(uintptr_t) GetProcAddress(handle, name)
#define HAVE_STRCPY_S 1
#else
#include <dlfcn.h>
#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 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, '/');
#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;
char* base_name = prefixed_name + prefix_length;
strcpy_s(base_name, PATH_MAX_LENGTH, name_pos);
// Trim the file extension.
char* ext_pos = strrchr(prefixed_name, '.');
if (ext_pos)
*ext_pos = 0;
// Replace all "-" with "_".
char* dash_pos = base_name;
while ((dash_pos = strchr(dash_pos, '-')) != NULL)
*dash_pos++ = '_';
// Search for the built function name.
while ((create_fn = DLL_GET_CREATE_FN(handle, prefixed_name)) == NULL)
{
// 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)
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;
}

View file

@ -0,0 +1,110 @@
/* 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 _base name_:
* "example_interpreter",
* - the function name "evmc_create_" + _base name_ is searched in the library:
* "evmc_create_example_interpreter",
* - 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.
*
* 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
/** @} */

143
vendor/github.com/ethereum/evmc/circle.yml generated vendored Normal file
View file

@ -0,0 +1,143 @@
version: 2
jobs:
lint:
docker:
- image: ethereum/cpp-build-env
steps:
- checkout
- run:
name: "Check code format"
command: |
find examples include lib test -name '*.hpp' -o -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format -i
git diff --color --exit-code
- run:
name: "Run codespell"
command: |
sudo pip3 install --upgrade pip setuptools
sudo pip3 install codespell
codespell --quiet-level=4 --ignore-words=./.codespell-whitelist
build: &build
docker:
- image: ethereum/cpp-build-env
steps:
- checkout
- run:
name: "Configure"
working_directory: ~/build
command: cmake ../project -DCMAKE_INSTALL_PREFIX=~/install -DBUILD_SHARED_LIBS=ON -DEVMC_EXAMPLES=ON -DEVMC_TESTING=ON
- run:
name: "Build"
command: cmake --build ~/build
- run:
name: "Unit tests"
working_directory: ~/build/test
command: ./evmc-test
- run:
name: "Test"
command: cmake --build ~/build --target test
- run:
name: "Install"
command: cmake --build ~/build --target install
- run:
name: "Package"
command: |
cmake --build ~/build --target package
mkdir ~/package
mv ~/build/evmc-*.tar.gz ~/package
- store_artifacts:
path: ~/package
destination: package
- run:
name: "Test CMake package config"
command: |
mkdir ~/build-example-evmc && cd ~/build-example-evmc
cmake ~/project/examples/use_evmc_in_cmake -DCMAKE_PREFIX_PATH=~/install
cmake --build .
mkdir ~/build-example-instructions && cd ~/build-example-instructions
cmake ~/project/examples/use_instructions_in_cmake -DCMAKE_PREFIX_PATH=~/install
cmake --build .
- run:
name: "Run evmc-vmtester libevmc-example-vm.so"
command: ~/install/bin/evmc-vmtester ~/install/lib/libevmc-example-vm.so
build-clang-3.8:
<<: *build
environment:
CC: clang-3.8
CXX: clang++-3.8
test-docs:
docker:
- image: ethereum/cpp-build-env
steps:
- checkout
- run:
name: "Test documentation"
command: |
cat Doxyfile | sed 's/HTML_OUTPUT = ./HTML_OUTPUT = ..\/docs/' | doxygen - > doxygen.log 2> doxygen.warnings
if [ -s doxygen.warnings ]; then
printf '\n\nDoxygen warnings:\n\n'
cat doxygen.warnings
exit 1
fi
cat doxygen.log
- store_artifacts:
path: ~/docs
destination: docs
upload-docs:
docker:
- image: ethereum/cpp-build-env
steps:
- checkout
- run:
name: "Generate documentation"
command: doxygen Doxyfile
- run:
name: "Upload documentation"
command: |
git config user.email "docs-bot@ethereum.org"
git config user.name "Documentation Bot"
git add --all
git commit -m "Update docs"
git push -f "https://$GITHUB_TOKEN@github.com/ethereum/evmc.git" HEAD:gh-pages
bindings-go-1.10:
docker:
- image: circleci/golang:1.10
steps: &bindings-go-steps
- checkout
- run:
name: "Go Build"
command: |
go get -v github.com/ethereum/go-ethereum/common
go build -v ./bindings/go/evmc
go vet -v ./bindings/go/evmc
bindings-go-1.9:
docker:
- image: circleci/golang:1.9
steps: *bindings-go-steps
workflows:
version: 2
evmc:
jobs:
- lint
- build
- build-clang-3.8
- bindings-go-1.10
- bindings-go-1.9
- test-docs
- upload-docs:
requires:
- test-docs
filters:
branches:
only:
- master
- docs

8
vendor/vendor.json vendored
View file

@ -116,6 +116,14 @@
"revision": "a3814ce5008e612a0c6d027608b54e1d0d9a5613", "revision": "a3814ce5008e612a0c6d027608b54e1d0d9a5613",
"revisionTime": "2018-01-22T22:25:45Z" "revisionTime": "2018-01-22T22:25:45Z"
}, },
{
"checksumSHA1": "HxlAMyHDmEEDsOIlULQD2HPoN40=",
"path": "github.com/ethereum/evmc/bindings/go/evmc",
"revision": "354ba6f540655649e081fb455e21998186bf5576",
"revisionTime": "2018-10-24T21:20:07Z",
"version": "=v6.0.0",
"versionExact": "v6.0.0"
},
{ {
"checksumSHA1": "7oFpbmDfGobwKsFLIf6wMUvVoKw=", "checksumSHA1": "7oFpbmDfGobwKsFLIf6wMUvVoKw=",
"path": "github.com/fatih/color", "path": "github.com/fatih/color",