diff --git a/circle.yml b/circle.yml index 61d890eb8..bd1999205 100644 --- a/circle.yml +++ b/circle.yml @@ -70,7 +70,7 @@ defaults: save-aleth-cache: &save-aleth-cache save_cache: - key: &aleth-cache-key aleth-prebuilt-cache-{{arch}}-{{checksum "toolchain"}}-v1.6.0 + key: &aleth-cache-key aleth-prebuilt-cache-{{arch}}-{{checksum "toolchain"}}-v1.8.0 paths: - ~/build - ~/.hunter @@ -84,7 +84,7 @@ defaults: name: "Checkout aleth repo" working_directory: ~/ command: | - git clone https://github.com/ethereum/aleth --branch v1.6.0 --single-branch --recurse-submodules --depth 1 + git clone https://github.com/ethereum/aleth --branch v1.8.0 --single-branch --recurse-submodules --depth 1 link-hera: &link-hera run: @@ -119,7 +119,7 @@ defaults: run: name: "Install aleth" command: | - VER=1.6.0 + VER=1.8.0 OS=$(uname | tr '[:upper:]' '[:lower:]') URL=https://github.com/ethereum/aleth/releases/download/v$VER/aleth-$VER-$OS-x86_64.tar.gz echo $URL @@ -184,6 +184,7 @@ defaults: run: name: "Upload coverage data" command: | + sudo pip3 install --upgrade --quiet --no-cache-dir codecov codecov --required --gcov-root ~/build --gcov-exec gcov-8 @@ -196,7 +197,7 @@ jobs: CC: clang GENERATOR: Ninja BUILD_PARALLEL_JOBS: 4 - CMAKE_OPTIONS: -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=OFF -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON -DEVMC_TEST_TOOLS=ON + CMAKE_OPTIONS: -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=OFF -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON docker: - image: ethereum/cpp-build-env:9 steps: @@ -214,7 +215,7 @@ jobs: - *test-binaryen - *test-wabt - *test-wavm - - *evmc-test +# - *evmc-test - *evm2wasm-test linux-clang-shared-asan: @@ -224,7 +225,7 @@ jobs: CC: clang GENERATOR: Ninja BUILD_PARALLEL_JOBS: 4 - CMAKE_OPTIONS: -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=OFF -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON -DEVMC_TEST_TOOLS=ON -DSANITIZE=address + CMAKE_OPTIONS: -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=OFF -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON -DSANITIZE=address # The ASan must the first loaded shared library. Force preloading it with this flag. PRELOAD_ASAN: true docker: @@ -243,7 +244,7 @@ jobs: - *test-binaryen - *test-wabt - *test-wavm - - *evmc-test +# - *evmc-test - *evm2wasm-test linux-gcc-shared-coverage: diff --git a/evmc b/evmc index e9d464820..2f75e060e 160000 --- a/evmc +++ b/evmc @@ -1 +1 @@ -Subproject commit e9d4648200d73c1ce63b74a33a50758db1fd48db +Subproject commit 2f75e060ef973d7a28c0d6ac1ef107a47c8e9f6e diff --git a/include/hera/hera.h b/include/hera/hera.h index 6c1518916..4538f5f4d 100644 --- a/include/hera/hera.h +++ b/include/hera/hera.h @@ -24,7 +24,7 @@ extern "C" { #endif -EVMC_EXPORT struct evmc_instance* evmc_create_hera(void) EVMC_NOEXCEPT; +EVMC_EXPORT struct evmc_vm* evmc_create_hera(void) EVMC_NOEXCEPT; #if __cplusplus } diff --git a/src/binaryen.cpp b/src/binaryen.cpp index ff42a1a9e..f1f2d6b2d 100644 --- a/src/binaryen.cpp +++ b/src/binaryen.cpp @@ -38,7 +38,7 @@ namespace hera { class BinaryenEthereumInterface : public wasm::ShellExternalInterface, EthereumInterface { public: explicit BinaryenEthereumInterface( - evmc_context* _context, + evmc::HostContext& _context, bytes_view _code, evmc_message const& _msg, ExecutionResult & _result, @@ -477,7 +477,7 @@ unique_ptr BinaryenEngine::create() // Execute the contract through Binaryen. ExecutionResult BinaryenEngine::execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, diff --git a/src/binaryen.h b/src/binaryen.h index 783fd6e86..88a5dce27 100644 --- a/src/binaryen.h +++ b/src/binaryen.h @@ -30,7 +30,7 @@ class BinaryenEngine : public WasmEngine { static std::unique_ptr create(); ExecutionResult execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, diff --git a/src/eei.cpp b/src/eei.cpp index ece340cff..e85423aec 100644 --- a/src/eei.cpp +++ b/src/eei.cpp @@ -24,7 +24,6 @@ #include "helpers.h" #include -#include // FIXME: Do not include deprecated helpers.hpp. using namespace std; @@ -523,7 +522,7 @@ void WasmEngine::collectBenchmarkingData() // These checks are in EIP150 but not in the YellowPaper // Charge valuetransfer gas if value is being transferred. - if ((kind == EEICallKind::Call || kind == EEICallKind::CallCode) && !is_zero(call_message.value)) { + if ((kind == EEICallKind::Call || kind == EEICallKind::CallCode) && !evmc::is_zero(call_message.value)) { takeInterfaceGas(GasSchedule::valuetransfer); if (!enoughSenderBalanceFor(call_message.value)) @@ -541,7 +540,7 @@ void WasmEngine::collectBenchmarkingData() takeInterfaceGas(gas); // Add gas stipend for value transfers - if (!is_zero(call_message.value)) + if (!evmc::is_zero(call_message.value)) gas += GasSchedule::valueStipend; call_message.gas = gas; diff --git a/src/eei.h b/src/eei.h index 6298e9bf2..4d7c7573b 100644 --- a/src/eei.h +++ b/src/eei.h @@ -43,7 +43,7 @@ class WasmEngine { virtual ~WasmEngine() noexcept = default; virtual ExecutionResult execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, @@ -85,13 +85,13 @@ class WasmEngine { class EthereumInterface { public: explicit EthereumInterface( - evmc_context* _context, + evmc::HostContext& _host, bytes_view _code, evmc_message const& _msg, ExecutionResult& _result, bool _meterGas ): - m_host(_context), + m_host{_host}, // FIXME: Change param to &. m_code{_code}, m_msg(_msg), m_result(_result), @@ -200,7 +200,7 @@ class EthereumInterface { static unsigned __int128 safeLoadUint128(evmc_uint256be const& value); - evmc::HostContext m_host; + evmc::HostContext& m_host; bytes_view m_code; evmc_message const& m_msg; bytes m_lastReturnData; diff --git a/src/hera.cpp b/src/hera.cpp index 1ef3e728b..251cb2294 100644 --- a/src/hera.cpp +++ b/src/hera.cpp @@ -24,7 +24,6 @@ #include #include -#include #include "debugging.h" #include "eei.h" @@ -88,24 +87,26 @@ WasmEngineCreateFn wasmEngineCreateFn = #endif ; -struct hera_instance : evmc_instance { +struct hera_instance : evmc_vm { unique_ptr engine = wasmEngineCreateFn(); hera_evm1mode evm1mode = hera_evm1mode::reject; bool metering = false; - map contract_preload_list; + map contract_preload_list; - hera_instance() noexcept : evmc_instance({EVMC_ABI_VERSION, "hera", hera_get_buildinfo()->project_version, nullptr, nullptr, nullptr, nullptr, nullptr}) {} + hera_instance() noexcept : evmc_vm({EVMC_ABI_VERSION, "hera", hera_get_buildinfo()->project_version, nullptr, nullptr, nullptr, nullptr}) {} }; -const evmc_address sentinelAddress = { .bytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xa } }; -const evmc_address evm2wasmAddress = { .bytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xb } }; -const evmc_address runevmAddress = { .bytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xc } }; +using namespace evmc::literals; + +constexpr auto sentinelAddress = 0x000000000000000000000000000000000000000a_address; +constexpr auto evm2wasmAddress = 0x000000000000000000000000000000000000000b_address; +constexpr auto runevmAddress = 0x000000000000000000000000000000000000000c_address; // Calls a system contract at @address with input data @input. // It is a "staticcall" with sender 000...000 and no value. // @returns output data from the contract and update the @gas variable with the gas left. pair callSystemContract( - evmc_context* context, + evmc::HostContext& context, evmc_address const& address, int64_t & gas, bytes_view input @@ -123,7 +124,7 @@ pair callSystemContract( .create2_salt = {}, }; - evmc_result result = context->host->call(context, &message); + evmc::result result = context.call(message); bytes ret; if (result.status_code == EVMC_SUCCESS && result.output_data) @@ -131,14 +132,11 @@ pair callSystemContract( gas = result.gas_left; - if (result.release) - result.release(&result); - return {result.status_code, ret}; } pair locallyExecuteSystemContract( - evmc_context* context, + evmc::HostContext& context, evmc_address const& address, int64_t & gas, bytes_view input, @@ -172,7 +170,7 @@ pair locallyExecuteSystemContract( // Calls the Sentinel contract with input data @input. // @returns the validated and metered output or empty output otherwise. -bytes sentinel(evmc_context* context, bytes_view input) +bytes sentinel(evmc::HostContext& context, bytes_view input) { HERA_DEBUG << "Metering (input " << input.size() << " bytes)...\n"; @@ -201,7 +199,7 @@ bytes sentinel(evmc_context* context, bytes_view input) // Calls the evm2wasm contract with input data @input. // @returns the compiled output or empty output otherwise. -bytes evm2wasm(evmc_context* context, bytes_view input) { +bytes evm2wasm(evmc::HostContext& context, bytes_view input) { HERA_DEBUG << "Calling evm2wasm (input " << input.size() << " bytes)...\n"; int64_t startgas = numeric_limits::max(); // do not charge for metering yet (give unlimited gas) @@ -229,7 +227,7 @@ bytes evm2wasm(evmc_context* context, bytes_view input) { // Calls the runevm contract. // @returns a wasm-based evm interpreter. -bytes runevm(evmc_context* context, bytes code) { +bytes runevm(evmc::HostContext& context, bytes code) { HERA_DEBUG << "Calling runevm (code " << code.size() << " bytes)...\n"; int64_t gas = numeric_limits::max(); // do not charge for metering yet (give unlimited gas) @@ -272,14 +270,16 @@ void hera_destroy_result(evmc_result const* result) noexcept } evmc_result hera_execute( - evmc_instance *instance, - evmc_context *context, + evmc_vm *vm, + const evmc_host_interface* host_interface, + evmc_host_context *context, enum evmc_revision rev, const evmc_message *msg, const uint8_t *code, size_t code_size ) noexcept { - hera_instance* hera = static_cast(instance); + hera_instance* hera = static_cast(vm); + evmc::HostContext host{*host_interface, context}; HERA_DEBUG << "Executing message in Hera\n"; @@ -311,7 +311,7 @@ evmc_result hera_execute( if (!isWasm) { switch (hera->evm1mode) { case hera_evm1mode::evm2wasm_contract: - run_code = evm2wasm(context, run_code); + run_code = evm2wasm(host, run_code); ensureCondition(run_code.size() > 8, ContractValidationFailure, "Transcompiling via evm2wasm failed"); // TODO: enable this once evm2wasm does metering of interfaces // meterInterfaceGas = false; @@ -325,7 +325,7 @@ evmc_result hera_execute( ret.status_code = EVMC_FAILURE; return ret; case hera_evm1mode::runevm_contract: - run_code = runevm(context, hera->contract_preload_list[runevmAddress]); + run_code = runevm(host, hera->contract_preload_list[runevmAddress]); ensureCondition(run_code.size() > 8, ContractValidationFailure, "Interpreting via runevm failed"); // Runevm does interface metering on its own meterInterfaceGas = false; @@ -343,7 +343,7 @@ evmc_result hera_execute( if (msg->kind == EVMC_CREATE && isWasm) { // Meter the deployment (constructor) code if it is WebAssembly if (hera->metering) - run_code = sentinel(context, run_code); + run_code = sentinel(host, run_code); ensureCondition( hasWasmPreamble(run_code) && hasWasmVersion(run_code, 1), ContractValidationFailure, @@ -354,7 +354,7 @@ evmc_result hera_execute( heraAssert(hera->engine, "Wasm engine not set."); WasmEngine& engine = *hera->engine; - ExecutionResult result = engine.execute(context, run_code, state_code, *msg, meterInterfaceGas); + ExecutionResult result = engine.execute(host, run_code, state_code, *msg, meterInterfaceGas); heraAssert(result.gasLeft >= 0, "Negative gas left after execution."); // copy call result @@ -369,7 +369,7 @@ evmc_result hera_execute( ); // Meter the deployed code if it is WebAssembly - returnValue = hera->metering ? sentinel(context, result.returnValue) : move(result.returnValue); + returnValue = hera->metering ? sentinel(host, result.returnValue) : move(result.returnValue); ensureCondition( hasWasmPreamble(returnValue) && hasWasmVersion(returnValue, 1), ContractValidationFailure, @@ -476,11 +476,11 @@ bool hera_parse_sys_option(hera_instance *hera, string const& _name, string cons } evmc_set_option_result hera_set_option( - evmc_instance *instance, + evmc_vm* vm, char const *name, char const *value ) noexcept { - hera_instance* hera = static_cast(instance); + hera_instance* hera = static_cast(vm); if (strcmp(name, "evm1mode") == 0) { if (evm1mode_options.count(value)) { @@ -525,16 +525,16 @@ evmc_set_option_result hera_set_option( return EVMC_SET_OPTION_INVALID_NAME; } -void hera_destroy(evmc_instance* instance) noexcept +void hera_destroy(evmc_vm* vm) noexcept { - hera_instance* hera = static_cast(instance); + hera_instance* hera = static_cast(vm); delete hera; } -evmc_capabilities_flagset hera_get_capabilities(evmc_instance* instance) +evmc_capabilities_flagset hera_get_capabilities(evmc_vm* vm) { evmc_capabilities_flagset caps = EVMC_CAPABILITY_EWASM; - if (static_cast(instance)->evm1mode != hera_evm1mode::reject) + if (static_cast(vm)->evm1mode != hera_evm1mode::reject) caps |= EVMC_CAPABILITY_EVM1; return caps; } @@ -543,7 +543,7 @@ evmc_capabilities_flagset hera_get_capabilities(evmc_instance* instance) extern "C" { -evmc_instance* evmc_create_hera() noexcept +evmc_vm* evmc_create_hera() noexcept { hera_instance* instance = new hera_instance; instance->destroy = hera_destroy; @@ -555,7 +555,7 @@ evmc_instance* evmc_create_hera() noexcept #if hera_EXPORTS // If compiled as shared library, also export this symbol. -EVMC_EXPORT evmc_instance* evmc_create() noexcept +EVMC_EXPORT evmc_vm* evmc_create() noexcept { return evmc_create_hera(); } diff --git a/src/wabt.cpp b/src/wabt.cpp index 69825f403..9bf208d53 100644 --- a/src/wabt.cpp +++ b/src/wabt.cpp @@ -42,7 +42,7 @@ namespace hera { class WabtEthereumInterface : public EthereumInterface { public: explicit WabtEthereumInterface( - evmc_context* _context, + evmc::HostContext& _context, bytes_view _code, evmc_message const& _msg, ExecutionResult & _result, @@ -75,7 +75,7 @@ unique_ptr WabtEngine::create() } ExecutionResult WabtEngine::execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, diff --git a/src/wabt.h b/src/wabt.h index 6639b78dc..26761a7fc 100644 --- a/src/wabt.h +++ b/src/wabt.h @@ -26,7 +26,7 @@ class WabtEngine : public WasmEngine { static std::unique_ptr create(); ExecutionResult execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, diff --git a/src/wavm.cpp b/src/wavm.cpp index 004b2bdfc..ce2fe7051 100644 --- a/src/wavm.cpp +++ b/src/wavm.cpp @@ -45,7 +45,7 @@ namespace hera { class WavmEthereumInterface : public EthereumInterface { public: explicit WavmEthereumInterface( - evmc_context* _context, + evmc::HostContext& _context, bytes_view _code, evmc_message const& _msg, ExecutionResult & _result, @@ -282,7 +282,7 @@ struct WavmInterfaceKeeper { }; ExecutionResult WavmEngine::execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, @@ -324,7 +324,7 @@ IR::Module WavmEngine::parseModule(bytes_view code) } ExecutionResult WavmEngine::internalExecute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, diff --git a/src/wavm.h b/src/wavm.h index 7295e3a87..73de2e444 100644 --- a/src/wavm.h +++ b/src/wavm.h @@ -31,7 +31,7 @@ class WavmEngine : public WasmEngine { static std::unique_ptr create(); ExecutionResult execute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg, @@ -42,7 +42,7 @@ class WavmEngine : public WasmEngine { private: ExecutionResult internalExecute( - evmc_context* context, + evmc::HostContext& context, bytes_view code, bytes_view state_code, evmc_message const& msg,