Skip to content

Commit

Permalink
Wasm Edge (#1864)
Browse files Browse the repository at this point in the history
* Integrate WasmEdge to Kagome
---------

Co-authored-by: Alexander Krutikov <[email protected]>
  • Loading branch information
Harrm and Alexander Krutikov authored Dec 1, 2023
1 parent d9b6c11 commit ee15e3d
Show file tree
Hide file tree
Showing 151 changed files with 2,580 additions and 1,478 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
- name: install
run: ./housekeeping/macos/dependency.sh
- name: build
run: ./housekeeping/make_build.sh -DCLEAR_OBJS=ON -DCOVERAGE=OFF -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/cxx20.cmake
run: ./housekeeping/make_build.sh -DCLEAR_OBJS=ON -DCOVERAGE=OFF -DWASM_COMPILER=WasmEdge -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/cxx20.cmake
env:
CI:

Expand Down
18 changes: 14 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ if(NOT($ENV{CI}) OR NOT($ENV{GITHUB_ACTIONS}))
endif()
option(EXTERNAL_PROJECT "Build external project" ${_EXTERNAL_PROJECT_DEFAULT})

set(WASM_COMPILER WAVM CACHE STRING "WebAssembly compiler built into Kagome: one of [WAVM, WasmEdge]")

if (NOT ${WASM_COMPILER} MATCHES "^(WAVM|WasmEdge)$")
fatal_error("WASM_COMPILER is set to ${WASM_COMPILER} but should be one of [WAVM, WasmEdge]")
endif()

# sanitizers will be enabled only for Kagome, and will be disabled for dependencies
option(ASAN "Enable address sanitizer" OFF)
option(LSAN "Enable leak sanitizer" OFF)
Expand All @@ -80,6 +86,8 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$")
# cmake-format: off

# enable those flags
add_flag(-fdiagnostics-show-template-tree)

add_flag(-Wall)
add_flag(-Wextra)
add_flag(-Woverloaded-virtual) # warn if you overload (not override) a virtual function
Expand Down Expand Up @@ -108,7 +116,8 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$")
add_flag(-Werror=unused-lambda-capture) # error if lambda capture is unused
add_flag(-Werror=return-type) # warning: control reaches end of non-void function [-Wreturn-type]
add_flag(-Werror=sign-compare) # warn the user if they compare a signed and unsigned numbers
add_flag(-Werror=reorder) # field '$1' will be initialized after field '$2'
# breaks soralog headers
# add_flag(-Werror=reorder) # field '$1' will be initialized after field '$2'
add_flag(-Werror=mismatched-tags) # warning: class '$1' was previously declared as struct
add_flag(-Werror=switch) # unhandled values in a switch statement
# cmake-format: on
Expand All @@ -124,9 +133,9 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$")
# cmake-format: on
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
# TODO(warchant): add flags
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#msvc

fatal_error("MSVC is not supported")
endif()

print("C flags: ${CMAKE_C_FLAGS}")
Expand Down Expand Up @@ -186,7 +195,8 @@ kagome_install_setup(
core/storage
core/subscription
core/telemetry
core/utils)
core/utils
)

include(CMakePackageConfigHelpers)

Expand Down
61 changes: 43 additions & 18 deletions cmake/Hunter/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,44 @@ hunter_config(
CMAKE_ARGS WITH_GFLAGS=OFF
)

hunter_config(
wavm
VERSION 1.0.14
KEEP_PACKAGE_SOURCES
)
if ("${WASM_COMPILER}" STREQUAL "WasmEdge")
hunter_config(
LLVM
VERSION 16.0.1
CMAKE_ARGS LLVM_ENABLE_PROJECTS=compiler-rt
)

hunter_config(
LLVM
VERSION 12.0.1-p4
CMAKE_ARGS
hunter_config(
WasmEdge
URL https://github.com/harrm/WasmEdge/archive/8a52b27e2592fc9934b6132e80f69ae6d6925997.zip
SHA1 fbdd08bd648faffa7d140387eb98b437d0f6d5ea
KEEP_PACKAGE_SOURCES
)
endif ()

if ("${WASM_COMPILER}" STREQUAL "WAVM")
hunter_config(
LLVM
VERSION 12.0.1-p4
CMAKE_ARGS
LLVM_ENABLE_PROJECTS=ir
KEEP_PACKAGE_SOURCES
)
KEEP_PACKAGE_SOURCES
)

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WAVM_CXX_FLAGS -Wno-redundant-move;-Wno-dangling-reference;-Wno-error=extra;)
else ()
set(WAVM_CXX_FLAGS -Wno-redundant-move)
endif ()

hunter_config(
wavm
VERSION 1.0.14
CMAKE_ARGS
WAVM_CXX_FLAGS=${WAVM_CXX_FLAGS}
KEEP_PACKAGE_SOURCES
)
endif ()

hunter_config(
scale
Expand All @@ -71,10 +96,10 @@ hunter_config(
)

# Fix for Apple clang (or clang from brew) of versions 15 and higher
if(APPLE AND (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL "15.0.0")
hunter_config(
binaryen
URL https://github.com/qdrvm/binaryen/archive/0744f64a584cae5b9255b1c2f0a4e0b5e06d7038.zip
SHA1 f953c5f38a0417e494901e15ab6f5d8267388d18
)
endif()
if (APPLE AND (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL "15.0.0")
hunter_config(
binaryen
URL https://github.com/qdrvm/binaryen/archive/0744f64a584cae5b9255b1c2f0a4e0b5e06d7038.zip
SHA1 f953c5f38a0417e494901e15ab6f5d8267388d18
)
endif ()
4 changes: 2 additions & 2 deletions cmake/Hunter/hunter-gate-url.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
HunterGate(
URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.23.257-qdrvm11.tar.gz
SHA1 b2a69ae501bdc99006fb86e55930640004468556
URL "https://github.com/qdrvm/hunter/archive/heads/feature/wasm-edge.zip"
SHA1 "27ee523652a59a8e88b50c9f28daf212d5a33fef"
LOCAL
)
27 changes: 17 additions & 10 deletions cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# https://docs.hunter.sh/en/latest/packages/

if (TESTING)
# https://docs.hunter.sh/en/latest/packages/pkg/GTest.html
hunter_add_package(GTest)
find_package(GTest CONFIG REQUIRED)
endif()
# https://docs.hunter.sh/en/latest/packages/pkg/GTest.html
hunter_add_package(GTest)
find_package(GTest CONFIG REQUIRED)
endif ()

if (BACKWARD)
hunter_add_package(backward-cpp)
find_package(Backward)
endif()
hunter_add_package(backward-cpp)
find_package(Backward)
endif ()

# https://docs.hunter.sh/en/latest/packages/pkg/Boost.html
hunter_add_package(Boost COMPONENTS random filesystem program_options date_time)
Expand Down Expand Up @@ -71,9 +71,16 @@ find_package(libsecp256k1 CONFIG REQUIRED)
hunter_add_package(scale)
find_package(scale CONFIG REQUIRED)

hunter_add_package(wavm)
find_package(LLVM CONFIG REQUIRED)
find_package(WAVM CONFIG REQUIRED)
if ("${WASM_COMPILER}" STREQUAL "WAVM")
hunter_add_package(wavm)
find_package(LLVM CONFIG REQUIRED)
find_package(WAVM CONFIG REQUIRED)
endif ()

if ("${WASM_COMPILER}" STREQUAL "WasmEdge")
hunter_add_package(WasmEdge)
find_library(WASM_EDGE_LIBRARY NAMES wasmedge REQUIRED PATHS "${WASMEDGE_ROOT}")
endif ()

hunter_add_package(zstd)
find_package(zstd CONFIG REQUIRED)
Expand Down
2 changes: 1 addition & 1 deletion cmake/install.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ endfunction()
### workaround for imported libraries
function(kagome_install_mini target)
install(TARGETS ${target} EXPORT kagomeTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/kagome
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/kagome
)
endfunction()

Expand Down
6 changes: 6 additions & 0 deletions cmake/kagomeConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ if (KAGOME_ENABLE_WAVM)
find_dependency(WAVM REQUIRED)
endif()

option(KAGOME_ENABLE_WASMEDGE "Include WasmEdge webassembly executor dependency" OFF)
if (KAGOME_ENABLE_WASMEDGE)
find_dependency(LLVM REQUIRED)
find_dependency(WasmEdge REQUIRED)
endif()

option(KAGOME_ENABLE_BINARYEN "Include Binaryen webassembly executor dependency" ON)
if (KAGOME_ENABLE_BINARYEN)
find_dependency(binaryen REQUIRED)
Expand Down
3 changes: 2 additions & 1 deletion core/api/service/state/impl/state_api_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ namespace kagome::api {
const std::optional<primitives::BlockHash> &opt_at) const {
auto at =
opt_at.has_value() ? opt_at.value() : block_tree_->bestBlock().hash;
return executor_->callAt(at, method, data);
OUTCOME_TRY(ctx, executor_->ctx().ephemeralAt(at));
return ctx.module_instance->callExportFunction(ctx, method, data);
}

outcome::result<std::vector<common::Buffer>> StateApiImpl::getKeysPaged(
Expand Down
6 changes: 5 additions & 1 deletion core/application/app_configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ namespace kagome::application {
*/
virtual SyncMethod syncMethod() const = 0;

enum class RuntimeExecutionMethod { Compile, Interpret };
enum class RuntimeExecutionMethod {
Compile,
Interpret,
};

/**
* @return enum constant of the chosen runtime backend
*/
Expand Down
21 changes: 14 additions & 7 deletions core/application/impl/app_configuration_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@

#include "application/impl/app_configuration_impl.hpp"

#include <charconv>
#include <limits>
#include <regex>
#include <string>

#include <fmt/std.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/filereadstream.h>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <charconv>
#include <libp2p/layer/websocket/wss_adaptor.hpp>

#include "api/transport/tuner.hpp"
Expand All @@ -30,7 +31,6 @@
#include "filesystem/common.hpp"
#include "filesystem/directories.hpp"
#include "log/formatters/filepath.hpp"
#include "log/formatters/optional.hpp"
#include "utils/read_file.hpp"

namespace {
Expand Down Expand Up @@ -156,6 +156,11 @@ namespace {
return std::nullopt;
}

std::array<std::string_view, 2> execution_methods{"Interpreted", "Compiled"};

std::string execution_methods_str =
fmt::format("[{}]", fmt::join(execution_methods, ", "));

std::optional<kagome::application::AppConfiguration::RuntimeExecutionMethod>
str_to_runtime_exec_method(std::string_view str) {
using REM = kagome::application::AppConfiguration::RuntimeExecutionMethod;
Expand Down Expand Up @@ -185,12 +190,12 @@ namespace {

std::optional<kagome::primitives::BlockId> str_to_recovery_state(
std::string_view str) {
kagome::primitives::BlockNumber bn;
auto res = kagome::primitives::BlockHash::fromHex(str);
if (res.has_value()) {
return {{res.value()}};
}

kagome::primitives::BlockNumber bn{};
auto result = std::from_chars(str.data(), str.data() + str.size(), bn);
if (result.ec != std::errc::invalid_argument && std::to_string(bn) == str) {
return {{bn}};
Expand Down Expand Up @@ -839,7 +844,7 @@ namespace kagome::application {
("sync", po::value<std::string>()->default_value(def_full_sync),
"choose the desired sync method (Full, Fast). Full is used by default.")
("wasm-execution", po::value<std::string>()->default_value(def_wasm_execution),
"choose the desired wasm execution method (Compiled, Interpreted)")
fmt::format("choose the desired wasm execution method ({})", execution_methods_str).c_str())
("unsafe-cached-wavm-runtime", "use WAVM runtime cache")
("purge-wavm-cache", "purge WAVM runtime cache")
("parachain-runtime-instance-cache-size",
Expand Down Expand Up @@ -1372,8 +1377,10 @@ namespace kagome::application {
if (not runtime_exec_method_opt) {
exec_method_value_error = true;
SL_ERROR(logger_,
"Invalid runtime execution method specified: '{}'",
val);
"Invalid runtime execution method specified: '{}'. "
"Available methods are: {}",
val,
execution_methods_str);
} else {
runtime_exec_method_ = runtime_exec_method_opt.value();
}
Expand Down Expand Up @@ -1455,7 +1462,7 @@ namespace kagome::application {
return false;
}
auto repeat_opt = find_argument<uint16_t>(vm, "repeat");
if (!to_opt) {
if (!repeat_opt) {
SL_ERROR(logger_, "Required argument --repeat is not provided");
return false;
}
Expand Down
1 change: 1 addition & 0 deletions core/application/impl/app_state_manager_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ namespace kagome::application {
if (state_ == State::Prepare) {
auto success = cb();
if (not success) {
SL_ERROR(logger_, "Preparation stage failed");
state_ = State::ShuttingDown;
}
}
Expand Down
Loading

0 comments on commit ee15e3d

Please sign in to comment.