From 309ca77626e90ea177e212b44f36d2e1a9ee41d2 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Thu, 17 Jun 2021 18:43:02 -0400 Subject: [PATCH 01/14] patch boost --- CMakeLists.txt | 5 ++++ external/boost/CMakeLists.txt | 26 ++++++++++++++++ external/boost/boost.patch | 56 +++++++++++++++++++++++++++++++++++ wasm/boost/CMakeLists.txt | 25 ---------------- 4 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 external/boost/CMakeLists.txt create mode 100644 external/boost/boost.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f89d4a88..02c0afb91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,10 @@ if(BUILD_NATIVE) file(APPEND ${CMAKE_BINARY_DIR}/CTestTestfile.cmake "subdirs(\"native\")\n") endif() +if(DEFINED WASI_SDK_PREFIX OR DEFINED ENV{EMSDK}) + add_subdirectory(external/boost) +endif() + if(DEFINED WASI_SDK_PREFIX) set(EDEN_ATOMIC_ASSETS_ACCOUNT atomicassets CACHE STRING "The account holding the atomicassets contract") set(EDEN_ATOMIC_MARKET_ACCOUNT atomicmarket CACHE STRING "The account holding the atomicmarket contract") @@ -43,6 +47,7 @@ if(DEFINED WASI_SDK_PREFIX) -DFORCE_COLORED_OUTPUT=${FORCE_COLORED_OUTPUT} -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} + -DBOOST_EXTRACTED=${BOOST_EXTRACTED} ) file(APPEND ${CMAKE_BINARY_DIR}/CTestTestfile.cmake "subdirs(\"wasm\")\n") ExternalProject_Add_StepTargets(wasm test) diff --git a/external/boost/CMakeLists.txt b/external/boost/CMakeLists.txt new file mode 100644 index 000000000..8d2759ffb --- /dev/null +++ b/external/boost/CMakeLists.txt @@ -0,0 +1,26 @@ +set(BOOST_URL https://github.com/eoscommunity/Eden/releases/download/deps/boost_1_75_0.tar.bz2) +set(BOOST_ARCHIVE ${CMAKE_CURRENT_BINARY_DIR}/boost_1_75_0.tar.bz2) +set(BOOST_EXTRACTED ${CMAKE_CURRENT_BINARY_DIR}/boost_1_75_0) +set(BOOST_EXTRACTED ${BOOST_EXTRACTED} PARENT_SCOPE) + +if(NOT EXISTS ${BOOST_ARCHIVE}) + message("Downloading ${BOOST_URL}") + file(DOWNLOAD ${BOOST_URL} ${BOOST_ARCHIVE} + STATUS BOOST_DOWNLOAD_STATUS + TIMEOUT 60 + SHOW_PROGRESS + TLS_VERIFY ON) + list(POP_BACK BOOST_DOWNLOAD_STATUS BOOST_DOWNLOAD_STATUS_MSG) + if(NOT BOOST_DOWNLOAD_STATUS EQUAL 0) + file(REMOVE ${BOOST_ARCHIVE}) + message(FATAL_ERROR "Download ${BOOST_URL} failed. ${BOOST_DOWNLOAD_STATUS_MSG}") + endif() +endif() + +if(NOT EXISTS ${BOOST_EXTRACTED}) + message("Extracting ${BOOST_ARCHIVE}") + execute_process( + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND bash -c "tar xf ${BOOST_ARCHIVE} && cd ${BOOST_EXTRACTED} && patch -p0 <${CMAKE_CURRENT_SOURCE_DIR}/boost.patch" + ) +endif() diff --git a/external/boost/boost.patch b/external/boost/boost.patch new file mode 100644 index 000000000..8a037ee69 --- /dev/null +++ b/external/boost/boost.patch @@ -0,0 +1,56 @@ +--- tools/build/src/tools/emscripten.jam 2020-12-03 00:02:49.000000000 -0500 ++++ ../emscripten.jam 2021-06-16 17:49:00.260000000 -0400 +@@ -9,6 +9,7 @@ + import common ; + import gcc ; + import type ; ++import generators ; + + feature.feature embind : off on : propagated ; + feature.feature closure : off on full : propagated ; +@@ -49,10 +50,12 @@ + off on + off on + ; ++generators.override builtin.lib-generator : emscripten.prebuilt ; ++generators.override emscripten.searched-lib-generator : searched-lib-generator ; + + type.set-generated-target-suffix EXE : emscripten : "js" ; +-type.set-generated-target-suffix OBJ : emscripten : "bc" ; +-type.set-generated-target-suffix STATIC_LIB : emscripten : "bc" ; ++type.set-generated-target-suffix OBJ : emscripten : "o" ; ++type.set-generated-target-suffix STATIC_LIB : emscripten : "a" ; + + toolset.flags emscripten.compile OPTIONS ; + toolset.flags emscripten.compile OPTIONS ; +@@ -94,7 +97,7 @@ + + actions archive + { +- "$(CONFIG_COMMAND)" $(AROPTIONS) -o "$(<)" "$(>)" ++ emar q "$(<)" "$(>)" + } + + toolset.flags emscripten.link USER_OPTIONS ; +--- boost/interprocess/detail/workaround.hpp 2020-12-03 00:01:42.000000000 -0500 ++++ ../bip-workaround.hpp 2021-06-17 15:21:14.930000000 -0400 +@@ -29,7 +29,7 @@ + ////////////////////////////////////////////////////// + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms + ////////////////////////////////////////////////////// +- #if !defined(__QNXNTO__) && !defined(__ANDROID__) && !defined(__HAIKU__) && !(__VXWORKS__) ++ #if !defined(__QNXNTO__) && !defined(__ANDROID__) && !defined(__HAIKU__) && !(__VXWORKS__) && !defined(__wasm__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +--- boost/test/impl/execution_monitor.ipp 2021-06-17 15:49:21.400000000 -0400 ++++ ../execution_monitor.ipp 2021-06-17 15:49:11.460000000 -0400 +@@ -163,7 +163,7 @@ + + // documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp + # if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \ +- (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && \ ++ (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && !defined(__wasm__) && \ + !defined(BOOST_TEST_DISABLE_ALT_STACK) + # define BOOST_TEST_USE_ALT_STACK + # endif diff --git a/wasm/boost/CMakeLists.txt b/wasm/boost/CMakeLists.txt index c19c4f944..57eee9ae7 100644 --- a/wasm/boost/CMakeLists.txt +++ b/wasm/boost/CMakeLists.txt @@ -1,30 +1,5 @@ -set(BOOST_URL https://github.com/eoscommunity/Eden/releases/download/deps/boost_1_75_0.tar.bz2) -set(BOOST_ARCHIVE ${CMAKE_CURRENT_BINARY_DIR}/boost_1_75_0.tar.bz2) -set(BOOST_EXTRACTED ${CMAKE_CURRENT_BINARY_DIR}/boost_1_75_0) set(BOOST_BOOST ${CMAKE_CURRENT_BINARY_DIR}/boost) -if(NOT EXISTS ${BOOST_ARCHIVE}) - message("Downloading ${BOOST_URL}") - file(DOWNLOAD ${BOOST_URL} ${BOOST_ARCHIVE} - STATUS BOOST_DOWNLOAD_STATUS - TIMEOUT 60 - SHOW_PROGRESS - TLS_VERIFY ON) - list(POP_BACK BOOST_DOWNLOAD_STATUS BOOST_DOWNLOAD_STATUS_MSG) - if(NOT BOOST_DOWNLOAD_STATUS EQUAL 0) - file(REMOVE ${BOOST_ARCHIVE}) - message(FATAL_ERROR "Download ${BOOST_URL} failed. ${BOOST_DOWNLOAD_STATUS_MSG}") - endif() -endif() - -if(NOT EXISTS ${BOOST_EXTRACTED}) - message("Extracting ${BOOST_ARCHIVE}") - execute_process( - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND tar xf ${BOOST_ARCHIVE} - ) -endif() - if(NOT EXISTS ${BOOST_BOOST}) message("Copying ${BOOST_BOOST}") execute_process( From 9da3f310b5604bb178f5094525d3a8b12a449b35 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Thu, 17 Jun 2021 19:14:41 -0400 Subject: [PATCH 02/14] emscripten: boost --- CMakeLists.txt | 17 +++++++++++++++++ emscripten/CMakeLists.txt | 28 ++++++++++++++++++++++++++++ external/boost/CMakeLists.txt | 4 ++-- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 emscripten/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 02c0afb91..4e0f41a73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,23 @@ else() message(WARNING "WASI_SDK_PREFIX isn't defined; skipping wasm") endif() +if(DEFINED ENV{EMSDK}) + ExternalProject_Add(emscripten + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/emscripten + BINARY_DIR emscripten + CMAKE_COMMAND emcmake + CMAKE_ARGS cmake + INSTALL_COMMAND "" + BUILD_ALWAYS 1 + TEST_EXCLUDE_FROM_MAIN 1 + CMAKE_ARGS + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DBOOST_EXTRACTED=${BOOST_EXTRACTED} + ) + file(APPEND ${CMAKE_BINARY_DIR}/CTestTestfile.cmake "subdirs(\"emscripten\")\n") + ExternalProject_Add_StepTargets(emscripten test) +endif() + ########## TS PACKAGES #################### if(NOT DEFINED SKIP_TS OR NOT SKIP_TS) add_custom_target(yarn ALL diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt new file mode 100644 index 000000000..4c3b82c74 --- /dev/null +++ b/emscripten/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.16.3) +cmake_policy(VERSION 3.16) +project(emscripten) +enable_testing() + +set(IS_EMSCRIPTEN YES) +get_filename_component(ROOT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/.. ABSOLUTE) +get_filename_component(ROOT_BINARY_DIR ${CMAKE_BINARY_DIR}/.. ABSOLUTE) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored output" TRUE) +if(${FORCE_COLORED_OUTPUT}) + add_compile_options(-fcolor-diagnostics) +endif() + +set(DEP_PREFIX ${CMAKE_BINARY_DIR}/deps) + +# Dependancy builds are done generation time so cmake's find_* commands can find them +if(NOT EXISTS ${DEP_PREFIX}/include/boost) + message("building boost") + execute_process( + WORKING_DIRECTORY ${BOOST_EXTRACTED} + COMMAND ./b2 --prefix=${DEP_PREFIX} --build-dir=${DEP_PREFIX}/build-boost toolset=emscripten variant=release runtime-link=static link=static --with-chrono --with-date_time --with-filesystem --with-iostreams --with-program_options --with-system --with-test install + ) +endif() diff --git a/external/boost/CMakeLists.txt b/external/boost/CMakeLists.txt index 8d2759ffb..8da0c5fff 100644 --- a/external/boost/CMakeLists.txt +++ b/external/boost/CMakeLists.txt @@ -18,9 +18,9 @@ if(NOT EXISTS ${BOOST_ARCHIVE}) endif() if(NOT EXISTS ${BOOST_EXTRACTED}) - message("Extracting ${BOOST_ARCHIVE}") + message("Bootstrapping ${BOOST_ARCHIVE}") execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND bash -c "tar xf ${BOOST_ARCHIVE} && cd ${BOOST_EXTRACTED} && patch -p0 <${CMAKE_CURRENT_SOURCE_DIR}/boost.patch" + COMMAND bash -c "tar xf ${BOOST_ARCHIVE} && cd ${BOOST_EXTRACTED} && patch -p0 <${CMAKE_CURRENT_SOURCE_DIR}/boost.patch && ./bootstrap.sh" ) endif() From d8feff0053502e6e3855884084b0498e99b1781a Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Fri, 18 Jun 2021 11:11:25 -0400 Subject: [PATCH 03/14] emscripten: gmp, openssl --- emscripten/CMakeLists.txt | 77 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 4c3b82c74..5795a7e9c 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -18,11 +18,84 @@ endif() set(DEP_PREFIX ${CMAKE_BINARY_DIR}/deps) -# Dependancy builds are done generation time so cmake's find_* commands can find them +set(DEP_URL https://github.com/eoscommunity/Eden/releases/download/deps) +set(GMP_ARCHIVE gmp-6.2.1.tar.zst) +set(GMP_EXTRACTED gmp-6.2.1) +set(OPENSSL_ARCHIVE openssl-1.1.1k.tar.gz) +set(OPENSSL_EXTRACTED openssl-1.1.1k) + +function(download url archive) + if(NOT EXISTS ${archive}) + message("Downloading ${url}") + file(DOWNLOAD ${url} ${archive} + STATUS download_status + TIMEOUT 60 + SHOW_PROGRESS + TLS_VERIFY ON) + list(POP_BACK download_status BOOST_DOWNLOAD_STATUS_MSG) + if(NOT download_status EQUAL 0) + file(REMOVE ${archive}) + message(FATAL_ERROR "Download ${url} failed. ${BOOST_DOWNLOAD_STATUS_MSG}") + endif() + endif() +endfunction() + +download(${DEP_URL}/${GMP_ARCHIVE} ${DEP_PREFIX}/${GMP_ARCHIVE}) +download(${DEP_URL}/${OPENSSL_ARCHIVE} ${DEP_PREFIX}/${OPENSSL_ARCHIVE}) + +# Dependancy builds are done at generation time so cmake's find_* commands can find them +if(NOT EXISTS ${DEP_PREFIX}/lib/libgmp.so) + message("building gmp") + execute_process( + WORKING_DIRECTORY ${DEP_PREFIX} + COMMAND bash -c "\ + rm -rf ${GMP_EXTRACTED} \ + && tar xf ${GMP_ARCHIVE} \ + && cd ${GMP_EXTRACTED} \ + && emconfigure ./configure --prefix=${DEP_PREFIX} --host none --disable-assembly \ + && emmake make -j \ + && emmake make -j install \ + && ln -sf libgmp.a ../lib/libgmp.so \ + " + ) +endif() + +if(NOT EXISTS ${DEP_PREFIX}/lib/libgmp.a) + message("building openssl") + execute_process( + WORKING_DIRECTORY ${DEP_PREFIX} + COMMAND bash -c "\ + rm -rf ${OPENSSL_EXTRACTED} \ + && tar xf ${OPENSSL_ARCHIVE} \ + && cd ${OPENSSL_EXTRACTED} \ + && emconfigure bash -c \ + \"CROSS_COMPILE= ./config --prefix=${DEP_PREFIX} no-asm no-afalgeng no-shared\" \ + && make -j build_libs \ + && make install_dev \ + " + ) +endif() + if(NOT EXISTS ${DEP_PREFIX}/include/boost) message("building boost") execute_process( WORKING_DIRECTORY ${BOOST_EXTRACTED} - COMMAND ./b2 --prefix=${DEP_PREFIX} --build-dir=${DEP_PREFIX}/build-boost toolset=emscripten variant=release runtime-link=static link=static --with-chrono --with-date_time --with-filesystem --with-iostreams --with-program_options --with-system --with-test install + COMMAND "\ + ./b2 \ + --prefix=${DEP_PREFIX} \ + --build-dir=${DEP_PREFIX}/build-boost \ + toolset=emscripten \ + variant=release \ + runtime-link=static \ + link=static \ + --with-chrono \ + --with-date_time \ + --with-filesystem \ + --with-iostreams \ + --with-program_options \ + --with-system \ + --with-test \ + install \ + " ) endif() From 01ee6f9bd6f69867a771b407893552ff94dc19e9 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Fri, 18 Jun 2021 13:56:51 -0400 Subject: [PATCH 04/14] emscripten: build chainlib --- CMakeLists.txt | 5 ++++- emscripten/CMakeLists.txt | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e0f41a73..223db5328 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,13 +60,16 @@ if(DEFINED ENV{EMSDK}) SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/emscripten BINARY_DIR emscripten CMAKE_COMMAND emcmake - CMAKE_ARGS cmake INSTALL_COMMAND "" BUILD_ALWAYS 1 TEST_EXCLUDE_FROM_MAIN 1 CMAKE_ARGS + cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_FIND_ROOT_PATH=${CMAKE_CURRENT_BINARY_DIR}/emscripten/deps -DBOOST_EXTRACTED=${BOOST_EXTRACTED} + -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} + -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} ) file(APPEND ${CMAKE_BINARY_DIR}/CTestTestfile.cmake "subdirs(\"emscripten\")\n") ExternalProject_Add_StepTargets(emscripten test) diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 5795a7e9c..073eecf3f 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -60,7 +60,7 @@ if(NOT EXISTS ${DEP_PREFIX}/lib/libgmp.so) ) endif() -if(NOT EXISTS ${DEP_PREFIX}/lib/libgmp.a) +if(NOT EXISTS ${DEP_PREFIX}/lib/libssl.a) message("building openssl") execute_process( WORKING_DIRECTORY ${DEP_PREFIX} @@ -80,7 +80,7 @@ if(NOT EXISTS ${DEP_PREFIX}/include/boost) message("building boost") execute_process( WORKING_DIRECTORY ${BOOST_EXTRACTED} - COMMAND "\ + COMMAND bash -c "\ ./b2 \ --prefix=${DEP_PREFIX} \ --build-dir=${DEP_PREFIX}/build-boost \ @@ -99,3 +99,15 @@ if(NOT EXISTS ${DEP_PREFIX}/include/boost) " ) endif() + +set(Boost_USE_STATIC_RUNTIME ON) +set(ECC_IMPL secp256k1) +set(SKIP_FC_TESTS YES) +option(ENABLE_TOOLS "enable building of tools" OFF) + +add_subdirectory(../external/eos/libraries/builtins builtins) +add_subdirectory(../external/eos/libraries/chain chain) +add_subdirectory(../external/eos/libraries/chainbase chainbase) +add_subdirectory(../external/eos/libraries/eos-vm eos-vm) +add_subdirectory(../external/eos/libraries/fc fc) +add_subdirectory(../external/eos/libraries/version version) From f2aa52d2fdff6046b5e258da8bdd1e8e315662b5 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Fri, 18 Jun 2021 18:46:19 -0400 Subject: [PATCH 05/14] cltestlib --- libraries/CMakeLists.txt | 1 + libraries/cltestlib/CMakeLists.txt | 3 + libraries/cltestlib/cltestlib.cpp | 107 +++++++++++++++ .../cltestlib/include/cltestlib/cltestlib.hpp | 36 ++++++ programs/cltester/CMakeLists.txt | 2 +- programs/cltester/main.cpp | 122 ++---------------- 6 files changed, 159 insertions(+), 112 deletions(-) create mode 100644 libraries/cltestlib/CMakeLists.txt create mode 100644 libraries/cltestlib/cltestlib.cpp create mode 100644 libraries/cltestlib/include/cltestlib/cltestlib.hpp diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 9977656cf..e7705b415 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -7,6 +7,7 @@ endif() if(DEFINED IS_NATIVE) add_subdirectory(chain_kv) + add_subdirectory(cltestlib) add_subdirectory(debug_eos_vm) add_subdirectory(state_history) endif() diff --git a/libraries/cltestlib/CMakeLists.txt b/libraries/cltestlib/CMakeLists.txt new file mode 100644 index 000000000..40d536ab9 --- /dev/null +++ b/libraries/cltestlib/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(cltestlib cltestlib.cpp) +target_include_directories(cltestlib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(cltestlib PUBLIC chain) diff --git a/libraries/cltestlib/cltestlib.cpp b/libraries/cltestlib/cltestlib.cpp new file mode 100644 index 000000000..cf493ed26 --- /dev/null +++ b/libraries/cltestlib/cltestlib.cpp @@ -0,0 +1,107 @@ +#include + +#include +#include + +using eosio::chain::builtin_protocol_feature_t; +using eosio::chain::digest_type; +using eosio::chain::protocol_feature_exception; +using eosio::chain::protocol_feature_set; + +namespace cltestlib +{ + eosio::chain::protocol_feature_set make_protocol_feature_set() + { + protocol_feature_set pfs; + std::map> visited_builtins; + + std::function add_builtins = + [&pfs, &visited_builtins, + &add_builtins](builtin_protocol_feature_t codename) -> digest_type { + auto res = visited_builtins.emplace(codename, std::optional()); + if (!res.second) + { + EOS_ASSERT(res.first->second, protocol_feature_exception, + "invariant failure: cycle found in builtin protocol feature dependencies"); + return *res.first->second; + } + + auto f = protocol_feature_set::make_default_builtin_protocol_feature( + codename, [&add_builtins](builtin_protocol_feature_t d) { return add_builtins(d); }); + + const auto& pf = pfs.add_feature(f); + res.first->second = pf.feature_digest; + + return pf.feature_digest; + }; + + for (const auto& p : eosio::chain::builtin_protocol_feature_codenames) + { + add_builtins(p.first); + } + + return pfs; + } + + void test_chain::start_block(int64_t skip_miliseconds) + { + mutating(); + if (control->is_building_block()) + finish_block(); + control->start_block(control->head_block_time() + + fc::microseconds(skip_miliseconds * 1000ll + block_interval_us), + 0); + } + + void test_chain::start_if_needed() + { + mutating(); + if (!control->is_building_block()) + control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0); + } + + void test_chain::finish_block() + { + start_if_needed(); + ilog("finish block ${n}", ("n", control->head_block_num())); + control->finalize_block( + [&](eosio::chain::digest_type d) { return std::vector{producer_key.sign(d)}; }); + control->commit_block(); + } + + eosio::chain::transaction_trace_ptr test_chain::push_transaction(uint32_t billed_cpu_time_us, + push_trx_args&& args) + { + auto transaction = fc::raw::unpack(args.transaction); + eosio::chain::signed_transaction signed_trx{ + std::move(transaction), std::move(args.signatures), std::move(args.context_free_data)}; + start_if_needed(); + for (auto& key : args.keys) + signed_trx.sign(key, control->get_chain_id()); + auto ptrx = std::make_shared( + std::move(signed_trx), eosio::chain::packed_transaction::compression_type::none); + auto fut = eosio::chain::transaction_metadata::start_recover_keys( + ptrx, control->get_thread_pool(), control->get_chain_id(), fc::microseconds::maximum()); + auto start_time = std::chrono::steady_clock::now(); + auto result = control->push_transaction(fut.get(), fc::time_point::maximum(), + billed_cpu_time_us, true, billed_cpu_time_us); + auto us = std::chrono::duration_cast( + std::chrono::steady_clock::now() - start_time); + ilog("chainlib transaction took ${u} us", ("u", us.count())); + return result; + } + + eosio::chain::transaction_trace_ptr test_chain::exec_deferred(uint32_t billed_cpu_time_us) + { + start_if_needed(); + const auto& idx = + control->db() + .get_index(); + auto itr = idx.begin(); + if (itr != idx.end() && itr->delay_until <= control->pending_block_time()) + return control->push_scheduled_transaction(itr->trx_id, fc::time_point::maximum(), + billed_cpu_time_us, true); + return nullptr; + } + +} // namespace cltestlib diff --git a/libraries/cltestlib/include/cltestlib/cltestlib.hpp b/libraries/cltestlib/include/cltestlib/cltestlib.hpp new file mode 100644 index 000000000..4442089de --- /dev/null +++ b/libraries/cltestlib/include/cltestlib/cltestlib.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +namespace cltestlib +{ + eosio::chain::protocol_feature_set make_protocol_feature_set(); + + struct push_trx_args + { + eosio::chain::bytes transaction; + std::vector context_free_data; + std::vector signatures; + std::vector keys; + }; + + struct test_chain + { + static constexpr int block_interval_us = 500'000; + eosio::chain::private_key_type producer_key{ + std::string{"5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"}}; + std::unique_ptr cfg; + std::unique_ptr control; + + virtual void mutating() {} + void start_block(int64_t skip_miliseconds = 0); + void start_if_needed(); + void finish_block(); + eosio::chain::transaction_trace_ptr push_transaction(uint32_t billed_cpu_time_us, + push_trx_args&& args); + eosio::chain::transaction_trace_ptr exec_deferred(uint32_t billed_cpu_time_us); + }; +} // namespace cltestlib + +FC_REFLECT(cltestlib::push_trx_args, (transaction)(context_free_data)(signatures)(keys)) diff --git a/programs/cltester/CMakeLists.txt b/programs/cltester/CMakeLists.txt index 1b1cd1000..0a110a243 100644 --- a/programs/cltester/CMakeLists.txt +++ b/programs/cltester/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(cltester main.cpp) -target_link_libraries(cltester abieos state_history rodeos_lib debug_eos_vm chain) +target_link_libraries(cltester abieos state_history cltestlib rodeos_lib debug_eos_vm chain) set_target_properties(cltester PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ROOT_BINARY_DIR}) add_custom_command(TARGET cltester POST_BUILD COMMAND mkdir -p ${ROOT_BINARY_DIR}/clsdk/bin diff --git a/programs/cltester/main.cpp b/programs/cltester/main.cpp index 8cbd2d102..f6eaa79ec 100644 --- a/programs/cltester/main.cpp +++ b/programs/cltester/main.cpp @@ -1,8 +1,7 @@ #define EOSIO_EOS_VM_JIT_RUNTIME_ENABLED +#include #include -#include -#include #include #include #include @@ -33,7 +32,6 @@ using eosio::convert_to_bin; using eosio::chain::block_state_ptr; using eosio::chain::builtin_protocol_feature_t; using eosio::chain::digest_type; -using eosio::chain::protocol_feature_exception; using eosio::chain::protocol_feature_set; using eosio::chain::signed_transaction; using eosio::chain::transaction_trace_ptr; @@ -76,8 +74,6 @@ using backend_t = eosio::vm::backend< // inline constexpr int max_backtrace_frames = 512; -inline constexpr int block_interval_ms = 500; -inline constexpr int block_interval_us = block_interval_ms * 1000; inline constexpr uint32_t billed_cpu_time_use = 2000; inline constexpr int32_t polyfill_root_dir_fd = 3; @@ -195,39 +191,6 @@ struct intrinsic_context } }; -protocol_feature_set make_protocol_feature_set() -{ - protocol_feature_set pfs; - std::map> visited_builtins; - - std::function add_builtins = - [&pfs, &visited_builtins, - &add_builtins](builtin_protocol_feature_t codename) -> digest_type { - auto res = visited_builtins.emplace(codename, std::optional()); - if (!res.second) - { - EOS_ASSERT(res.first->second, protocol_feature_exception, - "invariant failure: cycle found in builtin protocol feature dependencies"); - return *res.first->second; - } - - auto f = protocol_feature_set::make_default_builtin_protocol_feature( - codename, [&add_builtins](builtin_protocol_feature_t d) { return add_builtins(d); }); - - const auto& pf = pfs.add_feature(f); - res.first->second = pf.feature_digest; - - return pf.feature_digest; - }; - - for (const auto& p : eosio::chain::builtin_protocol_feature_codenames) - { - add_builtins(p.first); - } - - return pfs; -} - template using wasm_ptr = eosio::vm::argument_proxy; @@ -245,15 +208,10 @@ struct test_chain_ref test_chain_ref& operator=(const test_chain_ref&); }; -struct test_chain +struct test_chain : cltestlib::test_chain { - eosio::chain::private_key_type producer_key{ - "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"s}; - ::state& state; fc::temp_directory dir; - std::unique_ptr cfg; - std::unique_ptr control; std::optional applied_transaction_connection; std::optional accepted_block_connection; eosio::state_history::trace_converter trace_converter; @@ -287,13 +245,13 @@ struct test_chain } snapshot_file.emplace(snapshot, std::ios::in | std::ios::binary); snapshot_reader = std::make_shared(*snapshot_file); - control = std::make_unique(*cfg, make_protocol_feature_set(), - *chain_id); + control = std::make_unique( + *cfg, cltestlib::make_protocol_feature_set(), *chain_id); } else { - control = std::make_unique(*cfg, make_protocol_feature_set(), - genesis.compute_chain_id()); + control = std::make_unique( + *cfg, cltestlib::make_protocol_feature_set(), genesis.compute_chain_id()); } control->add_indices(); @@ -360,7 +318,7 @@ struct test_chain history[control->head_block_num()] = fc::raw::pack(state_result{message}); } - void mutating() { intr_ctx.reset(); } + void mutating() override { intr_ctx.reset(); } auto& get_apply_context() { @@ -371,32 +329,6 @@ struct test_chain } return *intr_ctx->apply_context; } - - void start_block(int64_t skip_miliseconds = 0) - { - mutating(); - if (control->is_building_block()) - finish_block(); - control->start_block(control->head_block_time() + - fc::microseconds(skip_miliseconds * 1000ll + block_interval_us), - 0); - } - - void start_if_needed() - { - mutating(); - if (!control->is_building_block()) - control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0); - } - - void finish_block() - { - start_if_needed(); - ilog("finish block ${n}", ("n", control->head_block_num())); - control->finalize_block( - [&](eosio::chain::digest_type d) { return std::vector{producer_key.sign(d)}; }); - control->commit_block(); - } }; // test_chain test_chain_ref::test_chain_ref(test_chain& chain) @@ -589,15 +521,6 @@ struct file } }; -struct push_trx_args -{ - eosio::chain::bytes transaction; - std::vector context_free_data; - std::vector signatures; - std::vector keys; -}; -FC_REFLECT(push_trx_args, (transaction)(context_free_data)(signatures)(keys)) - #define DB_WRAPPERS_SIMPLE_SECONDARY(IDX, TYPE) \ int32_t db_##IDX##_find_secondary(uint64_t code, uint64_t scope, uint64_t table, \ wasm_ptr secondary, wasm_ptr primary) \ @@ -1158,25 +1081,9 @@ struct callbacks uint32_t cb_alloc_data, uint32_t cb_alloc) { - auto args = unpack(args_packed); - auto transaction = unpack(args.transaction); - signed_transaction signed_trx{std::move(transaction), std::move(args.signatures), - std::move(args.context_free_data)}; auto& chain = assert_chain(chain_index); - chain.start_if_needed(); - for (auto& key : args.keys) - signed_trx.sign(key, chain.control->get_chain_id()); - auto ptrx = std::make_shared( - std::move(signed_trx), eosio::chain::packed_transaction::compression_type::none); - auto fut = eosio::chain::transaction_metadata::start_recover_keys( - ptrx, chain.control->get_thread_pool(), chain.control->get_chain_id(), - fc::microseconds::maximum()); - auto start_time = std::chrono::steady_clock::now(); - auto result = - chain.control->push_transaction(fut.get(), fc::time_point::maximum(), 2000, true, 2000); - auto us = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start_time); - ilog("chainlib transaction took ${u} us", ("u", us.count())); + auto args = unpack(args_packed); + auto result = chain.push_transaction(billed_cpu_time_use, std::move(args)); // ilog("${r}", ("r", fc::json::to_pretty_string(result))); set_data(cb_alloc_data, cb_alloc, convert_to_bin(chain_types::transaction_trace{convert(*result)})); @@ -1185,15 +1092,8 @@ struct callbacks bool tester_exec_deferred(uint32_t chain_index, uint32_t cb_alloc_data, uint32_t cb_alloc) { auto& chain = assert_chain(chain_index); - chain.start_if_needed(); - const auto& idx = - chain.control->db() - .get_index(); - auto itr = idx.begin(); - if (itr != idx.end() && itr->delay_until <= chain.control->pending_block_time()) + if (auto trace = chain.exec_deferred(billed_cpu_time_use)) { - auto trace = chain.control->push_scheduled_transaction( - itr->trx_id, fc::time_point::maximum(), billed_cpu_time_use, true); set_data(cb_alloc_data, cb_alloc, convert_to_bin(chain_types::transaction_trace{convert(*trace)})); return true; @@ -1327,7 +1227,7 @@ struct callbacks auto& chain = *r.chain.chain; chain.start_if_needed(); - auto args = unpack(packed_args); + auto args = unpack(packed_args); auto transaction = unpack(args.transaction); signed_transaction signed_trx{std::move(transaction), std::move(args.signatures), std::move(args.context_free_data)}; From ffd69f60983d02102bac3b59286ad734757ec363 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Fri, 18 Jun 2021 20:35:17 -0400 Subject: [PATCH 06/14] emscripten --- emscripten/CMakeLists.txt | 47 ++++++++++++++++++++++++++++++++++---- emscripten/test.cpp | 39 +++++++++++++++++++++++++++++++ external/boost/boost.patch | 20 ++++++++++++++++ 3 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 emscripten/test.cpp diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 073eecf3f..040936e67 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 3.16.3) cmake_policy(VERSION 3.16) project(emscripten) -enable_testing() set(IS_EMSCRIPTEN YES) get_filename_component(ROOT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/.. ABSOLUTE) @@ -23,6 +22,8 @@ set(GMP_ARCHIVE gmp-6.2.1.tar.zst) set(GMP_EXTRACTED gmp-6.2.1) set(OPENSSL_ARCHIVE openssl-1.1.1k.tar.gz) set(OPENSSL_EXTRACTED openssl-1.1.1k) +set(ZLIB_ARCHIVE zlib-1.2.11.tar.gz) +set(ZLIB_EXTRACTED zlib-1.2.11) function(download url archive) if(NOT EXISTS ${archive}) @@ -40,11 +41,26 @@ function(download url archive) endif() endfunction() -download(${DEP_URL}/${GMP_ARCHIVE} ${DEP_PREFIX}/${GMP_ARCHIVE}) -download(${DEP_URL}/${OPENSSL_ARCHIVE} ${DEP_PREFIX}/${OPENSSL_ARCHIVE}) - # Dependancy builds are done at generation time so cmake's find_* commands can find them + +if(NOT EXISTS ${DEP_PREFIX}/lib/libz.a) + download(${DEP_URL}/${ZLIB_ARCHIVE} ${DEP_PREFIX}/${ZLIB_ARCHIVE}) + message("building zlib") + execute_process( + WORKING_DIRECTORY ${DEP_PREFIX} + COMMAND bash -c "\ + rm -rf ${ZLIB_EXTRACTED} \ + && tar xf ${ZLIB_ARCHIVE} \ + && cd ${ZLIB_EXTRACTED} \ + && emconfigure ./configure --prefix=${DEP_PREFIX} --static \ + && emmake make -j \ + && emmake make -j install \ + " + ) +endif() + if(NOT EXISTS ${DEP_PREFIX}/lib/libgmp.so) + download(${DEP_URL}/${GMP_ARCHIVE} ${DEP_PREFIX}/${GMP_ARCHIVE}) message("building gmp") execute_process( WORKING_DIRECTORY ${DEP_PREFIX} @@ -61,6 +77,7 @@ if(NOT EXISTS ${DEP_PREFIX}/lib/libgmp.so) endif() if(NOT EXISTS ${DEP_PREFIX}/lib/libssl.a) + download(${DEP_URL}/${OPENSSL_ARCHIVE} ${DEP_PREFIX}/${OPENSSL_ARCHIVE}) message("building openssl") execute_process( WORKING_DIRECTORY ${DEP_PREFIX} @@ -81,6 +98,8 @@ if(NOT EXISTS ${DEP_PREFIX}/include/boost) execute_process( WORKING_DIRECTORY ${BOOST_EXTRACTED} COMMAND bash -c "\ + ZLIB_LIBRARY_PATH=${DEP_PREFIX}/lib \ + ZLIB_INCLUDE=${DEP_PREFIX}/include \ ./b2 \ --prefix=${DEP_PREFIX} \ --build-dir=${DEP_PREFIX}/build-boost \ @@ -104,6 +123,10 @@ set(Boost_USE_STATIC_RUNTIME ON) set(ECC_IMPL secp256k1) set(SKIP_FC_TESTS YES) option(ENABLE_TOOLS "enable building of tools" OFF) +set(EOSIO_ROOT_KEY "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV") + +add_compile_options(-fexceptions) +add_link_options(-fexceptions) add_subdirectory(../external/eos/libraries/builtins builtins) add_subdirectory(../external/eos/libraries/chain chain) @@ -111,3 +134,19 @@ add_subdirectory(../external/eos/libraries/chainbase chainbase) add_subdirectory(../external/eos/libraries/eos-vm eos-vm) add_subdirectory(../external/eos/libraries/fc fc) add_subdirectory(../external/eos/libraries/version version) +add_subdirectory(../external/eos/libraries/wasm-jit wasm-jit) +add_subdirectory(../libraries/cltestlib cltestlib) + +add_library(chain INTERFACE) +target_link_libraries(chain INTERFACE eosio_chain) + +add_executable(t test.cpp) +target_link_options(t PRIVATE -L${DEP_PREFIX}/lib) +target_link_libraries(t cltestlib) +target_link_options(t PRIVATE + "SHELL:-s DISABLE_EXCEPTION_CATCHING=0" + "SHELL:-s EXIT_RUNTIME=1" + "SHELL:-s ALLOW_MEMORY_GROWTH=1" + "SHELL:-s DEMANGLE_SUPPORT=1" +) +set_target_properties(t PROPERTIES SUFFIX .html) diff --git a/emscripten/test.cpp b/emscripten/test.cpp new file mode 100644 index 000000000..dac76a11d --- /dev/null +++ b/emscripten/test.cpp @@ -0,0 +1,39 @@ +#include +#include +#include + +int main() +{ + try + { + fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); + ilog("abcd"); + fc::temp_directory dir; + std::unique_ptr cfg; + std::unique_ptr control; + eosio::chain::genesis_state genesis; + genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); + cfg = std::make_unique(); + cfg->blocks_dir = dir.path() / "blocks"; + cfg->state_dir = dir.path() / "state"; + cfg->contracts_console = true; + cltestlib::test_chain t; + t.control = std::make_unique( + *cfg, cltestlib::make_protocol_feature_set(), genesis.compute_chain_id()); + elog("fghi"); + return 0; + } + catch (fc::exception& e) + { + std::cerr << "fc::exception: " << e.to_string() << "\n"; + } + catch (std::exception& e) + { + std::cerr << "std::exception: " << e.what() << "\n"; + } + catch (...) + { + std::cerr << "unknown exception\n"; + } + return 1; +} diff --git a/external/boost/boost.patch b/external/boost/boost.patch index 8a037ee69..762aa783b 100644 --- a/external/boost/boost.patch +++ b/external/boost/boost.patch @@ -54,3 +54,23 @@ !defined(BOOST_TEST_DISABLE_ALT_STACK) # define BOOST_TEST_USE_ALT_STACK # endif +--- ../operations.cpp 2021-06-18 20:10:10.380000000 -0400 ++++ ./libs/filesystem/src/operations.cpp 2021-06-18 20:10:14.310000000 -0400 +@@ -1663,7 +1663,7 @@ + BOOST_FILESYSTEM_DECL + path current_path(error_code* ec) + { +-# if defined(__wasm) ++# if defined(xxxx__wasm) + emit_error(BOOST_ERROR_NOT_SUPPORTED, ec, "boost::filesystem::current_path"); + return path(); + # elif defined(BOOST_POSIX_API) +@@ -1734,7 +1734,7 @@ + BOOST_FILESYSTEM_DECL + void current_path(const path& p, system::error_code* ec) + { +-# if defined(UNDER_CE) || defined(__wasm) ++# if defined(UNDER_CE) || defined(xxxx__wasm) + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::current_path"); + # else + error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0, From f82e4e7887a4927e4e46ea56bf5e9d629b2ec9fb Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Sat, 19 Jun 2021 21:44:51 -0400 Subject: [PATCH 07/14] emscripten --- emscripten/CMakeLists.txt | 11 ++++++++--- emscripten/test-pre.js | 1 + emscripten/test.cpp | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 emscripten/test-pre.js diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 040936e67..08aa33929 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -125,8 +125,8 @@ set(SKIP_FC_TESTS YES) option(ENABLE_TOOLS "enable building of tools" OFF) set(EOSIO_ROOT_KEY "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV") -add_compile_options(-fexceptions) -add_link_options(-fexceptions) +add_compile_options(-fexceptions -pthread) +add_link_options(-fexceptions -pthread) add_subdirectory(../external/eos/libraries/builtins builtins) add_subdirectory(../external/eos/libraries/chain chain) @@ -144,9 +144,14 @@ add_executable(t test.cpp) target_link_options(t PRIVATE -L${DEP_PREFIX}/lib) target_link_libraries(t cltestlib) target_link_options(t PRIVATE + -gsource-map + --source-map-base ./ + --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/test-pre.js "SHELL:-s DISABLE_EXCEPTION_CATCHING=0" - "SHELL:-s EXIT_RUNTIME=1" + "SHELL:-s EXIT_RUNTIME=0" "SHELL:-s ALLOW_MEMORY_GROWTH=1" "SHELL:-s DEMANGLE_SUPPORT=1" + "SHELL:-s PROXY_TO_PTHREAD=1" + "SHELL:-s STACK_OVERFLOW_CHECK=0" ) set_target_properties(t PROPERTIES SUFFIX .html) diff --git a/emscripten/test-pre.js b/emscripten/test-pre.js new file mode 100644 index 000000000..b0db37b07 --- /dev/null +++ b/emscripten/test-pre.js @@ -0,0 +1 @@ +Module['printErr'] = Module['print'] diff --git a/emscripten/test.cpp b/emscripten/test.cpp index dac76a11d..e02a8ec87 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -7,20 +7,29 @@ int main() try { fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); - ilog("abcd"); fc::temp_directory dir; std::unique_ptr cfg; - std::unique_ptr control; eosio::chain::genesis_state genesis; genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); cfg = std::make_unique(); cfg->blocks_dir = dir.path() / "blocks"; cfg->state_dir = dir.path() / "state"; cfg->contracts_console = true; + cfg->state_size = 200 * 1024 * 1024; + cfg->state_guard_size = 0; cltestlib::test_chain t; t.control = std::make_unique( *cfg, cltestlib::make_protocol_feature_set(), genesis.compute_chain_id()); - elog("fghi"); + t.control->add_indices(); + t.control->startup([] { return false; }, genesis); + t.control->start_block(t.control->head_block_time() + fc::microseconds(t.block_interval_us), + 0, + {*t.control->get_protocol_feature_manager().get_builtin_digest( + eosio::chain::builtin_protocol_feature_t::preactivate_feature)}); + t.start_block(0); + t.start_block(0); + t.start_block(0); + t.start_block(0); return 0; } catch (fc::exception& e) From c024cf2da36ab3308431483f3d6c6d33b9cc50e2 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Sun, 20 Jun 2021 15:54:28 -0400 Subject: [PATCH 08/14] emscripten --- emscripten/CMakeLists.txt | 22 +++-- emscripten/test.cpp | 192 ++++++++++++++++++++++++++++++-------- 2 files changed, 168 insertions(+), 46 deletions(-) diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 08aa33929..2b64ccae0 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -146,12 +146,18 @@ target_link_libraries(t cltestlib) target_link_options(t PRIVATE -gsource-map --source-map-base ./ - --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/test-pre.js - "SHELL:-s DISABLE_EXCEPTION_CATCHING=0" - "SHELL:-s EXIT_RUNTIME=0" - "SHELL:-s ALLOW_MEMORY_GROWTH=1" - "SHELL:-s DEMANGLE_SUPPORT=1" - "SHELL:-s PROXY_TO_PTHREAD=1" - "SHELL:-s STACK_OVERFLOW_CHECK=0" + #--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/test-pre.js + -flto + --embind + -sMODULARIZE=1 + -sEXPORT_NAME="createCLTester" + -sDISABLE_EXCEPTION_CATCHING=0 + -sEXIT_RUNTIME=0 + -sALLOW_MEMORY_GROWTH=1 + -sDEMANGLE_SUPPORT=1 + #-sPROXY_TO_PTHREAD=1 + -sSTACK_OVERFLOW_CHECK=0 + #-sASSERTIONS=1 + -Wno-pthreads-mem-growth ) -set_target_properties(t PROPERTIES SUFFIX .html) +#set_target_properties(t PROPERTIES SUFFIX .html) diff --git a/emscripten/test.cpp b/emscripten/test.cpp index e02a8ec87..b7a284f8c 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -1,48 +1,164 @@ +#include #include +#include +#include #include #include -int main() -{ - try +// JS function calls come in on the main thread then execute in the background thread. This +// * Stops chainlib from hitting browser restrictions that only apply to the main thread +// * Stops long chainlib operations from blocking the main thread +// +// The JS interface wraps this up with promises +boost::asio::thread_pool background(1); + +// clang-format off +EM_JS(void, init_js, (), { + // TODO: reuse entries in Module.promises + Module.promises = []; + Module.eatString = s => { - fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); - fc::temp_directory dir; - std::unique_ptr cfg; - eosio::chain::genesis_state genesis; - genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); - cfg = std::make_unique(); - cfg->blocks_dir = dir.path() / "blocks"; - cfg->state_dir = dir.path() / "state"; - cfg->contracts_console = true; - cfg->state_size = 200 * 1024 * 1024; - cfg->state_guard_size = 0; - cltestlib::test_chain t; - t.control = std::make_unique( - *cfg, cltestlib::make_protocol_feature_set(), genesis.compute_chain_id()); - t.control->add_indices(); - t.control->startup([] { return false; }, genesis); - t.control->start_block(t.control->head_block_time() + fc::microseconds(t.block_interval_us), - 0, - {*t.control->get_protocol_feature_manager().get_builtin_digest( - eosio::chain::builtin_protocol_feature_t::preactivate_feature)}); - t.start_block(0); - t.start_block(0); - t.start_block(0); - t.start_block(0); - return 0; - } - catch (fc::exception& e) + let result = UTF8ToString(s); + free(s); + return result; + }; + Module.createPromise = () => { - std::cerr << "fc::exception: " << e.to_string() << "\n"; - } - catch (std::exception& e) + let index = Module.promises.length; + let promise = new Promise((resolve, reject) => { // + Module.promises.push({resolve, reject}); + }); + return {promise, index}; + }; + Module.removePromise = index => { - std::cerr << "std::exception: " << e.what() << "\n"; - } - catch (...) + let result = Module.promises[index]; + Module.promises[index] = null; + return result; + }; + Module.resolvePromise = (index, result) => + { // + Module.removePromise(index).resolve(result); + }; + Module.withPromise = f => + { + let{promise, index} = Module.createPromise(); + f(index); + return promise; + }; + + class Chain + { + constructor(index) { this.index = index; } + destroy() { return Module.withPromise(p => Module._schedule_destroy_chain(p, this.index)); } + }; + Module.Chain = Chain; + Module.createChain = () => + { + return Module.withPromise(p => Module._schedule_create_chain(p)); + }; +}); // init_js +// clang-format on + +void send_error(uint32_t promise, const char* e) +{ + auto copy = strdup(e); + if (!copy) + abort(); + MAIN_THREAD_ASYNC_EM_ASM( + { // + Module.removePromise($0).reject(new Error(Module.eatString($1))); + }, + promise, copy); +} + +template +void run_in_background(uint32_t promise, F f) +{ + boost::asio::post(background, [=] { + try + { + f(); + } + catch (fc::exception& e) + { + elog("${e}\n", ("e", e)); + send_error(promise, e.to_string().c_str()); + } + catch (std::exception& e) + { + elog("${e}\n", ("e", e.what())); + send_error(promise, e.what()); + } + catch (...) + { + elog("unknown exception\n"); + send_error(promise, "unknown exception"); + } + }); +} + +struct test_chain : cltestlib::test_chain +{ + fc::temp_directory dir; + + test_chain() { - std::cerr << "unknown exception\n"; + eosio::chain::controller::config cfg; + cfg.blocks_dir = dir.path() / "blocks"; + cfg.state_dir = dir.path() / "state"; + cfg.contracts_console = true; + cfg.state_size = 200 * 1024 * 1024; + cfg.state_guard_size = 0; + + eosio::chain::genesis_state genesis; + genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); + + control = std::make_unique( + cfg, cltestlib::make_protocol_feature_set(), genesis.compute_chain_id()); + control->add_indices(); + control->startup([] { return false; }, genesis); + control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0, + {*control->get_protocol_feature_manager().get_builtin_digest( + eosio::chain::builtin_protocol_feature_t::preactivate_feature)}); } - return 1; +}; + +std::vector> chains; + +test_chain& assert_chain(uint32_t index) +{ + if (index >= chains.size() || !chains[index]) + throw std::runtime_error("unknown or destroyed chain"); + return *chains[index]; +} + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_create_chain(uint32_t promise) +{ + run_in_background(promise, [=] { + auto result = chains.size(); + chains.push_back(std::make_unique()); + MAIN_THREAD_ASYNC_EM_ASM( + { // + Module.resolvePromise($0, new Module.Chain($1)); + }, + promise, result); + }); +} + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_destroy_chain(uint32_t promise, uint32_t index) +{ + run_in_background(promise, [=] { + assert_chain(index); + chains[index] = nullptr; + MAIN_THREAD_ASYNC_EM_ASM({ Module.resolvePromise($0, undefined); }, promise); + }); +} + +int main() +{ + init_js(); + fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); + emscripten_exit_with_live_runtime(); + return 0; } From 7168db178518613c905ceea862d6721e70951702 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Sun, 20 Jun 2021 16:49:55 -0400 Subject: [PATCH 09/14] emscripten --- emscripten/CMakeLists.txt | 2 ++ emscripten/test.cpp | 33 ++++++++++++++++++++++++++++++++- emscripten/test.html | 25 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 emscripten/test.html diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 2b64ccae0..875401f12 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -161,3 +161,5 @@ target_link_options(t PRIVATE -Wno-pthreads-mem-growth ) #set_target_properties(t PROPERTIES SUFFIX .html) + +configure_file(test.html ${CMAKE_CURRENT_BINARY_DIR}/test.html COPYONLY) diff --git a/emscripten/test.cpp b/emscripten/test.cpp index b7a284f8c..f700fef1e 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -51,6 +51,14 @@ EM_JS(void, init_js, (), { { constructor(index) { this.index = index; } destroy() { return Module.withPromise(p => Module._schedule_destroy_chain(p, this.index)); } + startBlock(ms) + { + return Module.withPromise(p => Module._schedule_start_block(p, this.index, ms)); + } + finishBlock() + { + return Module.withPromise(p => Module._schedule_finish_block(p, this.index)); + } }; Module.Chain = Chain; Module.createChain = () => @@ -98,6 +106,11 @@ void run_in_background(uint32_t promise, F f) }); } +void ret(uint32_t promise) +{ + MAIN_THREAD_ASYNC_EM_ASM({ Module.resolvePromise($0, undefined); }, promise); +} + struct test_chain : cltestlib::test_chain { fc::temp_directory dir; @@ -151,7 +164,25 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_destroy_chain(uint32_t promise, ui run_in_background(promise, [=] { assert_chain(index); chains[index] = nullptr; - MAIN_THREAD_ASYNC_EM_ASM({ Module.resolvePromise($0, undefined); }, promise); + ret(promise); + }); +} + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_start_block(uint32_t promise, + uint32_t index, + double skip_miliseconds) +{ + run_in_background(promise, [=] { + assert_chain(index).start_block(skip_miliseconds); + ret(promise); + }); +} + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_finish_block(uint32_t promise, uint32_t index) +{ + run_in_background(promise, [=] { + assert_chain(index).finish_block(); + ret(promise); }); } diff --git a/emscripten/test.html b/emscripten/test.html new file mode 100644 index 000000000..9cf7bd680 --- /dev/null +++ b/emscripten/test.html @@ -0,0 +1,25 @@ + + + + + + +
+ + + + From 06284f0867384efd07d5615ff786b5ab9b0f72b6 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Sun, 20 Jun 2021 22:44:54 -0400 Subject: [PATCH 10/14] emscripten --- emscripten/CMakeLists.txt | 23 +- emscripten/package.json | 14 + emscripten/src/index.js | 21 + emscripten/test.html | 36 +- emscripten/webpack.config.js | 16 + emscripten/yarn.lock | 1091 ++++++++++++++++++++++++++++++++++ 6 files changed, 1170 insertions(+), 31 deletions(-) create mode 100644 emscripten/package.json create mode 100644 emscripten/src/index.js create mode 100644 emscripten/webpack.config.js create mode 100644 emscripten/yarn.lock diff --git a/emscripten/CMakeLists.txt b/emscripten/CMakeLists.txt index 875401f12..365b97903 100644 --- a/emscripten/CMakeLists.txt +++ b/emscripten/CMakeLists.txt @@ -140,13 +140,12 @@ add_subdirectory(../libraries/cltestlib cltestlib) add_library(chain INTERFACE) target_link_libraries(chain INTERFACE eosio_chain) -add_executable(t test.cpp) -target_link_options(t PRIVATE -L${DEP_PREFIX}/lib) -target_link_libraries(t cltestlib) -target_link_options(t PRIVATE +add_executable(cltester test.cpp) +target_link_options(cltester PRIVATE -L${DEP_PREFIX}/lib) +target_link_libraries(cltester cltestlib) +target_link_options(cltester PRIVATE -gsource-map --source-map-base ./ - #--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/test-pre.js -flto --embind -sMODULARIZE=1 @@ -155,11 +154,21 @@ target_link_options(t PRIVATE -sEXIT_RUNTIME=0 -sALLOW_MEMORY_GROWTH=1 -sDEMANGLE_SUPPORT=1 - #-sPROXY_TO_PTHREAD=1 -sSTACK_OVERFLOW_CHECK=0 #-sASSERTIONS=1 -Wno-pthreads-mem-growth ) -#set_target_properties(t PROPERTIES SUFFIX .html) +add_custom_command(TARGET cltester + POST_BUILD + COMMAND mkdir -p ${CMAKE_CURRENT_SOURCE_DIR}/node_modules + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/node_modules . + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/package.json . + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/src . + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/webpack.config.js . + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/yarn.lock . + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/test.html . + COMMAND yarn + COMMAND npx webpack +) configure_file(test.html ${CMAKE_CURRENT_BINARY_DIR}/test.html COPYONLY) diff --git a/emscripten/package.json b/emscripten/package.json new file mode 100644 index 000000000..4b04ecfcf --- /dev/null +++ b/emscripten/package.json @@ -0,0 +1,14 @@ +{ + "name": "cltester-js", + "version": "0.0.1", + "main": "index.js", + "license": "MIT", + "devDependencies": { + "copy-webpack-plugin": "^9.0.0", + "eosjs": "^22.0.0", + "webpack": "5", + "webpack-cli": "^4.7.2", + "xterm": "^4.13.0", + "xterm-addon-fit": "^0.5.0" + } +} diff --git a/emscripten/src/index.js b/emscripten/src/index.js new file mode 100644 index 000000000..f75d5d0d7 --- /dev/null +++ b/emscripten/src/index.js @@ -0,0 +1,21 @@ +import { Api, RpcError } from 'eosjs'; +import { JsSignatureProvider } from 'eosjs/dist/eosjs-jssig'; +import { Terminal } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; + +const term = new Terminal(); +const fitAddon = new FitAddon(); +term.loadAddon(fitAddon); +term.open(document.getElementById('terminal')); +fitAddon.fit(); +window.addEventListener('resize', () => fitAddon.fit()); + +(async () => { + let t = await createCLTester({ + printErr(s) { term.write(s + '\r\n'); } + }); + let c = await t.createChain(); + while (true) { + await c.finishBlock(); + } +})(); diff --git a/emscripten/test.html b/emscripten/test.html index 9cf7bd680..7b8d71443 100644 --- a/emscripten/test.html +++ b/emscripten/test.html @@ -1,25 +1,13 @@ - - - - - -
- - - - + + + + + + +
+ + + + + \ No newline at end of file diff --git a/emscripten/webpack.config.js b/emscripten/webpack.config.js new file mode 100644 index 000000000..a44a9918d --- /dev/null +++ b/emscripten/webpack.config.js @@ -0,0 +1,16 @@ +const CopyPlugin = require("copy-webpack-plugin"); + +module.exports = { + mode: 'production', + plugins: [ + new CopyPlugin({ + patterns: [ + { from: "node_modules/xterm/css/xterm.css" }, + { from: "cltester.js" }, + { from: "cltester.wasm" }, + { from: "cltester.worker.js" }, + { from: "test.html" }, + ], + }), + ], +}; diff --git a/emscripten/yarn.lock b/emscripten/yarn.lock new file mode 100644 index 000000000..85dea006c --- /dev/null +++ b/emscripten/yarn.lock @@ -0,0 +1,1091 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" + integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz#94c23db18ee4653e129abd26fb06f870ac9e1ee2" + integrity sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@types/eslint-scope@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" + integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "7.2.13" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.13.tgz#e0ca7219ba5ded402062ad6f926d491ebb29dd53" + integrity sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.48.tgz#18dc8091b285df90db2f25aa7d906cfc394b7f74" + integrity sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew== + +"@types/estree@^0.0.47": + version "0.0.47" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" + integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg== + +"@types/json-schema@*", "@types/json-schema@^7.0.6": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== + +"@types/node@*": + version "15.12.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.4.tgz#e1cf817d70a1e118e81922c4ff6683ce9d422e26" + integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA== + +"@webassemblyjs/ast@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" + integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + +"@webassemblyjs/floating-point-hex-parser@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c" + integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA== + +"@webassemblyjs/helper-api-error@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4" + integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w== + +"@webassemblyjs/helper-buffer@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642" + integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA== + +"@webassemblyjs/helper-numbers@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9" + integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.0" + "@webassemblyjs/helper-api-error" "1.11.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1" + integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA== + +"@webassemblyjs/helper-wasm-section@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b" + integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + +"@webassemblyjs/ieee754@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf" + integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b" + integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf" + integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw== + +"@webassemblyjs/wasm-edit@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78" + integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/helper-wasm-section" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + "@webassemblyjs/wasm-opt" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + "@webassemblyjs/wast-printer" "1.11.0" + +"@webassemblyjs/wasm-gen@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe" + integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/ieee754" "1.11.0" + "@webassemblyjs/leb128" "1.11.0" + "@webassemblyjs/utf8" "1.11.0" + +"@webassemblyjs/wasm-opt@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978" + integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + +"@webassemblyjs/wasm-parser@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754" + integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-api-error" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/ieee754" "1.11.0" + "@webassemblyjs/leb128" "1.11.0" + "@webassemblyjs/utf8" "1.11.0" + +"@webassemblyjs/wast-printer@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e" + integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ== + dependencies: + "@webassemblyjs/ast" "1.11.0" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.0.4.tgz#f03ce6311c0883a83d04569e2c03c6238316d2aa" + integrity sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ== + +"@webpack-cli/info@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.3.0.tgz#9d78a31101a960997a4acd41ffd9b9300627fe2b" + integrity sha512-ASiVB3t9LOKHs5DyVUcxpraBXDOKubYu/ihHhU+t1UPpxsivg6Od2E2qU4gJCekfEddzRBzHhzA/Acyw/mlK/w== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.5.1.tgz#b5fde2f0f79c1e120307c415a4c1d5eb15a6f278" + integrity sha512-4vSVUiOPJLmr45S8rMGy7WDvpWxfFxfP/Qx/cxZFCfvoypTYpPPL1X8VIZMe0WTA+Jr7blUxwUSEZNkjoMTgSw== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn@^8.2.1: + version "8.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.0.tgz#af53266e698d7cffa416714b503066a82221be60" + integrity sha512-ULr0LDaEqQrMFGyQ3bhJkLsbtrQ8QibAseGZeaSUiT/6zb9IvIkomWHJIvgvwad+hinRAgsI51JcWk2yvwyL+w== + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +bn.js@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserslist@^4.14.5: + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== + dependencies: + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +caniuse-lite@^1.0.30001219: + version "1.0.30001239" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz#66e8669985bb2cb84ccb10f68c25ce6dd3e4d2b8" + integrity sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +colorette@^1.2.1, colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +copy-webpack-plugin@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-9.0.0.tgz#2bf592785d2fcdde9342dfed3676490fe0aa7ce8" + integrity sha512-k8UB2jLIb1Jip2nZbCz83T/XfhfjX6mB1yLJNYKrpYi7FQimfOoFv/0//iT6HV1K8FwUB5yUbCcnpLebJXJTug== + dependencies: + fast-glob "^3.2.5" + glob-parent "^6.0.0" + globby "^11.0.3" + normalize-path "^3.0.0" + p-limit "^3.1.0" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +electron-to-chromium@^1.3.723: + version "1.3.752" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz#0728587f1b9b970ec9ffad932496429aef750d09" + integrity sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A== + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +enhanced-resolve@^5.8.0: + version "5.8.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b" + integrity sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +eosjs@^22.0.0: + version "22.0.0" + resolved "https://registry.yarnpkg.com/eosjs/-/eosjs-22.0.0.tgz#254744f233377169e06ecffe4964bb6a76fc8942" + integrity sha512-zwNtpcFo58whTve6A+jnaYKMUBVMezY8E4dRuRi7eakvrai6CXpVEMshyX9GlalzjQXoI0UjrY4EM6K0LmbgZg== + dependencies: + bn.js "5.2.0" + elliptic "6.5.4" + hash.js "1.1.7" + pako "2.0.3" + +es-module-lexer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e" + integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.1.1, fast-glob@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" + integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + +fastq@^1.6.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" + integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.0.tgz#f851b59b388e788f3a44d63fab50382b2859c33c" + integrity sha512-Hdd4287VEJcZXUwv1l8a+vXC1GjOQqXe+VS30w/ypihpcnu9M1n3xeYeJu5CBpeEQj2nAab2xxz28GuA3vp4Ww== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.2.4: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +is-core-module@^2.2.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" + integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +jest-worker@^27.0.2: + version "27.0.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.2.tgz#4ebeb56cef48b3e7514552f80d0d80c0129f0b05" + integrity sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.2: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +mime-db@1.48.0: + version "1.48.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" + integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== + +mime-types@^2.1.27: + version "2.1.31" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" + integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== + dependencies: + mime-db "1.48.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^1.1.71: + version "1.1.73" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" + integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.3.tgz#cdf475e31b678565251406de9e759196a0ea7a43" + integrity sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +rechoir@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" + integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== + dependencies: + resolve "^1.9.0" + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.9.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +schema-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== + dependencies: + "@types/json-schema" "^7.0.6" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +serialize-javascript@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-list-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-support@~0.5.19: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" + integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== + +terser-webpack-plugin@^5.1.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.3.tgz#30033e955ca28b55664f1e4b30a1347e61aa23af" + integrity sha512-cxGbMqr6+A2hrIB5ehFIF+F/iST5ZOxvOmy9zih9ySbP1C2oEWQSOUS+2SNBTjzx5xLKO4xnod9eywdfq1Nb9A== + dependencies: + jest-worker "^27.0.2" + p-limit "^3.1.0" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" + source-map "^0.6.1" + terser "^5.7.0" + +terser@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693" + integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g== + dependencies: + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.19" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +v8-compile-cache@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +watchpack@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" + integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.7.2.tgz#a718db600de6d3906a4357e059ae584a89f4c1a5" + integrity sha512-mEoLmnmOIZQNiRl0ebnjzQ74Hk0iKS5SiEEnpq3dRezoyR3yPaeQZCMCe+db4524pj1Pd5ghZXjT41KLzIhSLw== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.0.4" + "@webpack-cli/info" "^1.3.0" + "@webpack-cli/serve" "^1.5.1" + colorette "^1.2.1" + commander "^7.0.0" + execa "^5.0.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + v8-compile-cache "^2.2.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.0.tgz#9ed2de69b25143a4c18847586ad9eccb19278cfa" + integrity sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ== + dependencies: + source-list-map "^2.0.1" + source-map "^0.6.1" + +webpack@5: + version "5.39.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.39.1.tgz#d1e014b6d71e1aef385316ad528f21cd5b1f9784" + integrity sha512-ulOvoNCh2PvTUa+zbpRuEb1VPeQnhxpnHleMPVVCq3QqnaFogjsLyps+o42OviQFoaGtTQYrUqDXu1QNkvUPzw== + dependencies: + "@types/eslint-scope" "^3.7.0" + "@types/estree" "^0.0.47" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/wasm-edit" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + acorn "^8.2.1" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.8.0" + es-module-lexer "^0.4.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.4" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.0.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.1" + watchpack "^2.2.0" + webpack-sources "^2.3.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +xterm-addon-fit@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596" + integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ== + +xterm@^4.13.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.13.0.tgz#7998de1e2ad92c4796fe45807be4f31061f3d9d1" + integrity sha512-HVW1gdoLOTnkMaqQCr2r3mQy4fX9iSa5gWxKZ2UTYdLa4iqavv7QxJ8n1Ypse32shPVkhTYPLS6vHEFZp5ghzw== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 6f444448d723db44255f11e60b603b8a77daef66 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Mon, 21 Jun 2021 12:31:31 -0400 Subject: [PATCH 11/14] emscripten --- emscripten/src/index.js | 62 +++++++++++++++++++-- emscripten/test.cpp | 119 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 169 insertions(+), 12 deletions(-) diff --git a/emscripten/src/index.js b/emscripten/src/index.js index f75d5d0d7..2e82b0b70 100644 --- a/emscripten/src/index.js +++ b/emscripten/src/index.js @@ -9,13 +9,63 @@ term.loadAddon(fitAddon); term.open(document.getElementById('terminal')); fitAddon.fit(); window.addEventListener('resize', () => fitAddon.fit()); +function writeTerm(s) { + term.write(s.replace(/\r\n?|\n/g, '\r\n')); +} + +let testerOptions = { + printErr(s) { writeTerm(s + '\n'); } +}; + +const defaultPubKey = "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"; +const defaultPrivKey = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"; +const defaultSignatureProvider = new JsSignatureProvider([defaultPrivKey]); + + +function simpleAuth(key = defaultPubKey) { + return { + threshold: 1, + keys: [{ key, weight: 1 }], + accounts: [], + waits: [] + }; +} + +function createAccount(name) { + return { + account: 'eosio', + name: 'newaccount', + authorization: [{ + actor: 'eosio', + permission: 'active', + }], + data: { + creator: 'eosio', + name: 'bob', + owner: simpleAuth(), + active: simpleAuth(), + }, + }; +} (async () => { - let t = await createCLTester({ - printErr(s) { term.write(s + '\r\n'); } - }); - let c = await t.createChain(); - while (true) { - await c.finishBlock(); + try { + await (async () => { + let t = await createCLTester(testerOptions); + let c = await t.createChain(); + writeTerm(JSON.stringify(await c.get_info(), null, 4) + '\n'); + let api = new Api({ rpc: c, signatureProvider: defaultSignatureProvider }); + await api.transact({ + actions: [ + createAccount('alice'), + createAccount('bob'), + createAccount('sue'), + ] + }, { useLastIrreversible: true, expireSeconds: 1 }); + while (true) + await c.finishBlock(); + })(); + } catch (e) { + writeTerm(e + '\n'); } })(); diff --git a/emscripten/test.cpp b/emscripten/test.cpp index f700fef1e..62bbf5e76 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include // JS function calls come in on the main thread then execute in the background thread. This // * Stops chainlib from hitting browser restrictions that only apply to the main thread @@ -19,7 +21,13 @@ EM_JS(void, init_js, (), { Module.eatString = s => { let result = UTF8ToString(s); - free(s); + _free(s); + return result; + }; + Module.eatBuffer = (data, size) => + { + let result = new Uint8Array(GROWABLE_HEAP_U8().subarray(data, data + size)); + _free(data); return result; }; Module.createPromise = () => @@ -59,6 +67,14 @@ EM_JS(void, init_js, (), { { return Module.withPromise(p => Module._schedule_finish_block(p, this.index)); } + get_info() // eosjs JsonRpc + { + return Module.withPromise(p => Module._schedule_get_info(p, this.index)); + } + getRawAbi(account) // eosjs JsonRpc + { + return Module.withPromise(p => Module._schedule_get_raw_abi(p, this.index, account)); + } }; Module.Chain = Chain; Module.createChain = () => @@ -80,6 +96,35 @@ void send_error(uint32_t promise, const char* e) promise, copy); } +void ret(uint32_t promise) +{ + MAIN_THREAD_ASYNC_EM_ASM({ Module.resolvePromise($0, undefined); }, promise); +} + +void ret(uint32_t promise, const char* s) +{ + auto copy = strdup(s); + if (!copy) + throw std::bad_alloc(); + MAIN_THREAD_ASYNC_EM_ASM( + { // + Module.resolvePromise($0, Module.eatString($1)); + }, + promise, copy); +} + +void ret_json(uint32_t promise, const char* s) +{ + auto copy = strdup(s); + if (!copy) + throw std::bad_alloc(); + MAIN_THREAD_ASYNC_EM_ASM( + { // + Module.resolvePromise($0, JSON.parse(Module.eatString($1))); + }, + promise, copy); +} + template void run_in_background(uint32_t promise, F f) { @@ -106,11 +151,6 @@ void run_in_background(uint32_t promise, F f) }); } -void ret(uint32_t promise) -{ - MAIN_THREAD_ASYNC_EM_ASM({ Module.resolvePromise($0, undefined); }, promise); -} - struct test_chain : cltestlib::test_chain { fc::temp_directory dir; @@ -186,6 +226,73 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_finish_block(uint32_t promise, uin }); } +struct get_info_results +{ + eosio::chain::chain_id_type chain_id; + uint32_t head_block_num = 0; + uint32_t last_irreversible_block_num = 0; + eosio::chain::block_id_type last_irreversible_block_id; + eosio::chain::block_id_type head_block_id; + fc::time_point head_block_time; + eosio::chain::name head_block_producer; + uint64_t virtual_block_cpu_limit = 0; + uint64_t virtual_block_net_limit = 0; + uint64_t block_cpu_limit = 0; + uint64_t block_net_limit = 0; + uint32_t fork_db_head_block_num = 0; + eosio::chain::block_id_type fork_db_head_block_id; +}; +FC_REFLECT(get_info_results, + (chain_id)(head_block_num)(last_irreversible_block_num)(last_irreversible_block_id)( + head_block_id)(head_block_time)(head_block_producer)(virtual_block_cpu_limit)( + virtual_block_net_limit)(block_cpu_limit)(block_net_limit)(fork_db_head_block_num)( + fork_db_head_block_id)) + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_info(uint32_t promise, uint32_t index) +{ + run_in_background(promise, [=] { + auto& chain = assert_chain(index); + auto& control = *chain.control; + const auto& rm = control.get_resource_limits_manager(); + get_info_results results{ + control.get_chain_id(), + control.head_block_num(), + control.last_irreversible_block_num(), + control.last_irreversible_block_id(), + control.head_block_id(), + control.head_block_time(), + control.head_block_producer(), + rm.get_virtual_block_cpu_limit(), + rm.get_virtual_block_net_limit(), + rm.get_block_cpu_limit(), + rm.get_block_net_limit(), + control.fork_db_pending_head_block_num(), + control.fork_db_pending_head_block_id(), + }; + ret_json(promise, fc::json::to_string(results, fc::time_point::maximum()).c_str()); + }); +} + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_raw_abi(uint32_t promise, + uint32_t index, + const std::string& account) +{ + run_in_background(promise, [=] { + const auto& chain = assert_chain(index); + const auto& abi = chain.control->get_account(eosio::chain::name(account)).abi; + char* copy = (char*)malloc(abi.size()); + if (!copy) + throw std::bad_alloc(); + memcpy(copy, abi.data(), abi.size()); + MAIN_THREAD_ASYNC_EM_ASM( + { // + Module.removePromise($0).accept(Module.eatBuffer($1, $2)); + }, + promise, copy, abi.size()); + ret(promise); + }); +} + int main() { init_js(); From f5af3cf81938efa20de096cb0c991410686db727 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Mon, 21 Jun 2021 16:38:18 -0400 Subject: [PATCH 12/14] emscripten --- emscripten/src/index.js | 17 ++---- emscripten/test.cpp | 118 +++++++++++++++++++++++++++++++--------- 2 files changed, 98 insertions(+), 37 deletions(-) diff --git a/emscripten/src/index.js b/emscripten/src/index.js index 2e82b0b70..74a66ef84 100644 --- a/emscripten/src/index.js +++ b/emscripten/src/index.js @@ -31,20 +31,12 @@ function simpleAuth(key = defaultPubKey) { }; } -function createAccount(name) { +function createAccount(name, owner = simpleAuth(), active = simpleAuth()) { return { account: 'eosio', name: 'newaccount', - authorization: [{ - actor: 'eosio', - permission: 'active', - }], - data: { - creator: 'eosio', - name: 'bob', - owner: simpleAuth(), - active: simpleAuth(), - }, + authorization: [{ actor: 'eosio', permission: 'active' }], + data: { creator: 'eosio', name, owner, active }, }; } @@ -53,7 +45,10 @@ function createAccount(name) { await (async () => { let t = await createCLTester(testerOptions); let c = await t.createChain(); + await c.finishBlock(); writeTerm(JSON.stringify(await c.get_info(), null, 4) + '\n'); + writeTerm(JSON.stringify(await c.get_block(1), null, 4) + '\n'); + writeTerm(JSON.stringify(await c.get_block(2), null, 4) + '\n'); let api = new Api({ rpc: c, signatureProvider: defaultSignatureProvider }); await api.transact({ actions: [ diff --git a/emscripten/test.cpp b/emscripten/test.cpp index 62bbf5e76..c1531bd21 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -3,15 +3,27 @@ #include #include #include +#include #include #include #include +using eosio::chain::abi_def; +using eosio::chain::abi_serializer; +using eosio::chain::account_object; +using eosio::chain::block_id_type; +using eosio::chain::builtin_protocol_feature_t; +using eosio::chain::by_name; +using eosio::chain::chain_id_type; +using eosio::chain::controller; +using eosio::chain::genesis_state; +using eosio::chain::name; +using eosio::chain::signed_block_ptr; +using eosio::chain::unknown_block_exception; + // JS function calls come in on the main thread then execute in the background thread. This // * Stops chainlib from hitting browser restrictions that only apply to the main thread // * Stops long chainlib operations from blocking the main thread -// -// The JS interface wraps this up with promises boost::asio::thread_pool background(1); // clang-format off @@ -71,9 +83,18 @@ EM_JS(void, init_js, (), { { return Module.withPromise(p => Module._schedule_get_info(p, this.index)); } - getRawAbi(account) // eosjs JsonRpc + get_block(b) // eosjs JsonRpc + { + return Module.withPromise(p => ccall("schedule_get_block", null, + [ "number", "number", "string" ], + [ p, this.index, b + "" ])); + } + async getRawAbi(account) // eosjs JsonRpc { - return Module.withPromise(p => Module._schedule_get_raw_abi(p, this.index, account)); + const abi = await Module.withPromise(p => ccall("schedule_get_raw_abi", null, + [ "number", "number", "string" ], + [ p, this.index, account + "" ])); + return {accountName : account, abi}; } }; Module.Chain = Chain; @@ -125,6 +146,19 @@ void ret_json(uint32_t promise, const char* s) promise, copy); } +void ret_blob(uint32_t promise, const void* data, size_t size) +{ + char* copy = (char*)malloc(size); + if (!copy) + throw std::bad_alloc(); + memcpy(copy, data, size); + MAIN_THREAD_ASYNC_EM_ASM( + { // + Module.removePromise($0).resolve(Module.eatBuffer($1, $2)); + }, + promise, copy, size); +} + template void run_in_background(uint32_t promise, F f) { @@ -157,23 +191,23 @@ struct test_chain : cltestlib::test_chain test_chain() { - eosio::chain::controller::config cfg; + controller::config cfg; cfg.blocks_dir = dir.path() / "blocks"; cfg.state_dir = dir.path() / "state"; cfg.contracts_console = true; cfg.state_size = 200 * 1024 * 1024; cfg.state_guard_size = 0; - eosio::chain::genesis_state genesis; + genesis_state genesis; genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); - control = std::make_unique( - cfg, cltestlib::make_protocol_feature_set(), genesis.compute_chain_id()); + control = std::make_unique(cfg, cltestlib::make_protocol_feature_set(), + genesis.compute_chain_id()); control->add_indices(); control->startup([] { return false; }, genesis); control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0, {*control->get_protocol_feature_manager().get_builtin_digest( - eosio::chain::builtin_protocol_feature_t::preactivate_feature)}); + builtin_protocol_feature_t::preactivate_feature)}); } }; @@ -228,19 +262,19 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_finish_block(uint32_t promise, uin struct get_info_results { - eosio::chain::chain_id_type chain_id; + chain_id_type chain_id; uint32_t head_block_num = 0; uint32_t last_irreversible_block_num = 0; - eosio::chain::block_id_type last_irreversible_block_id; - eosio::chain::block_id_type head_block_id; + block_id_type last_irreversible_block_id; + block_id_type head_block_id; fc::time_point head_block_time; - eosio::chain::name head_block_producer; + name head_block_producer; uint64_t virtual_block_cpu_limit = 0; uint64_t virtual_block_net_limit = 0; uint64_t block_cpu_limit = 0; uint64_t block_net_limit = 0; uint32_t fork_db_head_block_num = 0; - eosio::chain::block_id_type fork_db_head_block_id; + block_id_type fork_db_head_block_id; }; FC_REFLECT(get_info_results, (chain_id)(head_block_num)(last_irreversible_block_num)(last_irreversible_block_id)( @@ -273,23 +307,55 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_info(uint32_t promise, uint32_ }); } +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_block(uint32_t promise, + uint32_t index, + const char* block_num_or_id) +{ + run_in_background(promise, [=] { + auto& chain = assert_chain(index); + auto& control = *chain.control; + signed_block_ptr block; + try + { + block = control.fetch_block_by_number(fc::to_uint64(block_num_or_id)); + } + catch (...) + { + block = control.fetch_block_by_id(fc::variant(block_num_or_id).as()); + } + EOS_ASSERT(block, unknown_block_exception, "Could not find block: ${block}", + ("block", block_num_or_id)); + fc::variant pretty_output; + auto yield = abi_serializer::create_yield_function(fc::microseconds::maximum()); + abi_serializer::to_variant( + *block, pretty_output, + [&](name account) -> fc::optional { + if (const auto* accnt = control.db().find(account)) + { + abi_def abi; + if (abi_serializer::to_abi(accnt->abi, abi)) + return abi_serializer(abi, yield); + } + return {}; + }, + yield); + uint32_t ref_block_prefix = block->id()._hash[1]; + auto result = fc::mutable_variant_object(pretty_output.get_object()) // + ("id", block->id()) // + ("block_num", block->block_num()) // + ("ref_block_prefix", ref_block_prefix); + ret_json(promise, fc::json::to_string(result, fc::time_point::maximum()).c_str()); + }); +} + extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_raw_abi(uint32_t promise, uint32_t index, - const std::string& account) + const char* account) { run_in_background(promise, [=] { const auto& chain = assert_chain(index); - const auto& abi = chain.control->get_account(eosio::chain::name(account)).abi; - char* copy = (char*)malloc(abi.size()); - if (!copy) - throw std::bad_alloc(); - memcpy(copy, abi.data(), abi.size()); - MAIN_THREAD_ASYNC_EM_ASM( - { // - Module.removePromise($0).accept(Module.eatBuffer($1, $2)); - }, - promise, copy, abi.size()); - ret(promise); + const auto& abi = chain.control->get_account(name(account)).abi; + ret_blob(promise, abi.data(), abi.size()); }); } From 1a712bcc4c3e6c6337a0bc2f14d7f08d84a62624 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Mon, 21 Jun 2021 18:54:39 -0400 Subject: [PATCH 13/14] emscripten --- emscripten/package.json | 1 + emscripten/test.cpp | 85 +++++++++++++++++++++++++++++++----- emscripten/webpack.config.js | 4 ++ emscripten/yarn.lock | 44 +++++++++++++------ 4 files changed, 109 insertions(+), 25 deletions(-) diff --git a/emscripten/package.json b/emscripten/package.json index 4b04ecfcf..182db65e7 100644 --- a/emscripten/package.json +++ b/emscripten/package.json @@ -4,6 +4,7 @@ "main": "index.js", "license": "MIT", "devDependencies": { + "buffer": "^6.0.3", "copy-webpack-plugin": "^9.0.0", "eosjs": "^22.0.0", "webpack": "5", diff --git a/emscripten/test.cpp b/emscripten/test.cpp index c1531bd21..793e270f9 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -4,10 +4,14 @@ #include #include #include +#include #include #include #include +using namespace std::literals; + +using boost::container::flat_set; using eosio::chain::abi_def; using eosio::chain::abi_serializer; using eosio::chain::account_object; @@ -18,7 +22,10 @@ using eosio::chain::chain_id_type; using eosio::chain::controller; using eosio::chain::genesis_state; using eosio::chain::name; +using eosio::chain::public_key_type; using eosio::chain::signed_block_ptr; +using eosio::chain::transaction; +using eosio::chain::transaction_type_exception; using eosio::chain::unknown_block_exception; // JS function calls come in on the main thread then execute in the background thread. This @@ -96,6 +103,14 @@ EM_JS(void, init_js, (), { [ p, this.index, account + "" ])); return {accountName : account, abi}; } + async getRequiredKeys(params) // eosjs JsonRpc + { + const json = JSON.stringify( + {transaction : params.transaction, available_keys : params.availableKeys}); + return await Module.withPromise(p => ccall("schedule_get_required_keys", null, + [ "number", "number", "string" ], + [ p, this.index, json ])); + } }; Module.Chain = Chain; Module.createChain = () => @@ -307,6 +322,20 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_info(uint32_t promise, uint32_ }); } +template +auto make_resolver(controller& control, Y& yield) +{ + return [&](name account) -> fc::optional { + if (const auto* accnt = control.db().find(account)) + { + abi_def abi; + if (abi_serializer::to_abi(accnt->abi, abi)) + return abi_serializer(abi, yield); + } + return {}; + }; +} + extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_block(uint32_t promise, uint32_t index, const char* block_num_or_id) @@ -327,18 +356,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_block(uint32_t promise, ("block", block_num_or_id)); fc::variant pretty_output; auto yield = abi_serializer::create_yield_function(fc::microseconds::maximum()); - abi_serializer::to_variant( - *block, pretty_output, - [&](name account) -> fc::optional { - if (const auto* accnt = control.db().find(account)) - { - abi_def abi; - if (abi_serializer::to_abi(accnt->abi, abi)) - return abi_serializer(abi, yield); - } - return {}; - }, - yield); + abi_serializer::to_variant(*block, pretty_output, make_resolver(control, yield), yield); uint32_t ref_block_prefix = block->id()._hash[1]; auto result = fc::mutable_variant_object(pretty_output.get_object()) // ("id", block->id()) // @@ -359,6 +377,49 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_raw_abi(uint32_t promise, }); } +struct get_required_keys_params +{ + fc::variant transaction; + flat_set available_keys; +}; +FC_REFLECT(get_required_keys_params, (transaction)(available_keys)) + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_required_keys(uint32_t promise, + uint32_t index, + const char* json) +{ + run_in_background(promise, [=] { + const auto& chain = assert_chain(index); + auto params = fc::json::from_string(json).as(); + transaction trx; + auto yield = abi_serializer::create_yield_function(fc::microseconds::maximum()); + auto resolver = make_resolver(*chain.control, yield); + try + { + abi_serializer::from_variant(params.transaction, trx, resolver, yield); + } + EOS_RETHROW_EXCEPTIONS(transaction_type_exception, "Invalid transaction") + auto required_keys = chain.control->get_authorization_manager().get_required_keys( + trx, params.available_keys, fc::seconds(trx.delay_sec)); + std::string result = "["; + bool need_comma = false; + for (auto& key : required_keys) + { + auto str = + fc::crypto::config::public_key_base_prefix + "_"s + + key._storage.visit( + fc::crypto::base58str_visitor({})); + if (need_comma) + result += ","; + result += "\"" + str + "\""; + } + result += "]"; + ret_json(promise, result.c_str()); + return result; + }); +} + int main() { init_js(); diff --git a/emscripten/webpack.config.js b/emscripten/webpack.config.js index a44a9918d..78a8ab4ed 100644 --- a/emscripten/webpack.config.js +++ b/emscripten/webpack.config.js @@ -1,3 +1,4 @@ +const webpack = require("webpack"); const CopyPlugin = require("copy-webpack-plugin"); module.exports = { @@ -12,5 +13,8 @@ module.exports = { { from: "test.html" }, ], }), + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + }) ], }; diff --git a/emscripten/yarn.lock b/emscripten/yarn.lock index 85dea006c..4d2406000 100644 --- a/emscripten/yarn.lock +++ b/emscripten/yarn.lock @@ -237,6 +237,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + bn.js@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" @@ -275,6 +280,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + caniuse-lite@^1.0.30001219: version "1.0.30001239" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz#66e8669985bb2cb84ccb10f68c25ce6dd3e4d2b8" @@ -339,9 +352,9 @@ dir-glob@^3.0.1: path-type "^4.0.0" electron-to-chromium@^1.3.723: - version "1.3.752" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz#0728587f1b9b970ec9ffad932496429aef750d09" - integrity sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A== + version "1.3.753" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.753.tgz#e5aa72c2a3a97c8187131fe307f0f18d1277b6e5" + integrity sha512-LBJJ4qnuveWMqnwP0fP+bSl+QIxeToqBH8Bb0qVkz6YnfOZQpOW/FlkxuPn0u/zh+py6Y7x6L4qsl5aBjE9Djw== elliptic@6.5.4: version "6.5.4" @@ -379,10 +392,10 @@ eosjs@^22.0.0: hash.js "1.1.7" pako "2.0.3" -es-module-lexer@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e" - integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA== +es-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.6.0.tgz#e72ab05b7412e62b9be37c37a09bdb6000d706f0" + integrity sha512-f8kcHX1ArhllUtb/wVSyvygoKCznIjnxhLxy7TCvIiMdT7fL4ZDTIKaadMe6eLvOXg6Wk02UeoFgUoZ2EKZZUA== escalade@^3.1.1: version "3.1.1" @@ -563,6 +576,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" @@ -951,7 +969,7 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== -terser-webpack-plugin@^5.1.1: +terser-webpack-plugin@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.3.tgz#30033e955ca28b55664f1e4b30a1347e61aa23af" integrity sha512-cxGbMqr6+A2hrIB5ehFIF+F/iST5ZOxvOmy9zih9ySbP1C2oEWQSOUS+2SNBTjzx5xLKO4xnod9eywdfq1Nb9A== @@ -1035,9 +1053,9 @@ webpack-sources@^2.3.0: source-map "^0.6.1" webpack@5: - version "5.39.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.39.1.tgz#d1e014b6d71e1aef385316ad528f21cd5b1f9784" - integrity sha512-ulOvoNCh2PvTUa+zbpRuEb1VPeQnhxpnHleMPVVCq3QqnaFogjsLyps+o42OviQFoaGtTQYrUqDXu1QNkvUPzw== + version "5.40.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.40.0.tgz#3182cfd324759d715252cf541901a226e57b5061" + integrity sha512-c7f5e/WWrxXWUzQqTBg54vBs5RgcAgpvKE4F4VegVgfo4x660ZxYUF2/hpMkZUnLjgytVTitjeXaN4IPlXCGIw== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.47" @@ -1048,7 +1066,7 @@ webpack@5: browserslist "^4.14.5" chrome-trace-event "^1.0.2" enhanced-resolve "^5.8.0" - es-module-lexer "^0.4.0" + es-module-lexer "^0.6.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -1059,7 +1077,7 @@ webpack@5: neo-async "^2.6.2" schema-utils "^3.0.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.1" + terser-webpack-plugin "^5.1.3" watchpack "^2.2.0" webpack-sources "^2.3.0" From 97c19716eda0699faa31cd9bf68fe3536c7404a2 Mon Sep 17 00:00:00 2001 From: Todd Fleming Date: Mon, 21 Jun 2021 21:05:21 -0400 Subject: [PATCH 14/14] push_transaction working --- emscripten/src/index.js | 9 +- emscripten/test.cpp | 128 +++++++++++++++++- libraries/cltestlib/cltestlib.cpp | 28 ++-- .../cltestlib/include/cltestlib/cltestlib.hpp | 3 + 4 files changed, 151 insertions(+), 17 deletions(-) diff --git a/emscripten/src/index.js b/emscripten/src/index.js index 74a66ef84..e6368d872 100644 --- a/emscripten/src/index.js +++ b/emscripten/src/index.js @@ -50,15 +50,16 @@ function createAccount(name, owner = simpleAuth(), active = simpleAuth()) { writeTerm(JSON.stringify(await c.get_block(1), null, 4) + '\n'); writeTerm(JSON.stringify(await c.get_block(2), null, 4) + '\n'); let api = new Api({ rpc: c, signatureProvider: defaultSignatureProvider }); - await api.transact({ + writeTerm(JSON.stringify(await api.transact({ actions: [ createAccount('alice'), createAccount('bob'), createAccount('sue'), ] - }, { useLastIrreversible: true, expireSeconds: 1 }); - while (true) - await c.finishBlock(); + }, { useLastIrreversible: true, expireSeconds: 1 }), null, 4) + '\n'); + await c.finishBlock(); + // while (true) + // await c.finishBlock(); })(); } catch (e) { writeTerm(e + '\n'); diff --git a/emscripten/test.cpp b/emscripten/test.cpp index 793e270f9..9ae945c3b 100644 --- a/emscripten/test.cpp +++ b/emscripten/test.cpp @@ -13,6 +13,7 @@ using namespace std::literals; using boost::container::flat_set; using eosio::chain::abi_def; +using eosio::chain::abi_exception; using eosio::chain::abi_serializer; using eosio::chain::account_object; using eosio::chain::block_id_type; @@ -20,14 +21,20 @@ using eosio::chain::builtin_protocol_feature_t; using eosio::chain::by_name; using eosio::chain::chain_id_type; using eosio::chain::controller; +using eosio::chain::digest_type; using eosio::chain::genesis_state; using eosio::chain::name; +using eosio::chain::packed_transaction; +using eosio::chain::packed_transaction_type_exception; using eosio::chain::public_key_type; using eosio::chain::signed_block_ptr; using eosio::chain::transaction; +using eosio::chain::transaction_id_type; using eosio::chain::transaction_type_exception; using eosio::chain::unknown_block_exception; +inline constexpr uint32_t billed_cpu_time_use = 2000; + // JS function calls come in on the main thread then execute in the background thread. This // * Stops chainlib from hitting browser restrictions that only apply to the main thread // * Stops long chainlib operations from blocking the main thread @@ -73,6 +80,13 @@ EM_JS(void, init_js, (), { f(index); return promise; }; + function arrayToHex(data) + { + let result = ""; + for (const x of data) + result += ("00" + x.toString(16)).slice(-2); + return result; + } class Chain { @@ -111,6 +125,19 @@ EM_JS(void, init_js, (), { [ "number", "number", "string" ], [ p, this.index, json ])); } + async push_transaction(args) // eosjs JsonRpc + { + const json = JSON.stringify({ + signatures : args.signatures, + compression : args.compression || 0, + packed_context_free_data : + arrayToHex(args.serializedContextFreeData || new Uint8Array(0)), + packed_trx : arrayToHex(args.serializedTransaction) + }); + return Module.withPromise(p => ccall("schedule_push_transaction", null, + [ "number", "number", "string" ], + [ p, this.index, json ])); + } }; Module.Chain = Chain; Module.createChain = () => @@ -340,7 +367,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_block(uint32_t promise, uint32_t index, const char* block_num_or_id) { - run_in_background(promise, [=] { + run_in_background(promise, [promise, index, block_num_or_id = std::string(block_num_or_id)] { auto& chain = assert_chain(index); auto& control = *chain.control; signed_block_ptr block; @@ -370,7 +397,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_raw_abi(uint32_t promise, uint32_t index, const char* account) { - run_in_background(promise, [=] { + run_in_background(promise, [promise, index, account = std::string(account)] { const auto& chain = assert_chain(index); const auto& abi = chain.control->get_account(name(account)).abi; ret_blob(promise, abi.data(), abi.size()); @@ -388,7 +415,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_required_keys(uint32_t promise uint32_t index, const char* json) { - run_in_background(promise, [=] { + run_in_background(promise, [promise, index, json = std::string(json)] { const auto& chain = assert_chain(index); auto params = fc::json::from_string(json).as(); transaction trx; @@ -420,6 +447,101 @@ extern "C" void EMSCRIPTEN_KEEPALIVE schedule_get_required_keys(uint32_t promise }); } +struct push_transaction_results +{ + transaction_id_type transaction_id; + fc::variant processed; +}; +FC_REFLECT(push_transaction_results, (transaction_id)(processed)) + +extern "C" void EMSCRIPTEN_KEEPALIVE schedule_push_transaction(uint32_t promise, + uint32_t index, + const char* json) +{ + run_in_background(promise, [promise, index, json = std::string(json)] { + auto& chain = assert_chain(index); + auto yield = abi_serializer::create_yield_function(fc::microseconds::maximum()); + auto resolver = make_resolver(*chain.control, yield); + auto params = fc::json::from_string(json); + auto packed = std::make_shared(); + try + { + abi_serializer::from_variant(params, *packed, std::move(resolver), yield); + } + EOS_RETHROW_EXCEPTIONS(packed_transaction_type_exception, "Invalid packed transaction") + auto trx_trace_ptr = chain.push_transaction(billed_cpu_time_use, std::move(packed)); + fc::variant output; + try + { + output = chain.control->to_variant_with_abi(*trx_trace_ptr, yield); + + // Create map of (closest_unnotified_ancestor_action_ordinal, global_sequence) with action + // trace + std::map, fc::mutable_variant_object> act_traces_map; + for (const auto& act_trace : output["action_traces"].get_array()) + { + if (act_trace["receipt"].is_null() && act_trace["except"].is_null()) + continue; + auto closest_unnotified_ancestor_action_ordinal = + act_trace["closest_unnotified_ancestor_action_ordinal"] + .as() + .value; + auto global_sequence = act_trace["receipt"].is_null() + ? std::numeric_limits::max() + : act_trace["receipt"]["global_sequence"].as(); + act_traces_map.emplace( + std::make_pair(closest_unnotified_ancestor_action_ordinal, global_sequence), + act_trace.get_object()); + } + + std::function(uint32_t)> convert_act_trace_to_tree_struct = + [&](uint32_t closest_unnotified_ancestor_action_ordinal) { + std::vector restructured_act_traces; + auto it = act_traces_map.lower_bound( + std::make_pair(closest_unnotified_ancestor_action_ordinal, 0)); + for (; it != act_traces_map.end() && + it->first.first == closest_unnotified_ancestor_action_ordinal; + ++it) + { + auto& act_trace_mvo = it->second; + + auto action_ordinal = + act_trace_mvo["action_ordinal"].as().value; + act_trace_mvo["inline_traces"] = + convert_act_trace_to_tree_struct(action_ordinal); + if (act_trace_mvo["receipt"].is_null()) + { + act_trace_mvo["receipt"] = fc::mutable_variant_object()("abi_sequence", 0) // + ("act_digest", + digest_type::hash( + trx_trace_ptr->action_traces[action_ordinal - 1].act)) // + ("auth_sequence", fc::flat_map()) // + ("code_sequence", 0) // + ("global_sequence", 0) // + ("receiver", act_trace_mvo["receiver"]) // + ("recv_sequence", 0); + } + restructured_act_traces.push_back(std::move(act_trace_mvo)); + } + return restructured_act_traces; + }; + + fc::mutable_variant_object output_mvo(output); + output_mvo["action_traces"] = convert_act_trace_to_tree_struct(0); + + output = output_mvo; + } + catch (abi_exception&) + { + output = *trx_trace_ptr; + } + + const transaction_id_type& id = trx_trace_ptr->id; + push_transaction_results results{id, output}; + ret_json(promise, fc::json::to_string(results, fc::time_point::maximum()).c_str()); + }); +} // schedule_push_transaction + int main() { init_js(); diff --git a/libraries/cltestlib/cltestlib.cpp b/libraries/cltestlib/cltestlib.cpp index cf493ed26..ad8b1de48 100644 --- a/libraries/cltestlib/cltestlib.cpp +++ b/libraries/cltestlib/cltestlib.cpp @@ -69,26 +69,34 @@ namespace cltestlib control->commit_block(); } + eosio::chain::transaction_trace_ptr test_chain::push_transaction( + uint32_t billed_cpu_time_us, + std::shared_ptr ptrx) + { + start_if_needed(); + auto start_time = std::chrono::steady_clock::now(); + auto fut = eosio::chain::transaction_metadata::start_recover_keys( + ptrx, control->get_thread_pool(), control->get_chain_id(), fc::microseconds::maximum()); + auto result = control->push_transaction(fut.get(), fc::time_point::maximum(), + billed_cpu_time_us, true, billed_cpu_time_us); + auto us = std::chrono::duration_cast( + std::chrono::steady_clock::now() - start_time); + ilog("chainlib transaction took ${u} us, billed ${b} us", + ("u", us.count())("b", billed_cpu_time_us)); + return result; + } + eosio::chain::transaction_trace_ptr test_chain::push_transaction(uint32_t billed_cpu_time_us, push_trx_args&& args) { auto transaction = fc::raw::unpack(args.transaction); eosio::chain::signed_transaction signed_trx{ std::move(transaction), std::move(args.signatures), std::move(args.context_free_data)}; - start_if_needed(); for (auto& key : args.keys) signed_trx.sign(key, control->get_chain_id()); auto ptrx = std::make_shared( std::move(signed_trx), eosio::chain::packed_transaction::compression_type::none); - auto fut = eosio::chain::transaction_metadata::start_recover_keys( - ptrx, control->get_thread_pool(), control->get_chain_id(), fc::microseconds::maximum()); - auto start_time = std::chrono::steady_clock::now(); - auto result = control->push_transaction(fut.get(), fc::time_point::maximum(), - billed_cpu_time_us, true, billed_cpu_time_us); - auto us = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start_time); - ilog("chainlib transaction took ${u} us", ("u", us.count())); - return result; + return push_transaction(billed_cpu_time_us, std::move(ptrx)); } eosio::chain::transaction_trace_ptr test_chain::exec_deferred(uint32_t billed_cpu_time_us) diff --git a/libraries/cltestlib/include/cltestlib/cltestlib.hpp b/libraries/cltestlib/include/cltestlib/cltestlib.hpp index 4442089de..b50769de5 100644 --- a/libraries/cltestlib/include/cltestlib/cltestlib.hpp +++ b/libraries/cltestlib/include/cltestlib/cltestlib.hpp @@ -27,6 +27,9 @@ namespace cltestlib void start_block(int64_t skip_miliseconds = 0); void start_if_needed(); void finish_block(); + eosio::chain::transaction_trace_ptr push_transaction( + uint32_t billed_cpu_time_us, + std::shared_ptr ptrx); eosio::chain::transaction_trace_ptr push_transaction(uint32_t billed_cpu_time_us, push_trx_args&& args); eosio::chain::transaction_trace_ptr exec_deferred(uint32_t billed_cpu_time_us);