Skip to content

Commit

Permalink
Merge branch 'gh-698' of github.com:AntelopeIO/leap into gh-698-part2
Browse files Browse the repository at this point in the history
  • Loading branch information
greg7mdp committed Apr 6, 2023
2 parents 51d2b5b + 43f64b3 commit 0b3cc3d
Show file tree
Hide file tree
Showing 108 changed files with 670 additions and 4,543 deletions.
2 changes: 1 addition & 1 deletion .github/actions/parallel-ctest-containers/dist/index.mjs

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions .github/actions/parallel-ctest-containers/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@ try {
if(child_process.spawnSync("docker", ["rm", "base"], {stdio:"inherit"}).status)
throw new Error("Failed to remove base container");

// the correct approach is by far "--show-only=json-v1" and then pluck out .tests[].name; but that doesn't work on U18's cmake 3.10 since it lacks json-v1 output
const test_query_result = child_process.spawnSync("docker", ["run", "--rm", "baseimage", "bash", "-e", "-o", "pipefail", "-c", `cd build; ctest -L '${tests_label}' --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]'`]);
const test_query_result = child_process.spawnSync("docker", ["run", "--rm", "baseimage", "bash", "-e", "-o", "pipefail", "-c", `cd build; ctest -L '${tests_label}' --show-only=json-v1`]);
if(test_query_result.status)
throw new Error("Failed to discover tests with label")
const tests = JSON.parse(test_query_result.stdout);
const tests = JSON.parse(test_query_result.stdout).tests;

let subprocesses = [];
tests.forEach(t => {
subprocesses.push(new Promise(resolve => {
child_process.spawn("docker", ["run", "--security-opt", "seccomp=unconfined", "-e", "GITHUB_ACTIONS=True", "--name", t, "--init", "baseimage", "bash", "-c", `cd build; ctest --output-on-failure -R '^${t}$' --timeout ${test_timeout}`], {stdio:"inherit"}).on('close', code => resolve(code));
child_process.spawn("docker", ["run", "--security-opt", "seccomp=unconfined", "-e", "GITHUB_ACTIONS=True", "--name", t.name, "--init", "baseimage", "bash", "-c", `cd build; ctest --output-on-failure -R '^${t.name}$' --timeout ${test_timeout}`], {stdio:"inherit"}).on('close', code => resolve(code));
}));
});

Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ jobs:
run: |
# https://github.com/actions/runner/issues/2033
chown -R $(id -u):$(id -g) $PWD
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -GNinja ..
ninja
tar -pc -C .. --exclude "*.o" build | zstd --long -T0 -9 > ../build.tar.zst
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -GNinja
cmake --build build
tar -pc --exclude "*.o" build | zstd --long -T0 -9 > build.tar.zst
- name: Upload builddir
uses: AntelopeIO/upload-artifact-large-chunks-action@v1
with:
Expand Down
16 changes: 3 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required( VERSION 3.8 )
cmake_minimum_required( VERSION 3.16 )

project( leap )
include(CTest) # suppresses DartConfiguration.tcl error
Expand Down Expand Up @@ -268,18 +268,8 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib/python3/dist-packages/TestHarness DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/python3/dist-packages COMPONENT dev EXCLUDE_FROM_ALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/leap_testing/bin DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/leap_testing COMPONENT dev EXCLUDE_FROM_ALL)
else()
# The following install(CODE ...) steps are necessary for `make dev-install` to work on cmake versions < 3.21.
# However, it can flag as an error if using `make package` instead of `make dev-install` for installation.
# This is due to those directories and symbolic links being created in the postinit script during the package install instead.

# Note If/when doing `make package`, it is not a true error if you see:
# Error creating directory "/<leap_install_dir>/lib/python3/dist-packages".
# CMake Error: failed to create symbolic link '/<leap_install_dir>/lib/python3/dist-packages/TestHarness': no such file or directory
# CMake Error: failed to create symbolic link '/<leap_install_dir>/share/leap_testing/bin': no such file or directory

install(CODE "execute_process( COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_FULL_LIBDIR}/python3/dist-packages)" COMPONENT dev EXCLUDE_FROM_ALL)
install(CODE "execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink ../../../share/leap_testing/tests/TestHarness ${CMAKE_INSTALL_FULL_LIBDIR}/python3/dist-packages/TestHarness)" COMPONENT dev EXCLUDE_FROM_ALL)
install(CODE "execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink ../../bin ${CMAKE_INSTALL_FULL_DATAROOTDIR}/leap_testing/bin)" COMPONENT dev EXCLUDE_FROM_ALL)
# The following install(SCRIPT ...) steps are necessary for `make dev-install` to work on cmake versions < 3.21.
install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/scripts/install_testharness_symlinks.cmake COMPONENT dev EXCLUDE_FROM_ALL)

# The `make package` installation of symlinks happens via the `postinst` script installed in cmake.package via the line below
endif()
Expand Down
2 changes: 0 additions & 2 deletions CMakeModules/EosioTester.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ find_library(libwasm WASM @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libwast WAST @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libir IR @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(liblogging Logging @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libruntime Runtime @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libsoftfloat softfloat @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
get_filename_component(cryptodir @OPENSSL_CRYPTO_LIBRARY@ DIRECTORY)
find_library(liboscrypto crypto "${cryptodir}" NO_DEFAULT_PATH)
Expand All @@ -89,7 +88,6 @@ macro(add_eosio_test_executable test_name)
${libfc}
${libwast}
${libwasm}
${libruntime}
${libir}
${libsoftfloat}
${liboscrypto}
Expand Down
2 changes: 0 additions & 2 deletions CMakeModules/EosioTesterBuild.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ find_library(libwasm WASM @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WASM NO_D
find_library(libwast WAST @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WAST NO_DEFAULT_PATH)
find_library(libir IR @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/IR NO_DEFAULT_PATH)
find_library(liblogging Logging @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/Logging NO_DEFAULT_PATH)
find_library(libruntime Runtime @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/Runtime NO_DEFAULT_PATH)
find_library(libsoftfloat softfloat @CMAKE_BINARY_DIR@/libraries/softfloat NO_DEFAULT_PATH)
get_filename_component(cryptodir @OPENSSL_CRYPTO_LIBRARY@ DIRECTORY)
find_library(liboscrypto crypto "${cryptodir}" NO_DEFAULT_PATH)
Expand All @@ -86,7 +85,6 @@ macro(add_eosio_test_executable test_name)
${libfc}
${libwast}
${libwasm}
${libruntime}
${libir}
${libsoftfloat}
${liboscrypto}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ You will need to build on a [supported operating system](#supported-operating-sy
Requirements to build:
- C++17 compiler and standard library
- boost 1.67+
- CMake 3.8+
- CMake 3.16+
- LLVM 7 - 11 - for Linux only
- newer versions do not work
- openssl 1.1+
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ add_library( eosio_chain
${HEADERS}
)

target_link_libraries( eosio_chain PUBLIC bn256 fc chainbase eosio_rapidjson Logging IR WAST WASM Runtime
target_link_libraries( eosio_chain PUBLIC bn256 fc chainbase eosio_rapidjson Logging IR WAST WASM
softfloat builtins ${CHAIN_EOSVM_LIBRARIES} ${LLVM_LIBS} ${CHAIN_RT_LINKAGE}
)
target_include_directories( eosio_chain
Expand Down
67 changes: 55 additions & 12 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ struct pending_state {
};

struct controller_impl {
enum class app_window_type {
write, // Only main thread is running; read-only threads are not running.
// All read-write and read-only tasks are sequentially executed.
read // Main thread and read-only threads are running read-ony tasks in parallel.
// Read-write tasks are not being executed.
};

// LLVM sets the new handler, we need to reset this to throw a bad_alloc exception so we can possibly exit cleanly
// and not just abort.
Expand Down Expand Up @@ -246,11 +252,10 @@ struct controller_impl {
#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
thread_local static vm::wasm_allocator wasm_alloc; // a copy for main thread and each read-only thread
#endif
// Ideally wasmif should be thread_local which must be a static.
// Unittests can create multiple controller objects (testers) at the same time,
// which overwrites the same static wasmif, is used for eosvmoc too.
wasm_interface wasmif; // used by main thread and all threads for EOSVMOC
thread_local static std::unique_ptr<wasm_interface> wasmif_thread_local; // a copy for each read-only thread, used by eos-vm and eos-vm-jit
std::mutex threaded_wasmifs_mtx;
std::unordered_map<std::thread::id, std::unique_ptr<wasm_interface>> threaded_wasmifs; // one for each read-only thread, used by eos-vm and eos-vm-jit
app_window_type app_window = app_window_type::write;

typedef pair<scope_name,action_name> handler_key;
map< account_name, map<handler_key, apply_handler> > apply_handlers;
Expand Down Expand Up @@ -337,7 +342,12 @@ struct controller_impl {
set_activation_handler<builtin_protocol_feature_t::crypto_primitives>();

self.irreversible_block.connect([this](const block_state_ptr& bsp) {
get_wasm_interface().current_lib(bsp->block_num);
// producer_plugin has already asserted irreversible_block signal is
// called in write window
wasmif.current_lib(bsp->block_num);
for (auto& w: threaded_wasmifs) {
w.second->current_lib(bsp->block_num);
}
});


Expand Down Expand Up @@ -497,9 +507,10 @@ struct controller_impl {

void replay(std::function<bool()> check_shutdown) {
auto blog_head = blog.head();
if( !blog_head && !fork_db.root() ) {
if( !fork_db.root() ) {
fork_db.reset( *head );
return;
if (!blog_head)
return;
}

replaying = true;
Expand Down Expand Up @@ -2687,12 +2698,25 @@ struct controller_impl {
wasmif.init_thread_local_data();
else
#endif
{
std::lock_guard g(threaded_wasmifs_mtx);
// Non-EOSVMOC needs a wasmif per thread
wasmif_thread_local = std::make_unique<wasm_interface>( conf.wasm_runtime, conf.eosvmoc_tierup, db, conf.state_dir, conf.eosvmoc_config, !conf.profile_accounts.empty());
threaded_wasmifs[std::this_thread::get_id()] = std::make_unique<wasm_interface>( conf.wasm_runtime, conf.eosvmoc_tierup, db, conf.state_dir, conf.eosvmoc_config, !conf.profile_accounts.empty());
}
}

bool is_on_main_thread() { return main_thread_id == std::this_thread::get_id(); };

void set_to_write_window() {
app_window = app_window_type::write;
}
void set_to_read_window() {
app_window = app_window_type::read;
}
bool is_write_window() const {
return app_window == app_window_type::write;
}

wasm_interface& get_wasm_interface() {
if ( is_on_main_thread()
#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
Expand All @@ -2701,7 +2725,17 @@ struct controller_impl {
)
return wasmif;
else
return *wasmif_thread_local;
return *threaded_wasmifs[std::this_thread::get_id()];
}

void code_block_num_last_used(const digest_type& code_hash, uint8_t vm_type, uint8_t vm_version, uint32_t block_num) {
// The caller of this function apply_eosio_setcode has already asserted that
// the transaction is not a read-only trx, which implies we are
// in write window. Safe to call threaded_wasmifs's code_block_num_last_used
wasmif.code_block_num_last_used(code_hash, vm_type, vm_version, block_num);
for (auto& w: threaded_wasmifs) {
w.second->code_block_num_last_used(code_hash, vm_type, vm_version, block_num);
}
}

block_state_ptr fork_db_head() const;
Expand All @@ -2711,7 +2745,6 @@ thread_local platform_timer controller_impl::timer;
#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
thread_local eosio::vm::wasm_allocator controller_impl::wasm_alloc;
#endif
thread_local std::unique_ptr<wasm_interface> controller_impl::wasmif_thread_local;

const resource_limits_manager& controller::get_resource_limits_manager()const
{
Expand Down Expand Up @@ -3686,8 +3719,18 @@ void controller::init_thread_local_data() {
my->init_thread_local_data();
}

bool controller::is_on_main_thread() const {
return my->is_on_main_thread();
void controller::set_to_write_window() {
my->set_to_write_window();
}
void controller::set_to_read_window() {
my->set_to_read_window();
}
bool controller::is_write_window() const {
return my->is_write_window();
}

void controller::code_block_num_last_used(const digest_type& code_hash, uint8_t vm_type, uint8_t vm_version, uint32_t block_num) {
return my->code_block_num_last_used(code_hash, vm_type, vm_version, block_num);
}

/// Protocol feature activation handlers:
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/eosio_contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void apply_eosio_setcode(apply_context& context) {
old_size = (int64_t)old_code_entry.code.size() * config::setcode_ram_bytes_multiplier;
if( old_code_entry.code_ref_count == 1 ) {
db.remove(old_code_entry);
context.control.get_wasm_interface().code_block_num_last_used(account.code_hash, account.vm_type, account.vm_version, context.control.head_block_num() + 1);
context.control.code_block_num_last_used(account.code_hash, account.vm_type, account.vm_version, context.control.head_block_num() + 1);
} else {
db.modify(old_code_entry, [](code_object& o) {
--o.code_ref_count;
Expand Down
5 changes: 4 additions & 1 deletion libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,10 @@ namespace eosio { namespace chain {
void set_db_read_only_mode();
void unset_db_read_only_mode();
void init_thread_local_data();
bool is_on_main_thread() const;
void set_to_write_window();
void set_to_read_window();
bool is_write_window() const;
void code_block_num_last_used(const digest_type& code_hash, uint8_t vm_type, uint8_t vm_version, uint32_t block_num);

private:
friend class apply_context;
Expand Down
2 changes: 0 additions & 2 deletions libraries/chain/include/eosio/chain/wasm_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include <eosio/chain/whitelisted_intrinsics.hpp>
#include <eosio/chain/exceptions.hpp>
#include <functional>
#include "Runtime/Linker.h"
#include "Runtime/Runtime.h"

namespace eosio { namespace chain {

Expand Down
41 changes: 1 addition & 40 deletions libraries/chain/include/eosio/chain/wasm_interface_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <fc/scoped_exit.hpp>

#include "IR/Module.h"
#include "Runtime/Intrinsics.h"
#include "Platform/Platform.h"
#include "WAST/WAST.h"
#include "IR/Validate.h"
Expand All @@ -26,7 +25,6 @@
using namespace fc;
using namespace eosio::chain::webassembly;
using namespace IR;
using namespace Runtime;

using boost::multi_index_container;

Expand All @@ -37,7 +35,6 @@ namespace eosio { namespace chain {
struct wasm_interface_impl {
struct wasm_cache_entry {
digest_type code_hash;
uint32_t first_block_num_used;
uint32_t last_block_num_used;
std::unique_ptr<wasm_instantiated_module_interface> module;
uint8_t vm_type = 0;
Expand Down Expand Up @@ -109,24 +106,6 @@ namespace eosio { namespace chain {
return it != wasm_instantiation_cache.end();
}

std::vector<uint8_t> parse_initial_memory(const Module& module) {
std::vector<uint8_t> mem_image;

for(const DataSegment& data_segment : module.dataSegments) {
EOS_ASSERT(data_segment.baseOffset.type == InitializerExpression::Type::i32_const, wasm_exception, "");
EOS_ASSERT(module.memories.defs.size(), wasm_exception, "");
const U32 base_offset = data_segment.baseOffset.i32;
const Uptr memory_size = (module.memories.defs[0].type.size.min << IR::numBytesPerPageLog2);
if(base_offset >= memory_size || base_offset + data_segment.data.size() > memory_size)
FC_THROW_EXCEPTION(wasm_execution_error, "WASM data segment outside of valid memory range");
if(base_offset + data_segment.data.size() > mem_image.size())
mem_image.resize(base_offset + data_segment.data.size(), 0x00);
memcpy(mem_image.data() + base_offset, data_segment.data.data(), data_segment.data.size());
}

return mem_image;
}

void code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num) {
wasm_cache_index::iterator it = wasm_instantiation_cache.find(boost::make_tuple(code_hash, vm_type, vm_version));
if(it != wasm_instantiation_cache.end())
Expand Down Expand Up @@ -157,7 +136,6 @@ namespace eosio { namespace chain {

it = wasm_instantiation_cache.emplace( wasm_interface_impl::wasm_cache_entry{
.code_hash = code_hash,
.first_block_num_used = codeobject->first_block_used,
.last_block_num_used = UINT32_MAX,
.module = nullptr,
.vm_type = vm_type,
Expand All @@ -173,24 +151,8 @@ namespace eosio { namespace chain {
trx_context.resume_billing_timer();
});
trx_context.pause_billing_timer();
IR::Module module;
std::vector<U8> bytes = {
(const U8*)codeobject->code.data(),
(const U8*)codeobject->code.data() + codeobject->code.size()};
try {
Serialization::MemoryInputStream stream((const U8*)bytes.data(),
bytes.size());
WASM::scoped_skip_checks no_check;
WASM::serialize(stream, module);
module.userSections.clear();
} catch (const Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
} catch (const IR::ValidationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
}

wasm_instantiation_cache.modify(it, [&](auto& c) {
c.module = runtime_interface->instantiate_module((const char*)bytes.data(), bytes.size(), parse_initial_memory(module), code_hash, vm_type, vm_version);
c.module = runtime_interface->instantiate_module(codeobject->code.data(), codeobject->code.size(), code_hash, vm_type, vm_version);
});
}
return it->module;
Expand All @@ -209,7 +171,6 @@ namespace eosio { namespace chain {
member<wasm_cache_entry, uint8_t, &wasm_cache_entry::vm_version>
>
>,
ordered_non_unique<tag<by_first_block_num>, member<wasm_cache_entry, uint32_t, &wasm_cache_entry::first_block_num_used>>,
ordered_non_unique<tag<by_last_block_num>, member<wasm_cache_entry, uint32_t, &wasm_cache_entry::last_block_num_used>>
>
> wasm_cache_index;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
namespace eosio { namespace chain { namespace webassembly { namespace eosvmoc {

using namespace IR;
using namespace Runtime;
using namespace fc;

using namespace eosio::chain::eosvmoc;
Expand All @@ -30,7 +29,7 @@ class eosvmoc_runtime : public eosio::chain::wasm_runtime_interface {
public:
eosvmoc_runtime(const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, const chainbase::database& db);
~eosvmoc_runtime();
std::unique_ptr<wasm_instantiated_module_interface> instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory,
std::unique_ptr<wasm_instantiated_module_interface> instantiate_module(const char* code_bytes, size_t code_size,
const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version) override;

void immediately_exit_currently_running_module() override;
Expand Down
Loading

0 comments on commit 0b3cc3d

Please sign in to comment.