diff --git a/CMakeLists.txt b/CMakeLists.txt index c4930aa62..ac770899b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,12 @@ if (HERA_WAVM) include(ProjectWAVM) endif() -if (NOT (HERA_BINARYEN OR HERA_WABT OR HERA_WAVM)) +option(HERA_V8 "Build with V8" OFF) +if (HERA_V8) + include(ProjectV8) +endif() + +if (NOT (HERA_BINARYEN OR HERA_WABT OR HERA_WAVM OR HERA_V8)) message(FATAL_ERROR "At least one one engine must be enabled.") endif() @@ -66,7 +71,6 @@ add_subdirectory(evmc) add_subdirectory(src) add_subdirectory(test) - install(DIRECTORY include/hera DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) write_basic_package_version_file(heraConfigVersion.cmake COMPATIBILITY SameMajorVersion) diff --git a/circle.yml b/circle.yml index 61d890eb8..b58ef32fa 100644 --- a/circle.yml +++ b/circle.yml @@ -1,4 +1,9 @@ defaults: + install-deps-linux: &install-deps-linux + run: + name: "Installing dependencies" + command: | + sudo apt update && sudo apt install -y xz-utils bzip2 pkg-config update-submodules: &update-submodules run: @@ -39,6 +44,7 @@ defaults: run: name: "Build" working_directory: ~/build + no_output_timeout: 2h command: | cmake --build . --target package -- -j $BUILD_PARALLEL_JOBS mkdir -p ~/package @@ -51,10 +57,10 @@ defaults: destination: package add-package-to-workspace: &add-package-to-workspace - persist_to_workspace: - root: ~/package - paths: - - "*" + persist_to_workspace: + root: ~/package + paths: + - "*" save-deps-cache: &save-deps-cache cache-save: @@ -160,6 +166,16 @@ defaults: testeth --version testeth -t GeneralStateTests/stEWASMTests -- --testpath tests --vm ~/build/src/libhera.$SO --singlenet Byzantium --evmc engine=wavm $TESTETH_OPTIONS + test-v8: &test-v8 + run: + name: "Test shared Hera (v8)" + command: | + export ASAN_OPTIONS=detect_leaks=0 + SO=$([ $(uname) = Darwin ] && echo dylib || echo so) + if [[ $PRELOAD_ASAN ]]; then export LD_PRELOAD=/usr/lib/clang/8/lib/linux/libclang_rt.asan-x86_64.so; fi + testeth --version + testeth -t GeneralStateTests/stEWASMTests -- --testpath tests --vm ~/build/src/libhera.$SO --singlenet Byzantium --evmc engine=v8 $TESTETH_OPTIONS + evmc-test: &evmc-test run: name: "Run evmc tests" @@ -194,13 +210,14 @@ jobs: BUILD_TYPE: Release CXX: clang++ CC: clang - GENERATOR: Ninja + GENERATOR: Unix Makefiles 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: -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=OFF -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON -DHERA_V8=ON -DEVMC_TEST_TOOLS=ON docker: - image: ethereum/cpp-build-env:9 steps: - checkout + - *install-deps-linux - *update-submodules - *environment-info - *restore-deps-cache @@ -214,6 +231,7 @@ jobs: - *test-binaryen - *test-wabt - *test-wavm + - *test-v8 - *evmc-test - *evm2wasm-test @@ -222,15 +240,16 @@ jobs: BUILD_TYPE: Release CXX: clang++ CC: clang - GENERATOR: Ninja + GENERATOR: Unix Makefiles 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: -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=OFF -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON -DHERA_V8=ON -DEVMC_TEST_TOOLS=ON -DSANITIZE=address # The ASan must the first loaded shared library. Force preloading it with this flag. PRELOAD_ASAN: true docker: - image: ethereum/cpp-build-env:9 steps: - checkout + - *install-deps-linux - *update-submodules - *environment-info - *restore-deps-cache @@ -243,6 +262,7 @@ jobs: - *test-binaryen - *test-wabt - *test-wavm + - *test-v8 - *evmc-test - *evm2wasm-test @@ -253,12 +273,13 @@ jobs: - CC: gcc - GENERATOR: Unix Makefiles - BUILD_PARALLEL_JOBS: 4 - - CMAKE_OPTIONS: -DCOVERAGE=ON -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WABT=ON -DHERA_WAVM=ON + - CMAKE_OPTIONS: -DCMAKE_VERBOSE_MAKEFILE=ON -DCOVERAGE=ON -DBUILD_SHARED_LIBS=ON -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WABT=ON -DHERA_WAVM=ON -DHERA_V8=ON - TESTETH_OPTIONS: --evmc benchmark=true docker: - image: ethereum/cpp-build-env:9 steps: - checkout + - *install-deps-linux - *update-submodules - *environment-info - *restore-deps-cache @@ -271,6 +292,7 @@ jobs: - *test-binaryen - *test-wabt - *test-wavm + - *test-v8 - *upload-coverage-data linux-gcc-static-debug: @@ -280,11 +302,12 @@ jobs: - CC: gcc - GENERATOR: Unix Makefiles - BUILD_PARALLEL_JOBS: 4 - - CMAKE_OPTIONS: -DBUILD_SHARED_LIBS=OFF -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON + - CMAKE_OPTIONS: -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=OFF -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WAVM=ON -DHERA_WABT=ON -DHERA_V8=ON docker: - image: ethereum/cpp-build-env:9 steps: - checkout + - *install-deps-linux - *update-submodules - *environment-info - *restore-deps-cache @@ -299,7 +322,7 @@ jobs: - CXX: c++ - GENERATOR: Unix Makefiles - BUILD_PARALLEL_JOBS: 4 - - CMAKE_OPTIONS: -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WABT=ON + - CMAKE_OPTIONS: -DCMAKE_VERBOSE_MAKEFILE=ON -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WABT=ON -DHERA_V8=ON macos: xcode: "10.1.0" steps: @@ -320,6 +343,7 @@ jobs: - *fetch-tests - *test-binaryen - *test-wabt + - *test-v8 lint: docker: diff --git a/cmake/ProjectV8.cmake b/cmake/ProjectV8.cmake new file mode 100644 index 000000000..d22222e40 --- /dev/null +++ b/cmake/ProjectV8.cmake @@ -0,0 +1,62 @@ +# +# based on https://github.com/aarlt/v8-cmake +# + +if (ProjectV8Included) + return() +endif () +set(ProjectV8Included TRUE) + +include(ExternalProject) + +set(V8_LIBRARY ${CMAKE_BINARY_DIR}/deps/v8/out.gn/x64.release.sample/obj/${CMAKE_STATIC_LIBRARY_PREFIX}v8_monolith${CMAKE_STATIC_LIBRARY_SUFFIX}) +set(V8_INCLUDE ${CMAKE_BINARY_DIR}/deps/v8/include) + +ExternalProject_Add(depot_tools + GIT_REPOSITORY https://chromium.googlesource.com/chromium/tools/depot_tools.git + GIT_TAG bc23ca13f1b3b684d9c2a127f33b618a71644829 + SOURCE_DIR "${CMAKE_BINARY_DIR}/deps/depot_tools" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" + BUILD_BYPRODUCTS "${V8_LIBRARY}" + BUILD_BYPRODUCTS "${V8_INCLUDE}" + ) + +ExternalProject_Add_Step(depot_tools fetch + COMMAND ${CMAKE_SOURCE_DIR}/cmake/v8_fetch.sh ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} + COMMENT "v8: fetch" + DEPENDEES install + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps" + ) + +ExternalProject_Add_Step(depot_tools v8gen + COMMAND ${CMAKE_BINARY_DIR}/deps/v8/tools/dev/v8gen.py -vv x64.release.sample + COMMENT "v8: v8gen.py x64.release.sample" + DEPENDEES fetch + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps/v8" + ) + +ExternalProject_Add_Step(depot_tools ninja + COMMAND ${CMAKE_BINARY_DIR}/deps/depot_tools/ninja -v -C out.gn/x64.release.sample v8_monolith + COMMENT "v8: ninja -v -C out.gn/x64.release.sample v8_monolith" + DEPENDEES v8gen + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps/v8" + ) + +add_library(v8::v8 STATIC IMPORTED) + +set_target_properties( + v8::v8 + PROPERTIES + IMPORTED_CONFIGURATIONS Release + IMPORTED_LOCATION_RELEASE ${V8_LIBRARY} +) +file(MAKE_DIRECTORY ${V8_INCLUDE}) +target_include_directories(v8::v8 INTERFACE + $ + $ +) + +add_dependencies(v8::v8 depot_tools) diff --git a/cmake/v8_fetch.sh b/cmake/v8_fetch.sh new file mode 100755 index 000000000..0ca244a4f --- /dev/null +++ b/cmake/v8_fetch.sh @@ -0,0 +1,11 @@ +#!/bin/bash +CMAKE_SOURCE_DIR=$1 +CMAKE_BINARY_DIR=$2 +if [ ! -f "${CMAKE_BINARY_DIR}/deps/v8/BUILD.gn" ] +then + rm -rf ${CMAKE_BINARY_DIR}/deps/v8 + ${CMAKE_SOURCE_DIR}/cmake/v8_wrap.sh ${CMAKE_BINARY_DIR}/deps/depot_tools fetch v8 +else + mkdir -p ${CMAKE_BINARY_DIR}/deps/v8/include + ${CMAKE_SOURCE_DIR}/cmake/v8_wrap.sh ${CMAKE_BINARY_DIR}/deps/depot_tools gclient sync +fi diff --git a/cmake/v8_wrap.sh b/cmake/v8_wrap.sh new file mode 100755 index 000000000..0cd42b6cf --- /dev/null +++ b/cmake/v8_wrap.sh @@ -0,0 +1,2 @@ +#!/bin/bash +PATH=${1}:$PATH ${2} ${3} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f558e2eae..55b7c1902 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,10 @@ if(HERA_WAVM) target_sources(hera PRIVATE wavm.cpp wavm.h) endif() +if(HERA_V8) + target_sources(hera PRIVATE v8.cpp v8.h) +endif() + option(HERA_DEBUGGING "Display debugging messages during execution." ON) if(HERA_DEBUGGING) target_compile_definitions(hera PRIVATE HERA_DEBUGGING=1) @@ -60,6 +64,11 @@ if(HERA_WAVM) target_link_libraries(hera PRIVATE wavm::wavm) endif() +if(HERA_V8) + target_compile_definitions(hera PRIVATE HERA_V8=1) + target_link_libraries(hera PRIVATE v8::v8) +endif() + install(TARGETS hera EXPORT heraTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/hera.cpp b/src/hera.cpp index 1ef3e728b..2e1b069e1 100644 --- a/src/hera.cpp +++ b/src/hera.cpp @@ -39,6 +39,9 @@ #if HERA_WABT #include "wabt.h" #endif +#if HERA_V8 +#include "v8.h" +#endif #include @@ -71,7 +74,10 @@ const map wasm_engine_map { { "wavm", WavmEngine::create }, #endif #if HERA_WABT - { "wabt", WabtEngine::create }, + { "wabt", WabtEngine::create }, +#endif +#if HERA_V8 + { "v8", V8Engine::create }, #endif }; @@ -83,6 +89,8 @@ WasmEngineCreateFn wasmEngineCreateFn = WabtEngine::create #elif HERA_WAVM WavmEngine::create +#elif HERA_V8 + V8Engine::create #else #error "No engine requested." #endif diff --git a/src/v8.cpp b/src/v8.cpp new file mode 100644 index 000000000..f7576718a --- /dev/null +++ b/src/v8.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Alexander Arlt + * + * 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. + */ + +#include + +#include "v8.h" +#include "debugging.h" +#include "eei.h" +#include "exceptions.h" + +using namespace std; + +namespace hera { + +std::unique_ptr hera::V8Engine::create() { + return nullptr; +} + +ExecutionResult hera::V8Engine::execute(evmc_context *context, + bytes_view code, + bytes_view state_code, + const evmc_message &msg, + bool meterInterfaceGas) { + (void) context; + (void) code; + (void) state_code; + (void) msg; + (void) meterInterfaceGas; + + ExecutionResult result{}; + return result; +} + +void hera::V8Engine::verifyContract(hera::bytes_view code) { + (void) code; +} + +} // namespace hera diff --git a/src/v8.h b/src/v8.h new file mode 100644 index 000000000..b16038f15 --- /dev/null +++ b/src/v8.h @@ -0,0 +1,43 @@ +/* + * Copyright 2019 Alexander Arlt + * + * 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. + */ + +#pragma once + +#include "eei.h" + +namespace IR { +class Module; +} + +namespace hera { + +class V8Engine : public WasmEngine { + public: + /// Factory method to create the WAVM Wasm Engine. + static std::unique_ptr create(); + + ExecutionResult execute( + evmc_context* context, + bytes_view code, + bytes_view state_code, + evmc_message const& msg, + bool meterInterfaceGas + ) override; + + void verifyContract(bytes_view code) override; +}; + +} // namespace hera