From 9d1ff5f8a804695d9c2407b0413567654ed091a9 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 2 Feb 2022 13:22:16 -0600 Subject: [PATCH 001/111] Add snapshot-to-json command line option --- .../chain/include/eosio/chain/snapshot.hpp | 15 ++++++ libraries/chain/snapshot.cpp | 39 ++++++++++++++ plugins/chain_plugin/chain_plugin.cpp | 54 ++++++++++++++++++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index e5bfd26243..cce1292963 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -342,7 +342,22 @@ namespace eosio { namespace chain { std::streampos header_pos; std::streampos section_pos; uint64_t row_count; + }; + + class ostream_json_snapshot_writer : public snapshot_writer { + public: + explicit ostream_json_snapshot_writer(std::ostream& snapshot); + + void write_start_section( const std::string& section_name ) override; + void write_row( const detail::abstract_snapshot_row_writer& row_writer ) override; + void write_end_section() override; + void finalize(); + + static const uint32_t magic_number = 0x30510550; + private: + detail::ostream_wrapper snapshot; + uint64_t row_count; }; class istream_snapshot_reader : public snapshot_reader { diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 66966ef6be..a3a6829639 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace eosio { namespace chain { @@ -190,6 +191,44 @@ void ostream_snapshot_writer::finalize() { snapshot.write((char*)&end_marker, sizeof(end_marker)); } +ostream_json_snapshot_writer::ostream_json_snapshot_writer(std::ostream& snapshot) + :snapshot(snapshot) + ,row_count(0) +{ + snapshot << "{\n"; + // write magic number + auto totem = magic_number; + snapshot << "\"magic_number\":" << fc::json::to_string(totem, fc::time_point::maximum()) << "\n"; + + // write version + auto version = current_snapshot_version; + snapshot << ",\"version\":" << fc::json::to_string(version, fc::time_point::maximum()) << "\n"; +} + +void ostream_json_snapshot_writer::write_start_section( const std::string& section_name ) +{ + snapshot.inner << "," << fc::json::to_string(section_name, fc::time_point::maximum()) << ":{\n"; +} + +void ostream_json_snapshot_writer::write_row( const detail::abstract_snapshot_row_writer& row_writer ) { + const auto yield = [&](size_t s) {}; + + if(row_count != 0) snapshot.inner << ","; + snapshot.inner << "\"row_" << row_count << "\":" << fc::json::to_string(row_writer.to_variant(), yield) << "\n"; + ++row_count; +} + +void ostream_json_snapshot_writer::write_end_section( ) { + snapshot.inner << "}\n"; + row_count = 0; +} + +void ostream_json_snapshot_writer::finalize() { + snapshot.inner << "}\n"; + snapshot.inner.flush(); +} + + istream_snapshot_reader::istream_snapshot_reader(std::istream& snapshot) :snapshot(snapshot) ,header_pos(snapshot.tellg()) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 9141072cde..4619921cbb 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -360,6 +360,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "print build environment information to console as JSON and exit") ("extract-build-info", bpo::value(), "extract build environment information as JSON, write into specified file, and exit") + ("snapshot-to-json", bpo::value(), + "convert snapshot to JSON format, and exit") ("force-all-checks", bpo::bool_switch()->default_value(false), "do not skip any validation checks while replaying blocks (useful for replaying blocks from untrusted source)") ("disable-replay-opts", bpo::bool_switch()->default_value(false), @@ -862,6 +864,57 @@ void chain_plugin::plugin_initialize(const variables_map& options) { EOS_THROW( extract_genesis_state_exception, "extracted genesis state from blocks.log" ); } + std::optional chain_id; + if( options.count("snapshot-to-json") ) { + my->snapshot_path = options.at( "snapshot-to-json" ).as(); + EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception, + "Cannot load snapshot, ${name} does not exist", ("name", my->snapshot_path->generic_string()) ); + + // recover genesis information from the snapshot + // used for validation code below + auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); + istream_snapshot_reader reader(infile); + reader.validate(); + chain_id = controller::extract_chain_id(reader); + infile.close(); + + boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + my->chain_config->state_dir = temp_dir / "state"; + my->blocks_dir = temp_dir / "blocks"; + my->chain_config->blog.log_dir = my->blocks_dir; + try { + auto shutdown = [](){ return app().quit(); }; + auto check_shutdown = [](){ return app().is_quiting(); }; + auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); + auto reader = std::make_shared(infile); + my->chain.emplace( *my->chain_config, std::move(pfs), *chain_id ); + my->chain->add_indices(); + my->chain->startup(shutdown, check_shutdown, reader); + infile.close(); + app().quit(); // shutdown as we will be finished after writing the snapshot + + ilog("Writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json")); + auto snap_out = std::ofstream( my->snapshot_path->generic_string() + ".json", (std::ios::out) ); + auto writer = std::make_shared( snap_out ); + my->chain->write_snapshot( writer ); + writer->finalize(); + snap_out.flush(); + snap_out.close(); + } catch (const database_guard_exception& e) { + log_guard_exception(e); + // make sure to properly close the db + my->chain.reset(); + fc::remove_all(temp_dir); + throw; + } + my->chain.reset(); + fc::remove_all(temp_dir); + ilog("Completed writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json")); + ilog("==== Ignore any additional log messages. ===="); + + EOS_THROW( node_management_success, "extracted json from snapshot" ); + } + // move fork_db to new location upgrade_from_reversible_to_fork_db( my.get() ); @@ -888,7 +941,6 @@ void chain_plugin::plugin_initialize(const variables_map& options) { wlog( "The --truncate-at-block option can only be used with --hard-replay-blockchain." ); } - std::optional chain_id; if (options.count( "snapshot" )) { my->snapshot_path = options.at( "snapshot" ).as(); EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception, From 84a4eae3547b0693fce9ef31ef0e74ee1c1000e4 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 7 Feb 2022 13:32:45 -0600 Subject: [PATCH 002/111] Address PR comments, add better description to option --- libraries/chain/snapshot.cpp | 1 + plugins/chain_plugin/chain_plugin.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index a3a6829639..ce6adec721 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -207,6 +207,7 @@ ostream_json_snapshot_writer::ostream_json_snapshot_writer(std::ostream& snapsho void ostream_json_snapshot_writer::write_start_section( const std::string& section_name ) { + row_count = 0; snapshot.inner << "," << fc::json::to_string(section_name, fc::time_point::maximum()) << ":{\n"; } diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 4619921cbb..cea50ccf7f 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -361,7 +361,7 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip ("extract-build-info", bpo::value(), "extract build environment information as JSON, write into specified file, and exit") ("snapshot-to-json", bpo::value(), - "convert snapshot to JSON format, and exit") + "snapshot file to convert to JSON format, writes to .json (tmp state dir used), and exit") ("force-all-checks", bpo::bool_switch()->default_value(false), "do not skip any validation checks while replaying blocks (useful for replaying blocks from untrusted source)") ("disable-replay-opts", bpo::bool_switch()->default_value(false), From 4970c7f3011d689d96c3bc2e7d9d1ded6ad70bd6 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 20 Jul 2022 15:52:39 -0500 Subject: [PATCH 003/111] fix build errors --- plugins/chain_plugin/chain_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index cea50ccf7f..07e240b517 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -881,7 +881,7 @@ void chain_plugin::plugin_initialize(const variables_map& options) { boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); my->chain_config->state_dir = temp_dir / "state"; my->blocks_dir = temp_dir / "blocks"; - my->chain_config->blog.log_dir = my->blocks_dir; + my->chain_config->blocks_dir = my->blocks_dir; try { auto shutdown = [](){ return app().quit(); }; auto check_shutdown = [](){ return app().is_quiting(); }; From afa88ddaafec568f9f65b161fa2954755dd3f179 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 27 Jul 2022 10:51:27 -0500 Subject: [PATCH 004/111] implement json snapshot reader --- .../chain/include/eosio/chain/snapshot.hpp | 22 ++++ libraries/chain/snapshot.cpp | 114 ++++++++++++------ plugins/chain_plugin/chain_plugin.cpp | 53 ++++++++ 3 files changed, 151 insertions(+), 38 deletions(-) diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index cce1292963..aefd0d6840 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -381,6 +381,28 @@ namespace eosio { namespace chain { uint64_t cur_row; }; + class istream_json_snapshot_reader : public snapshot_reader { + public: + explicit istream_json_snapshot_reader(std::istream& snapshot); + + void validate() const override; + void set_section( const string& section_name ) override; + bool read_row( detail::abstract_snapshot_row_reader& row_reader ) override; + bool empty ( ) override; + void clear_section() override; + void return_to_header() override; + + private: + bool validate_section() const; + + std::istream& snapshot; + std::streampos header_pos; + uint64_t num_rows; + uint64_t cur_row; + fc::variant_object var_obj; + fc::variant_object cur_section; + }; + class integrity_hash_snapshot_writer : public snapshot_writer { public: explicit integrity_hash_snapshot_writer(fc::sha256::encoder& enc); diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index ce6adec721..12b828f9ab 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -286,44 +286,6 @@ bool istream_snapshot_reader::validate_section() const { return true; } -bool istream_snapshot_reader::has_section( const string& section_name ) { - auto restore_pos = fc::make_scoped_exit([this,pos=snapshot.tellg()](){ - snapshot.seekg(pos); - }); - - const std::streamoff header_size = sizeof(ostream_snapshot_writer::magic_number) + sizeof(current_snapshot_version); - - auto next_section_pos = header_pos + header_size; - - while (true) { - snapshot.seekg(next_section_pos); - uint64_t section_size = 0; - snapshot.read((char*)§ion_size,sizeof(section_size)); - if (section_size == std::numeric_limits::max()) { - break; - } - - next_section_pos = snapshot.tellg() + std::streamoff(section_size); - - uint64_t ignore = 0; - snapshot.read((char*)&ignore,sizeof(ignore)); - - bool match = true; - for(auto c : section_name) { - if(snapshot.get() != c) { - match = false; - break; - } - } - - if (match && snapshot.get() == 0) { - return true; - } - } - - return false; -} - void istream_snapshot_reader::set_section( const string& section_name ) { auto restore_pos = fc::make_scoped_exit([this,pos=snapshot.tellg()](){ snapshot.seekg(pos); @@ -386,6 +348,82 @@ void istream_snapshot_reader::return_to_header() { clear_section(); } +istream_json_snapshot_reader::istream_json_snapshot_reader(std::istream& snapshot) + :snapshot(snapshot) + ,header_pos(snapshot.tellg()) + ,num_rows(0) + ,cur_row(0) +{ + std::stringstream my_buffer; + my_buffer << snapshot.rdbuf(); + auto var = fc::json::from_string(my_buffer.str(), fc::json::parse_type::relaxed_parser); + if (var.is_object()) { + var_obj = var.get_object(); + } +} + +void istream_json_snapshot_reader::validate() const { + try { + // validate totem + auto expected_totem = ostream_json_snapshot_writer::magic_number; + decltype(expected_totem) actual_totem; + if (var_obj.contains("magic_number")) { + auto magic_num = var_obj["magic_number"]; + from_variant(magic_num, actual_totem); + EOS_ASSERT(actual_totem == expected_totem, snapshot_exception, + "JSON snapshot has unexpected magic number!"); + } + + // validate version + auto expected_version = current_snapshot_version; + decltype(expected_version) actual_version; + if (var_obj.contains("version")) { + auto version_num = var_obj["version"]; + from_variant(version_num, actual_version); + EOS_ASSERT(actual_version == expected_version, snapshot_exception, + "JSON snapshot is an unsuppored version. Expected : ${expected}, Got: ${actual}", + ("expected", expected_version)("actual", actual_version)); + } + } catch( const std::exception& e ) { \ + snapshot_exception fce(FC_LOG_MESSAGE( warn, "JSON snapshot validation threw IO exception (${what})",("what",e.what()))); + throw fce; + } +} + +bool istream_json_snapshot_reader::validate_section() const { + return true; +} + +void istream_json_snapshot_reader::set_section( const string& section_name ) { + if (var_obj.contains(section_name.c_str())) { + cur_section = var_obj[section_name.c_str()].get_object(); + cur_row = 0; + num_rows = cur_section.size(); + } else { + EOS_THROW(snapshot_exception, "JSON snapshot has no section named ${n}", ("n", section_name)); + } +} + +bool istream_json_snapshot_reader::read_row( detail::abstract_snapshot_row_reader& row_reader ) { + std::string row_name = "row_" + std::to_string(cur_row); + row_reader.provide(cur_section[row_name.c_str()]); + return ++cur_row < num_rows; +} + +bool istream_json_snapshot_reader::empty ( ) { + return num_rows == 0; +} + +void istream_json_snapshot_reader::clear_section() { + num_rows = 0; + cur_row = 0; + cur_section = fc::variant_object(); +} + +void istream_json_snapshot_reader::return_to_header() { + clear_section(); +} + integrity_hash_snapshot_writer::integrity_hash_snapshot_writer(fc::sha256::encoder& enc) :enc(enc) { diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 07e240b517..4a19dc49f9 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -161,6 +161,7 @@ class chain_plugin_impl { std::optional wasm_runtime; fc::microseconds abi_serializer_max_time_us; std::optional snapshot_path; + std::optional json_snapshot_path; // retained references to channels for easy publication @@ -377,6 +378,7 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip ("terminate-at-block", bpo::value()->default_value(0), "terminate after reaching this block number (if set to a non-zero number)") ("snapshot", bpo::value(), "File to read Snapshot State from") + ("json-snapshot", bpo::value(), "JSON File to read Snapshot State from") ; } @@ -987,6 +989,52 @@ void chain_plugin::plugin_initialize(const variables_map& options) { } } + } else if (options.count( "json-snapshot" )) { + my->json_snapshot_path = options.at( "json-snapshot" ).as(); + EOS_ASSERT( fc::exists(*my->json_snapshot_path), plugin_config_exception, + "Cannot load snapshot, ${name} does not exist", ("name", my->json_snapshot_path->generic_string()) ); + + // recover genesis information from the snapshot + // used for validation code below + auto infile = std::ifstream(my->json_snapshot_path->generic_string(), (std::ios::in)); + istream_json_snapshot_reader reader(infile); + reader.validate(); + chain_id = controller::extract_chain_id(reader); + infile.close(); + + EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, + plugin_config_exception, + "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information"); + EOS_ASSERT( options.count( "genesis-json" ) == 0, + plugin_config_exception, + "--snapshot is incompatible with --genesis-json as the snapshot contains genesis information"); + + auto shared_mem_path = my->chain_config->state_dir / "shared_memory.bin"; + EOS_ASSERT( !fc::is_regular_file(shared_mem_path), + plugin_config_exception, + "Snapshot can only be used to initialize an empty database." ); + + if( fc::is_regular_file( my->blocks_dir / "blocks.log" )) { + auto block_log_genesis = block_log::extract_genesis_state(my->blocks_dir); + if( block_log_genesis ) { + const auto& block_log_chain_id = block_log_genesis->compute_chain_id(); + EOS_ASSERT( *chain_id == block_log_chain_id, + plugin_config_exception, + "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID from the genesis state in the block log (${block_log_chain_id})", + ("snapshot_chain_id", *chain_id) + ("block_log_chain_id", block_log_chain_id) + ); + } else { + const auto& block_log_chain_id = block_log::extract_chain_id(my->blocks_dir); + EOS_ASSERT( *chain_id == block_log_chain_id, + plugin_config_exception, + "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID (${block_log_chain_id}) in the block log", + ("snapshot_chain_id", *chain_id) + ("block_log_chain_id", block_log_chain_id) + ); + } + } + } else { chain_id = controller::extract_chain_id_from_db( my->chain_config->state_dir ); @@ -1309,6 +1357,11 @@ void chain_plugin::plugin_startup() auto reader = std::make_shared(infile); my->chain->startup(shutdown, check_shutdown, reader); infile.close(); + } else if (my->json_snapshot_path) { + auto infile = std::ifstream(my->json_snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); + auto reader = std::make_shared(infile); + my->chain->startup(shutdown, check_shutdown, reader); + infile.close(); } else if( my->genesis ) { my->chain->startup(shutdown, check_shutdown, *my->genesis); } else { From 1892a298918e15e4ca7c2273626d5b7dc1aa597e Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 27 Jul 2022 16:38:53 -0500 Subject: [PATCH 005/111] remove vestigial function 'has_section' --- libraries/chain/include/eosio/chain/snapshot.hpp | 8 -------- libraries/chain/snapshot.cpp | 11 ----------- 2 files changed, 19 deletions(-) diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index aefd0d6840..55c81a7ca0 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -272,11 +272,6 @@ namespace eosio { namespace chain { read_section(detail::snapshot_section_traits::section_name(), f); } - template - bool has_section(const std::string& suffix = std::string()) { - return has_section(suffix + detail::snapshot_section_traits::section_name()); - } - virtual void validate() const = 0; virtual void return_to_header() = 0; @@ -284,7 +279,6 @@ namespace eosio { namespace chain { virtual ~snapshot_reader(){}; protected: - virtual bool has_section( const std::string& section_name ) = 0; virtual void set_section( const std::string& section_name ) = 0; virtual bool read_row( detail::abstract_snapshot_row_reader& row_reader ) = 0; virtual bool empty( ) = 0; @@ -313,7 +307,6 @@ namespace eosio { namespace chain { explicit variant_snapshot_reader(const fc::variant& snapshot); void validate() const override; - bool has_section( const string& section_name ) override; void set_section( const string& section_name ) override; bool read_row( detail::abstract_snapshot_row_reader& row_reader ) override; bool empty ( ) override; @@ -365,7 +358,6 @@ namespace eosio { namespace chain { explicit istream_snapshot_reader(std::istream& snapshot); void validate() const override; - bool has_section( const string& section_name ) override; void set_section( const string& section_name ) override; bool read_row( detail::abstract_snapshot_row_reader& row_reader ) override; bool empty ( ) override; diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 12b828f9ab..28302d096b 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -77,17 +77,6 @@ void variant_snapshot_reader::validate() const { } } -bool variant_snapshot_reader::has_section( const string& section_name ) { - const auto& sections = snapshot["sections"].get_array(); - for( const auto& section: sections ) { - if (section["name"].as_string() == section_name) { - return true; - } - } - - return false; -} - void variant_snapshot_reader::set_section( const string& section_name ) { const auto& sections = snapshot["sections"].get_array(); for( const auto& section: sections ) { From 46445273ad722e9c28b075d89f202bdca54ed68b Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Thu, 28 Jul 2022 11:02:55 -0500 Subject: [PATCH 006/111] add json_snapshot to snapshot_suites so that the json_snapshot is being tested. --- .../include/eosio/testing/snapshot_suites.hpp | 55 +++++++++++++++++- unittests/snapshots.hpp.in | 19 +++++- unittests/snapshots/CMakeLists.txt | 6 ++ unittests/snapshots/snap_v2.bin.json.gz | Bin 0 -> 196716 bytes .../snapshots/snap_v2_prod_sched.bin.json.gz | Bin 0 -> 201819 bytes unittests/snapshots/snap_v3.bin.json.gz | Bin 0 -> 196716 bytes unittests/snapshots/snap_v4.bin.json.gz | Bin 0 -> 196716 bytes unittests/snapshots/snap_v5.bin.json.gz | Bin 0 -> 196716 bytes unittests/snapshots/snap_v6.bin.json.gz | Bin 0 -> 196716 bytes 9 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 unittests/snapshots/snap_v2.bin.json.gz create mode 100644 unittests/snapshots/snap_v2_prod_sched.bin.json.gz create mode 100644 unittests/snapshots/snap_v3.bin.json.gz create mode 100644 unittests/snapshots/snap_v4.bin.json.gz create mode 100644 unittests/snapshots/snap_v5.bin.json.gz create mode 100644 unittests/snapshots/snap_v6.bin.json.gz diff --git a/libraries/testing/include/eosio/testing/snapshot_suites.hpp b/libraries/testing/include/eosio/testing/snapshot_suites.hpp index adec77a22b..6b941cb4f5 100644 --- a/libraries/testing/include/eosio/testing/snapshot_suites.hpp +++ b/libraries/testing/include/eosio/testing/snapshot_suites.hpp @@ -106,5 +106,58 @@ struct buffered_snapshot_suite { } }; -using snapshot_suites = boost::mpl::list; + +struct json_snapshot_suite { + using writer_t = ostream_json_snapshot_writer; + using reader_t = istream_json_snapshot_reader; + using write_storage_t = std::ostringstream; + using snapshot_t = std::string; + using read_storage_t = std::istringstream; + + struct writer : public writer_t { + writer( const std::shared_ptr& storage ) + :writer_t(*storage) + ,storage(storage) + { + + } + + std::shared_ptr storage; + }; + + struct reader : public reader_t { + explicit reader(const std::shared_ptr& storage) + :reader_t(*storage) + ,storage(storage) + {} + + std::shared_ptr storage; + }; + + + static auto get_writer() { + return std::make_shared(std::make_shared()); + } + + static auto finalize(const std::shared_ptr& w) { + w->finalize(); + return w->storage->str(); + } + + static auto get_reader( const snapshot_t& buffer) { + return std::make_shared(std::make_shared(buffer)); + } + + static snapshot_t load_from_file(const std::string& filename) { + snapshot_input_file file(filename); + return file.read_as_string(); + } + + static void write_to_file( const std::string& basename, const snapshot_t& snapshot ) { + snapshot_output_file file(basename); + file.write(snapshot); + } +}; + +using snapshot_suites = boost::mpl::list; diff --git a/unittests/snapshots.hpp.in b/unittests/snapshots.hpp.in index 762872b6ff..46f8944e48 100644 --- a/unittests/snapshots.hpp.in +++ b/unittests/snapshots.hpp.in @@ -19,10 +19,12 @@ namespace eosio { // tags for snapshot type struct json {}; struct binary {}; + struct json_snapshot{}; } // ns eosio::testing::snapshot static inline constexpr snapshot::json json_tag; static inline constexpr snapshot::binary binary_tag; + static inline constexpr snapshot::json_snapshot json_snapshot_tag; namespace snapshot { template @@ -30,6 +32,9 @@ namespace eosio { template static inline constexpr bool is_binary_v =std::is_same_v, snapshot::binary>; + + template + static inline constexpr bool is_json_snapshot_v =std::is_same_v, snapshot::json_snapshot>; } // ns eosio::testing::snapshot template @@ -38,8 +43,10 @@ namespace eosio { static inline constexpr auto file_suffix() { if constexpr (snapshot::is_json_v) return ".json.gz"; - else + else if constexpr (snapshot::is_binary_v) return ".bin.gz"; + else + return ".bin.json.gz"; } std::string file_name; @@ -67,8 +74,10 @@ namespace eosio { auto read() const { if constexpr (snapshot::is_json_v) { return fc::json::from_string(read_as_string()); + } else if constexpr (snapshot::is_binary_v) { + return fc::json::from_string(read_as_string()); } else { - static_assert(snapshot::is_binary_v, "unsupported type"); + static_assert(snapshot::is_json_snapshot_v, "unsupported type"); return fc::json::from_string(read_as_string()); } } @@ -85,8 +94,12 @@ namespace eosio { if constexpr (snapshot::is_json_v) { out_string = fc::json::to_string(snapshot, fc::time_point::maximum()); + } else if constexpr (snapshot::is_binary_v) { + std::ostringstream out_stream; + out_stream.write(snapshot.data(), snapshot.size()); + out_string = out_stream.str(); } else { - static_assert(snapshot::is_binary_v, "unsupported type"); + static_assert(snapshot::is_json_snapshot_v, "unsupported type"); std::ostringstream out_stream; out_stream.write(snapshot.data(), snapshot.size()); out_string = out_stream.str(); diff --git a/unittests/snapshots/CMakeLists.txt b/unittests/snapshots/CMakeLists.txt index 26912f3ff7..5b085b16b1 100644 --- a/unittests/snapshots/CMakeLists.txt +++ b/unittests/snapshots/CMakeLists.txt @@ -1,14 +1,20 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/blocks.log ${CMAKE_CURRENT_BINARY_DIR}/blocks.log COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v2.bin.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v2.bin.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v2.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v2.json.gz COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v2.bin.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v2.bin.json.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/prod_sched/blocks.log ${CMAKE_CURRENT_BINARY_DIR}/prod_sched/blocks.log COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v2_prod_sched.bin.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v2_prod_sched.bin.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v2_prod_sched.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v2_prod_sched.json.gz COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v2_prod_sched.bin.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v2_prod_sched.bin.json.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v3.bin.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v3.bin.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v3.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v3.json.gz COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v3.bin.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v3.bin.json.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v4.bin.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v4.bin.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v4.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v4.json.gz COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v4.bin.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v4.bin.json.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v5.bin.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v5.bin.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v5.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v5.json.gz COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v5.bin.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v5.bin.json.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v6.bin.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v6.bin.gz COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v6.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v6.json.gz COPYONLY ) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/snap_v6.bin.json.gz ${CMAKE_CURRENT_BINARY_DIR}/snap_v6.bin.json.gz COPYONLY ) diff --git a/unittests/snapshots/snap_v2.bin.json.gz b/unittests/snapshots/snap_v2.bin.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..26dc275e41a479e0b1e7ce7bd9bb88bff462bd65 GIT binary patch literal 196716 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 E0ea|CA^-pY literal 0 HcmV?d00001 diff --git a/unittests/snapshots/snap_v2_prod_sched.bin.json.gz b/unittests/snapshots/snap_v2_prod_sched.bin.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..caf2524c661137354b87b2a10c6086f2556632ac GIT binary patch literal 201819 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 literal 0 HcmV?d00001 diff --git a/unittests/snapshots/snap_v3.bin.json.gz b/unittests/snapshots/snap_v3.bin.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..9be784ea07b5a0e62136c57327669e65a8c97764 GIT binary patch literal 196716 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

KSa!X4myG1@c;@X(wz$3D{Sy=*8eU59q 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 E17rwM`v3p{ literal 0 HcmV?d00001 From 30c833f70175b4c50e4aeb6c298a413eb1134837 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 3 Aug 2022 18:41:42 -0500 Subject: [PATCH 007/111] change so json snapshot reader doesn't put entire stream in memory. merge snapshot and jsonsnapshot code handling --- .../chain/include/eosio/chain/snapshot.hpp | 4 +- libraries/chain/snapshot.cpp | 10 +-- .../include/eosio/testing/snapshot_suites.hpp | 16 ++-- plugins/chain_plugin/chain_plugin.cpp | 89 ++++++------------- 4 files changed, 43 insertions(+), 76 deletions(-) diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index 55c81a7ca0..d3d85cd7ff 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -375,7 +375,7 @@ namespace eosio { namespace chain { class istream_json_snapshot_reader : public snapshot_reader { public: - explicit istream_json_snapshot_reader(std::istream& snapshot); + explicit istream_json_snapshot_reader(const fc::path& p); void validate() const override; void set_section( const string& section_name ) override; @@ -387,8 +387,6 @@ namespace eosio { namespace chain { private: bool validate_section() const; - std::istream& snapshot; - std::streampos header_pos; uint64_t num_rows; uint64_t cur_row; fc::variant_object var_obj; diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 28302d096b..e6e088aae0 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -337,15 +337,11 @@ void istream_snapshot_reader::return_to_header() { clear_section(); } -istream_json_snapshot_reader::istream_json_snapshot_reader(std::istream& snapshot) - :snapshot(snapshot) - ,header_pos(snapshot.tellg()) - ,num_rows(0) +istream_json_snapshot_reader::istream_json_snapshot_reader(const fc::path& p) + :num_rows(0) ,cur_row(0) { - std::stringstream my_buffer; - my_buffer << snapshot.rdbuf(); - auto var = fc::json::from_string(my_buffer.str(), fc::json::parse_type::relaxed_parser); + auto var = fc::json::from_file(p, fc::json::parse_type::relaxed_parser); if (var.is_object()) { var_obj = var.get_object(); } diff --git a/libraries/testing/include/eosio/testing/snapshot_suites.hpp b/libraries/testing/include/eosio/testing/snapshot_suites.hpp index 6b941cb4f5..ba3ea691de 100644 --- a/libraries/testing/include/eosio/testing/snapshot_suites.hpp +++ b/libraries/testing/include/eosio/testing/snapshot_suites.hpp @@ -126,12 +126,12 @@ struct json_snapshot_suite { }; struct reader : public reader_t { - explicit reader(const std::shared_ptr& storage) - :reader_t(*storage) - ,storage(storage) + explicit reader(const fc::path& p) + :reader_t(p) {} - - std::shared_ptr storage; + ~reader() { + remove("temp.bin.json"); + } }; @@ -145,7 +145,11 @@ struct json_snapshot_suite { } static auto get_reader( const snapshot_t& buffer) { - return std::make_shared(std::make_shared(buffer)); + std::ofstream fs("temp.bin.json"); + fs << buffer; + fs.close(); + fc::path p("temp.bin.json"); + return std::make_shared(p); } static snapshot_t load_from_file(const std::string& filename) { diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 4a19dc49f9..84d6dbfc96 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -943,76 +943,47 @@ void chain_plugin::plugin_initialize(const variables_map& options) { wlog( "The --truncate-at-block option can only be used with --hard-replay-blockchain." ); } - if (options.count( "snapshot" )) { - my->snapshot_path = options.at( "snapshot" ).as(); - EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception, - "Cannot load snapshot, ${name} does not exist", ("name", my->snapshot_path->generic_string()) ); - - // recover genesis information from the snapshot - // used for validation code below - auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); - istream_snapshot_reader reader(infile); - reader.validate(); - chain_id = controller::extract_chain_id(reader); - infile.close(); - - EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, - plugin_config_exception, - "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information"); - EOS_ASSERT( options.count( "genesis-json" ) == 0, - plugin_config_exception, - "--snapshot is incompatible with --genesis-json as the snapshot contains genesis information"); - - auto shared_mem_path = my->chain_config->state_dir / "shared_memory.bin"; - EOS_ASSERT( !fc::is_regular_file(shared_mem_path), - plugin_config_exception, - "Snapshot can only be used to initialize an empty database." ); - - if( fc::is_regular_file( my->blocks_dir / "blocks.log" )) { - auto block_log_genesis = block_log::extract_genesis_state(my->blocks_dir); - if( block_log_genesis ) { - const auto& block_log_chain_id = block_log_genesis->compute_chain_id(); - EOS_ASSERT( *chain_id == block_log_chain_id, - plugin_config_exception, - "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID from the genesis state in the block log (${block_log_chain_id})", - ("snapshot_chain_id", *chain_id) - ("block_log_chain_id", block_log_chain_id) - ); - } else { - const auto& block_log_chain_id = block_log::extract_chain_id(my->blocks_dir); - EOS_ASSERT( *chain_id == block_log_chain_id, - plugin_config_exception, - "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID (${block_log_chain_id}) in the block log", - ("snapshot_chain_id", *chain_id) - ("block_log_chain_id", block_log_chain_id) - ); - } + if (options.count( "snapshot" ) || options.count( "json-snapshot")) { + bfs::path snap_path; + std::string command; + bool is_json_snapshot = false; + if (options.count( "snapshot" )) { + snap_path = options.at( "snapshot" ).as(); + my->snapshot_path = snap_path; + command = "--snapshot"; + } else { + snap_path = options.at( "json-snapshot" ).as(); + is_json_snapshot = true; + my->json_snapshot_path = snap_path; + command = "--json-snapshot"; } - - } else if (options.count( "json-snapshot" )) { - my->json_snapshot_path = options.at( "json-snapshot" ).as(); - EOS_ASSERT( fc::exists(*my->json_snapshot_path), plugin_config_exception, - "Cannot load snapshot, ${name} does not exist", ("name", my->json_snapshot_path->generic_string()) ); + EOS_ASSERT( fc::exists(snap_path), plugin_config_exception, + "Cannot load snapshot, ${name} does not exist", ("name", snap_path.generic_string()) ); // recover genesis information from the snapshot // used for validation code below - auto infile = std::ifstream(my->json_snapshot_path->generic_string(), (std::ios::in)); - istream_json_snapshot_reader reader(infile); - reader.validate(); - chain_id = controller::extract_chain_id(reader); + auto infile = std::ifstream(snap_path.generic_string(), (std::ios::in | std::ios::binary)); + shared_ptr reader_ptr; + if (is_json_snapshot) { + reader_ptr = shared_ptr(new istream_json_snapshot_reader(snap_path)); + } else { + reader_ptr = shared_ptr(new istream_snapshot_reader(infile)); + } + reader_ptr->validate(); + chain_id = controller::extract_chain_id(*reader_ptr); infile.close(); EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, - plugin_config_exception, - "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information"); + plugin_config_exception, + command + " is incompatible with --genesis-timestamp as the snapshot contains genesis information"); EOS_ASSERT( options.count( "genesis-json" ) == 0, plugin_config_exception, - "--snapshot is incompatible with --genesis-json as the snapshot contains genesis information"); + command + " is incompatible with --genesis-json as the snapshot contains genesis information"); auto shared_mem_path = my->chain_config->state_dir / "shared_memory.bin"; EOS_ASSERT( !fc::is_regular_file(shared_mem_path), plugin_config_exception, - "Snapshot can only be used to initialize an empty database." ); + "A snapshot can only be used to initialize an empty database." ); if( fc::is_regular_file( my->blocks_dir / "blocks.log" )) { auto block_log_genesis = block_log::extract_genesis_state(my->blocks_dir); @@ -1358,10 +1329,8 @@ void chain_plugin::plugin_startup() my->chain->startup(shutdown, check_shutdown, reader); infile.close(); } else if (my->json_snapshot_path) { - auto infile = std::ifstream(my->json_snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); - auto reader = std::make_shared(infile); + auto reader = std::make_shared(fc::path(*my->json_snapshot_path)); my->chain->startup(shutdown, check_shutdown, reader); - infile.close(); } else if( my->genesis ) { my->chain->startup(shutdown, check_shutdown, *my->genesis); } else { From aff122104efe1f477b3012f1fc2c00c6b1452010 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 10 Aug 2022 13:28:56 -0500 Subject: [PATCH 008/111] switch over to rapidjson from fc::json for the json snapshot reader. --- .gitmodules | 5 +- libraries/CMakeLists.txt | 1 + .../chain/include/eosio/chain/snapshot.hpp | 10 ++-- libraries/chain/snapshot.cpp | 46 +++++++++++-------- libraries/rapidjson | 1 + 5 files changed, 38 insertions(+), 25 deletions(-) create mode 160000 libraries/rapidjson diff --git a/.gitmodules b/.gitmodules index ffb4b09dc5..87e73e052d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,9 +18,12 @@ [submodule "libraries/eos-vm"] path = libraries/eos-vm url = https://github.com/eosnetworkfoundation/mandel-eos-vm +[submodule "libraries/rapidjson"] + path = libraries/rapidjson + url = https://github.com/Tencent/rapidjson/ [submodule "eosio-wasm-spec-tests"] path = eosio-wasm-spec-tests url = https://github.com/eosnetworkfoundation/mandel-wasm-spec-tests [submodule "tests/abieos"] path = tests/abieos - url = https://github.com/eosnetworkfoundation/mandel-abieos + url = https://github.com/eosnetworkfoundation/mandel-abieos \ No newline at end of file diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 9598cd4d1f..3288d2e511 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory( chain ) add_subdirectory( testing ) add_subdirectory( version ) add_subdirectory( state_history ) +add_subdirectory( rapidjson ) set(USE_EXISTING_SOFTFLOAT ON CACHE BOOL "use pre-exisiting softfloat lib") set(ENABLE_TOOLS OFF CACHE BOOL "Build tools") diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index d3d85cd7ff..4764ebc55f 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -5,8 +5,10 @@ #include #include #include +#include "../rapidjson/include/rapidjson/document.h" namespace eosio { namespace chain { + /** * History: * Version 1: initial version with string identified sections and rows @@ -387,10 +389,10 @@ namespace eosio { namespace chain { private: bool validate_section() const; - uint64_t num_rows; - uint64_t cur_row; - fc::variant_object var_obj; - fc::variant_object cur_section; + uint64_t num_rows; + uint64_t cur_row; + rapidjson::Document doc; + std::string sec_name; }; class integrity_hash_snapshot_writer : public snapshot_writer { diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index e6e088aae0..8e22e4fe17 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -2,7 +2,9 @@ #include #include #include - +#include "../rapidjson/include/rapidjson/filereadstream.h" +#include "../rapidjson/include/rapidjson/stringbuffer.h" +#include "../rapidjson/include/rapidjson/writer.h" namespace eosio { namespace chain { variant_snapshot_writer::variant_snapshot_writer(fc::mutable_variant_object& snapshot) @@ -341,10 +343,12 @@ istream_json_snapshot_reader::istream_json_snapshot_reader(const fc::path& p) :num_rows(0) ,cur_row(0) { - auto var = fc::json::from_file(p, fc::json::parse_type::relaxed_parser); - if (var.is_object()) { - var_obj = var.get_object(); - } + // rapidjson::FileReadStream s(p.string().c_str()); + FILE* fp = fopen(p.string().c_str(), "rb"); + char readBuffer[65536]; + rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + doc.ParseStream(is); + fclose(fp); } void istream_json_snapshot_reader::validate() const { @@ -352,22 +356,20 @@ void istream_json_snapshot_reader::validate() const { // validate totem auto expected_totem = ostream_json_snapshot_writer::magic_number; decltype(expected_totem) actual_totem; - if (var_obj.contains("magic_number")) { - auto magic_num = var_obj["magic_number"]; - from_variant(magic_num, actual_totem); + if (doc.HasMember("magic_number")) { + actual_totem = doc["magic_number"].GetInt(); EOS_ASSERT(actual_totem == expected_totem, snapshot_exception, - "JSON snapshot has unexpected magic number!"); + "JSON snapshot has unexpected magic number!"); } // validate version auto expected_version = current_snapshot_version; decltype(expected_version) actual_version; - if (var_obj.contains("version")) { - auto version_num = var_obj["version"]; - from_variant(version_num, actual_version); - EOS_ASSERT(actual_version == expected_version, snapshot_exception, - "JSON snapshot is an unsuppored version. Expected : ${expected}, Got: ${actual}", - ("expected", expected_version)("actual", actual_version)); + if (doc.HasMember("version")) { + actual_version = doc["version"].GetInt(); + EOS_ASSERT(actual_version == expected_version, snapshot_exception, + "JSON snapshot is an unsuppored version. Expected : ${expected}, Got: ${actual}", + ("expected", expected_version)("actual", actual_version)); } } catch( const std::exception& e ) { \ snapshot_exception fce(FC_LOG_MESSAGE( warn, "JSON snapshot validation threw IO exception (${what})",("what",e.what()))); @@ -380,10 +382,10 @@ bool istream_json_snapshot_reader::validate_section() const { } void istream_json_snapshot_reader::set_section( const string& section_name ) { - if (var_obj.contains(section_name.c_str())) { - cur_section = var_obj[section_name.c_str()].get_object(); + if (doc.HasMember(section_name.c_str())) { + sec_name = section_name.c_str(); cur_row = 0; - num_rows = cur_section.size(); + num_rows = doc[section_name.c_str()].Size(); } else { EOS_THROW(snapshot_exception, "JSON snapshot has no section named ${n}", ("n", section_name)); } @@ -391,7 +393,11 @@ void istream_json_snapshot_reader::set_section( const string& section_name ) { bool istream_json_snapshot_reader::read_row( detail::abstract_snapshot_row_reader& row_reader ) { std::string row_name = "row_" + std::to_string(cur_row); - row_reader.provide(cur_section[row_name.c_str()]); + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + doc[sec_name.c_str()][row_name.c_str()].Accept(writer); + const auto& row = fc::json::from_string(buffer.GetString()); + row_reader.provide(row); return ++cur_row < num_rows; } @@ -402,7 +408,7 @@ bool istream_json_snapshot_reader::empty ( ) { void istream_json_snapshot_reader::clear_section() { num_rows = 0; cur_row = 0; - cur_section = fc::variant_object(); + sec_name = ""; } void istream_json_snapshot_reader::return_to_header() { diff --git a/libraries/rapidjson b/libraries/rapidjson new file mode 160000 index 0000000000..27c3a8dc0e --- /dev/null +++ b/libraries/rapidjson @@ -0,0 +1 @@ +Subproject commit 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d From ea5ce7cc6d041101ea3084884400da522901a939 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 10 Aug 2022 13:35:09 -0500 Subject: [PATCH 009/111] cleanup comment and newlines. --- .gitmodules | 2 +- libraries/chain/include/eosio/chain/snapshot.hpp | 1 - libraries/chain/snapshot.cpp | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 87e73e052d..e14b6bafaf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -26,4 +26,4 @@ url = https://github.com/eosnetworkfoundation/mandel-wasm-spec-tests [submodule "tests/abieos"] path = tests/abieos - url = https://github.com/eosnetworkfoundation/mandel-abieos \ No newline at end of file + url = https://github.com/eosnetworkfoundation/mandel-abieos diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index 4764ebc55f..f057769ae0 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -8,7 +8,6 @@ #include "../rapidjson/include/rapidjson/document.h" namespace eosio { namespace chain { - /** * History: * Version 1: initial version with string identified sections and rows diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 8e22e4fe17..0afd775c2c 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -343,7 +343,6 @@ istream_json_snapshot_reader::istream_json_snapshot_reader(const fc::path& p) :num_rows(0) ,cur_row(0) { - // rapidjson::FileReadStream s(p.string().c_str()); FILE* fp = fopen(p.string().c_str(), "rb"); char readBuffer[65536]; rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); From 2520099f7f4d1cc473d593bbba349fd477ae2745 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 12 Aug 2022 15:28:59 -0500 Subject: [PATCH 010/111] GH-771 Modify --snapshot option to determine json by extension instead of adding a new option. Improved memory usage so current WAX snapshot can be supported. Modified the JSON output so that table rows are an array which reduces file size and memory usage. Put rapidjson inside an eosio_rapidjson namespace to avoid ODR issues. Change CMakeLists to not compile rapidjson but only include it as it is a header only library. --- libraries/CMakeLists.txt | 1 - libraries/chain/CMakeLists.txt | 1 + .../chain/include/eosio/chain/snapshot.hpp | 8 +- libraries/chain/snapshot.cpp | 100 ++++++++++-------- plugins/chain_plugin/chain_plugin.cpp | 76 ++++++------- 5 files changed, 92 insertions(+), 94 deletions(-) diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 3288d2e511..9598cd4d1f 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -20,7 +20,6 @@ add_subdirectory( chain ) add_subdirectory( testing ) add_subdirectory( version ) add_subdirectory( state_history ) -add_subdirectory( rapidjson ) set(USE_EXISTING_SOFTFLOAT ON CACHE BOOL "use pre-exisiting softfloat lib") set(ENABLE_TOOLS OFF CACHE BOOL "Build tools") diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 4a05f74d1e..c59b97c28e 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -131,6 +131,7 @@ target_link_libraries( eosio_chain PUBLIC fc chainbase Logging IR WAST WASM Runt target_include_directories( eosio_chain PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include" + "${CMAKE_CURRENT_SOURCE_DIR}/../rapidjson/include" ) add_library(eosio_chain_wrap INTERFACE ) diff --git a/libraries/chain/include/eosio/chain/snapshot.hpp b/libraries/chain/include/eosio/chain/snapshot.hpp index f057769ae0..b4e8fb1a61 100644 --- a/libraries/chain/include/eosio/chain/snapshot.hpp +++ b/libraries/chain/include/eosio/chain/snapshot.hpp @@ -5,7 +5,7 @@ #include #include #include -#include "../rapidjson/include/rapidjson/document.h" +#include namespace eosio { namespace chain { /** @@ -377,6 +377,7 @@ namespace eosio { namespace chain { class istream_json_snapshot_reader : public snapshot_reader { public: explicit istream_json_snapshot_reader(const fc::path& p); + ~istream_json_snapshot_reader(); void validate() const override; void set_section( const string& section_name ) override; @@ -388,10 +389,7 @@ namespace eosio { namespace chain { private: bool validate_section() const; - uint64_t num_rows; - uint64_t cur_row; - rapidjson::Document doc; - std::string sec_name; + std::unique_ptr impl; }; class integrity_hash_snapshot_writer : public snapshot_writer { diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 0afd775c2c..3d87afdb81 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -2,9 +2,15 @@ #include #include #include -#include "../rapidjson/include/rapidjson/filereadstream.h" -#include "../rapidjson/include/rapidjson/stringbuffer.h" -#include "../rapidjson/include/rapidjson/writer.h" + +#define RAPIDJSON_NAMESPACE eosio_rapidjson +#include +#include +#include +#include + +using namespace eosio_rapidjson; + namespace eosio { namespace chain { variant_snapshot_writer::variant_snapshot_writer(fc::mutable_variant_object& snapshot) @@ -199,19 +205,19 @@ ostream_json_snapshot_writer::ostream_json_snapshot_writer(std::ostream& snapsho void ostream_json_snapshot_writer::write_start_section( const std::string& section_name ) { row_count = 0; - snapshot.inner << "," << fc::json::to_string(section_name, fc::time_point::maximum()) << ":{\n"; + snapshot.inner << "," << fc::json::to_string(section_name, fc::time_point::maximum()) << ":{\n\"rows\":[\n"; } void ostream_json_snapshot_writer::write_row( const detail::abstract_snapshot_row_writer& row_writer ) { const auto yield = [&](size_t s) {}; if(row_count != 0) snapshot.inner << ","; - snapshot.inner << "\"row_" << row_count << "\":" << fc::json::to_string(row_writer.to_variant(), yield) << "\n"; + snapshot.inner << fc::json::to_string(row_writer.to_variant(), yield) << "\n"; ++row_count; } void ostream_json_snapshot_writer::write_end_section( ) { - snapshot.inner << "}\n"; + snapshot.inner << "],\n\"num_rows\":" << row_count << "\n}\n"; row_count = 0; } @@ -339,37 +345,42 @@ void istream_snapshot_reader::return_to_header() { clear_section(); } +struct istream_json_snapshot_reader_impl { + uint64_t num_rows; + uint64_t cur_row; + eosio_rapidjson::Document doc; + std::string sec_name; +}; + +istream_json_snapshot_reader::~istream_json_snapshot_reader() = default; + istream_json_snapshot_reader::istream_json_snapshot_reader(const fc::path& p) - :num_rows(0) - ,cur_row(0) + : impl{new istream_json_snapshot_reader_impl{0, 0, {}, {}}} { FILE* fp = fopen(p.string().c_str(), "rb"); + EOS_ASSERT(fp, snapshot_exception, "Failed to JSON snapshot: ${file}", ("file", p)); + auto close = fc::make_scoped_exit( [&fp]() { fclose( fp ); } ); char readBuffer[65536]; - rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); - doc.ParseStream(is); - fclose(fp); + eosio_rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + impl->doc.ParseStream(is); } void istream_json_snapshot_reader::validate() const { try { // validate totem auto expected_totem = ostream_json_snapshot_writer::magic_number; - decltype(expected_totem) actual_totem; - if (doc.HasMember("magic_number")) { - actual_totem = doc["magic_number"].GetInt(); - EOS_ASSERT(actual_totem == expected_totem, snapshot_exception, - "JSON snapshot has unexpected magic number!"); - } + EOS_ASSERT(impl->doc.HasMember("magic_number"), snapshot_exception, "magic_number section not found" ); + auto actual_totem = impl->doc["magic_number"].GetInt(); + EOS_ASSERT( actual_totem == expected_totem, snapshot_exception, "JSON snapshot has unexpected magic number" ); // validate version auto expected_version = current_snapshot_version; - decltype(expected_version) actual_version; - if (doc.HasMember("version")) { - actual_version = doc["version"].GetInt(); - EOS_ASSERT(actual_version == expected_version, snapshot_exception, - "JSON snapshot is an unsuppored version. Expected : ${expected}, Got: ${actual}", - ("expected", expected_version)("actual", actual_version)); - } + EOS_ASSERT(impl->doc.HasMember("version"), snapshot_exception, "version section not found" ); + auto actual_version = impl->doc["version"].GetInt(); + EOS_ASSERT( actual_version == expected_version, snapshot_exception, + "JSON snapshot is an unsupported version. Expected : ${expected}, Got: ${actual}", + ("expected", expected_version)( "actual", actual_version ) ); + } catch( const std::exception& e ) { \ snapshot_exception fce(FC_LOG_MESSAGE( warn, "JSON snapshot validation threw IO exception (${what})",("what",e.what()))); throw fce; @@ -381,33 +392,38 @@ bool istream_json_snapshot_reader::validate_section() const { } void istream_json_snapshot_reader::set_section( const string& section_name ) { - if (doc.HasMember(section_name.c_str())) { - sec_name = section_name.c_str(); - cur_row = 0; - num_rows = doc[section_name.c_str()].Size(); - } else { - EOS_THROW(snapshot_exception, "JSON snapshot has no section named ${n}", ("n", section_name)); - } + EOS_ASSERT( impl->doc.HasMember( section_name.c_str() ), snapshot_exception, "JSON snapshot has no section ${sec}", ("sec", section_name) ); + EOS_ASSERT( impl->doc[section_name.c_str()].HasMember( "num_rows" ), snapshot_exception, "JSON snapshot ${sec} num_rows not found", ("sec", section_name) ); + EOS_ASSERT( impl->doc[section_name.c_str()].HasMember( "rows" ), snapshot_exception, "JSON snapshot ${sec} rows not found", ("sec", section_name) ); + EOS_ASSERT( impl->doc[section_name.c_str()]["rows"].IsArray(), snapshot_exception, "JSON snapshot ${sec} rows is not an array", ("sec_name", section_name) ); + + impl->sec_name = section_name; + impl->num_rows = impl->doc[section_name.c_str()]["num_rows"].GetInt(); + ilog( "reading ${section_name}, num_rows: ${num_rows}", ("section_name", section_name)( "num_rows", impl->num_rows ) ); } bool istream_json_snapshot_reader::read_row( detail::abstract_snapshot_row_reader& row_reader ) { - std::string row_name = "row_" + std::to_string(cur_row); - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - doc[sec_name.c_str()][row_name.c_str()].Accept(writer); - const auto& row = fc::json::from_string(buffer.GetString()); - row_reader.provide(row); - return ++cur_row < num_rows; + EOS_ASSERT( impl->cur_row < impl->num_rows, snapshot_exception, "JSON snapshot ${sect}'s cur_row ${cur_row} >= num_rows ${num_rows}", + ("sect_name", impl->sec_name)( "cur_row", impl->cur_row )( "num_rows", impl->num_rows ) ); + + const eosio_rapidjson::Value& rows = impl->doc[impl->sec_name.c_str()]["rows"]; + eosio_rapidjson::StringBuffer buffer; + eosio_rapidjson::Writer writer( buffer ); + rows[impl->cur_row].Accept( writer ); + + const auto& row = fc::json::from_string( buffer.GetString() ); + row_reader.provide( row ); + return ++impl->cur_row < impl->num_rows; } bool istream_json_snapshot_reader::empty ( ) { - return num_rows == 0; + return impl->num_rows == 0; } void istream_json_snapshot_reader::clear_section() { - num_rows = 0; - cur_row = 0; - sec_name = ""; + impl->num_rows = 0; + impl->cur_row = 0; + impl->sec_name = ""; } void istream_json_snapshot_reader::return_to_header() { diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 84d6dbfc96..cf6e40db50 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -161,7 +161,7 @@ class chain_plugin_impl { std::optional wasm_runtime; fc::microseconds abi_serializer_max_time_us; std::optional snapshot_path; - std::optional json_snapshot_path; + snapshot_reader_ptr snapshot_json_reader_ptr; // retained references to channels for easy publication @@ -377,8 +377,7 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "stop hard replay / block log recovery at this block number (if set to non-zero number)") ("terminate-at-block", bpo::value()->default_value(0), "terminate after reaching this block number (if set to a non-zero number)") - ("snapshot", bpo::value(), "File to read Snapshot State from") - ("json-snapshot", bpo::value(), "JSON File to read Snapshot State from") + ("snapshot", bpo::value(), "File to read snapshot state from, .json extension for JSON input.") ; } @@ -893,6 +892,7 @@ void chain_plugin::plugin_initialize(const variables_map& options) { my->chain->add_indices(); my->chain->startup(shutdown, check_shutdown, reader); infile.close(); + EOS_ASSERT( !app().is_quiting(), snapshot_exception, "Loading of snapshot failed" ); app().quit(); // shutdown as we will be finished after writing the snapshot ilog("Writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json")); @@ -943,62 +943,45 @@ void chain_plugin::plugin_initialize(const variables_map& options) { wlog( "The --truncate-at-block option can only be used with --hard-replay-blockchain." ); } - if (options.count( "snapshot" ) || options.count( "json-snapshot")) { - bfs::path snap_path; - std::string command; - bool is_json_snapshot = false; - if (options.count( "snapshot" )) { - snap_path = options.at( "snapshot" ).as(); - my->snapshot_path = snap_path; - command = "--snapshot"; - } else { - snap_path = options.at( "json-snapshot" ).as(); - is_json_snapshot = true; - my->json_snapshot_path = snap_path; - command = "--json-snapshot"; - } + if (options.count( "snapshot" )) { + bfs::path snap_path = options.at( "snapshot" ).as(); EOS_ASSERT( fc::exists(snap_path), plugin_config_exception, "Cannot load snapshot, ${name} does not exist", ("name", snap_path.generic_string()) ); + my->snapshot_path = snap_path; - // recover genesis information from the snapshot - // used for validation code below - auto infile = std::ifstream(snap_path.generic_string(), (std::ios::in | std::ios::binary)); - shared_ptr reader_ptr; - if (is_json_snapshot) { - reader_ptr = shared_ptr(new istream_json_snapshot_reader(snap_path)); + if( my->snapshot_path->extension().generic_string().compare( ".json" ) == 0 ) { + ilog("Reading JSON snapshot, this may take a significant amount of time."); + my->snapshot_json_reader_ptr.reset( new istream_json_snapshot_reader(snap_path) ); + my->snapshot_json_reader_ptr->validate(); + chain_id = controller::extract_chain_id(*my->snapshot_json_reader_ptr); } else { - reader_ptr = shared_ptr(new istream_snapshot_reader(infile)); + std::ifstream infile = std::ifstream(snap_path.generic_string(), (std::ios::in | std::ios::binary)); + istream_snapshot_reader reader(infile); + reader.validate(); + chain_id = controller::extract_chain_id(reader); } - reader_ptr->validate(); - chain_id = controller::extract_chain_id(*reader_ptr); - infile.close(); - EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, - plugin_config_exception, - command + " is incompatible with --genesis-timestamp as the snapshot contains genesis information"); - EOS_ASSERT( options.count( "genesis-json" ) == 0, - plugin_config_exception, - command + " is incompatible with --genesis-json as the snapshot contains genesis information"); + EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, plugin_config_exception, + "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information"); + EOS_ASSERT( options.count( "genesis-json" ) == 0, plugin_config_exception, + "--snapshot is incompatible with --genesis-json as the snapshot contains genesis information"); auto shared_mem_path = my->chain_config->state_dir / "shared_memory.bin"; - EOS_ASSERT( !fc::is_regular_file(shared_mem_path), - plugin_config_exception, + EOS_ASSERT( !fc::is_regular_file(shared_mem_path), plugin_config_exception, "A snapshot can only be used to initialize an empty database." ); if( fc::is_regular_file( my->blocks_dir / "blocks.log" )) { auto block_log_genesis = block_log::extract_genesis_state(my->blocks_dir); if( block_log_genesis ) { const auto& block_log_chain_id = block_log_genesis->compute_chain_id(); - EOS_ASSERT( *chain_id == block_log_chain_id, - plugin_config_exception, + EOS_ASSERT( *chain_id == block_log_chain_id, plugin_config_exception, "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID from the genesis state in the block log (${block_log_chain_id})", ("snapshot_chain_id", *chain_id) ("block_log_chain_id", block_log_chain_id) ); } else { const auto& block_log_chain_id = block_log::extract_chain_id(my->blocks_dir); - EOS_ASSERT( *chain_id == block_log_chain_id, - plugin_config_exception, + EOS_ASSERT( *chain_id == block_log_chain_id, plugin_config_exception, "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID (${block_log_chain_id}) in the block log", ("snapshot_chain_id", *chain_id) ("block_log_chain_id", block_log_chain_id) @@ -1324,13 +1307,14 @@ void chain_plugin::plugin_startup() auto shutdown = [](){ return app().quit(); }; auto check_shutdown = [](){ return app().is_quiting(); }; if (my->snapshot_path) { - auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); - auto reader = std::make_shared(infile); - my->chain->startup(shutdown, check_shutdown, reader); - infile.close(); - } else if (my->json_snapshot_path) { - auto reader = std::make_shared(fc::path(*my->json_snapshot_path)); - my->chain->startup(shutdown, check_shutdown, reader); + if( my->snapshot_json_reader_ptr ) { + my->chain->startup(shutdown, check_shutdown, my->snapshot_json_reader_ptr); + my->snapshot_json_reader_ptr.reset(); + } else { + auto infile = std::ifstream( my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary) ); + auto reader = std::make_shared( infile ); + my->chain->startup( shutdown, check_shutdown, reader ); + } } else if( my->genesis ) { my->chain->startup(shutdown, check_shutdown, *my->genesis); } else { From c54d0c27164f27bf23d8fb8cc3d5b607d6632df7 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Fri, 19 Aug 2022 13:08:40 -0500 Subject: [PATCH 011/111] update save json for snapshot test due to design change. --- unittests/snapshots/snap_v2.bin.json.gz | Bin 196716 -> 29241 bytes .../snapshots/snap_v2_prod_sched.bin.json.gz | Bin 201819 -> 35481 bytes unittests/snapshots/snap_v3.bin.json.gz | Bin 196716 -> 29241 bytes unittests/snapshots/snap_v4.bin.json.gz | Bin 196716 -> 29241 bytes unittests/snapshots/snap_v5.bin.json.gz | Bin 196716 -> 29241 bytes unittests/snapshots/snap_v6.bin.json.gz | Bin 196716 -> 29241 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/unittests/snapshots/snap_v2.bin.json.gz b/unittests/snapshots/snap_v2.bin.json.gz index 26dc275e41a479e0b1e7ce7bd9bb88bff462bd65..58d3177bb7f035412f535913e7707142027e2320 100644 GIT binary patch literal 29241 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 E0ea|CA^-pY diff --git a/unittests/snapshots/snap_v2_prod_sched.bin.json.gz b/unittests/snapshots/snap_v2_prod_sched.bin.json.gz index caf2524c661137354b87b2a10c6086f2556632ac..3148748dd96fcf7faf4b00c98d5ed1a260fab0ff 100644 GIT binary patch literal 35481 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%0D~jA8PoN4a68duJb3s)5cJwD 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 J0n)m*Q2-&nSDpX> literal 201819 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 diff --git a/unittests/snapshots/snap_v3.bin.json.gz b/unittests/snapshots/snap_v3.bin.json.gz index 9be784ea07b5a0e62136c57327669e65a8c97764..fe9f2c09d3e24f5641b89c6d67a4258ec7ba7d29 100644 GIT binary patch literal 29241 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 aS9`I(m*N#gCMi^YdG|$iY(%izfBp~H+HHLR literal 196716 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 DeZ^8I diff --git a/unittests/snapshots/snap_v4.bin.json.gz b/unittests/snapshots/snap_v4.bin.json.gz index bb21c1ec57c191cbab53336fa80237f9a55c33f0..92cfe77eee143ed4808ae02098cbab6b656a0b51 100644 GIT binary patch literal 29241 zcmeI*`Bzf;A29Imcb1y(v^dRFmg|(2yJTAC$~0xRsiTG~LTT;`;VuZwj8i&pG^1uN z$f&8glDmk?lnW^;sVORgDS`_EDFQAmPtSkxJm+xEy`Ou3y62wv{oMEKeeONy{n5?* z<{Q+;Uci68jE#Qy7@A;d77!L~79I6AXsvBE z^G}HILKd%H{PkYG(NBK=-gVwiT*w6<|FFIm5*(;^MY3RV?CZiI>`33xSK~n7hcA!< z;^f8uX*D&XEJ2lx(;$E4V-O=fe%Z8d&M7~k|L=AnI!?V^or|e*3ni2fTq-sDW0W(F zLBDD!V7!uSV%0D@Y6PY1lYISpwu|{__>>xuc7p=#B1{^z2f~*gU5<<6S0sSgbwQT? z4F%gypK3ZFncH?bfU2;*JEX+gSyFZgNmnr>lhq%{r5-|Py(qgQ}5{M7lXz2?}J=!IgP3;7{hV28Wo7IEd zq5V0sym`0D??c+#+oeUfljPg4U`P06BjblV-e}|ueMRThR$3JJ{7!72d%siv=CBv2Gr}e~ z)hC1d%@e=&hD$vXdF}IXkHo@1;?NS&spnzcC3^|ST}5ALeA2}ne>mQYA-|tE}gnd&Lxk-j>n4Fr!qcTIE_RO zoV<4|$BljhRkb=2+Iht*l6t`w!gzSjBlNV(mxaDt-Pwf|FLJ_X=i9W#{2eMDJv?9) zcb&eLQWf^9i1Y1a+-Zx*DL3s#%_CKsPaleInidBIjkjvqRI;yjRapeDf90X${{8y% zinXIwPikobm{JH6LZWk>f?NJgLdFL0qUI+{NM&7zN@uNN|G84?1@4J_;?^TZfa<6LqUgYD4H8%9G2z77Wk5dy29%op@g0C0W%!hwyI2|!^ z&)I7rYy2y#yKZ|^%@X+vE#>sf^99sGEda9;Sm{mu#c^xq&=btN6Yse5xn9!}Y}4pE zIQw%>GG+_w!*=6g{ zG*nC?x-yDf*Llqr?z8_SQI^g2tGmr`?|;RCwg_S_Z8Z8veFyAG3AE}Q*=eQ^2Vq4Nacr!xGfV!vrftIHlqlzcJ0XmnqaGy~G& zEB;jUUY+}KG0Ip7qb7bC&k6U}$W#pQ4@<`0V{*;Q(N$5t*I2@2QM+T{DT}-DZ&`&? z>n{Tp=V+h|uS7cyg9OSPqhji8{7E(See3)AjN8=>S;#M4v-WyPVicS%#a-n4wO9+Q z%_E+qp1@(~I4P7;p(wwcaxp37Q-Y>M$}ZbXumcW6-5TqjB_2J{#n_a7fcWBTbT=P8 zh|=a#6=dh9uKrf1zS8sTU-$*by3uB+Us_7(xr3XYbA6hdAIcTOq_nZu4U^^$K1Tj4 z&mu?1bs%AfBkd3dbK>R%rm3#h+<+kA*)%44kC3|>5`{Ou zcU*kiK*vUW{vWi58J7-7=>p7o)C)7B5=jOzv!})S)kNQ}1A~mqdL0(Gnq}#`qy7=X z*S((;i9CIvcl9y>c9YX=d2lR-)BY}YnDjpjPnUl~u4tah!y1j^r@Y&ybH^hVdXO{s z1P1_l01GReF=}cpr2_mhYj{F7BwFN$31G~B5uCn8;Zs*Um2#(ePPJ9wIX`{N||bhnPkO~>NF2mL8#ZRunaBvO2p4s)ue z->bapGd!#D-n!qR${{kz0$rx)o$>XGFBMJ+%EcGxUupQ=*o{4NH2l)(O`kBCrPUq! z4c;B>V7rLCF&8J0)Mbr7YW?NH2eOI&(pG%p&7KqfY8cOY`_`&?a3=&;uJC2|+ArTN z#r8Dh(@*5|e2hn!!S&8h(V+|C5ZTzm1fo7W&7t8>N0ex9F9)#U zhTjVQ6q7Z24%nF3mE)jAujw6+lo$X`B8M|8`w|Eg_Wq@#Fe~j0wb9LPwd44KGfwk3 zOp`FJw=IyRQHes5h7>wWKUwdse)T2)BD5%Gls|!(?CnIaL-(B+LNBS2{YE3lKU$Fd+Jz26tbCbc)G4am5fg|t?ki6WHpC+qxoVm}A{ zw$?~F3Q@Q~jUjS77rWn)ZDX3-k{FR~zb`ouji*;q? zTX&ydLUz9C6FITOZF7iD>56_5bF|H#x(#@mCA0HZC!$C7bZyh)&LN#@XFR1s8gF!e*43MQqy%-{oL-**}dxfn+|JM z+HAU-!nW|%@%QRQcIM2T)eCWqsQNEm?G!@6 z-+P-grO^seZrX3VQ7yZzNeUYcaq^^og`de6d4JC4Yhw^eq0L@42P=8ANfQwO09u?| zsK|5;{w+N!gCzIU9iM*7yr;LRcdYC#=cdHB{(kw8mpVA_PTqDc=+MN4UHu0fT}1_? zQdr_{;lnX}>6@MC4(BpN1}H-7|Ef08`Qr3;EFQOjv(@kO8hc8RK~MK?!H$q$d{Qb0 zp}v)hm`@v#pVrqtPOX0=jzuw#jZBR`9W-@%`1CCf;Xl67<$?dRtFa1jDr970w9vFO z(BO#kinyzenBY&c+mS*o71JLvm^E+4mUyk`i`+(*`pIXtmEhN0#YB^Q`#jm3vQMph zzi9mH0+OCjcEIWLw%gBY9+a42RJR+X}L)^WpGyg zGkzv=r6Na&uSl8u*LBF5x>s|i>kkT=9{;f3l=U%ny;v4?cvF1PI z*_LSVs{%TfYa4F`v3zch}4)pUAsx3VPwf z4Ex5(Z9OCKkWrcx#@RIXoww32>OFt!r8l2rVvdN(TSxj~}!^P@er5-x?HFcYl3>iCK zSEga2=GgTOq~6EP{bo#gQSx1eG}CzOuy{q-{m!9V+m+nb-F;8K^)*s*{>cvY3gc^k zkA=Ib>?fOZhxBO9WKOY5)EK)EEDp2q-Dygkfv7X0UuT4vFqc_Xp{7=%14~YBc=VIE zyY*eV+L91fj!{p5tx*)k0y39#he5e=`_$%o^nIqO-rD~iHTLh?av^rM0!JOfMm}%p zj{oKyu5GO@7WX#k}4h+1^sRY#Aa z|CQanHWabNG+1!HL%(Q-he^UcBKZ1K*kOAnfzE!@Xt04xLx*SKrO%n+lpAomn-zZZ-IC=JFAecl<)L zxF+-$2#4l-?$MJl=o2TL>50n3<6VVUJ%*VzUi21Rp%*LHiqw}wNi?zu5)Gpf{o(wt zB?t`UTIR<~%he!7jPdkQW@_F2TNX9$k9QR9;La+?SUn@hV-3qwf6K}meOqnp4gE8Q zla>_&n_5O=6ummLET@xRgL;R?KJTuBdYQHCzs~EkhcdzCCB zf3D0gd#{+i^=jkMkN4fR51uGFtY>PiIgkg)-L68EZ7d}j<*%d~)dI5WU)3Ha7}#kB zy1_5KFYmOOE8l+fj3iAfi$YfU>h`qnlb5mcGg2YT!qd5T_-|sE)F{B zmmcXZU%lSZ-rXG+cpG>~e|+&fM3wJ_2rtDKdY=N4&GzPTEO6*#W(Fk0b~oEx_|Ws_ z8gVnl+|?2Bt}?AIC9sWlWy_?j;nuD6oNw6Mznx|Jru#RoXy|IPKT+J7D0)=n0m%!kP$HuW}_KeeppCHjQnk8XLE-b(dE z-%4L*cEtSIO!IdHttJ1+1WYM7Qw7dOUT2NpLI0QMVc3;4F48aP)1xl>oNwm{4`6}T z_0QjLROpZUily#r?Bn*8RJB9LoB@cB>6w_2}x7+w{ zY$_eYE_i|4YM<&^|s82zd9d9d}?z z%v|0pfIbaL9hw4==NFDP3J&z`4~eG;bc(LaQz-zwOCxu`g6%C}c4_MRc-V!G)HsKX zsYpvr<+OJ?P^gg&oxta-V~}vnKG94(w;tMR;|pu7KTY3;x*AyqrY1GCM;0C z9T(MV=^K_+beC6m=sRx(=8jiSXR4i_; zKTfs;`}*7Z=;BHm&9u~9Tnf}(bJV@C1)345akJr~N39Ov)0QWndmiLr6n`4uJ(SAb zn;V{+TOVE<4hTfW$J>|2Az~)H9jv2{o}7MOoIQ~HW^FDY79Jn;Fe*N*wW~FzyVuU! zU(>{r98ox++d90nyngQ6xJ!FtawwiqGpP1zQM|fLF)gN*91)C_dybo>RLDczg&5 z<=``y9-zSB2J#37&`7q!RUxgQr8!hMv8l8%b6*Ob7HoK5k>>6;qo>EHdtDWKGfVEx zjI~k&kA2H|aQjBVW_L<=J$@?L=eQp~Cb0pvjV8{rX1Y)5Y%ClGNL|&`B$}zOoW|!d zr*QFOYJh2Bj=Gb2A9d8VLP}jZI4a`0xV5f}IBDZ=xPhm#QwK&f`?!kH)fi=yL3>08 zNf|cNy%YC-BjxlJsjicw8)tv;Q1!vl3KBcG`WUz1%^N|G+jfX_!{zA7L=DQ~Xz5f9 zzAbk+CbkuxfcW4Kz1l5HF(;e(o?T!#ORoUNTy5OA+^wl=u~x&~$%(CGMbHO-jNQ7^ zS6iZjkm*k1u+&@2iw6QNMZdStR% z#_q*+NQzDGH|z&eld*-8m&oc}7P?=$@u~%#(AkOnfs=`d(@2w-djX}ZidFgBw8g>X z@%0s6B9=wKobHBVugvbo#J!%q8Y)P!Sr?pW=rSR=`{WeuXZw^~iC9^(96-L8&!6gM znE8rZkOvR(LY$b)!SOVHx&LyY?V4izTH&w_R_vn9D;5Sa?YgXc=k2wlBUxHxp-EAS@TBMgofGMhoc|`0M;St>BP4<)E#4#fM&eHO0{f)X+??bC4n% zVqoOhgqesFaw7%Hq{(D(ICNBUp=*Me7N`n z+$xc3G}cyrzoE~CVBp6#811B+=|nqhsN*2>9w+3ytL?F3fq*bNy>5A6ZzsBL{*bXh ziRnw6pFLFf!}Ny2tIjx6O_%1Xn>h`^bgW9*I}cx$jPn3>X@2stD3#!E_ND zR6FjPcjuqQGg3}d2<)V~P&Edlq5On-r(xB=%biP+iJ}$$z}aCsHrQ~CT}mm(@d}5@ zyNj#l!&)2@B-Nf2?ls!33{+`1C)u6nXMxoqlgXZQF;A;S#?p_A8hhKMN_}mYppD52pKRWs;b2Uo6(>N1J;!>$#v zTCG_88xC_u6PM0swCnEBUaJF|TRGXuQE89@#$#}yKC|-Tw`tbx(ZmjZ+@3O2@*+gF# zdk8k@wD4>{=DV`6lE@LpBjH6rfx9)eXUttbQl8aZP-6!-$?s{gjXG|Kc9V8u$P9sc zODr+Ve1ZS6^X9n>7bHT8)D#YssKtS?heBeJf_qpaIXnV00=W#_WLsLrg zh%CoA<&Xh^E;)kJyY}lof|Hp&is;k)iR?=sf*7W(IQ_7a?P52|2cSpfU~-m|wL2#1 z#LXtZ`R&2|WJT>#(%2f*-8!Zb3--qwb60d$Rua~GPoO?t#N8#vUD3@$(pE;~1a5u| zKwMM2FnUW$hLSua6G`)?jpZB1I%<8uRadK%uW*R+>9vA~!+OUEZNc!%F5--odD{{3 zFuS+om?seB5}QoQiC<4OC#U2%Ty5O{XqPtNvEaDRG1nmy^C^*bQj^B;<=&(hv>qzE z+G}O^g~y;#*fyqU^3Aa_fQq#SoR#Bw-lLjlF!I#$F5{~ z%no-}-4ZX3YX}j4GfVfi4-HBYR>7 zJRE;EyTeimWr30v_=Y1fV&rolV>i#6;*?kkt!wA?LojG&Un2rI3lk?-I| z-CpF&lxLG&sTq_$(w9>!mhuogZ68WgYMK>rDUQ~XEuw)}MZ(jySOhEF{(y&%?pffp=VIF8_sPF{akph@@kvMNObC}$#^)ic+i~$%*caC+?ANmUBmIz zp1dzJj}t_rWJ$)m9}Z5!c`30d<%U^)LOI=a2)Z#(D-)A;WY2#!hX9v z3T77gC)i?*KOJ>3LoA6ef+mDSl-L0~YGHIg(&x6gRuE|&<(=tY*Ywbua!W-W0(kec8J*o(Z;J?s> zRCeCLzoK6yc84SrM3K(-#n|$(+$9i5;OuU@Ol%%UYN&ydcaD=!kwX?iElrB}!@8L7 z$&;322+ep|0(Xy@oXrj4V~G%Jy}#8@2NGQbB-fTpL!+E z(;UmV#@np38+VCiOJ>kO( zayYpMi5o;2T(qy#_T*f9fppP2(Rm&1 zpy?M9Bq)eSmD&fgNg*j5r?E!4E`{wshvd%t2#;mp7-*n4^HReRY1NwjM4*2=A_~V9 z^IH=HUXFnmBhrRE?v*c$O^=D1W-uVT6q71YeX$jO`dtun&|HxSt58zV7;+Ze!jMMl zIF!necU#qT>56C#;eox9+Wi4pDKlnqim#{>k@A3DHH`z;fYa)R1zJ%FdbF|Wdzx^$ z|C9~(l#5@(Om?Ue$_(7xZ=7UL?e7jEhC!bR&L$lkCfLg5BCLl*JN?2JA);wV=E& zqr*uhdRHc8FGiAq8A`JRuakuNz6-&Ne-y+!WJ^IyZ%2_bY-@$Ejvu7E2e44>a|JMS`^~o6hU;oLW6rH z{pwWI6$bVLN`DwSCBz4Sr;rt=T;YwjRAF)yuuy^wi_&FV7qLOJ@^OoHUXuj_2;9YrXI=?~ zKw3V39=hK1I6s!tIu@A780a827p*iCVuQe zX)NDbhiT&_r~(r&Q}g4YJ4RlTjsWMsrqAMpRGs8<@qJ14rU$kf%yP+-ZZo#HNMDdX zmif@v3B=spe?9}i@=9cnu%i7Uqx|z^HD@@s{m)DM%D|=&lZ1?F>1E*xobhK{f3lnf zw_B@1UE6ImTJoq*McmDWDC_h0*5B+=N{TglSUwO!Ld;RDMB52Hgq#Cc-vo_Gv!yN4 z!J4dw1eU%RP4=!jX!(!YXx@h$;zpSKzEB;%>uB8bWfLcy#S?C^OAzhJcc`$3T zg;7!4a-7#FgG97rZgXH$`_CSl-L+ zEtzoAUT)NwJrij+P3O$y-EHB;MBZ$<@~&z2 zT`YQ-%APH%_Trk$MVBA?kP{jAc#;re`LGaLIvBft7bfbym}4DlDESo-Le%TQy7Ksn zu|R;424;)Y`_6S!Rsg!8H`;KFR0~~}-dO9hgtbp}|1uvxDbwM-Y>;%8`mI~Ht&($y z#Ct^Bp5iE0{s0KAoW)#G8%U8_lS77(9~1)5dh&2y>ZI-Rj`iRKy60e4$q&}6T|3*v ztXEZ1(xRv1=A-@<+Q84?V(x0guI*C7+=63CK;K`no*?p}>}D)a%#DUG6q$`~g+i_$ zU-O@B5#fC&d&-SGP=U&s)k?(3bZ{|Fi_jTjJaA#u6c(uc1KS|RIpR5TLc?fSXa7AK zQc;vfZr2>0%wIR_R$-Vqj5d%n3YKo-V=FmK%e|3Z(2-&fb@@ka8 zQuiXxhhb#qTZ~6Kb=^Q0VuZOkw+{!Vr*1dKl2~7QO$~mEGJ_c_1*Ti;7aL|h&^Tqz znTC9w5OQ^TiKm%l-CEiG`SFp@&v%bD*(ceQvgnRzZPXZ#H!BW8!`ehwF=|SiHhGe1 z!}W!i3rDuq+#SqTA{J!(rRh$amJaSj-sRgyPV)NA>$gD2cC|vnkgZteKVY*y1p#Ig zPf>f|`uu^SfzjwXpe9hamUV7a_!r$OprQA8Q@VJgj*qrivwS-@gh~bsMA>s+dLvx| zao+Wn3)qrI_4PIN< zvnJdVX;enC^7J*wgW-bfZH4 zFg*^SlcPf|c1u)letIDF7#S=`69NP|ENNh3^A(2_<*uNUnA?lIsFPsp<#aI2{BOFg zALk8sU~wP4*Zs@^7PSG?(k^kvvV@isa?#3R79bmI26&#s5|-*f{4L*}(!E00eVR$a zR!G;7rfwDCY?ITB&3ZPK<67aldnO-XFYP4mniuvNtibDkK029b!FrC*xex>@H~%BL!c?Hc^@LT}X_^VZT5ZFFn}Nxg`S~8} zE*o97^2nhLM=*l<{xR`L@iozZ>8-sq>xUAOu(^Yc#r^lF+j!AG#0x~8s0cAe? z@G3C*9%mPO6*w|pj4C>ML5wAH0EUWJuZdmcf=&mSe-j4s52kbGkn4bgwtamb(t{?+ zf{8@w4tMWygm_Z2%#RjxCn>ZLW1(w~ZhK~0-L#~xa&2pg8!mmwp>lR7C=}ek)%v-c zKI<3Ba^`d zm?~ihmg9vS9gfR8q64(JVw2eu0msU3ZzfJC7% zjgi<_9NzVq5w6YG(mm{XAh80#Pi>HkX?Tk`M}s<`PeFTX9O7Kf>NZywscUuE zQPL1+c98=-Q@&u5sjf)EACQvNIoX> zg&It!cQ3`ZQzqWobTH*8qs}B2=mP$$C?4@x+DpT&;KZ~u&@{xF>yy33=!=RWAbr>E zrHE5Q;5>w*Y>U80%*t~uy^1okD{oeuF0Oww&^JWT$Fo^-;I=T!(-R5ni74rNIQ%Rd)Gn(1D*i(ZYGa=qP<&Ja2&jMJ0~Bw{wt<7 zzi4w|Nt9;VXew9#TK>P*&et+f4f}W4x4m86?GrMgc<=MtdnD|(l0638iHj+|c~gF6 zQEjPdr+YgylXs}@SO)Cuc-FTmM-An4)u%~}VpDUMY@gUaGIm+B2859z zIIdTIxxW{8NijsePy*bfzfcAykb%S=s>i2~2`TRC6~~^CwNgsuB^9x@x32?ipr~~^ zH7#?0XmsFQ_ODM;Mkh7@*%qGp;Z*!B<&{g$4LlwOX>LR8$~hl~dT=IjESF~W`8zE( z`qdC2+6M|%@;eaea<@%&jk^)lx|S`vuBW2X=%Qb`j5UeIC2p=QhsW7xBfW|v)&#rx auJ&SmFU2dWOj4ly^6rbO*oa`a|NI|jnQeRk literal 196716 zcmeI530PCt+O}=AjwrR_tfZ|2;s7eB$dFVibwpHD1c5k51Q}%vNorA05KvK3h6GT7 ziVzhQ5J*%+RE97|3=kngfIwmhA!Poyq5VEhG-7-D{im|7>zuVW$yza4Wq9_p@Ar9O zVIxN_&1%{^WT={{*?qCf$m6>$xP@*H+702UE5?!>3#<4CPvC|TM6uyd ztM4DXba1A#w9zRzHkdI-wqxTyw;%kboqXAIK6d!H2iBV3glpm?-Zv~~={(L5KAxUB z+j3G`IAO-kXiuKaEL)dhb};v&<(B(&#|arbAB3i>ARAH;UWYa934y3 zKb`1a6@7481Ig6c!~wI^P;nEMq8Q*OIK4Q};8| zC-eo{4f_=lDLDj}(gj_X1-mQ^a1$<0k{|mKR^&WSh^T2wXv3#pk;h%W7Tfj zg-f<+HjHXJm|=H)tUWVs>Z_$zD2+A7&539G5+BUdq^3^M+AQ0(r%yiFLioKLC4Y2m znvQ&XQu?L%qdt=o_p*qUeTHU>Eei~`ZO>X*v;AOb#=Or*!%6_dufODvW8V1 zyq97-x@uv=-jbUxN0SXEM3gU@zU<;PY?RvC@|>+P8O3vUo;mRTF9-Kd`L<<6z-xzSrVs`{AC;3TL2TeXjV5^P%g; z=r}%2xVfm%aN?M4KPNpqQEHem+I8`s1)*KpZAOLhIrxl{DOr{U_+u+Gw}qdY`u&6S z&}i)WTA4(azc%QSN6yclx4U;d)WR%sm{^P=j+CF7`n0J&dI4*g4!!k=&3Czs1AZ|X z^)^j&`1RO}oAbv;%$gO9%6%{~aNalY8PuZQT=$#&?_Xd89Q2&P{-!{g#kKZ_!_UtN(Gxti$ZRxRqy z4V`??TJt3_Z-Pt114pZu_kR2({ne!VY0qxva;sN$cZ(*ngRO3jX(%1}Tg%!mmLro@ zv}ECLOJ=(Trp~yJd;(jkQ9EJhJPUM)X3%+hgE_jwIF=h5CqUMptIktso?^{KvzX*JJW zWb=xy_obO=kJU=q2aBr+INNS(>JZO7qbrEov}>whIB5!hsN3XW&55w=Ez7eGdNoo4 zYeR=S&%n{+1<{NxxQc1;_B;c>+(=OfcQei;JQ6!S3GbijHGP~Ral(w7H8V0+HvtY`J=oR&vhi7M&Dh2*ZY!&j&sGrmvn7%cEP=1%COY1 zCgU}!yS!^s=DZxjsIaahMhjT%zE>~wxjsQRq}B#IHwBANOxe%#Z{8z5L+mPU+L2D{ zC8g^lJuq8)LV~?Uc{EN5D->DiM;^fS@Xc*|eZrPrY}kVH)K0swteo!p72jvLlQwJ= z8GUG`eOu-djd8QqeqG_**cg8O_QK(Mds|4Sy-w$jYI9!k+F-9yMv8Rlu4nNB)CvZb{hX{Ah z)EruJ>HwP8+j~quZVQZY@J&E>=~cfBU;G-vCjaZi6|rWg!wSD*>}`33^$#HFOW*iV zSINJB61Fk{H>qd}xA$R94vbm5$~meB7ITRA^6 z9iN9>!aaJ}OrBe%crDToW0&0!+nqy0+<{vGWpG;3#mccD}mN8~y!!!5+J#zSPlbp#L zZwo27r9|&ix-awAMG7Xwe+nbV7Zb_a�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 E2jHes(EtDd diff --git a/unittests/snapshots/snap_v6.bin.json.gz b/unittests/snapshots/snap_v6.bin.json.gz index b513f97b1e4e40e755ea2479dab087eb6d3bc031..ef7034004a4f905b610ff4a0a75257c80a30994b 100644 GIT binary patch literal 29241 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%0DHC8JyiUvdyCXSxWLS!^Y`ep&UB+HD#Nf0+~48 zP@!R>=G5~Iq|w*i<3?;{Ny;6%G~0OMuy|G2`_{2n+l|!G+k02O^)*s*{_zgQivD$g z=hB^Y*5l2ELwZyf61&tjdV*C97KdB-?X)D#LDcCnud+f-7$2E6VW!ri11rw%IMm}e zyNx}%+LBOao>5<*ol!K|0~p6aCePUoSu=>v8InRf6FSG{n~9E3d(w;tDj3;ShNIMj*Dk9M z|6E;I@lG*+^X10FAMbf+A3RZZSkKf(bEp82zg>f<*jPz6DqKxBst4pWzN|ltH?Y?X za))1fSJ`d5P`Ul^EqO%*-={o6!9TIHD95fu!p|ILTNMSmH{%by0LSSR#`43%MicZm z4ZX1k>ioQO-?#9{9k&vt-QMw=K7S|hx^ao@?ow=jFR8x#Y+6lmNTg&WW=|IHcQVr; ztrCzmG;s%GXWulP2L@-m{gGjvvfElV1JbA=fo)L`O4hX7*?CX#Xbqx9izb2lf%+v<#l)SwQk)s{&`)6JWidEc=c9gw4U-K12Cgt&lI^Bd7m|Y3;kb#r(sX>q)5MLK##KQd%lw`Jb(e( zG(LN`QKdiWCzg7wvyMAdQ`8O}a{(YeR64$Oi`YuYl6~B?)4j0c*#0FItC*!=dfg{~ zV^L^mR?)LtKNihXP_r*&^e&R}l37|p;?equ0DRo!MU9%^cL$ekBQJWcC8l4#7g^I# zPl<{MvJ4sX0E1c*raQp?r-Z+um8&q}ub)Sh@K+_v{Ht%i`|+n=|MTB3R41w+{69Yv zK9T5Mv>L0wE#3cJS`FRdjWs{+P8!_(<$U2E7w;d^JX|)n_TBg26gLojhBf6&)KcH? zb76hcZOA}QS+ecogL_4_mzKs-E!v*`_S28wee=~9s)H&7s#&0V5mdQAl@3)Rs5De* zsM1iSp-MxQhAItJ8mcr@X{gdrrJ+hgm4+$}RT`=^RB5QvP^F^Vat zV#de4BIuLQ^pP0=X>sXjv*5tM{)l)6Pb2HPK9K@YyHrx|OW58LdY7uMkAq$4N{@HU znu)U1RL=Tj0)-m6&?#J@IvNQ_?-R_#3*4}FTR&KH=$6?tBWmbHq%mbbuChN%TxEp6lq4L$InNI9=1DzPg|aR=5>&VR{Uvv=TJIl zZ((#{fjhcB8W@z8kl;`rkBFV}akPm(dUEzzY3@+|>-B}eICw(vgXo0t_MZ0G-hO+Z z08JB1Qe^RvZu{uYNA9_A<1g)rNntpA-LTrrW%1favS}%`?1*5Z(reNzy_%KJc@!R< z0B=VvhM8I4AR8O!4!s`T99_Tl9s!Sr_oXa=p?-GSWjSZd8?q;#8xIUE-w!rFThRS9 zD`u4fCmF4fwo<{`TEl7?POEsQu9vR(XG(;vpf@Loy&gPi8vxFZb4HJo)oG*CA(JCO zC>xi(az70WZX%7L0nH?PYz@*HTAoLN6I#lfv-hRYS;2;nl{A016*W6S+3Ts=n_KZ{ zrLUJ8c0=BYcY4^YP4s-%?FgX1EOt9v_F#Lk#}%?Ub{n?5w2J-|_nuf-}`3_2sb zh|2J}-ktb&8>y$Qq`J;d?(F^HL$wFTtB9DLFc&e9f z<|l4L9z4Vgb!ISzCo}k!0Uv|x))kXii$`rSVpnZmsW6CP-(%Ci=%5`F#nd7R?aQ~b zY2pqdFsw)(UhhA+?UFXWH+`AR5NA|97K>Oz@)3BFa(iuSL8X|tLR~IIl7kPwrOEdT|8+$=nVU%(>Y;r`!+1Y^_4J0x(bD&D z>m-WNL`UVlrU6&Hfj`S&yqjjG6XUp{j)g3Go{;mdbjFDV0{r+a*Yd#LPE5n%A>#ld z!;i2yf2iSy*$stvgK@T+F4avpdlrK3T9dMN9=s@<i$z>{#P)TWJr{!BEP98&Jrw<}^@LjC7c>&)j*`vhz14VZhV_X8=50WnVYO zsHVyJOqmbBp$ba7T=~mK1SX>{ukY#}`g?I0RmgV&le33bUsbuv*VfWSxdU27bhu5n zCrPoW#;P?VzkTO?E8e~3LX6H*4F(pys%y{&84?@o9g_JFR5 z_nT1fFYhu0F1}7>eufGxDuM!0MudaQrK8i`HRz5{{hIPhgYpFf!5ymEgdfZkYDn>t z+NMEFW<83t;gL)wvT1EN%jYmKzn9yd7;Q8uc&TGvbSn@Lvwuhdl&xfuF~t`yQfOj{ZjUhKH)-b)g6Eo3w;M}ftAa9MP-G9;pQ zE1EHZaRSkWsQUowxg!FHqmp3blWeq~o-UbM4)2po&S?GWu;;LOzh{QZVLY^82mk4cO_X1#>j zZq4LhcU&-z>%9Y?OIVYh`$yh%7L|+T9^jY>yhQZbMzB6AZhcIQ5}x#}kS9amv?zA7$Oj78+OV zDcGPYCg%<%u9yXM|2@m;LWln2Roju&7u&>Q7`nVy=UD}N%(FN*l zafBT6CH{-<8|SiIkq9YLQ#e$n9_P8=LR;5ugwdo4LI2#?=a>_rou$_7M^$ljO)1qg zsuJy-M*;-7<_S*kI&ggjC$sw$F{k-cxtHDt(@mN2`r&2UrS9bSK+mY*lpJRp4|MX0 z8!i5e+r#@Qiu#r0iFK%lO>8p;9Dp?;CUW~vqV3gAS87wN*aZ3PdeMVXy<_-}5cp+RaaQW0-I#ck z)!%i@3z+5_mqN@-;HI0CQu7?IH1B_~&lvJta@uE`>ktTqJ_@VW zdv*7@=dgRxX6jRYALgT(i2z_QZ5} z1nz8Zm!%TQ1f?i&O-EuU%J4^Yx_EId!?*bt>sZB{m#(83`CH~_K{b^gUfw_@-NuP} zy>UyfxM@U101l1aT2CCywYg!a?t*~DHanJz|FqPZwvF`YZQj3{mgX09&RCiDY<1)o z2!Fob()pu}4X1ifxF`{Fq)Y5xU1=emTK*U9koyx^5m4#A9YIN<54dlon=x-*fTP@WAA;2>*Rr{X|^ zmAFx`6E;-jNW?jr5wsyXw~p0V6(dVS{I29&pD9`uxy%p5uCTemyZ>XE02-L%oy}9{W*zI zu#+}s{8Rd?HqL09C~>ToE&G;+em=Zjd8Na1EGGTsbOM}EI_yCNW)(mr9!m7*uHiUJ zU%{8z$MK?Zk|gWx4+p2=ywtcf<%U^dWF*tNl7u~Bvvib)a2oSOQ~CBO5mcY!!a@52 zGI}2PC)i@0KO229ODst!fhLAVme~Wl>R~j0;^(%w)(~j}`K{?+SM^Yua!W-60UJI6_V-KopD6O^vM_C0`j8r0^=WG)olfy!>(o-V0P@X{L6Imeb}&b$;C zXij8Z`K&D*ybyq$tBMrMq7-mP4kn4J){%%MT{sU|g`#!_qC?Au_*u(=`$R;47P(4-u=g&~#L zbts)K@3pS$(G^jfB7*uQ_4`Azaz^a(3}4Y8A{GF9>Y9hH0%z3?i?pH>^{5lGcQxVi zfEioNDOdld8-B{X(MJskhAyigw->6zOTm=T?y>ASQzhHY))V{t&+)wOna_8;+h2#} zdI+(Bu9*LupzvLW-nELv=QJ*LFA8Ek!NDM~x{<%XPVwV8!*1>u%i{1QL-yl`+R}V3 zqaui9dREi2=VK|rjq1xkEB{G-=4s3Rkv&)d2)tX z%#ZSY@c}%PpVln3VM}By>hqdw+ATMU<%m7YF`)&yIQ~fG-P~S%dcCx97i^4;Y>F;& zLMww|e#78=CLZ*;Zc!JBljTVy@mvG9Ll|RYmS|01PYGV2ZgbOI!whjTGklMkeO#G! zAQ+F%NltS`5(+Y6Qv$2JF~tnbZop4fJ=vY>A01~i6|+=i?fNuxJsNRv1~0l+rNObv zyfPDQMaR5P(;tP-2yubn8D!NdH+ZuhMVJx|ES4a{qjgypg>^Q}$U+jHn(gaLq88d< z7&9pw-2tgZ#-3&r{+akqLWf7z9*^O^u*MHnXU!WZTc1m=?Bus zFdq0hgBZK}&*lIaUYYD6MzmjIRCu1G<^sob{&|UC9n=zPl9*L1y)0aX)Bo%kOp!C; z_UkoiS9hC@Ry-Ti5qI(-%ErPy?(02rS*b=J(-(qIj6I5xXgi}ukPG128=whkuCz@$ zT$j_7$kg|y%HGxnfBd69hW9>?un{i5CsfDnIvMwU8P5K^`bcMI4yun(OjG1r9?Y3; zqgU0p9p^R6Ad#KuTWr|O{?i9$cWmgSAqT@+7+d;#i)$nIvU`_K(O)7UhS%ZKml#>C zB@^%Q4M>N^S{#*oY4`g`clS2~d8l5-#6EuxUAs8TbKGZKl`AS3xON0AWY=JJspVMt z$)>XWL_d1preFN?d(=ebz_|b#g~lIeCUqfZHWY~yp`bLh`)d2V9E4SJ_j#fC!}@F@ zuTt(qvW|$>YCb;X(PPGW-MWhaZ#)D@&R40y15ngWiP5Y(objr^8U3u8H_^ld1oAxZ{O zSs*VeYX(QN9x^Fx$;a~tzqcLr5sXuwb6bmWa--(lxhVTt8hftbP8%;a>PDN@+m`va zai~!WYrdq`n`15)U4Gz8N}}K8NkR#gqe5u;a2)pzOw@ZZ&nC`L@+%;epx1|S#BS^cJ!It=p!o2y|ULPwDA6#}nD(r7{YwB5%Yo8c)`-@%-+A8giocD4yQ zFKeX4WiO}Ahl8usp`XE}oVBK1yOqR+C8x5$fxqIsK%_&ttr(t|69Zo=F&p0sgIqhl z9x&e~!ud`2RT_Dw1u5s&su5$eA*EO?e0Qkv(1meRSdjJ)EQ45=$Y;nY4Wm(={dXux zRdtejQ#Z`G$&lWb_U66@{H_obL~V0u3Pk(&VeD;?u7kCopZ2TMpPFibawuO-UX|&gGv<=s>bkQzX?khZYb5Y9swY$gYjlm*aS* zx;J4l94#~7qCeDW=mokGBF)A516VLEeY-i1$o$fKX82RI8O&HIFx}!_Y?}8(VU>Aj znhJG7Nwt|}US<-mjk5Ri<0GA4>>Y1$NVY9!(wtD*X%jr&yf_#I>kwT*t0`?e!)r#>Wc4Aq;kS%ux0?Z|x zqV&P_`9mc`<1r0DO`vW)^W3=bFPe2=Q~&XnOz}noALXEC`DS4xEd?+X?ZA2AgLDnT z`ZQKAY1i6R++`DA#^z-@JnE0plcV%j(>vx%9+q$keT9-SJJuQyL$ABrl>#amzRK0J z!QT~WR7Wuj^ff0#;DT!%#rro38fZX#mi6>mTE*qGu$uK(=u^Col^8_)tKH<@In7mJ zW;{SAPlrc$UW$mg_(QEZ>~cwW8@h$tGf| zr0Ymi_o@h%$!Yp#Ba6aztMb}CQwVU7b`y5Ziw6u=;f+5Zolde~KEvf*2nG|Gr>@T< z8CW;6HxZKo4=}kMhl+N=oXjXvUni=Y{}EGVD$wD0!K&;v%>-brj?v-GpcM4tVxLWq zt*%;S)X0Vt7{Pe_n3c;YO%EA-NhB34Zlj3e;MIZUeRc+GNU^gc-`o8lpNz#59Z!P= z=u^>At9yAp*b%td{)54b+-V15=Dc_S9!D_m-AK)3|1_HJA8g~8t*fMM(4iz|d6~kt z7uDT^-lV+wT=uxe2nFaS()*o9NtY0tl$9k&YL85;*yMa10_4g>wfS_Stb;h*1UNX`w4fpXpu6V|xeY0(+t(H$eJG+V zgg}t)aP}TWil-$X`7vV7G?^M|EOg7$?aa<-n3XhCuWzkzBBT%46!z{EnT-9nRzH8! zmwS;UXZ-iMw@Bap=F&4+{1))^6E=F}VyfnEXcD5kduKKAi4yVy%JVnnZlVm=_&Vt^ ziO{FRkOQ?9u!v89@012xp5MB4UH_{YhuK*TU1iJprLVW!PT7NmYUxiM75nTD17cv8 zsSrLM#QdSV-%vO<1$@D>$2KTG2 z;cl6u-L9)EK4t|+!#=&TvrUeh)o|@>#>7x>6gg)MP@#^fQ_#LT$9OlhhRwBQ%6bE4 zoH)XsUuFZ(R4$oht1FVRNOOX%lB}q>d7ZnroS6LmV6eTM_$3hXGrH@59YL7@DMV*K zSA*&F@1@#x%fvgIj;3s7^qHh0UBG`8rDL8edl}eOteAQRnt@n%d%U+Cb5St@r0u%D z5V7m<><92PyAtpbv&wu+?~?4?>Kj$3OB-Jg4UFLRajdl!4-4T-fsWbqj_*!W^C<3G zNkcZ&IQQd=@5ahF5pnAnO^Lo*ls(#&wQHe)22TO|H&Z6PP(JOeST@e5lU)ep{)(l!> ztF5%`^loQo^A0r}%YvPq%=tF;h~g@^|BE8^&wnI3hVVZV+h4ts_}}Jx!^t}-^BN@G zG|8`55a={u_l`KlFU5ApzRO-a_1S$7bjczUI3}R}btnB1p{2D)woe!wo4Bl52SUpb zY&WZ4?(M~2QjCx;lmRzs&y_)mBp{)W;`!-AVycIF)v?DUt<-XPSyi0ft!n^VXd0JB z$;jRx86P^A`|IP>@oCL}wuNVYIF)cyX?4k^iN`}D&20%idFR8^?w?7T$fsI={!WXD zc{zfQ@r6Q_{4PYM+2z%>!qkRy6B%NV@{*6Nt^2*BjO!$k=~_|>w?`v aHwUr4x8fy5CMi;WdFOdeTx5v*fBp}G32k}+ literal 196716 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

KSa!X4myG1@c;@X(wz$3D{Sy=*8eU59q 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 E17rwM`v3p{ From 408afb5817f9d87c033d88613a8eaac99e6191a0 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Fri, 19 Aug 2022 13:37:41 -0500 Subject: [PATCH 012/111] write rapidjson snapshot validity test case. --- unittests/snapshot_tests.cpp | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/unittests/snapshot_tests.cpp b/unittests/snapshot_tests.cpp index 2cd14db451..f9f0691b96 100644 --- a/unittests/snapshot_tests.cpp +++ b/unittests/snapshot_tests.cpp @@ -553,4 +553,56 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_restart_with_existing_state_and_truncated_blo verify_integrity_hash(*chain.control, *snap_chain.control); } +BOOST_AUTO_TEST_CASE(json_snapshot_validity_test) +{ + auto ordinal = 0; + tester chain; + + // prep the chain + chain.create_account("snapshot"_n); + chain.produce_blocks(1); + chain.set_code("snapshot"_n, contracts::snapshot_test_wasm()); + chain.set_abi("snapshot"_n, contracts::snapshot_test_abi().data()); + chain.produce_blocks(10); + chain.control->abort_block(); + + // create bin snapshot + auto writer_bin = buffered_snapshot_suite::get_writer(); + chain.control->write_snapshot(writer_bin); + auto snapshot_bin = buffered_snapshot_suite::finalize(writer_bin); + buffered_snapshot_suite::write_to_file("BinSnapshot", snapshot_bin); + + // create json snapshot + auto writer_json = json_snapshot_suite::get_writer(); + chain.control->write_snapshot(writer_json); + auto snapshot_json = json_snapshot_suite::finalize(writer_json); + json_snapshot_suite::write_to_file("JsonSnapshot", snapshot_json); + + // load bin snapshot + auto snapshot_bin_read = buffered_snapshot_suite::load_from_file("BinSnapshot"); + auto reader_bin = buffered_snapshot_suite::get_reader(snapshot_bin_read); + snapshotted_tester tester_bin(chain.get_config(), reader_bin, ordinal++); + + // load json snapshot + auto snapshot_json_read = json_snapshot_suite::load_from_file("JsonSnapshot"); + auto reader_json = json_snapshot_suite::get_reader(snapshot_json_read); + snapshotted_tester tester_json(chain.get_config(), reader_json, ordinal++); + + // create bin snapshot from loaded json snapshot + auto writer_bin_from_json = buffered_snapshot_suite::get_writer(); + tester_json.control->write_snapshot(writer_bin_from_json); + auto snapshot_bin_from_json = buffered_snapshot_suite::finalize(writer_bin_from_json); + buffered_snapshot_suite::write_to_file("BinFromJsonSnapshot", snapshot_bin_from_json); + + // load new bin snapshot + auto snapshot_bin_from_json_read = buffered_snapshot_suite::load_from_file("BinFromJsonSnapshot"); + auto reader_bin_from_json = buffered_snapshot_suite::get_reader(snapshot_bin_from_json_read); + snapshotted_tester tester_bin_from_json(chain.get_config(), reader_bin_from_json, ordinal++); + + // ensure all snapshots are equal + verify_integrity_hash(*tester_bin_from_json.control, *tester_bin.control); + verify_integrity_hash(*tester_bin_from_json.control, *tester_json.control); + verify_integrity_hash(*tester_json.control, *tester_bin.control); +} + BOOST_AUTO_TEST_SUITE_END() From 5fce72cb7168da16284b9f372a8cd835d6d5b546 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Fri, 19 Aug 2022 13:38:08 -0500 Subject: [PATCH 013/111] change rapidjson to interface library in cmakelist --- libraries/chain/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c59b97c28e..bcc25245d7 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -72,6 +72,10 @@ set(CHAIN_WEBASSEMBLY_SOURCES webassembly/transaction.cpp ) +add_library(rapidjson INTERFACE) +target_include_directories(rapidjson INTERFACE ../rapidjson/include) +target_compile_definitions(rapidjson INTERFACE) + ## SORT .cpp by most likely to change / break compile add_library( eosio_chain merkle.cpp @@ -125,13 +129,12 @@ add_library( eosio_chain ${HEADERS} ) -target_link_libraries( eosio_chain PUBLIC fc chainbase Logging IR WAST WASM Runtime +target_link_libraries( eosio_chain PUBLIC fc chainbase rapidjson Logging IR WAST WASM Runtime softfloat builtins ${CHAIN_EOSVM_LIBRARIES} ${LLVM_LIBS} ${CHAIN_RT_LINKAGE} ) target_include_directories( eosio_chain PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include" - "${CMAKE_CURRENT_SOURCE_DIR}/../rapidjson/include" ) add_library(eosio_chain_wrap INTERFACE ) From 92dc116c8e3c044b87d8de63eba5a244ce2d06ad Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Fri, 19 Aug 2022 17:04:11 -0500 Subject: [PATCH 014/111] move namespace collosion for rapidjson to top of include list to prevent possible collision. Rename rapidjson in libraries. --- libraries/chain/CMakeLists.txt | 7 +++---- libraries/chain/snapshot.cpp | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index bcc25245d7..e537398bb9 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -72,9 +72,8 @@ set(CHAIN_WEBASSEMBLY_SOURCES webassembly/transaction.cpp ) -add_library(rapidjson INTERFACE) -target_include_directories(rapidjson INTERFACE ../rapidjson/include) -target_compile_definitions(rapidjson INTERFACE) +add_library(eosio_rapidjson INTERFACE) +target_include_directories(eosio_rapidjson INTERFACE ../rapidjson/include) ## SORT .cpp by most likely to change / break compile add_library( eosio_chain @@ -129,7 +128,7 @@ add_library( eosio_chain ${HEADERS} ) -target_link_libraries( eosio_chain PUBLIC fc chainbase rapidjson Logging IR WAST WASM Runtime +target_link_libraries( eosio_chain PUBLIC fc chainbase eosio_rapidjson Logging IR WAST WASM Runtime softfloat builtins ${CHAIN_EOSVM_LIBRARIES} ${LLVM_LIBS} ${CHAIN_RT_LINKAGE} ) target_include_directories( eosio_chain diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 3d87afdb81..98b4254939 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -1,9 +1,10 @@ +#define RAPIDJSON_NAMESPACE eosio_rapidjson // This is ABSOLUTELY necessary anywhere that is using eosio_rapidjson + #include #include #include #include -#define RAPIDJSON_NAMESPACE eosio_rapidjson #include #include #include From 1061b945014507a227088322d9f7623af51ae48d Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 31 Aug 2022 11:07:24 -0500 Subject: [PATCH 015/111] allow new snapshot json test to pass when using multiple threads --- libraries/chain/snapshot.cpp | 2 +- .../include/eosio/testing/snapshot_suites.hpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 98b4254939..14b03bd9e7 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -359,7 +359,7 @@ istream_json_snapshot_reader::istream_json_snapshot_reader(const fc::path& p) : impl{new istream_json_snapshot_reader_impl{0, 0, {}, {}}} { FILE* fp = fopen(p.string().c_str(), "rb"); - EOS_ASSERT(fp, snapshot_exception, "Failed to JSON snapshot: ${file}", ("file", p)); + EOS_ASSERT(fp, snapshot_exception, "Failed to open JSON snapshot: ${file}", ("file", p)); auto close = fc::make_scoped_exit( [&fp]() { fclose( fp ); } ); char readBuffer[65536]; eosio_rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); diff --git a/libraries/testing/include/eosio/testing/snapshot_suites.hpp b/libraries/testing/include/eosio/testing/snapshot_suites.hpp index ba3ea691de..813563842f 100644 --- a/libraries/testing/include/eosio/testing/snapshot_suites.hpp +++ b/libraries/testing/include/eosio/testing/snapshot_suites.hpp @@ -125,12 +125,18 @@ struct json_snapshot_suite { std::shared_ptr storage; }; + static std::string temp_file() { + static fc::temp_directory temp_dir; + std::string temp_file = temp_dir.path().string() + "temp.bin.json"; + return temp_file; + } + struct reader : public reader_t { explicit reader(const fc::path& p) :reader_t(p) {} ~reader() { - remove("temp.bin.json"); + remove(json_snapshot_suite::temp_file().c_str()); } }; @@ -145,10 +151,10 @@ struct json_snapshot_suite { } static auto get_reader( const snapshot_t& buffer) { - std::ofstream fs("temp.bin.json"); + std::ofstream fs(json_snapshot_suite::temp_file()); fs << buffer; fs.close(); - fc::path p("temp.bin.json"); + fc::path p(json_snapshot_suite::temp_file()); return std::make_shared(p); } From 68827edfd68f1b2dbefc9f9f48e685814b3c767b Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Wed, 31 Aug 2022 13:10:31 -0500 Subject: [PATCH 016/111] delete snapshots from json_snapshot_validity_test --- unittests/snapshot_tests.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/unittests/snapshot_tests.cpp b/unittests/snapshot_tests.cpp index f9f0691b96..2bce4f57ef 100644 --- a/unittests/snapshot_tests.cpp +++ b/unittests/snapshot_tests.cpp @@ -603,6 +603,13 @@ BOOST_AUTO_TEST_CASE(json_snapshot_validity_test) verify_integrity_hash(*tester_bin_from_json.control, *tester_bin.control); verify_integrity_hash(*tester_bin_from_json.control, *tester_json.control); verify_integrity_hash(*tester_json.control, *tester_bin.control); + + auto bin_snap_path = bfs::path(snapshot_file::base_path) / "BinSnapshot.bin.gz"; + auto bin_from_json_snap_path = bfs::path(snapshot_file::base_path) / "BinFromJsonSnapshot.bin.gz"; + auto json_snap_path = bfs::path(snapshot_file::base_path) / "JsonSnapshot.bin.json.gz"; + remove(bin_snap_path); + remove(bin_from_json_snap_path); + remove(json_snap_path); } BOOST_AUTO_TEST_SUITE_END() From 76e3e418f4db803eb5708353b95fb776e2c500ce Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 1 Sep 2022 11:39:57 -0500 Subject: [PATCH 017/111] Remove hardcoded 10ms limit for chain_api_plugin calls and instead honor http-max-response-time-ms. --- plugins/chain_api_plugin/chain_api_plugin.cpp | 17 ++- plugins/chain_plugin/chain_plugin.cpp | 112 +++++++++--------- .../eosio/chain_plugin/chain_plugin.hpp | 95 +++++++++------ .../chain_plugin/test/test_chain_plugin.cpp | 4 +- plugins/http_plugin/http_plugin.cpp | 1 + .../include/eosio/http_plugin/common.hpp | 5 +- tests/chain_plugin_tests.cpp | 18 +-- tests/get_producers_tests.cpp | 10 +- tests/get_table_seckey_tests.cpp | 12 +- tests/get_table_tests.cpp | 76 ++++++------ 10 files changed, 192 insertions(+), 158 deletions(-) diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index 93bf9b91ab..79e9085611 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -51,10 +51,11 @@ parse_params(body);\ - fc::variant result( api_handle.call_name( std::move(params) ) ); \ + FC_CHECK_DEADLINE(deadline);\ + fc::variant result( api_handle.call_name( std::move(params), deadline ) ); \ cb(http_response_code, std::move(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ @@ -64,10 +65,11 @@ parse_params(body);\ - api_handle.call_name( std::move(params),\ + FC_CHECK_DEADLINE(deadline);\ + api_handle.call_name( std::move(params), \ [cb, body](const std::variant& result){\ if (std::holds_alternative(result)) {\ try {\ @@ -96,8 +98,11 @@ void chain_api_plugin::plugin_startup() { ilog( "starting chain_api_plugin" ); my.reset(new chain_api_plugin_impl(app().get_plugin().chain())); auto& chain = app().get_plugin(); - auto ro_api = chain.get_read_only_api(); - auto rw_api = chain.get_read_write_api(); + auto& http = app().get_plugin(); + fc::microseconds max_response_time = http.get_max_response_time(); + + auto ro_api = chain.get_read_only_api(max_response_time); + auto rw_api = chain.get_read_write_api(max_response_time); auto& _http_plugin = app().get_plugin(); ro_api.set_shorten_abi_errors( !_http_plugin.verbose_errors() ); diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 85c9d8c766..349543be1d 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -764,8 +764,7 @@ void chain_plugin::plugin_initialize(const variables_map& options) { LOAD_VALUE_SET( options, "profile-account", my->chain_config->profile_accounts ); - if(options.count("abi-serializer-max-time-ms")) - my->abi_serializer_max_time_us = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); + my->abi_serializer_max_time_us = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); my->chain_config->blocks_dir = my->blocks_dir; my->chain_config->state_dir = app().data_dir() / config::default_state_dir_name; @@ -1321,10 +1320,15 @@ void chain_plugin::handle_sighup() { _deep_mind_log.update_logger( deep_mind_logger_name ); } -chain_apis::read_write::read_write(controller& db, std::optional& trx_retry, const fc::microseconds& abi_serializer_max_time, bool api_accept_transactions) +chain_apis::read_write::read_write(controller& db, + std::optional& trx_retry, + const fc::microseconds& abi_serializer_max_time, + const fc::microseconds& http_max_response_time, + bool api_accept_transactions) : db(db) , trx_retry(trx_retry) , abi_serializer_max_time(abi_serializer_max_time) +, http_max_response_time(http_max_response_time) , api_accept_transactions(api_accept_transactions) { } @@ -1334,12 +1338,12 @@ void chain_apis::read_write::validate() const { "Not allowed, node has api-accept-transactions = false" ); } -chain_apis::read_write chain_plugin::get_read_write_api() { - return chain_apis::read_write(chain(), my->_trx_retry_db, get_abi_serializer_max_time(), api_accept_transactions()); +chain_apis::read_write chain_plugin::get_read_write_api(const fc::microseconds& http_max_response_time) { + return chain_apis::read_write(chain(), my->_trx_retry_db, get_abi_serializer_max_time(), http_max_response_time, api_accept_transactions()); } -chain_apis::read_only chain_plugin::get_read_only_api() const { - return chain_apis::read_only(chain(), my->_account_query_db, get_abi_serializer_max_time(), my->producer_plug, my->_trx_finality_status_processing.get()); +chain_apis::read_only chain_plugin::get_read_only_api(const fc::microseconds& http_max_response_time) const { + return chain_apis::read_only(chain(), my->_account_query_db, get_abi_serializer_max_time(), http_max_response_time, my->producer_plug, my->_trx_finality_status_processing.get()); } @@ -1425,7 +1429,7 @@ std::string itoh(I n, size_t hlen = sizeof(I)<<1) { return r; } -read_only::get_info_results read_only::get_info(const read_only::get_info_params&) const { +read_only::get_info_results read_only::get_info(const read_only::get_info_params&, const fc::time_point&) const { const auto& rm = db.get_resource_limits_manager(); return { @@ -1454,7 +1458,8 @@ read_only::get_info_results read_only::get_info(const read_only::get_info_params }; } -read_only::get_transaction_status_results read_only::get_transaction_status(const read_only::get_transaction_status_params& param) const { +read_only::get_transaction_status_results +read_only::get_transaction_status(const read_only::get_transaction_status_params& param, const fc::time_point& deadline) const { EOS_ASSERT(trx_finality_status_proc, unsupported_feature, "Transaction Status Interface not enabled. To enable, configure nodeos with '--transaction-finality-status-max-storage-size-gb '."); trx_finality_status_processing::chain_state ch_state = trx_finality_status_proc->get_chain_state(); @@ -1481,7 +1486,8 @@ read_only::get_transaction_status_results read_only::get_transaction_status(cons } read_only::get_activated_protocol_features_results -read_only::get_activated_protocol_features( const read_only::get_activated_protocol_features_params& params )const { +read_only::get_activated_protocol_features( const read_only::get_activated_protocol_features_params& params, + const fc::time_point& deadline )const { read_only::get_activated_protocol_features_results result; const auto& pfm = db.get_protocol_feature_manager(); @@ -1508,9 +1514,8 @@ read_only::get_activated_protocol_features( const read_only::get_activated_proto auto& activation_block_num_value = mvo["activation_block_num"]; auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time for( unsigned int count = 0; - cur_time <= end_time && count < params.limit && itr != end_itr; + cur_time <= deadline && count < params.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { const auto& conv_itr = convert_iterator( itr ); @@ -1695,7 +1700,7 @@ string get_table_type( const abi_def& abi, const name& table_name ) { EOS_ASSERT( false, chain::contract_table_query_exception, "Table ${table} is not specified in the ABI", ("table",table_name) ); } -read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p )const { +read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p, const fc::time_point& deadline )const { const abi_def abi = eosio::chain_apis::get_abi( db, p.code ); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -1705,43 +1710,43 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get EOS_ASSERT( p.table == table_with_index, chain::contract_table_query_exception, "Invalid table name ${t}", ( "t", p.table )); auto table_type = get_table_type( abi, p.table ); if( table_type == KEYi64 || p.key_type == "i64" || p.key_type == "name" ) { - return get_table_rows_ex(p,abi); + return get_table_rows_ex(p,abi,deadline); } EOS_ASSERT( false, chain::contract_table_query_exception, "Invalid table type ${type}", ("type",table_type)("abi",abi)); } else { EOS_ASSERT( !p.key_type.empty(), chain::contract_table_query_exception, "key type required for non-primary index" ); if (p.key_type == chain_apis::i64 || p.key_type == "name") { - return get_table_rows_by_seckey(p, abi, [](uint64_t v)->uint64_t { + return get_table_rows_by_seckey(p, abi, deadline, [](uint64_t v)->uint64_t { return v; }); } else if (p.key_type == chain_apis::i128) { - return get_table_rows_by_seckey(p, abi, [](uint128_t v)->uint128_t { + return get_table_rows_by_seckey(p, abi, deadline, [](uint128_t v)->uint128_t { return v; }); } else if (p.key_type == chain_apis::i256) { if ( p.encode_type == chain_apis::hex) { using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } else if (p.key_type == chain_apis::float64) { - return get_table_rows_by_seckey(p, abi, [](double v)->float64_t { + return get_table_rows_by_seckey(p, abi, deadline, [](double v)->float64_t { float64_t f = *(float64_t *)&v; return f; }); } else if (p.key_type == chain_apis::float128) { if ( p.encode_type == chain_apis::hex) { - return get_table_rows_by_seckey(p, abi, [](uint128_t v)->float128_t{ + return get_table_rows_by_seckey(p, abi, deadline, [](uint128_t v)->float128_t{ return *reinterpret_cast(&v); }); } - return get_table_rows_by_seckey(p, abi, [](double v)->float128_t{ + return get_table_rows_by_seckey(p, abi, deadline, [](double v)->float128_t{ float64_t f = *(float64_t *)&v; float128_t f128; f64_to_f128M(f, &f128); @@ -1750,18 +1755,18 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get } else if (p.key_type == chain_apis::sha256) { using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } else if(p.key_type == chain_apis::ripemd160) { using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } EOS_ASSERT(false, chain::contract_table_query_exception, "Unsupported secondary index type: ${t}", ("t", p.key_type)); } #pragma GCC diagnostic pop } -read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p )const { +read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p, const fc::time_point& deadline )const { read_only::get_table_by_scope_result result; const auto& d = db.db(); @@ -1785,8 +1790,7 @@ read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_o auto walk_table_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time - for( unsigned int count = 0; cur_time <= end_time && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { if( p.table && itr->table != p.table ) continue; result.rows.push_back( {itr->code, itr->scope, itr->table, itr->payer, itr->count} ); @@ -1809,7 +1813,7 @@ read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_o return result; } -vector read_only::get_currency_balance( const read_only::get_currency_balance_params& p )const { +vector read_only::get_currency_balance( const read_only::get_currency_balance_params& p, const fc::time_point& deadline )const { const abi_def abi = eosio::chain_apis::get_abi( db, p.code ); (void)get_table_type( abi, name("accounts") ); @@ -1835,7 +1839,7 @@ vector read_only::get_currency_balance( const read_only::get_currency_bal return results; } -fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_params& p )const { +fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_params& p, const fc::time_point& deadline )const { fc::mutable_variant_object results; const abi_def abi = eosio::chain_apis::get_abi( db, p.code ); @@ -1876,14 +1880,14 @@ fc::variant get_global_row( const database& db, const abi_def& abi, const abi_se return abis.binary_to_variant(abis.get_table_type("global"_n), data, abi_serializer::create_yield_function( abi_serializer_max_time_us ), shorten_abi_errors ); } -read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& p ) const try { +read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& params, const fc::time_point& deadline ) const try { const abi_def abi = eosio::chain_apis::get_abi(db, config::system_account_name); const auto table_type = get_table_type(abi, "producers"_n); const abi_serializer abis{ abi, abi_serializer::create_yield_function( abi_serializer_max_time ) }; EOS_ASSERT(table_type == KEYi64, chain::contract_table_query_exception, "Invalid table type ${type} for table producers", ("type",table_type)); const auto& d = db.db(); - const auto lower = name{p.lower_bound}; + const auto lower = name{params.lower_bound}; static const uint8_t secondary_index_num = 0; const auto* const table_id = d.find( @@ -1898,7 +1902,6 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p const auto& secondary_index_by_secondary = secondary_index.get(); read_only::get_producers_result result; - const auto stopTime = fc::time_point::now() + fc::microseconds(1000 * 10); // 10ms vector data; auto it = [&]{ @@ -1912,12 +1915,12 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p }(); for( ; it != secondary_index_by_secondary.end() && it->t_id == secondary_table_id->id; ++it ) { - if (result.rows.size() >= p.limit || fc::time_point::now() > stopTime) { + if (result.rows.size() >= params.limit || fc::time_point::now() > deadline) { result.more = name{it->primary_key}.to_string(); break; } copy_inline_row(*kv_index.find(boost::make_tuple(table_id->id, it->primary_key)), data); - if (p.json) + if (params.json) result.rows.emplace_back( abis.binary_to_variant( abis.get_table_type("producers"_n), data, abi_serializer::create_yield_function( abi_serializer_max_time ), shorten_abi_errors ) ); else result.rows.emplace_back(fc::variant(data)); @@ -1927,8 +1930,9 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p return result; } catch (...) { read_only::get_producers_result result; + result.rows.reserve(db.active_producers().producers.size()); - for (auto p : db.active_producers().producers) { + for (const auto& p : db.active_producers().producers) { auto row = fc::mutable_variant_object() ("owner", p.producer_name) ("producer_authority", p.authority) @@ -1943,13 +1947,13 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p } } - result.rows.push_back(row); + result.rows.emplace_back(std::move(row)); } return result; } -read_only::get_producer_schedule_result read_only::get_producer_schedule( const read_only::get_producer_schedule_params& p ) const { +read_only::get_producer_schedule_result read_only::get_producer_schedule( const read_only::get_producer_schedule_params& p, const fc::time_point& deadline ) const { read_only::get_producer_schedule_result result; to_variant(db.active_producers(), result.active); if(!db.pending_producers().producers.empty()) @@ -1981,7 +1985,7 @@ auto make_resolver(const controller& control, abi_serializer::yield_function_t y } read_only::get_scheduled_transactions_result -read_only::get_scheduled_transactions( const read_only::get_scheduled_transactions_params& p ) const { +read_only::get_scheduled_transactions( const read_only::get_scheduled_transactions_params& p, const fc::time_point& deadline ) const { const auto& d = db.db(); const auto& idx_by_delay = d.get_index(); @@ -2015,8 +2019,7 @@ read_only::get_scheduled_transactions( const read_only::get_scheduled_transactio auto resolver = make_resolver(db, abi_serializer::create_yield_function( abi_serializer_max_time )); uint32_t remaining = p.limit; - auto time_limit = fc::time_point::now() + fc::microseconds(1000 * 10); /// 10ms max time - while (itr != idx_by_delay.end() && remaining > 0 && time_limit > fc::time_point::now()) { + while (itr != idx_by_delay.end() && remaining > 0 && deadline > fc::time_point::now()) { auto row = fc::mutable_variant_object() ("trx_id", itr->trx_id) ("sender", itr->sender) @@ -2053,7 +2056,7 @@ read_only::get_scheduled_transactions( const read_only::get_scheduled_transactio return result; } -fc::variant read_only::get_block(const read_only::get_block_params& params) const { +fc::variant read_only::get_block(const read_only::get_block_params& params, const fc::time_point& deadline) const { signed_block_ptr block; std::optional block_num; @@ -2089,7 +2092,7 @@ fc::variant read_only::get_block(const read_only::get_block_params& params) cons ("ref_block_prefix", ref_block_prefix); } -fc::variant read_only::get_block_info(const read_only::get_block_info_params& params) const { +fc::variant read_only::get_block_info(const read_only::get_block_info_params& params, const fc::time_point& deadline) const { signed_block_ptr block; try { @@ -2118,7 +2121,7 @@ fc::variant read_only::get_block_info(const read_only::get_block_info_params& pa ("ref_block_prefix", ref_block_prefix); } -fc::variant read_only::get_block_header_state(const get_block_header_state_params& params) const { +fc::variant read_only::get_block_header_state(const get_block_header_state_params& params, const fc::time_point& deadline) const { block_state_ptr b; std::optional block_num; std::exception_ptr e; @@ -2360,7 +2363,7 @@ void read_write::send_transaction2(const read_write::send_transaction2_params& p } CATCH_AND_CALL(next); } -read_only::get_abi_results read_only::get_abi( const get_abi_params& params )const { +read_only::get_abi_results read_only::get_abi( const get_abi_params& params, const fc::time_point& deadline )const { get_abi_results result; result.account_name = params.account_name; const auto& d = db.db(); @@ -2374,7 +2377,7 @@ read_only::get_abi_results read_only::get_abi( const get_abi_params& params )con return result; } -read_only::get_code_results read_only::get_code( const get_code_params& params )const { +read_only::get_code_results read_only::get_code( const get_code_params& params, const fc::time_point& deadline )const { get_code_results result; result.account_name = params.account_name; const auto& d = db.db(); @@ -2397,7 +2400,7 @@ read_only::get_code_results read_only::get_code( const get_code_params& params ) return result; } -read_only::get_code_hash_results read_only::get_code_hash( const get_code_hash_params& params )const { +read_only::get_code_hash_results read_only::get_code_hash( const get_code_hash_params& params, const fc::time_point& deadline )const { get_code_hash_results result; result.account_name = params.account_name; const auto& d = db.db(); @@ -2409,7 +2412,7 @@ read_only::get_code_hash_results read_only::get_code_hash( const get_code_hash_p return result; } -read_only::get_raw_code_and_abi_results read_only::get_raw_code_and_abi( const get_raw_code_and_abi_params& params)const { +read_only::get_raw_code_and_abi_results read_only::get_raw_code_and_abi( const get_raw_code_and_abi_params& params, const fc::time_point& deadline)const { get_raw_code_and_abi_results result; result.account_name = params.account_name; @@ -2425,7 +2428,7 @@ read_only::get_raw_code_and_abi_results read_only::get_raw_code_and_abi( const g return result; } -read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& params )const { +read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& params, const fc::time_point& deadline )const { get_raw_abi_results result; result.account_name = params.account_name; @@ -2441,7 +2444,7 @@ read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& return result; } -read_only::get_account_results read_only::get_account( const get_account_params& params )const { +read_only::get_account_results read_only::get_account( const get_account_params& params, const fc::time_point& deadline )const { get_account_results result; result.account_name = params.account_name; @@ -2620,7 +2623,7 @@ static fc::variant action_abi_to_variant( const abi_def& abi, type_name action_t return v; }; -read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params )const try { +read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params, const fc::time_point& deadline )const try { abi_json_to_bin_result result; const auto code_account = db.db().find( params.code ); EOS_ASSERT(code_account != nullptr, contract_query_exception, "Contract can't be found ${contract}", ("contract", params.code)); @@ -2642,7 +2645,7 @@ read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::a } FC_RETHROW_EXCEPTIONS( warn, "code: ${code}, action: ${action}, args: ${args}", ("code", params.code)( "action", params.action )( "args", params.args )) -read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::abi_bin_to_json_params& params )const { +read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::abi_bin_to_json_params& params, const fc::time_point& deadline )const { abi_bin_to_json_result result; const auto& code_account = db.db().get( params.code ); abi_def abi; @@ -2655,7 +2658,7 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a return result; } -read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params )const { +read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params, const fc::time_point& deadline )const { transaction pretty_input; auto resolver = make_resolver(db, abi_serializer::create_yield_function( abi_serializer_max_time )); try { @@ -2702,12 +2705,13 @@ void read_only::compute_transaction(const compute_transaction_params& params, ne chain_plugin::handle_bad_alloc(); } CATCH_AND_CALL(next); } -read_only::get_transaction_id_result read_only::get_transaction_id( const read_only::get_transaction_id_params& params)const { +read_only::get_transaction_id_result read_only::get_transaction_id( const read_only::get_transaction_id_params& params, const fc::time_point& deadline)const { return params.id(); } -account_query_db::get_accounts_by_authorizers_result read_only::get_accounts_by_authorizers( const account_query_db::get_accounts_by_authorizers_params& args) const +account_query_db::get_accounts_by_authorizers_result +read_only::get_accounts_by_authorizers( const account_query_db::get_accounts_by_authorizers_params& args, const fc::time_point& deadline) const { EOS_ASSERT(aqdb.has_value(), plugin_config_exception, "Account Queries being accessed when not enabled"); return aqdb->get_accounts_by_authorizers(args); @@ -2753,7 +2757,7 @@ chain::symbol read_only::extract_core_symbol()const { } read_only::get_consensus_parameters_results -read_only::get_consensus_parameters(const get_consensus_parameters_params& ) const { +read_only::get_consensus_parameters(const get_consensus_parameters_params&, const fc::time_point& deadline ) const { get_consensus_parameters_results results; results.chain_config = db.get_global_properties().configuration; diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index ddf4c8132c..fd071640fa 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -91,6 +91,7 @@ class read_only { const controller& db; const std::optional& aqdb; const fc::microseconds abi_serializer_max_time; + const fc::microseconds http_max_response_time; bool shorten_abi_errors = true; const producer_plugin* producer_plug; const trx_finality_status_processing* trx_finality_status_proc; @@ -98,12 +99,26 @@ class read_only { public: static const string KEYi64; - read_only(const controller& db, const std::optional& aqdb, const fc::microseconds& abi_serializer_max_time, const producer_plugin* producer_plug, const trx_finality_status_processing* trx_finality_status_proc) - : db(db), aqdb(aqdb), abi_serializer_max_time(abi_serializer_max_time), producer_plug(producer_plug), trx_finality_status_proc(trx_finality_status_proc) { + read_only(const controller& db, const std::optional& aqdb, + const fc::microseconds& abi_serializer_max_time, const fc::microseconds& http_max_response_time, + const producer_plugin* producer_plug, + const trx_finality_status_processing* trx_finality_status_proc) + : db(db) + , aqdb(aqdb) + , abi_serializer_max_time(abi_serializer_max_time) + , http_max_response_time(http_max_response_time) + , producer_plug(producer_plug) + , trx_finality_status_proc(trx_finality_status_proc) { } void validate() const {} + // return deadline for call + fc::time_point start() const { + validate(); + return fc::time_point::now() + http_max_response_time; + } + void set_shorten_abi_errors( bool f ) { shorten_abi_errors = f; } using get_info_params = empty; @@ -134,7 +149,7 @@ class read_only { std::optional earliest_available_block_num; std::optional last_irreversible_block_time; }; - get_info_results get_info(const get_info_params&) const; + get_info_results get_info(const get_info_params&, const fc::time_point& deadline) const; struct get_transaction_status_params { chain::transaction_id_type id; @@ -155,7 +170,7 @@ class read_only { chain::block_id_type earliest_tracked_block_id; uint32_t earliest_tracked_block_number = 0; }; - get_transaction_status_results get_transaction_status(const get_transaction_status_params& params) const; + get_transaction_status_results get_transaction_status(const get_transaction_status_params& params, const fc::time_point& deadline) const; struct get_activated_protocol_features_params { @@ -171,7 +186,8 @@ class read_only { std::optional more; }; - get_activated_protocol_features_results get_activated_protocol_features( const get_activated_protocol_features_params& params )const; + get_activated_protocol_features_results + get_activated_protocol_features( const get_activated_protocol_features_params& params, const fc::time_point& deadline )const; struct producer_info { name producer_name; @@ -229,7 +245,7 @@ class read_only { name account_name; std::optional expected_core_symbol; }; - get_account_results get_account( const get_account_params& params )const; + get_account_results get_account( const get_account_params& params, const fc::time_point& deadline )const; struct get_code_results { @@ -286,11 +302,11 @@ class read_only { }; - get_code_results get_code( const get_code_params& params )const; - get_code_hash_results get_code_hash( const get_code_hash_params& params )const; - get_abi_results get_abi( const get_abi_params& params )const; - get_raw_code_and_abi_results get_raw_code_and_abi( const get_raw_code_and_abi_params& params)const; - get_raw_abi_results get_raw_abi( const get_raw_abi_params& params)const; + get_code_results get_code( const get_code_params& params, const fc::time_point& deadline )const; + get_code_hash_results get_code_hash( const get_code_hash_params& params, const fc::time_point& deadline )const; + get_abi_results get_abi( const get_abi_params& params, const fc::time_point& deadline )const; + get_raw_code_and_abi_results get_raw_code_and_abi( const get_raw_code_and_abi_params& params, const fc::time_point& deadline)const; + get_raw_abi_results get_raw_abi( const get_raw_abi_params& params, const fc::time_point& deadline)const; @@ -303,7 +319,7 @@ class read_only { vector binargs; }; - abi_json_to_bin_result abi_json_to_bin( const abi_json_to_bin_params& params )const; + abi_json_to_bin_result abi_json_to_bin( const abi_json_to_bin_params& params, const fc::time_point& deadline )const; struct abi_bin_to_json_params { @@ -315,7 +331,7 @@ class read_only { fc::variant args; }; - abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params )const; + abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params, const fc::time_point& deadline )const; struct get_required_keys_params { @@ -326,30 +342,30 @@ class read_only { flat_set required_keys; }; - get_required_keys_result get_required_keys( const get_required_keys_params& params)const; + get_required_keys_result get_required_keys( const get_required_keys_params& params, const fc::time_point& deadline)const; using get_transaction_id_params = transaction; using get_transaction_id_result = transaction_id_type; - get_transaction_id_result get_transaction_id( const get_transaction_id_params& params)const; + get_transaction_id_result get_transaction_id( const get_transaction_id_params& params, const fc::time_point& deadline)const; struct get_block_params { string block_num_or_id; }; - fc::variant get_block(const get_block_params& params) const; + fc::variant get_block(const get_block_params& params, const fc::time_point& deadline) const; struct get_block_info_params { uint32_t block_num = 0; }; - fc::variant get_block_info(const get_block_info_params& params) const; + fc::variant get_block_info(const get_block_info_params& params, const fc::time_point& deadline) const; struct get_block_header_state_params { string block_num_or_id; }; - fc::variant get_block_header_state(const get_block_header_state_params& params) const; + fc::variant get_block_header_state(const get_block_header_state_params& params, const fc::time_point& deadline) const; struct get_table_rows_params { bool json = false; @@ -373,7 +389,7 @@ class read_only { string next_key; ///< fill lower_bound with this value to fetch more rows }; - get_table_rows_result get_table_rows( const get_table_rows_params& params )const; + get_table_rows_result get_table_rows( const get_table_rows_params& params, const fc::time_point& deadline )const; struct get_table_by_scope_params { name code; // mandatory @@ -395,7 +411,7 @@ class read_only { string more; ///< fill lower_bound with this value to fetch more rows }; - get_table_by_scope_result get_table_by_scope( const get_table_by_scope_params& params )const; + get_table_by_scope_result get_table_by_scope( const get_table_by_scope_params& params, const fc::time_point& deadline )const; struct get_currency_balance_params { name code; @@ -403,7 +419,7 @@ class read_only { std::optional symbol; }; - vector get_currency_balance( const get_currency_balance_params& params )const; + vector get_currency_balance( const get_currency_balance_params& params, const fc::time_point& deadline )const; struct get_currency_stats_params { name code; @@ -417,7 +433,7 @@ class read_only { account_name issuer; }; - fc::variant get_currency_stats( const get_currency_stats_params& params )const; + fc::variant get_currency_stats( const get_currency_stats_params& params, const fc::time_point& deadline )const; struct get_producers_params { bool json = false; @@ -431,7 +447,7 @@ class read_only { string more; ///< fill lower_bound with this value to fetch more rows }; - get_producers_result get_producers( const get_producers_params& params )const; + get_producers_result get_producers( const get_producers_params& params, const fc::time_point& deadline )const; struct get_producer_schedule_params { }; @@ -442,7 +458,7 @@ class read_only { fc::variant proposed; }; - get_producer_schedule_result get_producer_schedule( const get_producer_schedule_params& params )const; + get_producer_schedule_result get_producer_schedule( const get_producer_schedule_params& params, const fc::time_point& deadline )const; struct get_scheduled_transactions_params { bool json = false; @@ -455,7 +471,7 @@ class read_only { string more; ///< fill lower_bound with this to fetch next set of transactions }; - get_scheduled_transactions_result get_scheduled_transactions( const get_scheduled_transactions_params& params ) const; + get_scheduled_transactions_result get_scheduled_transactions( const get_scheduled_transactions_params& params, const fc::time_point& deadline ) const; struct compute_transaction_results { chain::transaction_id_type transaction_id; fc::variant processed; @@ -494,7 +510,7 @@ class read_only { static uint64_t get_table_index_name(const read_only::get_table_rows_params& p, bool& primary); template - read_only::get_table_rows_result get_table_rows_by_seckey( const read_only::get_table_rows_params& p, const abi_def& abi, ConvFn conv )const { + read_only::get_table_rows_result get_table_rows_by_seckey( const read_only::get_table_rows_params& p, const abi_def& abi, const fc::time_point& deadline, ConvFn conv )const { read_only::get_table_rows_result result; const auto& d = db.db(); @@ -551,9 +567,8 @@ class read_only { auto walk_table_row_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time vector data; - for( unsigned int count = 0; cur_time <= end_time && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { const auto* itr2 = d.find( boost::make_tuple(t_id->id, itr->primary_key) ); if( itr2 == nullptr ) continue; copy_inline_row(*itr2, data); @@ -591,7 +606,7 @@ class read_only { } template - read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, const abi_def& abi )const { + read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, const abi_def& abi, const fc::time_point& deadline )const { read_only::get_table_rows_result result; const auto& d = db.db(); @@ -630,9 +645,8 @@ class read_only { auto walk_table_row_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time vector data; - for( unsigned int count = 0; cur_time <= end_time && count < p.limit && itr != end_itr; ++count, ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= deadline && count < p.limit && itr != end_itr; ++count, ++itr, cur_time = fc::time_point::now() ) { copy_inline_row(*itr, data); fc::variant data_var; @@ -667,7 +681,7 @@ class read_only { using get_accounts_by_authorizers_result = account_query_db::get_accounts_by_authorizers_result; using get_accounts_by_authorizers_params = account_query_db::get_accounts_by_authorizers_params; - get_accounts_by_authorizers_result get_accounts_by_authorizers( const get_accounts_by_authorizers_params& args) const; + get_accounts_by_authorizers_result get_accounts_by_authorizers( const get_accounts_by_authorizers_params& args, const fc::time_point& deadline) const; chain::symbol extract_core_symbol()const; @@ -676,18 +690,27 @@ class read_only { chain::chain_config chain_config; chain::wasm_config wasm_config; }; - get_consensus_parameters_results get_consensus_parameters(const get_consensus_parameters_params&) const; + get_consensus_parameters_results get_consensus_parameters(const get_consensus_parameters_params&, const fc::time_point& deadline) const; }; class read_write { controller& db; std::optional& trx_retry; const fc::microseconds abi_serializer_max_time; + const fc::microseconds http_max_response_time; const bool api_accept_transactions; public: - read_write(controller& db, std::optional& trx_retry, const fc::microseconds& abi_serializer_max_time, bool api_accept_transactions); + read_write(controller& db, std::optional& trx_retry, + const fc::microseconds& abi_serializer_max_time, const fc::microseconds& http_max_response_time, + bool api_accept_transactions); void validate() const; + // return deadline for call + fc::time_point start() const { + validate(); + return fc::time_point::now() + http_max_response_time; + } + using push_block_params = chain::signed_block; using push_block_results = empty; void push_block(push_block_params&& params, chain::plugin_interface::next_function next); @@ -803,8 +826,8 @@ class chain_plugin : public plugin { void plugin_shutdown(); void handle_sighup() override; - chain_apis::read_write get_read_write_api(); - chain_apis::read_only get_read_only_api() const; + chain_apis::read_write get_read_write_api(const fc::microseconds& http_max_response_time); + chain_apis::read_only get_read_only_api(const fc::microseconds& http_max_response_time) const; bool accept_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ); void accept_transaction(const chain::packed_transaction_ptr& trx, chain::plugin_interface::next_function next); diff --git a/plugins/chain_plugin/test/test_chain_plugin.cpp b/plugins/chain_plugin/test/test_chain_plugin.cpp index f8e31dcf5c..15b7533aa2 100644 --- a/plugins/chain_plugin/test/test_chain_plugin.cpp +++ b/plugins/chain_plugin/test/test_chain_plugin.cpp @@ -235,8 +235,8 @@ class chain_plugin_tester : public TESTER { read_only::get_account_results get_account_info(const account_name acct){ auto account_object = control->get_account(acct); read_only::get_account_params params = { account_object.name }; - chain_apis::read_only plugin(*(control.get()), {}, fc::microseconds::maximum(), {}, {}); - return plugin.get_account(params); + chain_apis::read_only plugin(*(control.get()), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); + return plugin.get_account(params, fc::time_point::maximum()); } transaction_trace_ptr setup_producer_accounts( const std::vector& accounts ) { diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index 13c4a59f10..11ddf7a081 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -287,6 +287,7 @@ class http_plugin_impl : public std::enable_shared_from_this { } my->plugin_state->max_requests_in_flight = options.at( "http-max-in-flight-requests" ).as(); my->plugin_state->max_response_time = fc::microseconds( options.at("http-max-response-time-ms").as() * 1000 ); + my->plugin_state->abi_serializer_max_time = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); my->plugin_state->validate_host = options.at("http-validate-host").as(); if( options.count( "http-alias" )) { diff --git a/plugins/http_plugin/include/eosio/http_plugin/common.hpp b/plugins/http_plugin/include/eosio/http_plugin/common.hpp index 211147ec78..91e9a6ad4f 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/common.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/common.hpp @@ -124,6 +124,7 @@ struct http_plugin_state { size_t max_bytes_in_flight = 0; int32_t max_requests_in_flight = -1; fc::microseconds max_response_time{30 * 1000}; + fc::microseconds abi_serializer_max_time; std::optional ctx;// only for ssl @@ -218,12 +219,12 @@ auto make_http_response_handler(std::shared_ptr plugin_state, return; } - // post back to an HTTP thread to to allow the response handler to be called from any thread + // post back to an HTTP thread to allow the response handler to be called from any thread boost::asio::post(plugin_state->thread_pool->get_executor(), [plugin_state, session_ptr, code, tracked_response = std::move(tracked_response)]() { try { if(tracked_response->obj().has_value()) { - std::string json = fc::json::to_string(*tracked_response->obj(), fc::time_point::now() + plugin_state->max_response_time); + std::string json = fc::json::to_string(*tracked_response->obj(), fc::time_point::now() + plugin_state->abi_serializer_max_time); auto tracked_json = make_in_flight(std::move(json), plugin_state); session_ptr->send_response(std::move(tracked_json->obj()), code); } else { diff --git a/tests/chain_plugin_tests.cpp b/tests/chain_plugin_tests.cpp index 6f9ea3a28f..cee9ab4ba3 100644 --- a/tests/chain_plugin_tests.cpp +++ b/tests/chain_plugin_tests.cpp @@ -90,10 +90,10 @@ BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, TESTER ) try { char headnumstr[20]; sprintf(headnumstr, "%d", headnum); chain_apis::read_only::get_block_params param{headnumstr}; - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); // block should be decoded successfully - std::string block_str = json::to_pretty_string(plugin.get_block(param)); + std::string block_str = json::to_pretty_string(plugin.get_block(param, fc::time_point::maximum())); BOOST_TEST(block_str.find("procassert") != std::string::npos); BOOST_TEST(block_str.find("condition") != std::string::npos); BOOST_TEST(block_str.find("Should Not Assert!") != std::string::npos); @@ -111,7 +111,7 @@ BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, TESTER ) try { BOOST_CHECK_THROW(resolver("asserter"_n), invalid_type_inside_abi); // get the same block as string, results in decode failed(invalid abi) but not exception - std::string block_str2 = json::to_pretty_string(plugin.get_block(param)); + std::string block_str2 = json::to_pretty_string(plugin.get_block(param, fc::time_point::maximum())); BOOST_TEST(block_str2.find("procassert") != std::string::npos); BOOST_TEST(block_str2.find("condition") == std::string::npos); // decode failed BOOST_TEST(block_str2.find("Should Not Assert!") == std::string::npos); // decode failed @@ -123,9 +123,9 @@ BOOST_FIXTURE_TEST_CASE( get_consensus_parameters, TESTER ) try { produce_blocks(1); chain_apis::read_only::get_info_params p; - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), nullptr, nullptr); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), nullptr, nullptr); - auto parms = plugin.get_consensus_parameters({}); + auto parms = plugin.get_consensus_parameters({}, fc::time_point::maximum()); // verifying chain_config BOOST_TEST(parms.chain_config.max_block_cpu_usage == control->get_global_properties().configuration.max_block_cpu_usage); @@ -170,11 +170,11 @@ BOOST_FIXTURE_TEST_CASE( get_account, TESTER ) try { produce_block(); - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), nullptr, nullptr); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), nullptr, nullptr); chain_apis::read_only::get_account_params p{"alice"_n}; - chain_apis::read_only::get_account_results result = plugin.read_only::get_account(p); + chain_apis::read_only::get_account_results result = plugin.read_only::get_account(p, fc::time_point::maximum()); auto check_result_basic = [](chain_apis::read_only::get_account_results result, eosio::name nm, bool isPriv) { BOOST_REQUIRE_EQUAL(nm, result.account_name); @@ -214,7 +214,7 @@ BOOST_FIXTURE_TEST_CASE( get_account, TESTER ) try { // test link authority link_authority(name("alice"_n), name("bob"_n), name("active"_n), name("foo"_n)); produce_block(); - result = plugin.read_only::get_account(p); + result = plugin.read_only::get_account(p, fc::time_point::maximum()); check_result_basic(result, name("alice"_n), false); auto perm = result.permissions[0]; @@ -232,7 +232,7 @@ BOOST_FIXTURE_TEST_CASE( get_account, TESTER ) try { // test link authority to eosio.any link_authority(name("alice"_n), name("bob"_n), name("eosio.any"_n), name("foo"_n)); produce_block(); - result = plugin.read_only::get_account(p); + result = plugin.read_only::get_account(p, fc::time_point::maximum()); check_result_basic(result, name("alice"_n), false); // active permission should no longer have linked auth, as eosio.any replaces it perm = result.permissions[0]; diff --git a/tests/get_producers_tests.cpp b/tests/get_producers_tests.cpp index 7611672ccd..b3c24c720f 100644 --- a/tests/get_producers_tests.cpp +++ b/tests/get_producers_tests.cpp @@ -16,10 +16,10 @@ using namespace eosio::testing; BOOST_AUTO_TEST_CASE( get_producers) { try { tester chain; - eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_producers_params params = { .json = true, .lower_bound = "", .limit = 21 }; - auto results = plugin.get_producers(params); + auto results = plugin.get_producers(params, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(results.more, ""); BOOST_REQUIRE_EQUAL(results.rows.size(), 1); const auto& row = results.rows[0].get_object(); @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( get_producers) { try { chain.set_producers( {"dan"_n,"sam"_n,"pam"_n} ); chain.produce_blocks(30); - results = plugin.get_producers(params); + results = plugin.get_producers(params, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(results.rows.size(), 3); auto owners = std::vector{"dan", "sam", "pam"}; auto it = owners.begin(); @@ -52,10 +52,10 @@ BOOST_AUTO_TEST_CASE( get_producers_from_table) { try { // ensure that enough voting is occurring so that producer1111 is elected as the producer chain.cross_15_percent_threshold(); - eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_producers_params params = { .json = true, .lower_bound = "", .limit = 21 }; - auto results = plugin.get_producers(params); + auto results = plugin.get_producers(params, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(results.more, ""); BOOST_REQUIRE_EQUAL(results.rows.size(), 1); const auto& row = results.rows[0].get_object(); diff --git a/tests/get_table_seckey_tests.cpp b/tests/get_table_seckey_tests.cpp index fa97dbc266..751db74684 100644 --- a/tests/get_table_seckey_tests.cpp +++ b/tests/get_table_seckey_tests.cpp @@ -42,7 +42,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { set_abi( "test"_n, contracts::get_table_seckey_test_abi().data() ); produce_block(); - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); chain_apis::read_only::get_table_rows_params params = []{ chain_apis::read_only::get_table_rows_params params{}; params.json=true; @@ -66,17 +66,17 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "6"; params.lower_bound = "a"; params.upper_bound = "a"; - auto res_nm = plugin.get_table_rows(params); + auto res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 1); params.lower_bound = "a"; params.upper_bound = "b"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 2); params.lower_bound = "a"; params.upper_bound = "c"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 3); push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 8)("nm", "1111")); @@ -85,12 +85,12 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.lower_bound = "1111"; params.upper_bound = "3333"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 3); params.lower_bound = "2222"; params.upper_bound = "3333"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 2); } FC_LOG_AND_RETHROW() /// get_table_next_key_test diff --git a/tests/get_table_tests.cpp b/tests/get_table_tests.cpp index f384495d9d..41a72b8525 100644 --- a/tests/get_table_tests.cpp +++ b/tests/get_table_tests.cpp @@ -89,9 +89,9 @@ BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try { produce_blocks(1); // iterate over scope - eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_table_by_scope_params param{"eosio.token"_n, "accounts"_n, "inita", "", 10}; - eosio::chain_apis::read_only::get_table_by_scope_result result = plugin.read_only::get_table_by_scope(param); + eosio::chain_apis::read_only::get_table_by_scope_result result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL("", result.more); @@ -109,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try { param.lower_bound = "initb"; param.upper_bound = "initc"; - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(2u, result.rows.size()); BOOST_REQUIRE_EQUAL("", result.more); if (result.rows.size() >= 2) { @@ -118,17 +118,17 @@ BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try { } param.limit = 1; - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL("initc", result.more); param.table = name(0); - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL("initc", result.more); param.table = "invalid"_n; - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(0u, result.rows.size()); BOOST_REQUIRE_EQUAL("", result.more); @@ -194,14 +194,14 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { produce_blocks(1); // get table: normal case - eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_table_rows_params p; p.code = "eosio.token"_n; p.scope = "inita"; p.table = "accounts"_n; p.json = true; p.index_position = "primary"; - eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p); + eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -213,7 +213,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { // get table: reverse ordered p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -226,7 +226,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { // get table: reverse ordered, with ram payer p.reverse = true; p.show_payer = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -245,7 +245,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = "BBB"; p.upper_bound = "CCC"; p.reverse = false; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(2u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 2) { @@ -257,7 +257,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = "BBB"; p.upper_bound = "CCC"; p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(2u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 2) { @@ -269,7 +269,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = p.upper_bound = ""; p.limit = 1; p.reverse = false; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -280,7 +280,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = p.upper_bound = ""; p.limit = 1; p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -292,7 +292,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.upper_bound = "CCC"; p.limit = 1; p.reverse = false; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -304,7 +304,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.upper_bound = "CCC"; p.limit = 1; p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -363,7 +363,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { produce_blocks(1); // get table: normal case - eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_table_rows_params p; p.code = "eosio"_n; p.scope = "eosio"; @@ -371,7 +371,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { p.json = true; p.index_position = "secondary"; // ordered by high_bid p.key_type = "i64"; - eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p); + eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -395,7 +395,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { // reverse search, with show ram payer p.reverse = true; p.show_payer = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -424,7 +424,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { p.reverse = false; p.show_payer = false; p.limit = 1; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -437,7 +437,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { p.reverse = true; p.show_payer = false; p.limit = 1; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -515,7 +515,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { // } - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); chain_apis::read_only::get_table_rows_params params = []{ chain_apis::read_only::get_table_rows_params params{}; params.json=true; @@ -532,12 +532,12 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "1"; params.lower_bound = "0"; - auto res_1 = plugin.get_table_rows(params); + auto res_1 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_1.rows.size() > 0); BOOST_TEST(res_1.rows[0].get_object()["key"].as() == 0); BOOST_TEST(res_1.next_key == "1"); params.lower_bound = res_1.next_key; - auto more2_res_1 = plugin.get_table_rows(params); + auto more2_res_1 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(more2_res_1.rows.size() > 0); BOOST_TEST(more2_res_1.rows[0].get_object()["key"].as() == 1); @@ -547,12 +547,12 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "2"; params.lower_bound = "5"; - auto res_2 = plugin.get_table_rows(params); + auto res_2 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_2.rows.size() > 0); BOOST_TEST(res_2.rows[0].get_object()["sec64"].as() == 5); BOOST_TEST(res_2.next_key == "7"); params.lower_bound = res_2.next_key; - auto more2_res_2 = plugin.get_table_rows(params); + auto more2_res_2 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(more2_res_2.rows.size() > 0); BOOST_TEST(more2_res_2.rows[0].get_object()["sec64"].as() == 7); @@ -561,13 +561,13 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "3"; params.lower_bound = "5"; - auto res_3 = plugin.get_table_rows(params); + auto res_3 = plugin.get_table_rows(params, fc::time_point::maximum()); chain::uint128_t sec128_expected_value = 5; BOOST_REQUIRE(res_3.rows.size() > 0); BOOST_CHECK(res_3.rows[0].get_object()["sec128"].as() == sec128_expected_value); BOOST_TEST(res_3.next_key == "7"); params.lower_bound = res_3.next_key; - auto more2_res_3 = plugin.get_table_rows(params); + auto more2_res_3 = plugin.get_table_rows(params, fc::time_point::maximum()); chain::uint128_t more2_sec128_expected_value = 7; BOOST_REQUIRE(more2_res_3.rows.size() > 0); BOOST_CHECK(more2_res_3.rows[0].get_object()["sec128"].as() == more2_sec128_expected_value); @@ -577,14 +577,14 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "4"; params.lower_bound = "5.0"; - auto res_4 = plugin.get_table_rows(params); + auto res_4 = plugin.get_table_rows(params, fc::time_point::maximum()); float64_t secdouble_expected_value = ui64_to_f64(5); BOOST_REQUIRE(res_4.rows.size() > 0); float64_t secdouble_res_value = res_4.rows[0].get_object()["secdouble"].as(); BOOST_CHECK(secdouble_res_value == secdouble_expected_value); BOOST_TEST(res_4.next_key == "7.00000000000000000"); params.lower_bound = res_4.next_key; - auto more2_res_4 = plugin.get_table_rows(params); + auto more2_res_4 = plugin.get_table_rows(params, fc::time_point::maximum()); float64_t more2_secdouble_expected_value = ui64_to_f64(7); BOOST_REQUIRE(more2_res_4.rows.size() > 0); float64_t more2_secdouble_res_value = more2_res_4.rows[0].get_object()["secdouble"].as(); @@ -595,14 +595,14 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "5"; params.lower_bound = "5.0"; - auto res_5 = plugin.get_table_rows(params); + auto res_5 = plugin.get_table_rows(params, fc::time_point::maximum()); float128_t secldouble_expected_value = ui64_to_f128(5); BOOST_REQUIRE(res_5.rows.size() > 0); float128_t secldouble_res_value = res_5.rows[0].get_object()["secldouble"].as(); BOOST_TEST(secldouble_res_value == secldouble_expected_value); BOOST_TEST(res_5.next_key == "7.00000000000000000"); params.lower_bound = res_5.next_key; - auto more2_res_5 = plugin.get_table_rows(params); + auto more2_res_5 = plugin.get_table_rows(params, fc::time_point::maximum()); float128_t more2_secldouble_expected_value = ui64_to_f128(7); BOOST_REQUIRE(more2_res_5.rows.size() > 0); float128_t more2_secldouble_res_value = more2_res_5.rows[0].get_object()["secldouble"].as(); @@ -615,7 +615,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "2"; params.lower_bound = "2652d68fbbf6000c703b35fdc607b09cd8218cbeea1d108b5c9e84842cdd5ea5"; // This is hash of "thirdinput" - auto res_6 = plugin.get_table_rows(params); + auto res_6 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type sec256_expected_value = checksum256_type::hash(std::string("thirdinput")); BOOST_REQUIRE(res_6.rows.size() > 0); checksum256_type sec256_res_value = res_6.rows[0].get_object()["sec256"].as(); @@ -623,7 +623,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { BOOST_TEST(res_6.rows[0].get_object()["hash_input"].as() == std::string("thirdinput")); BOOST_TEST(res_6.next_key == "3cb93a80b47b9d70c5296be3817d34b48568893b31468e3a76337bb7d3d0c264"); params.lower_bound = res_6.next_key; - auto more2_res_6 = plugin.get_table_rows(params); + auto more2_res_6 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type more2_sec256_expected_value = checksum256_type::hash(std::string("secondinput")); BOOST_REQUIRE(more2_res_6.rows.size() > 0); checksum256_type more2_sec256_res_value = more2_res_6.rows[0].get_object()["sec256"].as(); @@ -635,7 +635,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "2"; params.lower_bound = "0x2652d68fbbf6000c703b35fdc607b09cd8218cbeea1d108b5c9e84842cdd5ea5"; // This is sha256 hash of "thirdinput" as number - auto res_7 = plugin.get_table_rows(params); + auto res_7 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type i256_expected_value = checksum256_type::hash(std::string("thirdinput")); BOOST_REQUIRE(res_7.rows.size() > 0); checksum256_type i256_res_value = res_7.rows[0].get_object()["sec256"].as(); @@ -643,7 +643,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { BOOST_TEST(res_7.rows[0].get_object()["hash_input"].as() == "thirdinput"); BOOST_TEST(res_7.next_key == "0x3cb93a80b47b9d70c5296be3817d34b48568893b31468e3a76337bb7d3d0c264"); params.lower_bound = res_7.next_key; - auto more2_res_7 = plugin.get_table_rows(params); + auto more2_res_7 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type more2_i256_expected_value = checksum256_type::hash(std::string("secondinput")); BOOST_REQUIRE(more2_res_7.rows.size() > 0); checksum256_type more2_i256_res_value = more2_res_7.rows[0].get_object()["sec256"].as(); @@ -655,7 +655,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "3"; params.lower_bound = "ab4314638b573fdc39e5a7b107938ad1b5a16414"; // This is ripemd160 hash of "thirdinput" - auto res_8 = plugin.get_table_rows(params); + auto res_8 = plugin.get_table_rows(params, fc::time_point::maximum()); ripemd160 sec160_expected_value = ripemd160::hash(std::string("thirdinput")); BOOST_REQUIRE(res_8.rows.size() > 0); ripemd160 sec160_res_value = res_8.rows[0].get_object()["sec160"].as(); @@ -663,7 +663,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { BOOST_TEST(res_8.rows[0].get_object()["hash_input"].as() == "thirdinput"); BOOST_TEST(res_8.next_key == "fb9d03d3012dc2a6c7b319f914542e3423550c2a"); params.lower_bound = res_8.next_key; - auto more2_res_8 = plugin.get_table_rows(params); + auto more2_res_8 = plugin.get_table_rows(params, fc::time_point::maximum()); ripemd160 more2_sec160_expected_value = ripemd160::hash(std::string("secondinput")); BOOST_REQUIRE(more2_res_8.rows.size() > 0); ripemd160 more2_sec160_res_value = more2_res_8.rows[0].get_object()["sec160"].as(); From 06ac1bcc8c8c113663680cc9badee044322a744d Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 2 Sep 2022 10:41:30 -0500 Subject: [PATCH 018/111] Use http-max-response-time for limit on complete run of http call including time for main thread and http thread. Puts limit on complete execution including conversion to JSON. --- plugins/chain_api_plugin/chain_api_plugin.cpp | 4 +-- .../db_size_api_plugin/db_size_api_plugin.cpp | 2 +- plugins/http_plugin/http_plugin.cpp | 25 +++++++++---------- .../include/eosio/http_plugin/common.hpp | 13 +++++++--- .../include/eosio/http_plugin/http_plugin.hpp | 4 +-- plugins/login_plugin/login_plugin.cpp | 2 +- plugins/net_api_plugin/net_api_plugin.cpp | 2 +- .../producer_api_plugin.cpp | 4 +-- .../test_control_api_plugin.cpp | 2 +- plugins/trace_api_plugin/trace_api_plugin.cpp | 20 ++++++++------- .../txn_test_gen_plugin.cpp | 4 +-- .../wallet_api_plugin/wallet_api_plugin.cpp | 2 +- programs/keosd/main.cpp | 6 ++++- 13 files changed, 50 insertions(+), 40 deletions(-) diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index 79e9085611..f2a6543135 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -56,7 +56,7 @@ parse_params(body);\ FC_CHECK_DEADLINE(deadline);\ fc::variant result( api_handle.call_name( std::move(params), deadline ) ); \ - cb(http_response_code, std::move(result)); \ + cb(http_response_code, deadline, std::move(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -78,7 +78,7 @@ parse_params(body); \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index 11ddf7a081..aa854c6461 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -93,8 +93,8 @@ class http_plugin_impl : public std::enable_shared_from_this { return; } - url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, std::optional resp) { - then(code, std::move(resp)); + url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, const fc::time_point& deadline, std::optional resp) { + then(code, deadline, std::move(resp)); }; // post to the app thread taking shared ownership of next (via std::shared_ptr), @@ -287,8 +287,7 @@ class http_plugin_impl : public std::enable_shared_from_this { } my->plugin_state->max_requests_in_flight = options.at( "http-max-in-flight-requests" ).as(); my->plugin_state->max_response_time = fc::microseconds( options.at("http-max-response-time-ms").as() * 1000 ); - my->plugin_state->abi_serializer_max_time = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); - + my->plugin_state->validate_host = options.at("http-validate-host").as(); if( options.count( "http-alias" )) { const auto& aliases = options["http-alias"].as>(); @@ -431,7 +430,7 @@ class http_plugin_impl : public std::enable_shared_from_this { try { if (body.empty()) body = "{}"; auto result = (*this).get_supported_apis(); - cb(200, fc::variant(result)); + cb(200, fc::time_point::maximum(), fc::variant(result)); } catch (...) { handle_exception("node", "get_supported_apis", body, cb); } @@ -488,36 +487,36 @@ class http_plugin_impl : public std::enable_shared_from_this { throw; } catch (chain::unknown_block_exception& e) { error_results results{400, "Unknown Block", error_results::error_info(e, verbose_http_errors)}; - cb( 400, fc::variant( results )); + cb( 400, fc::time_point::maximum(), fc::variant( results )); } catch (chain::invalid_http_request& e) { error_results results{400, "Invalid Request", error_results::error_info(e, verbose_http_errors)}; - cb( 400, fc::variant( results )); + cb( 400, fc::time_point::maximum(), fc::variant( results )); } catch (chain::unsatisfied_authorization& e) { error_results results{401, "UnAuthorized", error_results::error_info(e, verbose_http_errors)}; - cb( 401, fc::variant( results )); + cb( 401, fc::time_point::maximum(), fc::variant( results )); } catch (chain::tx_duplicate& e) { error_results results{409, "Conflict", error_results::error_info(e, verbose_http_errors)}; - cb( 409, fc::variant( results )); + cb( 409, fc::time_point::maximum(), fc::variant( results )); } catch (fc::eof_exception& e) { error_results results{422, "Unprocessable Entity", error_results::error_info(e, verbose_http_errors)}; - cb( 422, fc::variant( results )); + cb( 422, fc::time_point::maximum(), fc::variant( results )); fc_elog( logger(), "Unable to parse arguments to ${api}.${call}", ("api", api_name)( "call", call_name ) ); fc_dlog( logger(), "Bad arguments: ${args}", ("args", body) ); } catch (fc::exception& e) { error_results results{500, "Internal Service Error", error_results::error_info(e, verbose_http_errors)}; - cb( 500, fc::variant( results )); + cb( 500, fc::time_point::maximum(), fc::variant( results )); fc_dlog( logger(), "Exception while processing ${api}.${call}: ${e}", ("api", api_name)( "call", call_name )("e", e.to_detail_string()) ); } catch (std::exception& e) { error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, e.what())), verbose_http_errors)}; - cb( 500, fc::variant( results )); + cb( 500, fc::time_point::maximum(), fc::variant( results )); fc_elog( logger(), "STD Exception encountered while processing ${api}.${call}", ("api", api_name)( "call", call_name ) ); fc_dlog( logger(), "Exception Details: ${e}", ("e", e.what()) ); } catch (...) { error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, "Unknown Exception" )), verbose_http_errors)}; - cb( 500, fc::variant( results )); + cb( 500, fc::time_point::maximum(), fc::variant( results )); fc_elog( logger(), "Unknown Exception encountered while processing ${api}.${call}", ("api", api_name)( "call", call_name ) ); } diff --git a/plugins/http_plugin/include/eosio/http_plugin/common.hpp b/plugins/http_plugin/include/eosio/http_plugin/common.hpp index 91e9a6ad4f..faabf789bb 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/common.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/common.hpp @@ -124,7 +124,6 @@ struct http_plugin_state { size_t max_bytes_in_flight = 0; int32_t max_requests_in_flight = -1; fc::microseconds max_response_time{30 * 1000}; - fc::microseconds abi_serializer_max_time; std::optional ctx;// only for ssl @@ -213,18 +212,24 @@ auto make_in_flight(T&& object, std::shared_ptr plugin_state) */ auto make_http_response_handler(std::shared_ptr plugin_state, detail::abstract_conn_ptr session_ptr) { return [plugin_state{std::move(plugin_state)}, - session_ptr{std::move(session_ptr)}](int code, std::optional response) { + session_ptr{std::move(session_ptr)}](int code, fc::time_point deadline, std::optional response) { auto tracked_response = make_in_flight(std::move(response), plugin_state); if(!session_ptr->verify_max_bytes_in_flight()) { return; } + auto start = fc::time_point::now(); + if( deadline == fc::time_point::maximum() ) { // no caller supplied deadline so use http configured deadline + deadline = start + plugin_state->max_response_time; + } + // post back to an HTTP thread to allow the response handler to be called from any thread boost::asio::post(plugin_state->thread_pool->get_executor(), - [plugin_state, session_ptr, code, tracked_response = std::move(tracked_response)]() { + [plugin_state, session_ptr, code, deadline, start, + tracked_response = std::move(tracked_response)]() { try { if(tracked_response->obj().has_value()) { - std::string json = fc::json::to_string(*tracked_response->obj(), fc::time_point::now() + plugin_state->abi_serializer_max_time); + std::string json = fc::json::to_string(*tracked_response->obj(), deadline + (fc::time_point::now() - start)); auto tracked_json = make_in_flight(std::move(json), plugin_state); session_ptr->send_response(std::move(tracked_json->obj()), code); } else { diff --git a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp index c8882d8fc8..a842c0b326 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp @@ -12,9 +12,9 @@ namespace eosio { * @brief A callback function provided to a URL handler to * allow it to specify the HTTP response code and body * - * Arguments: response_code, response_body + * Arguments: response_code, deadline, response_body */ - using url_response_callback = std::function)>; + using url_response_callback = std::function)>; /** * @brief Callback type for a URL handler diff --git a/plugins/login_plugin/login_plugin.cpp b/plugins/login_plugin/login_plugin.cpp index 5d1903c093..9ad2b498dc 100644 --- a/plugins/login_plugin/login_plugin.cpp +++ b/plugins/login_plugin/login_plugin.cpp @@ -65,7 +65,7 @@ void login_plugin::plugin_initialize(const variables_map& options) { if (body.empty()) \ body = "{}"; \ fc::variant result( call_name(fc::json::from_string(body).as()) ); \ - cb(http_response_code, std::move(result)); \ + cb(http_response_code, fc::time_point::maximum(), std::move(result)); \ } catch (...) { \ http_plugin::handle_exception("login", #call_name, body, cb); \ } \ diff --git a/plugins/net_api_plugin/net_api_plugin.cpp b/plugins/net_api_plugin/net_api_plugin.cpp index 6274f1189e..479ee6418d 100644 --- a/plugins/net_api_plugin/net_api_plugin.cpp +++ b/plugins/net_api_plugin/net_api_plugin.cpp @@ -24,7 +24,7 @@ using namespace eosio; [&api_handle](string, string body, url_response_callback cb) mutable { \ try { \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/plugins/producer_api_plugin/producer_api_plugin.cpp b/plugins/producer_api_plugin/producer_api_plugin.cpp index fa9f55080a..023e7bcb00 100644 --- a/plugins/producer_api_plugin/producer_api_plugin.cpp +++ b/plugins/producer_api_plugin/producer_api_plugin.cpp @@ -32,7 +32,7 @@ struct async_result_visitor : public fc::visitor { [&api_handle](string, string body, url_response_callback cb) mutable { \ try { \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -50,7 +50,7 @@ struct async_result_visitor : public fc::visitor { http_plugin::handle_exception(#api_name, #call_name, body, cb);\ }\ } else {\ - cb(http_response_code, std::visit(async_result_visitor(), result));\ + cb(http_response_code, fc::time_point::maximum(), std::visit(async_result_visitor(), result));\ }\ };\ INVOKE\ diff --git a/plugins/test_control_api_plugin/test_control_api_plugin.cpp b/plugins/test_control_api_plugin/test_control_api_plugin.cpp index 7aefdaf464..03e8be75ef 100644 --- a/plugins/test_control_api_plugin/test_control_api_plugin.cpp +++ b/plugins/test_control_api_plugin/test_control_api_plugin.cpp @@ -37,7 +37,7 @@ struct async_result_visitor : public fc::visitor { try { \ auto params = parse_params(body);\ fc::variant result( api_handle.call_name( std::move(params) ) ); \ - cb(http_response_code, std::move(result)); \ + cb(http_response_code, fc::time_point::maximum(), std::move(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/plugins/trace_api_plugin/trace_api_plugin.cpp b/plugins/trace_api_plugin/trace_api_plugin.cpp index c3c37bd24d..3279a7e68f 100644 --- a/plugins/trace_api_plugin/trace_api_plugin.cpp +++ b/plugins/trace_api_plugin/trace_api_plugin.cpp @@ -255,6 +255,8 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); + auto block_number = ([&body]() -> std::optional { if (body.empty()) { return {}; @@ -274,19 +276,18 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); auto resp = that->req_handler->get_block_trace(*block_number, [deadline]() { FC_CHECK_DEADLINE(deadline); }); if (resp.is_null()) { error_results results{404, "Trace API: block trace missing"}; - cb( 404, fc::variant( results )); + cb( 404, deadline, fc::variant( results )); } else { - cb( 200, std::move(resp) ); + cb( 200, deadline, std::move(resp) ); } } catch (...) { http_plugin::handle_exception("trace_api", "get_block", body, cb); @@ -302,6 +303,8 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); + auto trx_id = ([&body]() -> std::optional { if (body.empty()) { return {}; @@ -320,24 +323,23 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); // search for the block that contains the transaction get_block_n blk_num = common->store->get_trx_block_number(*trx_id, common->minimum_irreversible_history_blocks, [deadline]() { FC_CHECK_DEADLINE(deadline); }); if (!blk_num.has_value()){ error_results results{404, "Trace API: transaction id missing in the transaction id log files"}; - cb( 404, fc::variant( results )); + cb( 404, deadline, fc::variant( results )); } else { auto resp = that->req_handler->get_transaction_trace(*trx_id, *blk_num, [deadline]() { FC_CHECK_DEADLINE(deadline); }); if (resp.is_null()) { error_results results{404, "Trace API: transaction trace missing"}; - cb( 404, fc::variant( results )); + cb( 404, deadline, fc::variant( results )); } else { - cb( 200, std::move(resp) ); + cb( 200, deadline, std::move(resp) ); } } } catch (...) { diff --git a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp index 4715b28842..49365ad82b 100644 --- a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp +++ b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp @@ -45,7 +45,7 @@ using namespace eosio::chain; try { \ if (body.empty()) body = "{}"; \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -80,7 +80,7 @@ using namespace eosio::chain; http_plugin::handle_exception(#api_name, #call_name, body, cb);\ }\ } else {\ - cb(http_response_code, fc::variant(eosio::detail::txn_test_gen_empty())); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(eosio::detail::txn_test_gen_empty())); \ }\ };\ INVOKE \ diff --git a/plugins/wallet_api_plugin/wallet_api_plugin.cpp b/plugins/wallet_api_plugin/wallet_api_plugin.cpp index 35b18b8e3a..24ffca3f4d 100644 --- a/plugins/wallet_api_plugin/wallet_api_plugin.cpp +++ b/plugins/wallet_api_plugin/wallet_api_plugin.cpp @@ -25,7 +25,7 @@ using namespace eosio; [&api_handle](string, string body, url_response_callback cb) mutable { \ try { \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/programs/keosd/main.cpp b/programs/keosd/main.cpp index 15893cd3bb..e3391fe951 100644 --- a/programs/keosd/main.cpp +++ b/programs/keosd/main.cpp @@ -93,7 +93,11 @@ int main(int argc, char** argv) } initialize_logging(); auto& http = app().get_plugin(); - http.add_handler("/v1/" + keosd::config::key_store_executable_name + "/stop", [&a=app()](string, string, url_response_callback cb) { cb(200, fc::variant(fc::variant_object())); a.quit(); } ); + http.add_handler("/v1/" + keosd::config::key_store_executable_name + "/stop", + [&a=app()](string, string, url_response_callback cb) { + cb(200, fc::time_point::maximum(), fc::variant(fc::variant_object())); + a.quit(); + } ); app().startup(); app().exec(); } catch (const fc::exception& e) { From da60fe3ec59910c454a1ae5e70f3feb1bd2d088e Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 2 Sep 2022 11:50:08 -0500 Subject: [PATCH 019/111] Add support for time_limit_ms to API endpoints: get_activated_protocol_features, get_table_rows, get_table_by_scope, get_producers, get_scheduled_transactions --- plugins/chain_plugin/chain_plugin.cpp | 32 ++++++++-- .../eosio/chain_plugin/chain_plugin.hpp | 40 +++++++++---- programs/cleos/main.cpp | 60 +++++++++++-------- 3 files changed, 92 insertions(+), 40 deletions(-) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 349543be1d..07e00766ed 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -1505,6 +1505,9 @@ read_only::get_activated_protocol_features( const read_only::get_activated_proto if( upper_bound_value < lower_bound_value ) return result; + fc::microseconds params_time_limit = params.time_limit_ms ? fc::milliseconds(*params.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + auto walk_range = [&]( auto itr, auto end_itr, auto&& convert_iterator ) { fc::mutable_variant_object mvo; mvo( "activation_ordinal", 0 ); @@ -1515,9 +1518,10 @@ read_only::get_activated_protocol_features( const read_only::get_activated_proto auto cur_time = fc::time_point::now(); for( unsigned int count = 0; - cur_time <= deadline && count < params.limit && itr != end_itr; + cur_time <= params_deadline && count < params.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); const auto& conv_itr = convert_iterator( itr ); activation_ordinal_value = conv_itr.activation_ordinal(); activation_block_num_value = conv_itr.activation_block_num(); @@ -1766,7 +1770,12 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get #pragma GCC diagnostic pop } -read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p, const fc::time_point& deadline )const { +read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p, + const fc::time_point& deadline )const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + read_only::get_table_by_scope_result result; const auto& d = db.db(); @@ -1790,7 +1799,8 @@ read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_o auto walk_table_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - for( unsigned int count = 0; cur_time <= deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= params_deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); if( p.table && itr->table != p.table ) continue; result.rows.push_back( {itr->code, itr->scope, itr->table, itr->payer, itr->count} ); @@ -1880,7 +1890,8 @@ fc::variant get_global_row( const database& db, const abi_def& abi, const abi_se return abis.binary_to_variant(abis.get_table_type("global"_n), data, abi_serializer::create_yield_function( abi_serializer_max_time_us ), shorten_abi_errors ); } -read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& params, const fc::time_point& deadline ) const try { +read_only::get_producers_result +read_only::get_producers( const read_only::get_producers_params& params, const fc::time_point& deadline ) const try { const abi_def abi = eosio::chain_apis::get_abi(db, config::system_account_name); const auto table_type = get_table_type(abi, "producers"_n); const abi_serializer abis{ abi, abi_serializer::create_yield_function( abi_serializer_max_time ) }; @@ -1914,8 +1925,12 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p boost::make_tuple(secondary_table_id->id, lower.to_uint64_t()))); }(); + fc::microseconds params_time_limit = params.time_limit_ms ? fc::milliseconds(*params.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + for( ; it != secondary_index_by_secondary.end() && it->t_id == secondary_table_id->id; ++it ) { - if (result.rows.size() >= params.limit || fc::time_point::now() > deadline) { + FC_CHECK_DEADLINE(deadline); + if (result.rows.size() >= params.limit || fc::time_point::now() > params_deadline) { result.more = name{it->primary_key}.to_string(); break; } @@ -1986,6 +2001,10 @@ auto make_resolver(const controller& control, abi_serializer::yield_function_t y read_only::get_scheduled_transactions_result read_only::get_scheduled_transactions( const read_only::get_scheduled_transactions_params& p, const fc::time_point& deadline ) const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + const auto& d = db.db(); const auto& idx_by_delay = d.get_index(); @@ -2019,7 +2038,8 @@ read_only::get_scheduled_transactions( const read_only::get_scheduled_transactio auto resolver = make_resolver(db, abi_serializer::create_yield_function( abi_serializer_max_time )); uint32_t remaining = p.limit; - while (itr != idx_by_delay.end() && remaining > 0 && deadline > fc::time_point::now()) { + while (itr != idx_by_delay.end() && remaining > 0 && params_deadline > fc::time_point::now()) { + FC_CHECK_DEADLINE(deadline); auto row = fc::mutable_variant_object() ("trx_id", itr->trx_id) ("sender", itr->sender) diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index fd071640fa..377adb00ae 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -179,6 +179,7 @@ class read_only { uint32_t limit = 10; bool search_by_block_num = false; bool reverse = false; + std::optional time_limit_ms; // defaults to 10ms }; struct get_activated_protocol_features_results { @@ -380,7 +381,8 @@ class read_only { string index_position; // 1 - primary (first), 2 - secondary index (in order defined by multi_index), 3 - third index, etc string encode_type{"dec"}; //dec, hex , default=dec std::optional reverse; - std::optional show_payer; // show RAM pyer + std::optional show_payer; // show RAM payer + std::optional time_limit_ms; // defaults to 10ms }; struct get_table_rows_result { @@ -398,6 +400,7 @@ class read_only { string upper_bound; // upper bound of scope, optional uint32_t limit = 10; std::optional reverse; + std::optional time_limit_ms; // defaults to 10ms }; struct get_table_by_scope_result_row { name code; @@ -439,6 +442,7 @@ class read_only { bool json = false; string lower_bound; uint32_t limit = 50; + std::optional time_limit_ms; // defaults to 10ms }; struct get_producers_result { @@ -464,6 +468,7 @@ class read_only { bool json = false; string lower_bound; /// timestamp OR transaction ID uint32_t limit = 50; + std::optional time_limit_ms; // defaults to 10ms }; struct get_scheduled_transactions_result { @@ -510,7 +515,14 @@ class read_only { static uint64_t get_table_index_name(const read_only::get_table_rows_params& p, bool& primary); template - read_only::get_table_rows_result get_table_rows_by_seckey( const read_only::get_table_rows_params& p, const abi_def& abi, const fc::time_point& deadline, ConvFn conv )const { + read_only::get_table_rows_result get_table_rows_by_seckey( const read_only::get_table_rows_params& p, + const abi_def& abi, + const fc::time_point& deadline, + ConvFn conv )const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + read_only::get_table_rows_result result; const auto& d = db.db(); @@ -568,7 +580,8 @@ class read_only { auto walk_table_row_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); vector data; - for( unsigned int count = 0; cur_time <= deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= params_deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); const auto* itr2 = d.find( boost::make_tuple(t_id->id, itr->primary_key) ); if( itr2 == nullptr ) continue; copy_inline_row(*itr2, data); @@ -606,7 +619,13 @@ class read_only { } template - read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, const abi_def& abi, const fc::time_point& deadline )const { + read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, + const abi_def& abi, + const fc::time_point& deadline )const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + read_only::get_table_rows_result result; const auto& d = db.db(); @@ -646,7 +665,8 @@ class read_only { auto walk_table_row_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); vector data; - for( unsigned int count = 0; cur_time <= deadline && count < p.limit && itr != end_itr; ++count, ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= params_deadline && count < p.limit && itr != end_itr; ++count, ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); copy_inline_row(*itr, data); fc::variant data_var; @@ -878,7 +898,7 @@ FC_REFLECT(eosio::chain_apis::read_only::get_info_results, FC_REFLECT(eosio::chain_apis::read_only::get_transaction_status_params, (id) ) FC_REFLECT(eosio::chain_apis::read_only::get_transaction_status_results, (state)(block_number)(block_id)(block_timestamp)(expiration)(head_number)(head_id) (head_timestamp)(irreversible_number)(irreversible_id)(irreversible_timestamp)(earliest_tracked_block_id)(earliest_tracked_block_number) ) -FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_params, (lower_bound)(upper_bound)(limit)(search_by_block_num)(reverse) ) +FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_params, (lower_bound)(upper_bound)(limit)(search_by_block_num)(reverse)(time_limit_ms) ) FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_results, (activated_protocol_features)(more) ) FC_REFLECT(eosio::chain_apis::read_only::get_block_params, (block_num_or_id)) FC_REFLECT(eosio::chain_apis::read_only::get_block_info_params, (block_num)) @@ -887,10 +907,10 @@ FC_REFLECT(eosio::chain_apis::read_only::get_block_header_state_params, (block_n FC_REFLECT( eosio::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) ) FC_REFLECT( eosio::chain_apis::read_write::send_transaction2_params, (return_failure_trace)(retry_trx)(retry_trx_num_blocks)(transaction) ) -FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(code)(scope)(table)(table_key)(lower_bound)(upper_bound)(limit)(key_type)(index_position)(encode_type)(reverse)(show_payer) ) +FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(code)(scope)(table)(table_key)(lower_bound)(upper_bound)(limit)(key_type)(index_position)(encode_type)(reverse)(show_payer)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more)(next_key) ); -FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_params, (code)(table)(lower_bound)(upper_bound)(limit)(reverse) ) +FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_params, (code)(table)(lower_bound)(upper_bound)(limit)(reverse)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_result_row, (code)(scope)(table)(payer)(count)); FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_result, (rows)(more) ); @@ -898,13 +918,13 @@ FC_REFLECT( eosio::chain_apis::read_only::get_currency_balance_params, (code)(ac FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_params, (code)(symbol)); FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_result, (supply)(max_supply)(issuer)); -FC_REFLECT( eosio::chain_apis::read_only::get_producers_params, (json)(lower_bound)(limit) ) +FC_REFLECT( eosio::chain_apis::read_only::get_producers_params, (json)(lower_bound)(limit)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_producers_result, (rows)(total_producer_vote_weight)(more) ); FC_REFLECT_EMPTY( eosio::chain_apis::read_only::get_producer_schedule_params ) FC_REFLECT( eosio::chain_apis::read_only::get_producer_schedule_result, (active)(pending)(proposed) ); -FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_params, (json)(lower_bound)(limit) ) +FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_params, (json)(lower_bound)(limit)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_result, (transactions)(more) ); FC_REFLECT( eosio::chain_apis::read_only::account_resource_info, (used)(available)(max)(last_usage_update_time)(current_used) ) diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 3d73abf31c..3d0cf920e5 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -1420,6 +1420,7 @@ struct unapprove_producer_subcommand { struct list_producers_subcommand { bool print_json = false; uint32_t limit = 50; + uint32_t time_limit_ms = 10; std::string lower; list_producers_subcommand(CLI::App* actionRoot) { @@ -1427,15 +1428,18 @@ struct list_producers_subcommand { list_producers->add_flag("--json,-j", print_json, localized("Output in JSON format")); list_producers->add_option("-l,--limit", limit, localized("The maximum number of rows to return")); list_producers->add_option("-L,--lower", lower, localized("Lower bound value of key, defaults to first")); + list_producers->add_option("--time-limit", time_limit_ms, localized("Limit time of execution in milliseconds, defaults to 10ms")); list_producers->callback([this] { - auto rawResult = call(get_producers_func, fc::mutable_variant_object - ("json", true)("lower_bound", lower)("limit", limit)); + fc::mutable_variant_object mo; + mo("json", true)("lower_bound", lower)("limit", limit); + if( time_limit_ms != 10 ) mo("time_limit_ms", time_limit_ms); + auto rawResult = call(get_producers_func, mo); if ( print_json ) { std::cout << fc::json::to_pretty_string(rawResult) << std::endl; return; } auto result = rawResult.as(); - if ( result.rows.empty() ) { + if ( result.rows.empty() && result.more.empty() ) { std::cout << "No producers found" << std::endl; return; } @@ -3060,6 +3064,7 @@ int main( int argc, char** argv ) { string encode_type{"dec"}; bool binary = false; uint32_t limit = 10; + uint32_t time_limit_ms = 10; string index_position; bool reverse = false; bool show_payer = false; @@ -3068,6 +3073,7 @@ int main( int argc, char** argv ) { getTable->add_option( "scope", scope, localized("The scope within the contract in which the table is found") )->required(); getTable->add_option( "table", table, localized("The name of the table as specified by the contract abi") )->required(); getTable->add_option( "-l,--limit", limit, localized("The maximum number of rows to return") ); + getTable->add_option( "--time-limit", time_limit_ms, localized("Limit time of execution in milliseconds, defaults to 10ms")); getTable->add_option( "-k,--key", table_key, localized("Deprecated") ); getTable->add_option( "-L,--lower", lower, localized("JSON representation of lower bound value of key, defaults to first") ); getTable->add_option( "-U,--upper", upper, localized("JSON representation of upper bound value of key, defaults to last") ); @@ -3086,20 +3092,22 @@ int main( int argc, char** argv ) { getTable->callback([&] { - auto result = call(get_table_func, fc::mutable_variant_object("json", !binary) - ("code",code) - ("scope",scope) - ("table",table) - ("table_key",table_key) // not used - ("lower_bound",lower) - ("upper_bound",upper) - ("limit",limit) - ("key_type",key_type) - ("index_position", index_position) - ("encode_type", encode_type) - ("reverse", reverse) - ("show_payer", show_payer) - ); + fc::mutable_variant_object mo; + mo( "json", !binary ) + ( "code", code ) + ( "scope", scope ) + ( "table", table ) + ( "table_key", table_key ) // not used + ( "lower_bound", lower ) + ( "upper_bound", upper ) + ( "limit", limit ) + ( "key_type", key_type ) + ( "index_position", index_position ) + ( "encode_type", encode_type ) + ( "reverse", reverse ) + ( "show_payer", show_payer ); + if( time_limit_ms != 10 ) mo( "time_limit_ms", time_limit_ms ); + auto result = call( get_table_func, mo ); std::cout << fc::json::to_pretty_string(result) << std::endl; @@ -3109,17 +3117,21 @@ int main( int argc, char** argv ) { getScope->add_option( "contract", code, localized("The contract who owns the table") )->required(); getScope->add_option( "-t,--table", table, localized("The name of the table as filter") ); getScope->add_option( "-l,--limit", limit, localized("The maximum number of rows to return") ); + getScope->add_option( "--time-limit", time_limit_ms, localized("Limit time of execution in milliseconds, defaults to 10ms")); getScope->add_option( "-L,--lower", lower, localized("Lower bound of scope") ); getScope->add_option( "-U,--upper", upper, localized("Upper bound of scope") ); getScope->add_flag("-r,--reverse", reverse, localized("Iterate in reverse order")); getScope->callback([&] { - auto result = call(get_table_by_scope_func, fc::mutable_variant_object("code",code) - ("table",table) - ("lower_bound",lower) - ("upper_bound",upper) - ("limit",limit) - ("reverse", reverse) - ); + fc::mutable_variant_object mo; + mo( "code", code ) + ( "table", table ) + ( "lower_bound", lower ) + ( "upper_bound", upper ) + ( "limit", limit ) + ( "reverse", reverse ); + if( time_limit_ms != 10 ) mo( "time_limit_ms", time_limit_ms ); + auto result = call( get_table_by_scope_func, mo ); + std::cout << fc::json::to_pretty_string(result) << std::endl; }); From 30736e9b0c3fc934c67e6e5095150585d3ba6053 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 2 Sep 2022 12:30:44 -0500 Subject: [PATCH 020/111] Support -1 for http-max-response-time-ms for unlimited. --- plugins/http_plugin/http_plugin.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index aa854c6461..6e91cf0020 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -253,8 +253,8 @@ class http_plugin_impl : public std::enable_shared_from_this { "Maximum size in megabytes http_plugin should use for processing http requests. -1 for unlimited. 429 error response when exceeded." ) ("http-max-in-flight-requests", bpo::value()->default_value(-1), "Maximum number of requests http_plugin should use for processing http requests. 429 error response when exceeded." ) - ("http-max-response-time-ms", bpo::value()->default_value(30), - "Maximum time for processing a request.") + ("http-max-response-time-ms", bpo::value()->default_value(30), + "Maximum time for processing a request, -1 for unlimited") ("verbose-http-errors", bpo::bool_switch()->default_value(false), "Append the error log to HTTP responses") ("http-validate-host", boost::program_options::value()->default_value(true), @@ -286,7 +286,12 @@ class http_plugin_impl : public std::enable_shared_from_this { my->plugin_state->max_bytes_in_flight = max_bytes_mb * 1024 * 1024; } my->plugin_state->max_requests_in_flight = options.at( "http-max-in-flight-requests" ).as(); - my->plugin_state->max_response_time = fc::microseconds( options.at("http-max-response-time-ms").as() * 1000 ); + int64_t max_reponse_time_ms = options.at("http-max-response-time-ms").as(); + EOS_ASSERT( max_reponse_time_ms == -1 || max_reponse_time_ms >= 0, chain::plugin_config_exception, + "http-max-response-time-ms must be -1, or non-negative: ${m}", ("m", max_reponse_time_ms) ); + // set to one year for -1, unlimited, since this is added to fc::time_point::now() for a deadline + my->plugin_state->max_response_time = max_reponse_time_ms == -1 ? + fc::days(365) : fc::microseconds( max_reponse_time_ms * 1000 ); my->plugin_state->validate_host = options.at("http-validate-host").as(); if( options.count( "http-alias" )) { From 39d2830104b02f2dd13c0cadae78bae52028376e Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Tue, 6 Sep 2022 17:36:19 -0500 Subject: [PATCH 021/111] undo changes to nodeos for json snapshots. --- plugins/chain_plugin/chain_plugin.cpp | 116 +++++++------------------- 1 file changed, 29 insertions(+), 87 deletions(-) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 203de56dc7..85c9d8c766 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -161,7 +161,6 @@ class chain_plugin_impl { std::optional wasm_runtime; fc::microseconds abi_serializer_max_time_us; std::optional snapshot_path; - snapshot_reader_ptr snapshot_json_reader_ptr; // retained references to channels for easy publication @@ -361,8 +360,6 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "print build environment information to console as JSON and exit") ("extract-build-info", bpo::value(), "extract build environment information as JSON, write into specified file, and exit") - ("snapshot-to-json", bpo::value(), - "snapshot file to convert to JSON format, writes to .json (tmp state dir used), and exit") ("force-all-checks", bpo::bool_switch()->default_value(false), "do not skip any validation checks while replaying blocks (useful for replaying blocks from untrusted source)") ("disable-replay-opts", bpo::bool_switch()->default_value(false), @@ -377,7 +374,7 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "stop hard replay / block log recovery at this block number (if set to non-zero number)") ("terminate-at-block", bpo::value()->default_value(0), "terminate after reaching this block number (if set to a non-zero number)") - ("snapshot", bpo::value(), "File to read snapshot state from, .json extension for JSON input.") + ("snapshot", bpo::value(), "File to read Snapshot State from") ; } @@ -865,58 +862,6 @@ void chain_plugin::plugin_initialize(const variables_map& options) { EOS_THROW( extract_genesis_state_exception, "extracted genesis state from blocks.log" ); } - std::optional chain_id; - if( options.count("snapshot-to-json") ) { - my->snapshot_path = options.at( "snapshot-to-json" ).as(); - EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception, - "Cannot load snapshot, ${name} does not exist", ("name", my->snapshot_path->generic_string()) ); - - // recover genesis information from the snapshot - // used for validation code below - auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); - istream_snapshot_reader reader(infile); - reader.validate(); - chain_id = controller::extract_chain_id(reader); - infile.close(); - - boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - my->chain_config->state_dir = temp_dir / "state"; - my->blocks_dir = temp_dir / "blocks"; - my->chain_config->blocks_dir = my->blocks_dir; - try { - auto shutdown = [](){ return app().quit(); }; - auto check_shutdown = [](){ return app().is_quiting(); }; - auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); - auto reader = std::make_shared(infile); - my->chain.emplace( *my->chain_config, std::move(pfs), *chain_id ); - my->chain->add_indices(); - my->chain->startup(shutdown, check_shutdown, reader); - infile.close(); - EOS_ASSERT( !app().is_quiting(), snapshot_exception, "Loading of snapshot failed" ); - app().quit(); // shutdown as we will be finished after writing the snapshot - - ilog("Writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json")); - auto snap_out = std::ofstream( my->snapshot_path->generic_string() + ".json", (std::ios::out) ); - auto writer = std::make_shared( snap_out ); - my->chain->write_snapshot( writer ); - writer->finalize(); - snap_out.flush(); - snap_out.close(); - } catch (const database_guard_exception& e) { - log_guard_exception(e); - // make sure to properly close the db - my->chain.reset(); - fc::remove_all(temp_dir); - throw; - } - my->chain.reset(); - fc::remove_all(temp_dir); - ilog("Completed writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json")); - ilog("==== Ignore any additional log messages. ===="); - - EOS_THROW( node_management_success, "extracted json from snapshot" ); - } - // move fork_db to new location upgrade_from_reversible_to_fork_db( my.get() ); @@ -953,45 +898,46 @@ void chain_plugin::plugin_initialize(const variables_map& options) { wlog( "The --truncate-at-block option can only be used with --hard-replay-blockchain." ); } + std::optional chain_id; if (options.count( "snapshot" )) { - bfs::path snap_path = options.at( "snapshot" ).as(); - EOS_ASSERT( fc::exists(snap_path), plugin_config_exception, - "Cannot load snapshot, ${name} does not exist", ("name", snap_path.generic_string()) ); - my->snapshot_path = snap_path; - - if( my->snapshot_path->extension().generic_string().compare( ".json" ) == 0 ) { - ilog("Reading JSON snapshot, this may take a significant amount of time."); - my->snapshot_json_reader_ptr.reset( new istream_json_snapshot_reader(snap_path) ); - my->snapshot_json_reader_ptr->validate(); - chain_id = controller::extract_chain_id(*my->snapshot_json_reader_ptr); - } else { - std::ifstream infile = std::ifstream(snap_path.generic_string(), (std::ios::in | std::ios::binary)); - istream_snapshot_reader reader(infile); - reader.validate(); - chain_id = controller::extract_chain_id(reader); - } + my->snapshot_path = options.at( "snapshot" ).as(); + EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception, + "Cannot load snapshot, ${name} does not exist", ("name", my->snapshot_path->generic_string()) ); + + // recover genesis information from the snapshot + // used for validation code below + auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); + istream_snapshot_reader reader(infile); + reader.validate(); + chain_id = controller::extract_chain_id(reader); + infile.close(); - EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, plugin_config_exception, - "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information"); - EOS_ASSERT( options.count( "genesis-json" ) == 0, plugin_config_exception, + EOS_ASSERT( options.count( "genesis-timestamp" ) == 0, + plugin_config_exception, + "--snapshot is incompatible with --genesis-timestamp as the snapshot contains genesis information"); + EOS_ASSERT( options.count( "genesis-json" ) == 0, + plugin_config_exception, "--snapshot is incompatible with --genesis-json as the snapshot contains genesis information"); auto shared_mem_path = my->chain_config->state_dir / "shared_memory.bin"; - EOS_ASSERT( !fc::is_regular_file(shared_mem_path), plugin_config_exception, - "A snapshot can only be used to initialize an empty database." ); + EOS_ASSERT( !fc::is_regular_file(shared_mem_path), + plugin_config_exception, + "Snapshot can only be used to initialize an empty database." ); if( fc::is_regular_file( my->blocks_dir / "blocks.log" )) { auto block_log_genesis = block_log::extract_genesis_state(my->blocks_dir); if( block_log_genesis ) { const auto& block_log_chain_id = block_log_genesis->compute_chain_id(); - EOS_ASSERT( *chain_id == block_log_chain_id, plugin_config_exception, + EOS_ASSERT( *chain_id == block_log_chain_id, + plugin_config_exception, "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID from the genesis state in the block log (${block_log_chain_id})", ("snapshot_chain_id", *chain_id) ("block_log_chain_id", block_log_chain_id) ); } else { const auto& block_log_chain_id = block_log::extract_chain_id(my->blocks_dir); - EOS_ASSERT( *chain_id == block_log_chain_id, plugin_config_exception, + EOS_ASSERT( *chain_id == block_log_chain_id, + plugin_config_exception, "snapshot chain ID (${snapshot_chain_id}) does not match the chain ID (${block_log_chain_id}) in the block log", ("snapshot_chain_id", *chain_id) ("block_log_chain_id", block_log_chain_id) @@ -1317,14 +1263,10 @@ void chain_plugin::plugin_startup() auto shutdown = [](){ return app().quit(); }; auto check_shutdown = [](){ return app().is_quiting(); }; if (my->snapshot_path) { - if( my->snapshot_json_reader_ptr ) { - my->chain->startup(shutdown, check_shutdown, my->snapshot_json_reader_ptr); - my->snapshot_json_reader_ptr.reset(); - } else { - auto infile = std::ifstream( my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary) ); - auto reader = std::make_shared( infile ); - my->chain->startup( shutdown, check_shutdown, reader ); - } + auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); + auto reader = std::make_shared(infile); + my->chain->startup(shutdown, check_shutdown, reader); + infile.close(); } else if( my->genesis ) { my->chain->startup(shutdown, check_shutdown, *my->genesis); } else { From 37845160864a859d7d0fb65a8041cabf0febc04f Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Wed, 7 Sep 2022 15:13:24 -0400 Subject: [PATCH 022/111] validate input of set_whitelist_blacklist, add_greylist_accounts and remove_greylist_accounts --- plugins/producer_plugin/producer_plugin.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 8e4a7919cb..21af51690e 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1335,6 +1335,8 @@ producer_plugin::runtime_options producer_plugin::get_runtime_options() const { } void producer_plugin::add_greylist_accounts(const greylist_params& params) { + EOS_ASSERT(params.accounts.size() > 0, chain::invalid_http_request, "At least one account is required"); + chain::controller& chain = my->chain_plug->chain(); for (auto &acc : params.accounts) { chain.add_resource_greylist(acc); @@ -1342,6 +1344,8 @@ void producer_plugin::add_greylist_accounts(const greylist_params& params) { } void producer_plugin::remove_greylist_accounts(const greylist_params& params) { + EOS_ASSERT(params.accounts.size() > 0, chain::invalid_http_request, "At least one account is required"); + chain::controller& chain = my->chain_plug->chain(); for (auto &acc : params.accounts) { chain.remove_resource_greylist(acc); @@ -1372,6 +1376,11 @@ producer_plugin::whitelist_blacklist producer_plugin::get_whitelist_blacklist() } void producer_plugin::set_whitelist_blacklist(const producer_plugin::whitelist_blacklist& params) { + EOS_ASSERT(params.actor_whitelist || params.actor_blacklist || params.contract_whitelist || params.contract_blacklist || params.action_blacklist || params.key_blacklist, + chain::invalid_http_request, + "At least one of actor_whitelist, actor_blacklist, contract_whitelist, contract_blacklist, action_blacklist, and key_blacklist is required" + ); + chain::controller& chain = my->chain_plug->chain(); if(params.actor_whitelist) chain.set_actor_whitelist(*params.actor_whitelist); if(params.actor_blacklist) chain.set_actor_blacklist(*params.actor_blacklist); From 1364041fb6ec1114ed3eaf7b27ca6ab941732dc7 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 8 Sep 2022 14:33:32 +0200 Subject: [PATCH 023/111] .gitignore: Don't ignore package.cmake --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8bf88545cc..7083c29c68 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.abi.hpp *.cmake !.cicd +!package.cmake !CMakeModules/*.cmake *.ninja \#* From f3d95914534627e698d99681c43794f59cd3e466 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 8 Sep 2022 14:34:21 +0200 Subject: [PATCH 024/111] package.cmake: Proper setup .deb filename in CPACK_DEBIAN_FILE_NAME variable. --- package.cmake | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/package.cmake b/package.cmake index 66f01e6195..c782db15c7 100644 --- a/package.cmake +++ b/package.cmake @@ -21,6 +21,20 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.9" AND EXISTS /etc/os-release) string(APPEND CPACK_PACKAGE_FILE_NAME "-el${CMAKE_MATCH_1}") endif() endif() + +# Fix debian package filename as it should have the format: +# __.deb + +# Find architecture using dpkg +if (DPKG_FOUND) + execute_process(COMMAND bash -c "${DPKG_FOUND} --print-architecture" + OUTPUT_VARIABLE DEB_ARCH + OUTPUT_STRIP_TRAILING_WHITESPACE) +else() + set(DEB_ARCH "${CMAKE_SYSTEM_PROCESSOR}") +endif() +string(REGEX REPLACE "^${CMAKE_PROJECT_NAME}-(.*)$" "${CMAKE_PROJECT_NAME}_\\1_${DEB_ARCH}" CPACK_DEBIAN_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") + string(APPEND CPACK_PACKAGE_FILE_NAME "-${CMAKE_SYSTEM_PROCESSOR}") set(CPACK_PACKAGE_CONTACT "EOS Network Foundation") From c325c1746e7f0710d22fef1b525d17c6e91710b8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 8 Sep 2022 14:38:12 +0200 Subject: [PATCH 025/111] package.cmake: use CPACK_DEBIAN_FILE_NAME when setting CPACK_DEBIAN_BASE_FILE_NAME --- package.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.cmake b/package.cmake index c782db15c7..c95742d800 100644 --- a/package.cmake +++ b/package.cmake @@ -57,7 +57,7 @@ list(REMOVE_ITEM CPACK_COMPONENTS_ALL "Unspecified") #enable per component packages for .deb; ensure main package is just "leap", not "leap-base", and make the dev package have "leap-dev" at the front not the back set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_BASE_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") -set(CPACK_DEBIAN_BASE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.deb") +set(CPACK_DEBIAN_BASE_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.deb") string(REGEX REPLACE "^(${CMAKE_PROJECT_NAME})" "\\1-dev" CPACK_DEBIAN_DEV_FILE_NAME "${CPACK_DEBIAN_BASE_FILE_NAME}") #deb package tooling will be unable to detect deps for the dev package. llvm is tricky since we don't know what package could have been used; try to figure it out From 086ba23c0c9cff391669aa6c9edcc32276b57af8 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 8 Sep 2022 08:27:58 -0500 Subject: [PATCH 026/111] uint32_t for microseconds of subjective billing only allows for 1.2hrs before wrapping. Use int64_t instead which matches type used for objective billing. --- libraries/chain/controller.cpp | 4 ++-- libraries/chain/include/eosio/chain/controller.hpp | 2 +- .../chain/include/eosio/chain/transaction_context.hpp | 2 +- .../include/eosio/producer_plugin/producer_plugin.hpp | 2 +- .../eosio/producer_plugin/subjective_billing.hpp | 10 +++++----- plugins/producer_plugin/producer_plugin.cpp | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index e517e4544b..3e1c3c746b 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -1452,7 +1452,7 @@ struct controller_impl { fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time, - uint32_t subjective_cpu_bill_us ) + int64_t subjective_cpu_bill_us ) { EOS_ASSERT(block_deadline != fc::time_point(), transaction_exception, "deadline cannot be uninitialized"); @@ -2824,7 +2824,7 @@ void controller::push_block( std::future& block_state_future, transaction_trace_ptr controller::push_transaction( const transaction_metadata_ptr& trx, fc::time_point block_deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time, - uint32_t subjective_cpu_bill_us ) { + int64_t subjective_cpu_bill_us ) { validate_db_available_size(); EOS_ASSERT( get_read_mode() != db_read_mode::IRREVERSIBLE, transaction_type_exception, "push transaction not allowed in irreversible mode" ); EOS_ASSERT( trx && !trx->implicit && !trx->scheduled, transaction_type_exception, "Implicit/Scheduled transaction not allowed" ); diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 142f09c5a1..3267495ece 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -152,7 +152,7 @@ namespace eosio { namespace chain { transaction_trace_ptr push_transaction( const transaction_metadata_ptr& trx, fc::time_point deadline, fc::microseconds max_transaction_time, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time, - uint32_t subjective_cpu_bill_us ); + int64_t subjective_cpu_bill_us ); /** * Attempt to execute a specific transaction in our deferred trx database diff --git a/libraries/chain/include/eosio/chain/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp index 5c850c1436..aa0d7acff3 100644 --- a/libraries/chain/include/eosio/chain/transaction_context.hpp +++ b/libraries/chain/include/eosio/chain/transaction_context.hpp @@ -144,7 +144,7 @@ namespace eosio { namespace chain { fc::time_point block_deadline = fc::time_point::maximum(); fc::microseconds leeway = fc::microseconds( config::default_subjective_cpu_leeway_us ); int64_t billed_cpu_time_us = 0; - uint32_t subjective_cpu_bill_us = 0; + int64_t subjective_cpu_bill_us = 0; bool explicit_billed_cpu_time = false; transaction_checktime_timer transaction_timer; diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp index f41560d8af..60ebca0a25 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp @@ -84,7 +84,7 @@ class producer_plugin : public appbase::plugin { bool is_producer_key(const chain::public_key_type& key) const; chain::signature_type sign_compact(const chain::public_key_type& key, const fc::sha256& digest) const; - uint32_t get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const; + int64_t get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const; virtual void plugin_initialize(const boost::program_options::variables_map& options); virtual void plugin_startup(); diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/subjective_billing.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/subjective_billing.hpp index 8b10477488..ad72825f3f 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/subjective_billing.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/subjective_billing.hpp @@ -28,7 +28,7 @@ class subjective_billing { struct trx_cache_entry { transaction_id_type trx_id; account_name account; - uint32_t subjective_cpu_bill; + int64_t subjective_cpu_bill; fc::time_point expiry; }; struct by_id; @@ -121,7 +121,7 @@ class subjective_billing { const fc::microseconds& elapsed, bool in_pending_block ) { if( !_disabled && !_disabled_accounts.count( first_auth ) ) { - uint32_t bill = std::max( 0, elapsed.count() ); + int64_t bill = std::max( 0, elapsed.count() ); auto p = _trx_cache_index.emplace( trx_cache_entry{id, first_auth, @@ -139,13 +139,13 @@ class subjective_billing { void subjective_bill_failure( const account_name& first_auth, const fc::microseconds& elapsed, const fc::time_point& now ) { if( !_disabled && !_disabled_accounts.count( first_auth ) ) { - uint32_t bill = std::max( 0, elapsed.count() ); + int64_t bill = std::max( 0, elapsed.count() ); const auto time_ordinal = time_ordinal_for(now); _account_subjective_bill_cache[first_auth].expired_accumulator.add(bill, time_ordinal, _expired_accumulator_average_window); } } - uint32_t get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const { + int64_t get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const { if( _disabled || _disabled_accounts.count( first_auth ) ) return 0; const auto time_ordinal = time_ordinal_for(now); const subjective_billing_info* sub_bill_info = nullptr; @@ -161,7 +161,7 @@ class subjective_billing { if (sub_bill_info) { EOS_ASSERT(sub_bill_info->pending_cpu_us >= in_block_pending_cpu_us, chain::tx_resource_exhaustion, "Logic error subjective billing ${a}", ("a", first_auth) ); - uint32_t sub_bill = sub_bill_info->pending_cpu_us - in_block_pending_cpu_us + sub_bill_info->expired_accumulator.value_at(time_ordinal, _expired_accumulator_average_window ); + int64_t sub_bill = sub_bill_info->pending_cpu_us - in_block_pending_cpu_us + sub_bill_info->expired_accumulator.value_at(time_ordinal, _expired_accumulator_average_window ); return sub_bill; } else { return 0; diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 8e4a7919cb..59132f3210 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -688,7 +688,7 @@ class producer_plugin_impl : public std::enable_shared_from_thisread_only; - uint32_t sub_bill = 0; + int64_t sub_bill = 0; if( !disable_subjective_billing ) sub_bill = _subjective_billing.get_subjective_bill( first_auth, fc::time_point::now() ); @@ -909,7 +909,7 @@ bool producer_plugin::is_producer_key(const chain::public_key_type& key) const return false; } -uint32_t producer_plugin::get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const +int64_t producer_plugin::get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const { return my->_subjective_billing.get_subjective_bill( first_auth, now ); } @@ -2032,7 +2032,7 @@ bool producer_plugin_impl::process_unapplied_trxs( const fc::time_point& deadlin } // no subjective billing since we are producing or processing persisted trxs - const uint32_t sub_bill = 0; + const int64_t sub_bill = 0; bool disable_subjective_billing = ( _pending_block_mode == pending_block_mode::producing ) || ( (itr->trx_type == trx_enum_type::persisted) && _disable_subjective_api_billing ) || ( !(itr->trx_type == trx_enum_type::persisted) && _disable_subjective_p2p_billing ) From c489ba4c195a78ade70a85523c502224d74f5084 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 9 Sep 2022 08:43:47 -0500 Subject: [PATCH 027/111] GH-115 No harm in sending a handshake when no block has ever been received. --- plugins/net_plugin/net_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 310b0f2df6..c8f4151844 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -1161,7 +1161,7 @@ namespace eosio { close(false); } return; - } else if( latest_blk_time > 0 ) { + } else { const tstamp timeout = std::max(hb_timeout/2, 2*std::chrono::milliseconds(config::block_interval_ms).count()); if ( current_time > latest_blk_time + timeout ) { send_handshake(); From e46a6386dfe4848885182f8cb089638105c80598 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 9 Sep 2022 12:29:54 -0500 Subject: [PATCH 028/111] GH-127 Verify on the correct fork before verifying trx status --- tests/trx_finality_status_forked_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/trx_finality_status_forked_test.py b/tests/trx_finality_status_forked_test.py index 4063539d41..5e2b218f17 100755 --- a/tests/trx_finality_status_forked_test.py +++ b/tests/trx_finality_status_forked_test.py @@ -240,6 +240,7 @@ def getState(status): f"\n\nprod 0 info: {json.dumps(prodNodes[0].getInfo(), indent=1)}\n\nprod 1 info: {json.dumps(prodNodes[1].getInfo(), indent=1)}" afterForkInBlockState = retStatus + afterForkBlockId = retStatus["block_id"] assert afterForkInBlockState["block_number"] > originalInBlockState["block_number"], \ "ERROR: The way the test is designed, the transaction should be added to a block that has a higher number than it was in originally before it was forked out." + \ f"\n\noriginal in block state: {json.dumps(originalInBlockState, indent=1)}\n\nafter fork in block state: {json.dumps(afterForkInBlockState, indent=1)}" @@ -248,6 +249,12 @@ def getState(status): f"ERROR: Block never finalized.\n\nprod 0 info: {json.dumps(prodNodes[0].getInfo(), indent=1)}\n\nprod 1 info: {json.dumps(prodNodes[1].getInfo(), indent=1)}" + \ f"\n\nafter fork in block state: {json.dumps(afterForkInBlockState, indent=1)}" + retStatus = prodNodes[1].getTransactionStatus(transId) + if afterForkBlockId != retStatus["block_id"]: # might have been forked out, if so wait for new block to become LIB + assert prodNodes[1].waitForBlock(retStatus["block_number"], blockType=BlockType.lib), \ + f"ERROR: Block never finalized.\n\nprod 0 info: {json.dumps(prodNodes[0].getInfo(), indent=1)}\n\nprod 1 info: {json.dumps(prodNodes[1].getInfo(), indent=1)}" + \ + f"\n\nafter fork in block state: {json.dumps(afterForkInBlockState, indent=1)}" + retStatus = prodNodes[1].getTransactionStatus(transId) state = getState(retStatus) From ac0cf77f5a3e488bcf089da1bcf809f448272a2c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 9 Sep 2022 14:37:33 -0500 Subject: [PATCH 029/111] GH-115 Only reset sync_source if actually used. Otherwise code is expecting a response from a different source than sync_source. --- plugins/net_plugin/net_plugin.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index c8f4151844..5a262716bd 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -1618,28 +1618,29 @@ namespace eosio { * otherwise select the next available from the list, round-robin style. */ + connection_ptr new_sync_source = sync_source; if (conn && conn->current() ) { - sync_source = conn; + new_sync_source = conn; } else { std::shared_lock g( my_impl->connections_mtx ); if( my_impl->connections.size() == 0 ) { - sync_source.reset(); + new_sync_source.reset(); } else if( my_impl->connections.size() == 1 ) { - if (!sync_source) { - sync_source = *my_impl->connections.begin(); + if (!new_sync_source) { + new_sync_source = *my_impl->connections.begin(); } } else { // init to a linear array search auto cptr = my_impl->connections.begin(); auto cend = my_impl->connections.end(); // do we remember the previous source? - if (sync_source) { + if (new_sync_source) { //try to find it in the list - cptr = my_impl->connections.find( sync_source ); + cptr = my_impl->connections.find( new_sync_source ); cend = cptr; if( cptr == my_impl->connections.end() ) { //not there - must have been closed! cend is now connections.end, so just flatten the ring. - sync_source.reset(); + new_sync_source.reset(); cptr = my_impl->connections.begin(); } else { //was found - advance the start to the next. cend is the old source. @@ -1657,7 +1658,7 @@ namespace eosio { if( !(*cptr)->is_transactions_only_connection() && (*cptr)->current() ) { std::lock_guard g_conn( (*cptr)->conn_mtx ); if( (*cptr)->last_handshake_recv.last_irreversible_block_num >= sync_known_lib_num ) { - sync_source = *cptr; + new_sync_source = *cptr; break; } } @@ -1670,8 +1671,9 @@ namespace eosio { } // verify there is an available source - if( !sync_source || !sync_source->current() || sync_source->is_transactions_only_connection() ) { + if( !new_sync_source || !new_sync_source->current() || new_sync_source->is_transactions_only_connection() ) { fc_elog( logger, "Unable to continue syncing at this time"); + if( !new_sync_source ) sync_source.reset(); sync_known_lib_num = lib_block_num; reset_last_requested_num(g_sync); set_state( in_sync ); // probably not, but we can't do anything else @@ -1686,12 +1688,12 @@ namespace eosio { end = sync_known_lib_num; if( end > 0 && end >= start ) { sync_last_requested_num = end; - connection_ptr c = sync_source; + sync_source = new_sync_source; g_sync.unlock(); request_sent = true; - c->strand.post( [c, start, end]() { - peer_ilog( c, "requesting range ${s} to ${e}", ("s", start)("e", end) ); - c->request_sync_blocks( start, end ); + new_sync_source->strand.post( [new_sync_source, start, end]() { + peer_ilog( new_sync_source, "requesting range ${s} to ${e}", ("s", start)("e", end) ); + new_sync_source->request_sync_blocks( start, end ); } ); } } From 474acaaf92f9169b5919f753326c1b087c1774e7 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Fri, 9 Sep 2022 16:30:13 -0400 Subject: [PATCH 030/111] Revert "remove YubiHSM support from keosd" --- .cicd/platforms/ubuntu18.Dockerfile | 3 + .cicd/platforms/ubuntu20.Dockerfile | 3 + .cicd/platforms/ubuntu22.Dockerfile | 3 + .gitmodules | 3 + CMakeLists.txt | 4 + README.md | 12 +- docs/03_keosd/10_usage.md | 5 + .../how-to-attach-a-yubihsm-hard-wallet.md | 73 +++++ docs/03_keosd/30_how-to-guides/index.md | 5 + libraries/CMakeLists.txt | 14 + libraries/yubihsm | 1 + plugins/wallet_plugin/CMakeLists.txt | 6 +- .../eosio/wallet_plugin/yubihsm_wallet.hpp | 41 +++ plugins/wallet_plugin/wallet_plugin.cpp | 14 + plugins/wallet_plugin/yubihsm_wallet.cpp | 268 ++++++++++++++++++ scripts/install_deps.sh | 2 +- 16 files changed, 451 insertions(+), 6 deletions(-) create mode 100644 docs/03_keosd/30_how-to-guides/how-to-attach-a-yubihsm-hard-wallet.md create mode 100644 docs/03_keosd/30_how-to-guides/index.md create mode 160000 libraries/yubihsm create mode 100644 plugins/wallet_plugin/include/eosio/wallet_plugin/yubihsm_wallet.hpp create mode 100644 plugins/wallet_plugin/yubihsm_wallet.cpp diff --git a/.cicd/platforms/ubuntu18.Dockerfile b/.cicd/platforms/ubuntu18.Dockerfile index 9620ac7891..256ba84186 100644 --- a/.cicd/platforms/ubuntu18.Dockerfile +++ b/.cicd/platforms/ubuntu18.Dockerfile @@ -7,10 +7,13 @@ RUN apt-get update && apt-get upgrade -y && \ g++-8 \ git \ jq \ + libcurl4-openssl-dev \ libgmp-dev \ libssl-dev \ + libusb-1.0-0-dev \ llvm-7-dev \ ninja-build \ + pkg-config \ python3 \ software-properties-common \ zlib1g-dev \ diff --git a/.cicd/platforms/ubuntu20.Dockerfile b/.cicd/platforms/ubuntu20.Dockerfile index e6d8d3b68f..a2fcb2763a 100644 --- a/.cicd/platforms/ubuntu20.Dockerfile +++ b/.cicd/platforms/ubuntu20.Dockerfile @@ -7,8 +7,11 @@ RUN apt-get update && apt-get upgrade -y && \ git \ jq \ libboost-all-dev \ + libcurl4-openssl-dev \ libgmp-dev \ libssl-dev \ + libusb-1.0-0-dev \ llvm-11-dev \ ninja-build \ + pkg-config \ zstd diff --git a/.cicd/platforms/ubuntu22.Dockerfile b/.cicd/platforms/ubuntu22.Dockerfile index 38aeaa40a4..a0c3b096a1 100644 --- a/.cicd/platforms/ubuntu22.Dockerfile +++ b/.cicd/platforms/ubuntu22.Dockerfile @@ -7,8 +7,11 @@ RUN apt-get update && apt-get upgrade -y && \ git \ jq \ libboost-all-dev \ + libcurl4-openssl-dev \ libgmp-dev \ libssl-dev \ + libusb-1.0-0-dev \ llvm-11-dev \ ninja-build \ + pkg-config \ zstd diff --git a/.gitmodules b/.gitmodules index 888b5d47d3..cd8c78f992 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,6 +16,9 @@ [submodule "libraries/rapidjson"] path = libraries/rapidjson url = https://github.com/Tencent/rapidjson/ +[submodule "libraries/yubihsm"] + path = libraries/yubihsm + url = https://github.com/Yubico/yubihsm-shell [submodule "tests/abieos"] path = tests/abieos url = https://github.com/AntelopeIO/abieos diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d9d0f8b96..74b4834731 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,7 @@ configure_file(libraries/fc/src/network/LICENSE.go licenses configure_file(libraries/eos-vm/LICENSE licenses/leap/LICENSE.eos-vm COPYONLY) configure_file(libraries/fc/libraries/ff/LICENSE licenses/leap/LICENSE.libff COPYONLY) configure_file(programs/cleos/LICENSE.CLI11 licenses/leap/LICENSE.CLI11 COPYONLY) +configure_file(libraries/yubihsm/LICENSE licenses/leap/LICENSE.yubihsm COPYONLY) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/licenses/leap" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/" COMPONENT base) @@ -237,6 +238,9 @@ add_custom_target(dev-install USES_TERMINAL ) +get_property(_CTEST_CUSTOM_TESTS_IGNORE GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE) +file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "SET(CTEST_CUSTOM_TESTS_IGNORE ${_CTEST_CUSTOM_TESTS_IGNORE})") + include(doxygen) include(package.cmake) diff --git a/README.md b/README.md index 27bf938e64..be3a9586f7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Recent Ubuntu LTS releases are the only Linux distributions that we fully suppor * CMake 3.8+ * (for Linux only) LLVM 7 - 11 (newer versions do not work) -A few other common libraries are tools also required such as openssl 1.1+, curl, GMP, Python 3, and zlib. +A few other common libraries are tools also required such as openssl 1.1+, libcurl, curl, libusb, GMP, Python 3, and zlib. **A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in Leap are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes. @@ -33,8 +33,6 @@ The binary package will be produced in the Leap build directory that was supplie #### Manual (non "pinned") Build Instructions -These instructions are valid for this branch. Other release branches may have different requirements so ensure you follow the directions in the branch or release you intend to build. -

Ubuntu 20.04 & 22.04 Build Instructions @@ -46,9 +44,12 @@ apt-get update && apt-get install \ curl \ git \ libboost-all-dev \ + libcurl4-openssl-dev \ libgmp-dev \ libssl-dev \ - llvm-11-dev + libusb-1.0-0-dev \ + llvm-11-dev \ + pkg-config ``` and perform the build: ``` @@ -71,9 +72,12 @@ apt-get update && apt-get install \ curl \ g++-8 \ git \ + libcurl4-openssl-dev \ libgmp-dev \ libssl-dev \ + libusb-1.0-0-dev \ llvm-7-dev \ + pkg-config \ python3 \ zlib1g-dev diff --git a/docs/03_keosd/10_usage.md b/docs/03_keosd/10_usage.md index eecdaa2a94..b66775ddcf 100644 --- a/docs/03_keosd/10_usage.md +++ b/docs/03_keosd/10_usage.md @@ -91,6 +91,11 @@ Config Options for eosio::wallet_plugin: number of seconds of inactivity. Activity is defined as any wallet command e.g. list-wallets. + --yubihsm-url URL Override default URL of + http://localhost:12345 for connecting + to yubihsm-connector + --yubihsm-authkey key_num Enables YubiHSM support using given + Authkey Application Config Options: --plugin arg Plugin(s) to enable, may be specified diff --git a/docs/03_keosd/30_how-to-guides/how-to-attach-a-yubihsm-hard-wallet.md b/docs/03_keosd/30_how-to-guides/how-to-attach-a-yubihsm-hard-wallet.md new file mode 100644 index 0000000000..ab32720aad --- /dev/null +++ b/docs/03_keosd/30_how-to-guides/how-to-attach-a-yubihsm-hard-wallet.md @@ -0,0 +1,73 @@ +--- +content_title: How To Attach a YubiHSM Hard Wallet +link_text: How To Attach a YubiHSM Hard Wallet +--- + +## Goal + +Attach a YubiHSM as a hard wallet + +## Before you begin + +* Install the currently supported version of `keosd` + +* Install YubiHSM2 Software Toolkit (YubiHSM2 SDK) + +* Create an AuthKey with at least the following Capabilities: + + * sign-ecdsa + * generate-asymmetric-key + * export-wrapped + +* **Delete the default AuthKey** + +[[warning | Security]] +| It is extremely important to create a new AuthKey and remove the default AuthKey before proceed to the following steps. + +## Steps + +### Configure `keosd` + + There are two options to connect `keosd` to YubiHSM: + + #### Using a YubiHSM connector + + By default, `keosd` will connect to the YubiHSM connector on the default host and port. If a non-default URL is used, set the `--yubihsm-url` option or `yubihsm-url` in `config.ini` with the correct connector URL + + #### Directly connect via USB + + `keosd` also can directly connect to YubiHSM via USB protocol + + If this option is used, set `keosd` startup option as the below: + + ```sh + --yubihsm-url=ysb:// + ``` + +### Start `keosd` with AuthKey: + + ```sh + --yubihsm-authkey Your_AuthKey_Object_Number + ``` + + if a YubiHSM connector is used, check the YubiHSM connector is up and running by visiting YubiHSM URL: + http://YubiHSM_HOST:YubiHSM_PORT/connector/status ((Default HOST and Port: http://127.0.0.1:12345) + + You should see something like this: + + ```console + status=OK + serial=* + version=2.0.0 + pid=666 + address=localhost + port=12345 + ``` + +### Unlock YubiHSM wallet with the password of AuthKey using the following option: + + ```sh + cleos wallet unlock -n YubiHSM --password YOUR_AUTHKEY_PASSWORD + ``` + +After unlocking the wallet, you can use `cleos wallet` commands as usual. Beware as a part of security mechanism, some wallet subcommands, such as retrieve private keys, or remove a key, are not supported when a YubiHSM is used \ No newline at end of file diff --git a/docs/03_keosd/30_how-to-guides/index.md b/docs/03_keosd/30_how-to-guides/index.md new file mode 100644 index 0000000000..ec0bd09ccf --- /dev/null +++ b/docs/03_keosd/30_how-to-guides/index.md @@ -0,0 +1,5 @@ +--- +content_title: Keosd How-to Guides +--- + +* [How to attach a YubiHSM hard wallet](how-to-attach-a-yubihsm-hard-wallet.md) diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 1f74f8db08..9598cd4d1f 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -30,3 +30,17 @@ set(ENABLE_PROFILE OFF CACHE BOOL "Enable for profile builds") if(eos-vm IN_LIST EOSIO_WASM_RUNTIMES OR eos-vm-jit IN_LIST EOSIO_WASM_RUNTIMES) add_subdirectory( eos-vm ) endif() + +set(ENABLE_STATIC ON) +set(CMAKE_MACOSX_RPATH OFF) +set(BUILD_ONLY_LIB ON CACHE BOOL "Library only build") +message(STATUS "Starting yubihsm configuration...") +add_subdirectory( yubihsm EXCLUDE_FROM_ALL ) +target_compile_options(yubihsm_static PRIVATE -fno-lto -fcommon) +message(STATUS "yubihsm configuration complete") + +get_property(_CTEST_CUSTOM_TESTS_IGNORE GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE) +set_property(GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE + "change_authkey import_ed decrypt_ec decrypt_rsa ssh logs generate_rsa import_ec echo\ + yubico_otp wrap_data wrap info import_rsa import_authkey generate_hmac generate_ec\ + attest pbkdf2 parsing ${_CTEST_CUSTOM_TESTS_IGNORE}") diff --git a/libraries/yubihsm b/libraries/yubihsm new file mode 160000 index 0000000000..9189fdb92c --- /dev/null +++ b/libraries/yubihsm @@ -0,0 +1 @@ +Subproject commit 9189fdb92cc90840e51760de5f297ac7d908b3cd diff --git a/plugins/wallet_plugin/CMakeLists.txt b/plugins/wallet_plugin/CMakeLists.txt index 039b8ee190..27f0147c8d 100644 --- a/plugins/wallet_plugin/CMakeLists.txt +++ b/plugins/wallet_plugin/CMakeLists.txt @@ -19,7 +19,11 @@ add_library( wallet_plugin wallet_plugin.cpp wallet_manager.cpp ${SE_WALLET_SOURCES} + yubihsm_wallet.cpp ${HEADERS} ) -target_link_libraries( wallet_plugin eosio_chain appbase ${security_framework} ${corefoundation_framework} ${localauthentication_framework} ${cocoa_framework}) +target_link_libraries( wallet_plugin yubihsm_static eosio_chain appbase ${security_framework} ${corefoundation_framework} ${localauthentication_framework} ${cocoa_framework}) target_include_directories( wallet_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +#sadly old cmake 2.8 support in yubihsm cmake prevents usage of target_include_directories there +target_include_directories( wallet_plugin PRIVATE "${CMAKE_SOURCE_DIR}/libraries/yubihsm/lib" ) \ No newline at end of file diff --git a/plugins/wallet_plugin/include/eosio/wallet_plugin/yubihsm_wallet.hpp b/plugins/wallet_plugin/include/eosio/wallet_plugin/yubihsm_wallet.hpp new file mode 100644 index 0000000000..abafbe8478 --- /dev/null +++ b/plugins/wallet_plugin/include/eosio/wallet_plugin/yubihsm_wallet.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +using namespace std; +using namespace eosio::chain; + +namespace eosio { namespace wallet { + +namespace detail { +struct yubihsm_wallet_impl; +} + +class yubihsm_wallet final : public wallet_api { + public: + yubihsm_wallet(const string& connector, const uint16_t authkey); + ~yubihsm_wallet(); + + private_key_type get_private_key(public_key_type pubkey) const override; + + bool is_locked() const override; + void lock() override; + void unlock(string password) override; + void check_password(string password) override; + void set_password(string password) override; + + map list_keys() override; + flat_set list_public_keys() override; + + bool import_key(string wif_key) override; + string create_key(string key_type) override; + bool remove_key(string key) override; + + std::optional try_sign_digest(const digest_type digest, const public_key_type public_key) override; + + private: + std::unique_ptr my; +}; + +}} diff --git a/plugins/wallet_plugin/wallet_plugin.cpp b/plugins/wallet_plugin/wallet_plugin.cpp index 2b22adf4d5..519e8bbb92 100644 --- a/plugins/wallet_plugin/wallet_plugin.cpp +++ b/plugins/wallet_plugin/wallet_plugin.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -26,6 +27,10 @@ void wallet_plugin::set_program_options(options_description& cli, options_descri "Timeout for unlocked wallet in seconds (default 900 (15 minutes)). " "Wallets will automatically lock after specified number of seconds of inactivity. " "Activity is defined as any wallet command e.g. list-wallets.") + ("yubihsm-url", bpo::value()->value_name("URL"), + "Override default URL of http://localhost:12345 for connecting to yubihsm-connector") + ("yubihsm-authkey", bpo::value()->value_name("key_num"), + "Enables YubiHSM support using given Authkey") ; } @@ -48,6 +53,15 @@ void wallet_plugin::plugin_initialize(const variables_map& options) { std::chrono::seconds t(timeout); wallet_manager_ptr->set_timeout(t); } + if (options.count("yubihsm-authkey")) { + uint16_t key = options.at("yubihsm-authkey").as(); + string connector_endpoint = "http://localhost:12345"; + if(options.count("yubihsm-url")) + connector_endpoint = options.at("yubihsm-url").as(); + try { + wallet_manager_ptr->own_and_use_wallet("YubiHSM", make_unique(connector_endpoint, key)); + }FC_LOG_AND_RETHROW() + } } FC_LOG_AND_RETHROW() } diff --git a/plugins/wallet_plugin/yubihsm_wallet.cpp b/plugins/wallet_plugin/yubihsm_wallet.cpp new file mode 100644 index 0000000000..d2de96ae6d --- /dev/null +++ b/plugins/wallet_plugin/yubihsm_wallet.cpp @@ -0,0 +1,268 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace eosio { namespace wallet { + +using namespace fc::crypto::r1; + +namespace detail { + +struct yubihsm_wallet_impl { + using key_map_type = map; + + yubihsm_wallet_impl(const string& ep, const uint16_t ak) : endpoint(ep), authkey(ak) { + yh_rc rc; + if((rc = yh_init())) + FC_THROW("yubihsm init failure: ${c}", ("c", yh_strerror(rc))); + } + + ~yubihsm_wallet_impl() { + lock(); + yh_exit(); + //bizarre, is there no way to destroy a yh_connector?? + + ///XXX Probably a race condition on timer shutdown and appbase destruction + } + + bool is_locked() const { + return !connector; + } + + key_map_type::iterator populate_key_map_with_keyid(const uint16_t key_id) { + yh_rc rc; + size_t blob_sz = 128; + uint8_t blob[blob_sz]; + if((rc = yh_util_get_public_key(session, key_id, blob, &blob_sz, nullptr))) + FC_THROW_EXCEPTION(chain::wallet_exception, "yh_util_get_public_key failed: ${m}", ("m", yh_strerror(rc))); + if(blob_sz != 64) + FC_THROW_EXCEPTION(chain::wallet_exception, "unexpected pubkey size from yh_util_get_public_key"); + + ///XXX This is junky and common with SE wallet; commonize it + char serialized_pub_key[sizeof(public_key_data) + 1]; + serialized_pub_key[0] = 0x01; //means R1 key + serialized_pub_key[1] = 0x02 + (blob[63]&1); //R1 header; even or odd Y + memcpy(serialized_pub_key+2, blob, 32); //copy in the 32 bytes of X + + public_key_type pub_key; + fc::datastream ds(serialized_pub_key, sizeof(serialized_pub_key)); + fc::raw::unpack(ds, pub_key); + + return _keys.emplace(pub_key, key_id).first; + } + + void unlock(const string& password) { + yh_rc rc; + + try { + if((rc = yh_init_connector(endpoint.c_str(), &connector))) + FC_THROW_EXCEPTION(chain::wallet_exception, "Failled to initialize yubihsm connector URL: ${c}", ("c", yh_strerror(rc))); + if((rc = yh_connect(connector, 0))) + FC_THROW_EXCEPTION(chain::wallet_exception, "Failed to connect to YubiHSM connector: ${m}", ("m", yh_strerror(rc))); + if((rc = yh_create_session_derived(connector, authkey, (const uint8_t *)password.data(), password.size(), false, &session))) + FC_THROW_EXCEPTION(chain::wallet_exception, "Failed to create YubiHSM session: ${m}", ("m", yh_strerror(rc))); + if((rc = yh_authenticate_session(session))) + FC_THROW_EXCEPTION(chain::wallet_exception, "Failed to authenticate YubiHSM session: ${m}", ("m", yh_strerror(rc))); + + yh_object_descriptor authkey_desc; + if((rc = yh_util_get_object_info(session, authkey, YH_AUTHENTICATION_KEY, &authkey_desc))) + FC_THROW_EXCEPTION(chain::wallet_exception, "Failed to get authkey info: ${m}", ("m", yh_strerror(rc))); + + authkey_caps = authkey_desc.capabilities; + authkey_domains = authkey_desc.domains; + + if(!yh_check_capability(&authkey_caps, "sign-ecdsa")) + FC_THROW_EXCEPTION(chain::wallet_exception, "Given authkey cannot perform signing"); + + size_t found_objects_n = 64*1024; + yh_object_descriptor found_objs[found_objects_n]; + yh_capabilities find_caps; + yh_string_to_capabilities("sign-ecdsa", &find_caps); + if((rc = yh_util_list_objects(session, 0, YH_ASYMMETRIC_KEY, 0, &find_caps, YH_ALGO_EC_P256, nullptr, found_objs, &found_objects_n))) + FC_THROW_EXCEPTION(chain::wallet_exception, "yh_util_list_objects failed: ${m}", ("m", yh_strerror(rc))); + + for(size_t i = 0; i < found_objects_n; ++i) + populate_key_map_with_keyid(found_objs[i].id); + } + catch(chain::wallet_exception& e) { + lock(); + throw; + } + + prime_keepalive_timer(); + } + + void lock() { + if(session) { + yh_util_close_session(session); + yh_destroy_session(&session); + } + session = nullptr; + if(connector) + yh_disconnect(connector); + //it would seem like this would leak-- there is no destroy() call for it. But I clearly can't reuse connectors + // as that fails with a "Unable to find a suitable connector" + connector = nullptr; + + _keys.clear(); + keepalive_timer.cancel(); + } + + void prime_keepalive_timer() { + keepalive_timer.expires_at(std::chrono::steady_clock::now() + std::chrono::seconds(20)); + keepalive_timer.async_wait([this](const boost::system::error_code& ec){ + if(ec || !session) + return; + + uint8_t data, resp; + yh_cmd resp_cmd; + size_t resp_sz = 1; + if(yh_send_secure_msg(session, YHC_ECHO, &data, 1, &resp_cmd, &resp, &resp_sz)) + lock(); + else + prime_keepalive_timer(); + }); + } + + std::optional try_sign_digest(const digest_type d, const public_key_type public_key) { + auto it = _keys.find(public_key); + if(it == _keys.end()) + return std::optional(); + + size_t der_sig_sz = 128; + uint8_t der_sig[der_sig_sz]; + yh_rc rc; + if((rc = yh_util_sign_ecdsa(session, it->second, (uint8_t*)d.data(), d.data_size(), der_sig, &der_sig_sz))) { + lock(); + FC_THROW_EXCEPTION(chain::wallet_exception, "yh_util_sign_ecdsa failed: ${m}", ("m", yh_strerror(rc))); + } + + ///XXX a lot of this below is similar to SE wallet; commonize it in non-junky way + fc::ecdsa_sig sig = ECDSA_SIG_new(); + BIGNUM *r = BN_new(), *s = BN_new(); + BN_bin2bn(der_sig+4, der_sig[3], r); + BN_bin2bn(der_sig+6+der_sig[3], der_sig[4+der_sig[3]+1], s); + ECDSA_SIG_set0(sig, r, s); + + char pub_key_shim_data[64]; + fc::datastream eds(pub_key_shim_data, sizeof(pub_key_shim_data)); + fc::raw::pack(eds, it->first); + public_key_data* kd = (public_key_data*)(pub_key_shim_data+1); + + compact_signature compact_sig; + compact_sig = signature_from_ecdsa(key, *kd, sig, d); + + char serialized_signature[sizeof(compact_sig) + 1]; + serialized_signature[0] = 0x01; + memcpy(serialized_signature+1, compact_sig.data, sizeof(compact_sig)); + + signature_type final_signature; + fc::datastream ds(serialized_signature, sizeof(serialized_signature)); + fc::raw::unpack(ds, final_signature); + return final_signature; + } + + public_key_type create() { + if(!yh_check_capability(&authkey_caps, "generate-asymmetric-key")) + FC_THROW_EXCEPTION(chain::wallet_exception, "Given authkey cannot create keys"); + + yh_rc rc; + uint16_t new_key_id = 0; + yh_capabilities creation_caps = {}; + if(yh_string_to_capabilities("sign-ecdsa:export-wrapped", &creation_caps)) + FC_THROW_EXCEPTION(chain::wallet_exception, "Cannot create caps mask"); + + try { + if((rc = yh_util_generate_ec_key(session, &new_key_id, "keosd created key", authkey_domains, &creation_caps, YH_ALGO_EC_P256))) + FC_THROW_EXCEPTION(chain::wallet_exception, "yh_util_generate_ec_key failed: ${m}", ("m", yh_strerror(rc))); + return populate_key_map_with_keyid(new_key_id)->first; + } + catch(chain::wallet_exception& e) { + lock(); + throw; + } + } + + yh_connector* connector = nullptr; + yh_session* session = nullptr; + string endpoint; + uint16_t authkey; + + map _keys; + + yh_capabilities authkey_caps; + uint16_t authkey_domains; + + boost::asio::steady_timer keepalive_timer{appbase::app().get_io_service()}; + fc::ec_key key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); +}; + + +} + +yubihsm_wallet::yubihsm_wallet(const string& connector, const uint16_t authkey) : my(new detail::yubihsm_wallet_impl(connector, authkey)) { +} + +yubihsm_wallet::~yubihsm_wallet() { +} + +private_key_type yubihsm_wallet::get_private_key(public_key_type pubkey) const { + FC_THROW_EXCEPTION(chain::wallet_exception, "Obtaining private key for a key stored in YubiHSM is impossible"); +} + +bool yubihsm_wallet::is_locked() const { + return my->is_locked(); +} +void yubihsm_wallet::lock() { + FC_ASSERT(!is_locked()); + my->lock(); +} + +void yubihsm_wallet::unlock(string password) { + my->unlock(password); +} +void yubihsm_wallet::check_password(string password) { + //just leave this as a noop for now; remove_key from wallet_mgr calls through here +} +void yubihsm_wallet::set_password(string password) { + FC_THROW_EXCEPTION(chain::wallet_exception, "YubiHSM wallet cannot have a password set"); +} + +map yubihsm_wallet::list_keys() { + FC_THROW_EXCEPTION(chain::wallet_exception, "Getting the private keys from the YubiHSM wallet is impossible"); +} +flat_set yubihsm_wallet::list_public_keys() { + flat_set keys; + boost::copy(my->_keys | boost::adaptors::map_keys, std::inserter(keys, keys.end())); + return keys; +} + +bool yubihsm_wallet::import_key(string wif_key) { + FC_THROW_EXCEPTION(chain::wallet_exception, "It is not possible to import a key in to the YubiHSM wallet"); +} + +string yubihsm_wallet::create_key(string key_type) { + EOS_ASSERT(key_type.empty() || key_type == "R1", chain::unsupported_key_type_exception, "YubiHSM wallet only supports R1 keys"); + return my->create().to_string(); +} + +bool yubihsm_wallet::remove_key(string key) { + FC_ASSERT(!is_locked()); + FC_THROW_EXCEPTION(chain::wallet_exception, "YubiHSM wallet does not currently support removal of keys"); + return true; +} + +std::optional yubihsm_wallet::try_sign_digest(const digest_type digest, const public_key_type public_key) { + return my->try_sign_digest(digest, public_key); +} + +}} diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 919cdbda55..da3587f4e7 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -3,4 +3,4 @@ apt-get update apt-get update --fix-missing DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata -apt-get -y install zip unzip libncurses5 wget git build-essential cmake curl libgmp-dev libssl-dev libzstd-dev time zlib1g-dev libtinfo-dev bzip2 libbz2-dev python3 file +apt-get -y install zip unzip libncurses5 wget git build-essential cmake curl libcurl4-openssl-dev libgmp-dev libssl-dev libusb-1.0.0-dev libzstd-dev time pkg-config zlib1g-dev libtinfo-dev bzip2 libbz2-dev python3 file From 623477958bf45f1827a3fe52e2024c96ed97ca7f Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Fri, 9 Sep 2022 18:05:30 -0400 Subject: [PATCH 031/111] bump abieos submodule to branch with 2.0/3.1 ship fixes --- tests/abieos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/abieos b/tests/abieos index 551f67d0c5..8ae027d008 160000 --- a/tests/abieos +++ b/tests/abieos @@ -1 +1 @@ -Subproject commit 551f67d0c5f1c3ae8e4744d62d2e49b3e0e606da +Subproject commit 8ae027d008cdebdea73f5d52ffb5f6e0396bc99d From a0747e7f91b78a61a5de49ad7a7155c1c9ce1955 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Fri, 9 Sep 2022 18:23:59 -0400 Subject: [PATCH 032/111] bump abieos submodule to refreshed 2.0/3.1 fix branch --- tests/abieos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/abieos b/tests/abieos index 8ae027d008..43d966d526 160000 --- a/tests/abieos +++ b/tests/abieos @@ -1 +1 @@ -Subproject commit 8ae027d008cdebdea73f5d52ffb5f6e0396bc99d +Subproject commit 43d966d52624fc85630c5562f873b5db378c9504 From 1f1ec234adf778541bfc58d258fa8ddb560eecc3 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Sat, 10 Sep 2022 12:53:06 -0400 Subject: [PATCH 033/111] bump abieos submodule to main with 2.0/3.1 ship fixes --- tests/abieos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/abieos b/tests/abieos index 43d966d526..e8b82b38d5 160000 --- a/tests/abieos +++ b/tests/abieos @@ -1 +1 @@ -Subproject commit 43d966d52624fc85630c5562f873b5db378c9504 +Subproject commit e8b82b38d5cfcde87d698a0cb135b568003c16a5 From e56ea68db10a081eb9053a3500080454cfc1116b Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Sat, 10 Sep 2022 14:19:49 -0500 Subject: [PATCH 034/111] GH-119 Track and report block idle time and trx times per block for produced and speculative blocks --- plugins/producer_plugin/producer_plugin.cpp | 83 +++++++++++++++------ 1 file changed, 59 insertions(+), 24 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 7a4f6a635e..710e6f1e20 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -145,6 +145,19 @@ class account_failures { max_failures_per_account = max_failures; } + void add_idle_time( const fc::microseconds& idle ) const { + block_idle_time += idle; + } + + void add_fail_time( const fc::microseconds& fail_time ) { + trx_fail_time += fail_time; + } + + void add_success_time( const fc::microseconds& time ) { + trx_success_time += time; + } + + void add( const account_name& n, int64_t exception_code ) { auto& fa = failed_accounts[n]; ++fa.num_failures; @@ -162,9 +175,13 @@ class account_failures { return false; } - void report() const { + void report( const fc::time_point& idle_trx_time ) const { if( _log.is_enabled( fc::log_level::debug ) ) { auto now = fc::time_point::now(); + add_idle_time( now - idle_trx_time ); + fc_dlog( _log, "Block trx idle: ${i}us out of ${t}us, success: ${s}us, fail: ${f}us, other: ${o}us", + ("i", block_idle_time)("t", now - clear_time)("s", trx_success_time)("f", trx_fail_time) + ("o", (now - clear_time) - block_idle_time - trx_success_time - trx_fail_time) ); for( const auto& e : failed_accounts ) { std::string reason; if( e.second.is_deadline() ) reason += "deadline"; @@ -189,6 +206,8 @@ class account_failures { void clear() { failed_accounts.clear(); + block_idle_time = trx_fail_time = trx_success_time = fc::microseconds{}; + clear_time = fc::time_point::now(); } private: @@ -226,6 +245,10 @@ class account_failures { std::map failed_accounts; uint32_t max_failures_per_account = 3; + mutable fc::microseconds block_idle_time; + fc::microseconds trx_success_time; + fc::microseconds trx_fail_time; + fc::time_point clear_time{fc::time_point::now()}; const eosio::subjective_billing& subjective_billing; }; @@ -291,7 +314,7 @@ class producer_plugin_impl : public std::enable_shared_from_this _protocol_features_to_activate; bool _protocol_features_signaled = false; // to mark whether it has been signaled in start_block @@ -388,6 +411,8 @@ class producer_plugin_impl : public std::enable_shared_from_this& block_id) { @@ -414,6 +439,7 @@ class producer_plugin_impl : public std::enable_shared_from_thisheader.timestamp.next().to_time_point() >= fc::time_point::now() ) { + auto now = fc::time_point::now(); + if( hbs->header.timestamp.next().to_time_point() >= now ) { _production_enabled = true; } - if( fc::time_point::now() - block->timestamp < fc::minutes(5) || (blk_num % 1000 == 0) ) { + if( now - block->timestamp < fc::minutes(5) || (blk_num % 1000 == 0) ) { ilog("Received block ${id}... #${n} @ ${t} signed by ${p} " "[trxs: ${count}, lib: ${lib}, conf: ${confs}, net: ${net}, cpu: ${cpu}, elapsed: ${elapsed}, time: ${time}, latency: ${latency} ms]", ("p",block->producer)("id",id.str().substr(8,16))("n",blk_num)("t",block->timestamp) ("count",block->transactions.size())("lib",chain.last_irreversible_block_num()) ("confs", block->confirmed)("net", br.total_net_usage)("cpu", br.total_cpu_usage_us) ("elapsed", br.total_elapsed_time)("time", br.total_time) - ("latency", (fc::time_point::now() - block->timestamp).count()/1000 ) ); + ("latency", (now - block->timestamp).count()/1000 ) ); if( chain.get_read_mode() != db_read_mode::IRREVERSIBLE && hbs->id != id && hbs->block != nullptr ) { // not applied to head ilog("Block not applied to head ${id}... #${n} @ ${t} signed by ${p} " "[trxs: ${count}, dpos: ${dpos}, conf: ${confs}, net: ${net}, cpu: ${cpu}, elapsed: ${elapsed}, time: ${time}, latency: ${latency} ms]", @@ -472,7 +499,7 @@ class producer_plugin_impl : public std::enable_shared_from_thisblock->transactions.size())("dpos", hbs->dpos_irreversible_blocknum) ("confs", hbs->block->confirmed)("net", br.total_net_usage)("cpu", br.total_cpu_usage_us) ("elapsed", br.total_elapsed_time)("time", br.total_time) - ("latency", (fc::time_point::now() - hbs->block->timestamp).count()/1000 ) ); + ("latency", (now - hbs->block->timestamp).count()/1000 ) ); } } @@ -481,8 +508,11 @@ class producer_plugin_impl : public std::enable_shared_from_thischain(); + + _account_fails.report(_idle_trx_time); + // abort the pending block - _unapplied_transactions.add_aborted( chain.abort_block() ); + abort_block(); schedule_production_loop(); } @@ -1490,7 +1520,6 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { const fc::time_point now = fc::time_point::now(); const fc::time_point block_time = calculate_pending_block_time(); const fc::time_point preprocess_deadline = calculate_block_deadline(block_time); - _idle_trx_time = now; const pending_block_mode previous_pending_mode = _pending_block_mode; _pending_block_mode = pending_block_mode::producing; @@ -1658,7 +1687,6 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { // limit execution of pending incoming to once per block auto incoming_itr = _unapplied_transactions.incoming_begin(); - _account_fails.clear(); if( !process_unapplied_trxs( preprocess_deadline ) ) return start_block_result::exhausted; @@ -1872,7 +1900,9 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, next_function next ) { auto start = fc::time_point::now(); - fc_dlog( _trx_successful_trace_log, "Time since last trx: ${t}us", ("t", start - _idle_trx_time) ); + auto idle_time = start - _idle_trx_time; + _account_fails.add_idle_time( idle_time ); + fc_dlog( _trx_successful_trace_log, "Time since last trx: ${t}us", ("t", idle_time) ); auto first_auth = trx->packed_trx()->get_transaction().first_authorizer(); if( _pending_block_mode == pending_block_mode::producing && _account_fails.failure_limit( first_auth ) ) { @@ -1884,6 +1914,7 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, next( except_ptr ); } _idle_trx_time = fc::time_point::now(); + _account_fails.add_fail_time(_idle_trx_time - start); return push_result{.failed = true}; } @@ -1910,8 +1941,10 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, } auto trace = chain.push_transaction( trx, block_deadline, max_trx_time, prev_billed_cpu_time_us, false, sub_bill ); + auto end = fc::time_point::now(); push_result pr; if( trace->except ) { + _account_fails.add_fail_time(end - start); if( exception_is_exhausted( *trace->except ) ) { if( _pending_block_mode == pending_block_mode::producing ) { fc_dlog(_trx_failed_trace_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} COULD NOT FIT, tx: ${txid} RETRYING ", @@ -1924,20 +1957,18 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, } else { pr.failed = true; fc_dlog( _trx_failed_trace_log, "Subjective bill for failed ${a}: ${b} elapsed ${t}us, time ${r}us", - ("a",first_auth)("b",sub_bill)("t",trace->elapsed)("r", fc::time_point::now() - start)); + ("a",first_auth)("b",sub_bill)("t",trace->elapsed)("r", end - start)); if (!disable_subjective_billing) _subjective_billing.subjective_bill_failure( first_auth, trace->elapsed, fc::time_point::now() ); log_trx_results( trx, trace, start ); - if( _pending_block_mode == pending_block_mode::producing ) { - auto failure_code = trace->except->code(); - if( failure_code != tx_duplicate::code_value ) { - // this failed our configured maximum transaction time, we don't want to replay it - fc_dlog( _log, "Failed ${c} trx, auth: ${a}, prev billed: ${p}us, ran: ${r}us, id: ${id}", - ("c", failure_code)("a", first_auth)("p", prev_billed_cpu_time_us) - ( "r", fc::time_point::now() - start )( "id", trx->id() ) ); - _account_fails.add( first_auth, failure_code ); - } + auto failure_code = trace->except->code(); + if( failure_code != tx_duplicate::code_value ) { + // this failed our configured maximum transaction time, we don't want to replay it + fc_dlog( _log, "Failed ${c} trx, auth: ${a}, prev billed: ${p}us, ran: ${r}us, id: ${id}", + ("c", failure_code)("a", first_auth)("p", prev_billed_cpu_time_us) + ( "r", end - start )( "id", trx->id() ) ); + _account_fails.add( first_auth, failure_code ); } if( next ) { if( return_failure_trace ) { @@ -1950,7 +1981,8 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, } } else { fc_dlog( _trx_successful_trace_log, "Subjective bill for success ${a}: ${b} elapsed ${t}us, time ${r}us", - ("a",first_auth)("b",sub_bill)("t",trace->elapsed)("r", fc::time_point::now() - start)); + ("a",first_auth)("b",sub_bill)("t",trace->elapsed)("r", end - start)); + _account_fails.add_success_time(end - start); log_trx_results( trx, trace, start ); if( persist_until_expired && !_disable_persist_until_expired ) { // if this trx didn't fail/soft-fail and the persist flag is set @@ -2110,7 +2142,9 @@ void producer_plugin_impl::process_scheduled_and_incoming_trxs( const fc::time_p if( max_trx_time.count() < 0 ) max_trx_time = fc::microseconds::maximum(); auto trace = chain.push_scheduled_transaction(trx_id, deadline, max_trx_time, 0, false); + auto end = fc::time_point::now(); if (trace->except) { + _account_fails.add_fail_time(end - start); if (exception_is_exhausted(*trace->except)) { if( block_is_exhausted() ) { exhausted = true; @@ -2120,7 +2154,7 @@ void producer_plugin_impl::process_scheduled_and_incoming_trxs( const fc::time_p fc_dlog(_trx_failed_trace_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} is REJECTING scheduled tx: ${txid}, time: ${r}, auth: ${a} : ${details}", ("block_num", chain.head_block_num() + 1)("prod", get_pending_block_producer()) - ("txid", trx_id)("r", fc::time_point::now() - start)("a", get_first_authorizer(trace)) + ("txid", trx_id)("r", end - start)("a", get_first_authorizer(trace)) ("details", get_detailed_contract_except_info(nullptr, trace, nullptr))); fc_dlog(_trx_trace_failure_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} is REJECTING scheduled tx: ${entire_trace}", ("block_num", chain.head_block_num() + 1)("prod", get_pending_block_producer()) @@ -2130,10 +2164,11 @@ void producer_plugin_impl::process_scheduled_and_incoming_trxs( const fc::time_p num_failed++; } } else { + _account_fails.add_success_time(end - start); fc_dlog(_trx_successful_trace_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} is ACCEPTING scheduled tx: ${txid}, time: ${r}, auth: ${a}, cpu: ${cpu}", ("block_num", chain.head_block_num() + 1)("prod", get_pending_block_producer()) - ("txid", trx_id)("r", fc::time_point::now() - start)("a", get_first_authorizer(trace)) + ("txid", trx_id)("r", end - start)("a", get_first_authorizer(trace)) ("cpu", trace->receipt ? trace->receipt->cpu_usage_us : 0)); fc_dlog(_trx_trace_success_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} is ACCEPTING scheduled tx: ${entire_trace}", ("block_num", chain.head_block_num() + 1)("prod", get_pending_block_producer()) @@ -2397,7 +2432,7 @@ void producer_plugin_impl::produce_block() { block_state_ptr new_bs = chain.head_block_state(); - _account_fails.report(); + _account_fails.report(_idle_trx_time); _account_fails.clear(); controller::block_report br; From bfac689761b40d5586245d5776ec55171104431b Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 12 Sep 2022 12:08:50 -0500 Subject: [PATCH 035/111] GH-119 Refactor trx idle time calculation. Track and report failed/successful trx #/time. --- plugins/producer_plugin/producer_plugin.cpp | 52 ++++++++++++--------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 710e6f1e20..8038465490 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -151,10 +151,12 @@ class account_failures { void add_fail_time( const fc::microseconds& fail_time ) { trx_fail_time += fail_time; + ++trx_fail_num; } void add_success_time( const fc::microseconds& time ) { trx_success_time += time; + ++trx_success_num; } @@ -179,8 +181,9 @@ class account_failures { if( _log.is_enabled( fc::log_level::debug ) ) { auto now = fc::time_point::now(); add_idle_time( now - idle_trx_time ); - fc_dlog( _log, "Block trx idle: ${i}us out of ${t}us, success: ${s}us, fail: ${f}us, other: ${o}us", - ("i", block_idle_time)("t", now - clear_time)("s", trx_success_time)("f", trx_fail_time) + fc_dlog( _log, "Block trx idle: ${i}us out of ${t}us, success: ${sn}, ${s}us, fail: ${fn}, ${f}us, other: ${o}us", + ("i", block_idle_time)("t", now - clear_time)("sn", trx_success_num)("s", trx_success_time) + ("fn", trx_fail_num)("f", trx_fail_time) ("o", (now - clear_time) - block_idle_time - trx_success_time - trx_fail_time) ); for( const auto& e : failed_accounts ) { std::string reason; @@ -207,6 +210,7 @@ class account_failures { void clear() { failed_accounts.clear(); block_idle_time = trx_fail_time = trx_success_time = fc::microseconds{}; + trx_fail_num = trx_success_num = 0; clear_time = fc::time_point::now(); } @@ -246,6 +250,8 @@ class account_failures { std::map failed_accounts; uint32_t max_failures_per_account = 3; mutable fc::microseconds block_idle_time; + uint32_t trx_success_num = 0; + uint32_t trx_fail_num = 0; fc::microseconds trx_success_time; fc::microseconds trx_fail_time; fc::time_point clear_time{fc::time_point::now()}; @@ -409,6 +415,9 @@ class producer_plugin_impl : public std::enable_shared_from_thischain(); + if( chain.is_building_block() ) { + _account_fails.report( _idle_trx_time ); + } _unapplied_transactions.add_aborted( chain.abort_block() ); _subjective_billing.abort_block(); _account_fails.clear(); @@ -439,7 +448,6 @@ class producer_plugin_impl : public std::enable_shared_from_thischain(); - _account_fails.report(_idle_trx_time); - // abort the pending block abort_block(); @@ -551,9 +557,13 @@ class producer_plugin_impl : public std::enable_shared_from_thislog_trx_results( trx, nullptr, ex, 0, fc::time_point::now() ); + auto start = fc::time_point::now(); + auto exception_handler = [self, &next, trx{std::move(trx)}, &start](fc::exception_ptr ex) { + self->_account_fails.add_idle_time( start - self->_idle_trx_time ); + self->log_trx_results( trx, nullptr, ex, 0, start ); next( std::move(ex) ); + self->_idle_trx_time = fc::time_point::now(); + self->_account_fails.add_fail_time(self->_idle_trx_time - start); }; try { auto result = future.get(); @@ -564,6 +574,7 @@ class producer_plugin_impl : public std::enable_shared_from_thisrestart_speculative_block(); } } + self->_idle_trx_time = fc::time_point::now(); } CATCH_AND_CALL(exception_handler); } ); } @@ -574,9 +585,13 @@ class producer_plugin_impl : public std::enable_shared_from_this next) { + auto start = fc::time_point::now(); + auto idle_time = start - _idle_trx_time; + _account_fails.add_idle_time( idle_time ); + fc_dlog( _trx_successful_trace_log, "Time since last trx: ${t}us", ("t", idle_time) ); + bool exhausted = false; chain::controller& chain = chain_plug->chain(); - try { const auto& id = trx->id(); @@ -623,7 +638,6 @@ class producer_plugin_impl : public std::enable_shared_from_this next ) { auto start = fc::time_point::now(); - auto idle_time = start - _idle_trx_time; - _account_fails.add_idle_time( idle_time ); - fc_dlog( _trx_successful_trace_log, "Time since last trx: ${t}us", ("t", idle_time) ); auto first_auth = trx->packed_trx()->get_transaction().first_authorizer(); if( _pending_block_mode == pending_block_mode::producing && _account_fails.failure_limit( first_auth ) ) { @@ -1913,8 +1925,7 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, log_trx_results( trx, except_ptr ); next( except_ptr ); } - _idle_trx_time = fc::time_point::now(); - _account_fails.add_fail_time(_idle_trx_time - start); + _account_fails.add_fail_time(fc::time_point::now() - start); return push_result{.failed = true}; } @@ -1998,7 +2009,6 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, if( next ) next( trace ); } - _idle_trx_time = fc::time_point::now(); return pr; } @@ -2095,7 +2105,6 @@ void producer_plugin_impl::process_scheduled_and_incoming_trxs( const fc::time_p num_processed++; - _idle_trx_time = fc::time_point::now(); // configurable ratio of incoming txns vs deferred txns while (incoming_trx_weight >= 1.0 && itr != end ) { if (deadline <= fc::time_point::now()) { @@ -2195,7 +2204,6 @@ bool producer_plugin_impl::process_incoming_trxs( const fc::time_point& deadline bool exhausted = false; auto end = _unapplied_transactions.incoming_end(); if( itr != end ) { - _idle_trx_time = fc::time_point::now(); size_t processed = 0; fc_dlog( _log, "Processing ${n} pending transactions", ("n", _unapplied_transactions.incoming_size()) ); while( itr != end ) { @@ -2249,6 +2257,8 @@ void producer_plugin_impl::schedule_production_loop() { auto result = start_block(); + _idle_trx_time = fc::time_point::now(); + if (result == start_block_result::failed) { elog("Failed to start a pending block, will try again later"); _timer.expires_from_now( boost::posix_time::microseconds( config::block_interval_us / 10 )); From ac6fdb8ccde18ce133e3c22b6ec729385987ed4c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 12 Sep 2022 13:49:54 -0500 Subject: [PATCH 036/111] GH-119 Move idle reporting into on_incoming_transaction_async --- plugins/producer_plugin/producer_plugin.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 8038465490..e1e9aaf3fb 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -558,6 +558,10 @@ class producer_plugin_impl : public std::enable_shared_from_this_idle_trx_time; + self->_account_fails.add_idle_time( idle_time ); + fc_dlog( _trx_successful_trace_log, "Time since last trx: ${t}us", ("t", idle_time) ); + auto exception_handler = [self, &next, trx{std::move(trx)}, &start](fc::exception_ptr ex) { self->_account_fails.add_idle_time( start - self->_idle_trx_time ); self->log_trx_results( trx, nullptr, ex, 0, start ); @@ -585,11 +589,6 @@ class producer_plugin_impl : public std::enable_shared_from_this next) { - auto start = fc::time_point::now(); - auto idle_time = start - _idle_trx_time; - _account_fails.add_idle_time( idle_time ); - fc_dlog( _trx_successful_trace_log, "Time since last trx: ${t}us", ("t", idle_time) ); - bool exhausted = false; chain::controller& chain = chain_plug->chain(); try { From bdfba6720c7624678aa54fa2c769f8b798fd0365 Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Mon, 12 Sep 2022 15:34:47 -0500 Subject: [PATCH 037/111] use pid to avoid collision in snapshot tests when running multithreaded. --- unittests/snapshot_tests.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/unittests/snapshot_tests.cpp b/unittests/snapshot_tests.cpp index 2bce4f57ef..64f78c11e1 100644 --- a/unittests/snapshot_tests.cpp +++ b/unittests/snapshot_tests.cpp @@ -566,25 +566,30 @@ BOOST_AUTO_TEST_CASE(json_snapshot_validity_test) chain.produce_blocks(10); chain.control->abort_block(); + auto pid_string = std::to_string(getpid()); + auto bin_file = pid_string + "BinSnapshot"; + auto json_file = pid_string + "JsonSnapshot"; + auto bin_from_json_file = pid_string + "BinFromJsonSnapshot"; + // create bin snapshot auto writer_bin = buffered_snapshot_suite::get_writer(); chain.control->write_snapshot(writer_bin); auto snapshot_bin = buffered_snapshot_suite::finalize(writer_bin); - buffered_snapshot_suite::write_to_file("BinSnapshot", snapshot_bin); + buffered_snapshot_suite::write_to_file(bin_file, snapshot_bin); // create json snapshot auto writer_json = json_snapshot_suite::get_writer(); chain.control->write_snapshot(writer_json); auto snapshot_json = json_snapshot_suite::finalize(writer_json); - json_snapshot_suite::write_to_file("JsonSnapshot", snapshot_json); + json_snapshot_suite::write_to_file(json_file, snapshot_json); // load bin snapshot - auto snapshot_bin_read = buffered_snapshot_suite::load_from_file("BinSnapshot"); + auto snapshot_bin_read = buffered_snapshot_suite::load_from_file(bin_file); auto reader_bin = buffered_snapshot_suite::get_reader(snapshot_bin_read); snapshotted_tester tester_bin(chain.get_config(), reader_bin, ordinal++); // load json snapshot - auto snapshot_json_read = json_snapshot_suite::load_from_file("JsonSnapshot"); + auto snapshot_json_read = json_snapshot_suite::load_from_file(json_file); auto reader_json = json_snapshot_suite::get_reader(snapshot_json_read); snapshotted_tester tester_json(chain.get_config(), reader_json, ordinal++); @@ -592,10 +597,10 @@ BOOST_AUTO_TEST_CASE(json_snapshot_validity_test) auto writer_bin_from_json = buffered_snapshot_suite::get_writer(); tester_json.control->write_snapshot(writer_bin_from_json); auto snapshot_bin_from_json = buffered_snapshot_suite::finalize(writer_bin_from_json); - buffered_snapshot_suite::write_to_file("BinFromJsonSnapshot", snapshot_bin_from_json); + buffered_snapshot_suite::write_to_file(bin_from_json_file, snapshot_bin_from_json); // load new bin snapshot - auto snapshot_bin_from_json_read = buffered_snapshot_suite::load_from_file("BinFromJsonSnapshot"); + auto snapshot_bin_from_json_read = buffered_snapshot_suite::load_from_file(bin_from_json_file); auto reader_bin_from_json = buffered_snapshot_suite::get_reader(snapshot_bin_from_json_read); snapshotted_tester tester_bin_from_json(chain.get_config(), reader_bin_from_json, ordinal++); @@ -604,9 +609,9 @@ BOOST_AUTO_TEST_CASE(json_snapshot_validity_test) verify_integrity_hash(*tester_bin_from_json.control, *tester_json.control); verify_integrity_hash(*tester_json.control, *tester_bin.control); - auto bin_snap_path = bfs::path(snapshot_file::base_path) / "BinSnapshot.bin.gz"; - auto bin_from_json_snap_path = bfs::path(snapshot_file::base_path) / "BinFromJsonSnapshot.bin.gz"; - auto json_snap_path = bfs::path(snapshot_file::base_path) / "JsonSnapshot.bin.json.gz"; + auto bin_snap_path = bfs::path(snapshot_file::base_path) / bin_file; + auto bin_from_json_snap_path = bfs::path(snapshot_file::base_path) / bin_from_json_file; + auto json_snap_path = bfs::path(snapshot_file::base_path) / json_file; remove(bin_snap_path); remove(bin_from_json_snap_path); remove(json_snap_path); From 636c0f5855c81e125910e2847be6bbec78925cd9 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 12 Sep 2022 15:03:08 -0500 Subject: [PATCH 038/111] GH-134 Use file under temp dir. --- libraries/testing/include/eosio/testing/snapshot_suites.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/testing/include/eosio/testing/snapshot_suites.hpp b/libraries/testing/include/eosio/testing/snapshot_suites.hpp index 813563842f..5fa8326842 100644 --- a/libraries/testing/include/eosio/testing/snapshot_suites.hpp +++ b/libraries/testing/include/eosio/testing/snapshot_suites.hpp @@ -127,8 +127,8 @@ struct json_snapshot_suite { static std::string temp_file() { static fc::temp_directory temp_dir; - std::string temp_file = temp_dir.path().string() + "temp.bin.json"; - return temp_file; + auto temp_file = temp_dir.path() / "temp.bin.json"; + return temp_file.string(); } struct reader : public reader_t { From 88e6f0dd1089018b65f06405f47c4e263eed443d Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 12 Sep 2022 16:16:18 -0500 Subject: [PATCH 039/111] GH-119 Move log of every failed trx to transaction_failure_tracing logger. --- plugins/producer_plugin/producer_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index e1e9aaf3fb..3bf670a6f7 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1975,7 +1975,7 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, auto failure_code = trace->except->code(); if( failure_code != tx_duplicate::code_value ) { // this failed our configured maximum transaction time, we don't want to replay it - fc_dlog( _log, "Failed ${c} trx, auth: ${a}, prev billed: ${p}us, ran: ${r}us, id: ${id}", + fc_dlog( _trx_failed_trace_log, "Failed ${c} trx, auth: ${a}, prev billed: ${p}us, ran: ${r}us, id: ${id}", ("c", failure_code)("a", first_auth)("p", prev_billed_cpu_time_us) ( "r", end - start )( "id", trx->id() ) ); _account_fails.add( first_auth, failure_code ); From acd452e37bf17ffd66772e3d71aba181f5600dba Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 13 Sep 2022 15:44:52 +0200 Subject: [PATCH 040/111] package.cmake: set CPACK_DEBIAN_PACKAGE_ARCHITECTURE instead of DEB_ARCH. --- package.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.cmake b/package.cmake index c95742d800..3ec67d290d 100644 --- a/package.cmake +++ b/package.cmake @@ -28,12 +28,12 @@ endif() # Find architecture using dpkg if (DPKG_FOUND) execute_process(COMMAND bash -c "${DPKG_FOUND} --print-architecture" - OUTPUT_VARIABLE DEB_ARCH + OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) else() - set(DEB_ARCH "${CMAKE_SYSTEM_PROCESSOR}") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}") endif() -string(REGEX REPLACE "^${CMAKE_PROJECT_NAME}-(.*)$" "${CMAKE_PROJECT_NAME}_\\1_${DEB_ARCH}" CPACK_DEBIAN_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") +string(REGEX REPLACE "^${CMAKE_PROJECT_NAME}-(.*)$" "${CMAKE_PROJECT_NAME}_\\1_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}" CPACK_DEBIAN_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") string(APPEND CPACK_PACKAGE_FILE_NAME "-${CMAKE_SYSTEM_PROCESSOR}") From d6b3efebe34c8b657a0c96397ead82a9aee6162c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 13 Sep 2022 11:51:19 -0500 Subject: [PATCH 041/111] GH-149 Add 3-strike rule to speculative blocks. --- plugins/producer_plugin/producer_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 3bf670a6f7..d18f628e29 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1916,7 +1916,7 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, auto start = fc::time_point::now(); auto first_auth = trx->packed_trx()->get_transaction().first_authorizer(); - if( _pending_block_mode == pending_block_mode::producing && _account_fails.failure_limit( first_auth ) ) { + if( _account_fails.failure_limit( first_auth ) ) { if( next ) { auto except_ptr = std::static_pointer_cast( std::make_shared( FC_LOG_MESSAGE( error, "transaction ${id} exceeded failure limit for account ${a}", From 3220de9527aa8ead5f0201ec09cfc3d8e1876dab Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Tue, 13 Sep 2022 21:51:37 -0400 Subject: [PATCH 042/111] fix two signed/unsigned warnings in json snapshot reader --- libraries/chain/snapshot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/snapshot.cpp b/libraries/chain/snapshot.cpp index 14b03bd9e7..4dedf29926 100644 --- a/libraries/chain/snapshot.cpp +++ b/libraries/chain/snapshot.cpp @@ -371,13 +371,13 @@ void istream_json_snapshot_reader::validate() const { // validate totem auto expected_totem = ostream_json_snapshot_writer::magic_number; EOS_ASSERT(impl->doc.HasMember("magic_number"), snapshot_exception, "magic_number section not found" ); - auto actual_totem = impl->doc["magic_number"].GetInt(); + auto actual_totem = impl->doc["magic_number"].GetUint(); EOS_ASSERT( actual_totem == expected_totem, snapshot_exception, "JSON snapshot has unexpected magic number" ); // validate version auto expected_version = current_snapshot_version; EOS_ASSERT(impl->doc.HasMember("version"), snapshot_exception, "version section not found" ); - auto actual_version = impl->doc["version"].GetInt(); + auto actual_version = impl->doc["version"].GetUint(); EOS_ASSERT( actual_version == expected_version, snapshot_exception, "JSON snapshot is an unsupported version. Expected : ${expected}, Got: ${actual}", ("expected", expected_version)( "actual", actual_version ) ); From 8cd2e11610899579aca2b5b89e32061afcab901e Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Tue, 13 Sep 2022 22:06:03 -0400 Subject: [PATCH 043/111] always overwrite old downloads in pinned build script --- scripts/pinned_build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/pinned_build.sh b/scripts/pinned_build.sh index 6e4ee37870..7f96484945 100755 --- a/scripts/pinned_build.sh +++ b/scripts/pinned_build.sh @@ -69,7 +69,7 @@ install_clang() { echo "Installing Clang ${CLANG_VER} @ ${CLANG_DIR}" mkdir -p ${CLANG_DIR} CLANG_FN=clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-16.04.tar.xz - try wget https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VER}/${CLANG_FN} + try wget -O ${CLANG_FN} https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VER}/${CLANG_FN} try tar -xvf ${CLANG_FN} -C ${CLANG_DIR} pushdir ${CLANG_DIR} mv clang+*/* . @@ -85,7 +85,7 @@ install_llvm() { if [ ! -d "${LLVM_DIR}" ]; then echo "Installing LLVM ${LLVM_VER} @ ${LLVM_DIR}" mkdir -p ${LLVM_DIR} - try wget https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/llvm-${LLVM_VER}.src.tar.xz + try wget -O llvm-${LLVM_VER}.src.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/llvm-${LLVM_VER}.src.tar.xz try tar -xvf llvm-${LLVM_VER}.src.tar.xz pushdir "${LLVM_DIR}.src" pushdir build @@ -105,7 +105,7 @@ install_boost() { if [ ! -d "${BOOST_DIR}" ]; then echo "Installing Boost ${BOOST_VER} @ ${BOOST_DIR}" - try wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VER}/source/boost_${BOOST_VER//\./_}.tar.gz + try wget -O boost_${BOOST_VER//\./_}.tar.gz https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VER}/source/boost_${BOOST_VER//\./_}.tar.gz try tar --transform="s:^boost_${BOOST_VER//\./_}:boost_${BOOST_VER//\./_}patched:" -xvzf boost_${BOOST_VER//\./_}.tar.gz -C ${DEP_DIR} pushdir ${BOOST_DIR} patch -p1 < "${SCRIPT_DIR}/0001-beast-fix-moved-from-executor.patch" From 7aa26d5dc38b8ba1a0f3c0a87db777871a129d10 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 14 Sep 2022 09:57:05 -0500 Subject: [PATCH 044/111] GH-118 Revert back to not automatically unpacking action data. Instead only unpack action data when explicitly aksed via --unpack-action-data option. --- programs/cleos/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 3d0cf920e5..53b127eabb 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -166,6 +166,7 @@ const fc::microseconds abi_serializer_max_time = fc::seconds(10); // No risk to string tx_ref_block_num_or_id; bool tx_force_unique = false; bool tx_dont_broadcast = false; +bool tx_unpack_data = false; bool tx_return_packed = false; bool tx_skip_sign = false; bool tx_print_json = false; @@ -226,6 +227,7 @@ void add_standard_transaction_options(CLI::App* cmd, string default_permission = cmd->add_flag("-j,--json", tx_print_json, localized("Print result as JSON")); cmd->add_option("--json-file", tx_json_save_file, localized("Save result in JSON format into a file")); cmd->add_flag("-d,--dont-broadcast", tx_dont_broadcast, localized("Don't broadcast transaction to the network (just print to stdout)")); + cmd->add_flag("-u,--unpack-action-data", tx_unpack_data, localized("Unpack all action data within transaction, needs interaction with ${n} unless --abi-file. Used in conjunction with --dont-broadcast.", ("n", node_executable_name))); cmd->add_flag("--return-packed", tx_return_packed, localized("Used in conjunction with --dont-broadcast to get the packed transaction")); cmd->add_option("-r,--ref-block", tx_ref_block_num_or_id, (localized("Set the reference block num or block id used for TAPOS (Transaction as Proof-of-Stake)"))); cmd->add_flag("--use-old-rpc", tx_use_old_rpc, localized("Use old RPC push_transaction, rather than new RPC send_transaction")); @@ -499,14 +501,15 @@ fc::variant push_transaction( signed_transaction& trx, const std::vector Date: Wed, 14 Sep 2022 09:57:59 -0500 Subject: [PATCH 045/111] GH-118 Update test case for unpacked-action-data option. Also add new test case expecting default of packed action data. --- tests/nodeos_run_test.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/nodeos_run_test.py b/tests/nodeos_run_test.py index aa49eff704..e23fea2cd6 100755 --- a/tests/nodeos_run_test.py +++ b/tests/nodeos_run_test.py @@ -573,10 +573,11 @@ if actual != expected: errorExit("FAILURE - Wrong currency1111 balance (expected=%s, actual=%s)" % (str(expected), str(actual)), raw=True) - Print("push transfer action to currency1111 contract with sign skipping option enabled") + # Test skip sign with unpacked action data + Print("push transfer action to currency1111 contract with sign skipping and unpack action data options enabled") data="{\"from\":\"currency1111\",\"to\":\"defproducera\",\"quantity\":" data +="\"00.0001 CUR\",\"memo\":\"test\"}" - opts="-s -d --permission currency1111@active" + opts="-s -d -u --permission currency1111@active" trans=node.pushMessage(contract, action, data, opts, expectTrxTrace=False) try: @@ -603,6 +604,37 @@ if actual != expected: errorExit("FAILURE - Wrong currency1111 balance (expectedgma=%s, actual=%s)" % (str(expected), str(actual)), raw=True) + # Test skip sign with packed action data + Print("push transfer action to currency1111 contract with sign skipping option enabled") + data="{\"from\":\"currency1111\",\"to\":\"defproducera\",\"quantity\":" + data +="\"00.0002 CUR\",\"memo\":\"test packed\"}" + opts="-s -d --permission currency1111@active" + trans=node.pushMessage(contract, action, data, opts, expectTrxTrace=False) + + try: + assert(not trans[1]["signatures"]) + except (AssertionError, KeyError) as _: + Print("ERROR: Expected signatures array to be empty due to skipping option enabled.") + raise + + try: + data = trans[1]["actions"][0]["data"] + Print(f"Action data: {data}") + assert data == "1042081e4d75af4660ae423ad15b974a020000000000000004435552000000000b74657374207061636b6564" + except (AssertionError, KeyError) as _: + Print("ERROR: Expecting packed data on push transfer action json result.") + raise + + result=node.pushTransaction(trans[1], None) + + amountStr=node.getTableAccountBalance("currency1111", currencyAccount.name) + + expected="99999.9997 CUR" + actual=amountStr + if actual != expected: + errorExit("FAILURE - Wrong currency1111 balance (expectedgma=%s, actual=%s)" % (str(expected), str(actual)), raw=True) + + Print("---- Test for signing transaction ----") testeraAccountAmountBeforeTrx=node.getAccountEosBalanceStr(testeraAccount.name) currencyAccountAmountBeforeTrx=node.getAccountEosBalanceStr(currencyAccount.name) From 19110808768295c224b742b451e6600371702276 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Wed, 14 Sep 2022 17:25:57 -0400 Subject: [PATCH 046/111] move parallel tests to 'hightier' runner --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4df01cf178..b95d924124 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -126,7 +126,7 @@ jobs: fail-fast: false matrix: platform: [ubuntu20] - runs-on: ["self-hosted", "enf-x86-beefy"] + runs-on: ["self-hosted", "enf-x86-hightier"] container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}} steps: - uses: actions/checkout@v3 From c0233fbc3c4f8cf7eac60dbb056ae4434bd08d89 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 14 Sep 2022 16:27:12 -0500 Subject: [PATCH 047/111] GH-119 Cleanup const use. --- plugins/producer_plugin/producer_plugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 3bf670a6f7..5536b209b7 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -145,7 +145,7 @@ class account_failures { max_failures_per_account = max_failures; } - void add_idle_time( const fc::microseconds& idle ) const { + void add_idle_time( const fc::microseconds& idle ) { block_idle_time += idle; } @@ -177,7 +177,7 @@ class account_failures { return false; } - void report( const fc::time_point& idle_trx_time ) const { + void report( const fc::time_point& idle_trx_time ) { if( _log.is_enabled( fc::log_level::debug ) ) { auto now = fc::time_point::now(); add_idle_time( now - idle_trx_time ); @@ -249,7 +249,7 @@ class account_failures { std::map failed_accounts; uint32_t max_failures_per_account = 3; - mutable fc::microseconds block_idle_time; + fc::microseconds block_idle_time; uint32_t trx_success_num = 0; uint32_t trx_fail_num = 0; fc::microseconds trx_success_time; From b18984782517339bf3f38483d4a1f64306c53fc3 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Wed, 14 Sep 2022 19:09:38 -0400 Subject: [PATCH 048/111] use a temp dir for release-build test as it can leak creation of config --- tests/release-build.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/release-build.sh b/tests/release-build.sh index c969bec0d6..3bfff3740e 100755 --- a/tests/release-build.sh +++ b/tests/release-build.sh @@ -11,7 +11,11 @@ echo 'nodeos from source should perform a "release build" which excludes asserts echo 'debugging symbols, and performs compiler optimizations.' echo '' -NODEOS_DEBUG=$(programs/nodeos/nodeos --extract-build-info >(python3 -c 'import json,sys; print(str(json.load(sys.stdin)["debug"]).lower());') &> /dev/null) +TDIR=$(mktemp -d || exit 1) +NODEOS_DEBUG=$(programs/nodeos/nodeos --config-dir "${TDIR}" --data-dir "${TDIR}" --extract-build-info >(python3 -c 'import json,sys; print(str(json.load(sys.stdin)["debug"]).lower());') &> /dev/null) +#avoiding an rm -rf out of paranoia, but with the tradeoff this could change somehow in the future +rm "${TDIR}/config.ini" || exit 1 +rmdir "${TDIR}" || exit 1 if [[ "${NODEOS_DEBUG}" == 'false' ]]; then echo 'PASS: Debug flag is not set.' echo '' From f66af885ab3841b5f652b6bc0a9d55793261f17d Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 14 Sep 2022 19:17:55 -0500 Subject: [PATCH 049/111] Remove initial_chain_id in genesis.json as it is not supported. A remnant of long ago... --- tutorials/bios-boot-tutorial/genesis.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tutorials/bios-boot-tutorial/genesis.json b/tutorials/bios-boot-tutorial/genesis.json index 6e27e3cd87..f0f77b4fbb 100644 --- a/tutorials/bios-boot-tutorial/genesis.json +++ b/tutorials/bios-boot-tutorial/genesis.json @@ -19,6 +19,5 @@ "max_inline_action_size": 4096, "max_inline_action_depth": 4, "max_authority_depth": 6 - }, - "initial_chain_id": "0000000000000000000000000000000000000000000000000000000000000000" + } } From b473d78aa0e0ce4c94058265790e44f8a0b34ca8 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Thu, 15 Sep 2022 14:44:56 -0400 Subject: [PATCH 050/111] commit package-lock.json to ensure reproducibility of dist/ generation --- .../package-lock.json | 351 ++++++++++++++++++ .../parallel-ctest-containers/package.json | 2 +- 2 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 .github/actions/parallel-ctest-containers/package-lock.json diff --git a/.github/actions/parallel-ctest-containers/package-lock.json b/.github/actions/parallel-ctest-containers/package-lock.json new file mode 100644 index 0000000000..7da87a8f2d --- /dev/null +++ b/.github/actions/parallel-ctest-containers/package-lock.json @@ -0,0 +1,351 @@ +{ + "name": "parallel-ctest-containers", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "@actions/core": "^1.9.1", + "@vercel/ncc": "^0.34.0", + "tar-stream": "^2.2.0" + } + }, + "node_modules/@actions/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "dependencies": { + "tunnel": "^0.0.6" + } + }, + "node_modules/@vercel/ncc": { + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz", + "integrity": "sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A==", + "bin": { + "ncc": "dist/ncc/cli.js" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + }, + "dependencies": { + "@actions/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "requires": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "requires": { + "tunnel": "^0.0.6" + } + }, + "@vercel/ncc": { + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz", + "integrity": "sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + } +} diff --git a/.github/actions/parallel-ctest-containers/package.json b/.github/actions/parallel-ctest-containers/package.json index af0899aa98..23aa941a70 100644 --- a/.github/actions/parallel-ctest-containers/package.json +++ b/.github/actions/parallel-ctest-containers/package.json @@ -1,7 +1,7 @@ { "dependencies": { "@actions/core": "^1.9.1", + "@vercel/ncc": "^0.34.0", "tar-stream": "^2.2.0" } - } From 2aefa0d3c91007a480d39d41f6b5e01eab15421c Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Thu, 15 Sep 2022 13:30:36 -0700 Subject: [PATCH 051/111] updated swagger for http production producer plugin --- .../producer_api_plugin/producer.swagger.yaml | 574 ++++++++++-------- 1 file changed, 315 insertions(+), 259 deletions(-) diff --git a/plugins/producer_api_plugin/producer.swagger.yaml b/plugins/producer_api_plugin/producer.swagger.yaml index aea863a798..fdab07368b 100644 --- a/plugins/producer_api_plugin/producer.swagger.yaml +++ b/plugins/producer_api_plugin/producer.swagger.yaml @@ -6,7 +6,7 @@ info: name: MIT url: https://opensource.org/licenses/MIT contact: - url: https://eos.io + url: https://eosnetwork.com tags: - name: eosio servers: @@ -30,259 +30,162 @@ paths: /producer/pause: post: summary: pause - description: Pause producer node + description: Pause producer node. Takes no arguments returns no values. operationId: pause - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: boolean - description: "returns status" + $ref: '#/component/schema/OK' /producer/resume: post: summary: resume - description: Resume producer node + description: Resume producer node. Takes no arguments returns no values. operationId: resume - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - description: Resumes activity for producer responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' /producer/paused: post: summary: paused - description: Retreives paused status for producer node + description: Retreives paused status for producer node. Takes no arguments returns no values. operationId: paused - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: boolean - description: True if producer is paused, false otherwise + $ref: '#/component/schema/OK' /producer/get_runtime_options: post: summary: get_runtime_options - description: Retreives run time options for producer node + description: Retreives run time options for producer node. Only `incoming_defer_ratio` is a floating point number the other return values are signed integers. operationId: get_runtime_options - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: object - description: Returns run time options set for the producer - properties: - max_transaction_time: - type: integer - description: Max transaction time - max_irreversible_block_age: - type: integer - description: Max irreversible block age - produce_time_offset_us: - type: integer - description: Time offset - last_block_time_offset_us: - type: integer - description: Last block time offset - max_scheduled_transaction_time_per_block_ms: - type: integer - description: Max scheduled transaction time per block in ms - subjective_cpu_leeway_us: - type: integer - description: Subjective CPU leeway - incoming_defer_ratio: - type: integer - description: Incoming defer ration + $ref: '#/component/schema/Runtime_Options' + /producer/update_runtime_options: post: summary: update_runtime_options - description: Update run time options for producer node + description: Update run time options for producer node. May post any of the runtime options in combination or along. Only `incoming_defer_ratio` is a floating point number the other values are signed integers. operationId: update_runtime_options - parameters: [] requestBody: content: application/json: schema: - type: object - required: - - options - properties: - options: - type: object - description: Defines the run time options to set for the producer - properties: - max_transaction_time: - type: integer - description: Max transaction time - max_irreversible_block_age: - type: integer - description: Max irreversible block age - produce_time_offset_us: - type: integer - description: Time offset - last_block_time_offset_us: - type: integer - description: Last block time offset - max_scheduled_transaction_time_per_block_ms: - type: integer - description: Max scheduled transaction time per block in ms - subjective_cpu_leeway_us: - type: integer - description: Subjective CPU leeway - incoming_defer_ratio: - type: integer - description: Incoming defer ration + $ref: '#/component/schema/Runtime_Options' responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' /producer/get_greylist: post: summary: get_greylist - description: Retreives the greylist for producer node + description: Retreives the greylist for producer node. operationId: get_greylist - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: array - description: List of account names stored in the greylist - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + type: object + properties: + accounts: + type: array + description: Array of account names stored in the greylist + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" /producer/add_greylist_accounts: post: summary: add_greylist_accounts - description: Adds accounts to grey list for producer node + description: Adds accounts to grey list for producer node. At least one account is required. operationId: add_greylist_accounts - parameters: [] requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - properties: - accounts: - type: array - description: List of account names to add - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + accounts: + type: array + description: List of account names to add + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/remove_greylist_accounts: post: summary: remove_greylist_accounts - description: Removes accounts from greylist for producer node + description: Removes accounts from greylist for producer node. At least one account is required. operationId: remove_greylist_accounts - parameters: [] requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - properties: - accounts: - type: array - description: List of account names to remove - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + accounts: + type: array + description: List of account names to remove + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - type: array - description: List of account names stored in the greylist - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - + $ref: '#/component/schema/OK' + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/get_whitelist_blacklist: post: summary: get_whitelist_blacklist - description: Retreives the white list and black list for producer node + description: Retreives the white list and black list for producer node. A json object containing whitelist and blacklist information. `actor_whitelist` , `actor_blacklist`, `contract_whitelist`, `contract_blacklist` are represented by an array of Names. `action_blacklist` is an array of tuples consisting of Name and Action. `key_blacklist` is an array of Public Keys. Name is a string represeting a NamePrivileged or NameBasic or NameBid or NameCatchAll operationId: get_whitelist_blacklist - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: type: object - description: Defines the actor whitelist and blacklist, the contract whitelist and blacklist, the action blacklist and key blacklist properties: actor_whitelist: type: array @@ -317,106 +220,105 @@ paths: /producer/set_whitelist_blacklist: post: summary: set_whitelist_blacklist - description: Sets the white list and black list for producer node + description: Defines the whitelist and blacklist for a producer node. Takes a json object containing whitelist and blacklist information. At least one of actor_whitelist, actor_blacklist, contract_whitelist, contract_blacklist, action_blacklist, and key_blacklist is required. `actor_whitelist` , `actor_blacklist`, `contract_whitelist`, `contract_blacklist` take an array of Names. `action_blacklist` is an array of tuples consisting of Name and Action. `key_blacklist` is an array of Public Keys. Name is a string represeting a NamePrivileged or NameBasic or NameBid or NameCatchAll operationId: set_whitelist_blacklist - parameters: [] + required: true requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - description: Defines the actor whitelist and blacklist, the contract whitelist and blacklist, the action blacklist and key blacklist - properties: - actor_whitelist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - actor_blacklist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - contract_whitelist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - contract_blacklist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - action_blacklist: - type: array - items: - type: array - description: Array of two string values, the account name as the first and action name as the second - items: - allOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/CppSignature.yaml" - key_blacklist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/KeyType.yaml" - + actor_whitelist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + actor_blacklist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + contract_whitelist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + contract_blacklist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + action_blacklist: + type: array + items: + type: array + description: Array of two string values, the account name as the first and action name as the second + items: + anyOf: + - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + - $ref: "https://eosio.github.io/schemata/v2.0/oas/CppSignature.yaml" + key_blacklist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/KeyType.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' + + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' + /producer/create_snapshot: post: summary: create_snapshot - description: Creates a snapshot for producer node + description: Creates a snapshot for producer node. Returns error when unable to create snapshot. operationId: create_snapshot - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - required: - - next - properties: - next: - type: object - description: Defines the snapshot to be created - properties: - snapshot_name: - type: string - description: The name of the snapshot - head_block_id: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" - - responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + type: object + properties: + head_block_id: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + head_block_num: + type: integer + descripiton: Highest block number on the chain + example: 5102 + head_block_time: + type: string + description: Highest block unix timestamp + example: 2020-11-16T00:00:00.000 + version: + type: integer + description: version number + example: 6 + snapshot_name: + type: string + description: The path and file name of the snapshot + example: /home/me/nodes/node-name/snapshots/snapshot-0000999f99999f9f999f99f99ff9999f999f9fff99ff99ffff9f9f9fff9f9999.bin + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/get_integrity_hash: post: summary: get_integrity_hash description: Retreives the integrity hash for producer node operationId: get_integrity_hash - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: @@ -424,69 +326,61 @@ paths: type: object description: Defines the integrity hash information details properties: - integrity_hash: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" head_block_id: $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + integrity_hash: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" /producer/schedule_protocol_feature_activations: post: summary: schedule_protocol_feature_activations - description: Schedule protocol feature activation for producer node + description: Schedule protocol feature activation for producer node. Note some features may require pre-activation. Will return error for duplicate requests or when feature required pre-activation. operationId: schedule_protocol_feature_activations - parameters: [] requestBody: content: application/json: schema: type: object - required: - - schedule properties: - schedule: - type: object - properties: - protocol_features_to_activate: - type: array - description: List of protocol features to activate - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" - + protocol_features_to_activate: + type: array + description: List of protocol features to activate + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/get_supported_protocol_features: post: summary: get_supported_protocol_features - description: Retreives supported protocol features for producer node + description: Retreives supported protocol features for producer node. Pass filters in as part of the request body. operationId: get_supported_protocol_features - parameters: [] requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - description: Defines filters based on which to return the supported protocol features - properties: - exclude_disabled: - type: boolean - description: Exclude disabled protocol features - exclude_unactivatable: - type: boolean - description: Exclude unactivatable protocol features - + exclude_disabled: + type: boolean + description: Exclude disabled protocol features + exclude_unactivatable: + type: boolean + description: Exclude unactivatable protocol features + example: false responses: - "200": + "201": description: OK content: application/json: @@ -494,4 +388,166 @@ paths: type: array description: Variant type, an array of strings with the supported protocol features items: - type: string + type: object + properties: + feature_digest: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + subjective_restrictions: + type: object + properties: + enabled: + type: boolean + example: true + preactivation_required: + type: boolean + example: true + earliest_allowed_activation_time: + type: string + example: "1970-01-01T00:00:00.000" + description_digest: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + dependancies: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + protocol_feature_type: + type: string + example: "builtin" + specification: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + + + /producer/get_account_ram_corrections: + post: + summary: get_account_ram_corrections + description: Retreives accounts with ram corrections. + operationId: get_account_ram_corrections + requestBody: + content: + application/json: + schema: + type: object + properties: + lower_bound: + type: int + description: lowest account key + upper_bound: + type: int + description: highest account key + limit: + type: int + description: number of rows to scans + example: 10 + reverse: + type: boolean + description: direction of search + example: false + responses: + "201": + description: OK + content: + application/json: + schema: + type: object + properties: + rows: + type: array + items: + type: string + +component: + schema: + Error: + type: object + properties: + code: + type: integer + description: http return code + example: 400 + message: + type: string + description: summary of error + example: Invalid Request + error: + type: object + description: details on the error + properties: + code: + type: integer + description: internal error code + example: 3200006 + name: + type: string + description: name of error + example: invalid_http_request + what: + type: string + description: prettier version of error name + example: invalid http request + details: + type: array + description: list of additional information for debugging + items: + type: object + properties: + message: + type: string + description: debugging message + example: Unable to parse valid input from POST body + file: + type: string + description: file where error was thrown + example: http_plugin.hpp + line_number: + type: integer + description: line number in file where error was thrown + example: 246 + method: + type: string + description: function executed when error occured + example: parse_params + OK: + type: object + properties: + result: + type: string + description: status + example: ok + Runtime_Options: + type: object + properties: + max_transaction_time: + type: integer + description: Max transaction time + example: 100 + max_irreversible_block_age: + type: integer + description: Max irreversible block age + example: -1 + produce_time_offset_us: + type: integer + description: Time offset + example: -100000 + last_block_time_offset_us: + type: integer + description: Last block time offset + example: -200000 + max_scheduled_transaction_time_per_block_ms: + type: integer + description: Max scheduled transaction time per block in ms + example: 100 + incoming_defer_ratio: + type: string + description: Incoming defer ration, parsed to double + example: "1.00000000000000000" + greylist_limit: + type: integer + description: limit on number of Names supported by greylist + example: 1000 From e9d99f71f589782ac4a43f0652c4f393df98a66f Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Thu, 15 Sep 2022 14:41:25 -0400 Subject: [PATCH 052/111] move NP&LR test population into action; fix action zstd on u18 --- .github/actions/parallel-ctest-containers/action.yml | 4 ++-- .../actions/parallel-ctest-containers/dist/index.mjs | 4 ++-- .github/actions/parallel-ctest-containers/main.mjs | 10 ++++++++-- .github/workflows/build.yaml | 10 ++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/actions/parallel-ctest-containers/action.yml b/.github/actions/parallel-ctest-containers/action.yml index 1216aa2acb..b2a613dc8b 100644 --- a/.github/actions/parallel-ctest-containers/action.yml +++ b/.github/actions/parallel-ctest-containers/action.yml @@ -1,5 +1,5 @@ name: 'Parallel ctest' -description: 'Runs a set of ctests in parallel via multiple docker containers' +description: 'Runs a set of labeled ctests in parallel via multiple docker containers' inputs: container: required: true @@ -7,7 +7,7 @@ inputs: required: true log-tarball-prefix: required: true - tests: + tests-label: required: true runs: using: 'node16' diff --git a/.github/actions/parallel-ctest-containers/dist/index.mjs b/.github/actions/parallel-ctest-containers/dist/index.mjs index f440ba8f6b..7ed5739f53 100644 --- a/.github/actions/parallel-ctest-containers/dist/index.mjs +++ b/.github/actions/parallel-ctest-containers/dist/index.mjs @@ -1,3 +1,3 @@ -import{createRequire as e}from"module";var t={5886:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};Object.defineProperty(t,"__esModule",{value:true});t.issue=t.issueCommand=void 0;const o=a(r(2037));const s=r(6266);function issueCommand(e,t,r){const n=new Command(e,t,r);process.stdout.write(n.toString()+o.EOL)}t.issueCommand=issueCommand;function issue(e,t=""){issueCommand(e,{},t)}t.issue=issue;const u="::";class Command{constructor(e,t,r){if(!e){e="missing.command"}this.command=e;this.properties=t;this.message=r}toString(){let e=u+this.command;if(this.properties&&Object.keys(this.properties).length>0){e+=" ";let t=true;for(const r in this.properties){if(this.properties.hasOwnProperty(r)){const n=this.properties[r];if(n){if(t){t=false}else{e+=","}e+=`${r}=${escapeProperty(n)}`}}}}e+=`${u}${escapeData(this.message)}`;return e}}function escapeData(e){return s.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function escapeProperty(e){return s.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}},9362:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};var o=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.getIDToken=t.getState=t.saveState=t.group=t.endGroup=t.startGroup=t.info=t.notice=t.warning=t.error=t.debug=t.isDebug=t.setFailed=t.setCommandEcho=t.setOutput=t.getBooleanInput=t.getMultilineInput=t.getInput=t.addPath=t.setSecret=t.exportVariable=t.ExitCode=void 0;const s=r(5886);const u=r(1859);const l=r(6266);const c=a(r(2037));const d=a(r(1017));const h=r(6470);const p=r(2082);var g;(function(e){e[e["Success"]=0]="Success";e[e["Failure"]=1]="Failure"})(g=t.ExitCode||(t.ExitCode={}));function exportVariable(e,t){const r=l.toCommandValue(t);process.env[e]=r;const n=process.env["GITHUB_ENV"]||"";if(n){const t=`ghadelimiter_${h.v4()}`;if(e.includes(t)){throw new Error(`Unexpected input: name should not contain the delimiter "${t}"`)}if(r.includes(t)){throw new Error(`Unexpected input: value should not contain the delimiter "${t}"`)}const n=`${e}<<${t}${c.EOL}${r}${c.EOL}${t}`;u.issueCommand("ENV",n)}else{s.issueCommand("set-env",{name:e},r)}}t.exportVariable=exportVariable;function setSecret(e){s.issueCommand("add-mask",{},e)}t.setSecret=setSecret;function addPath(e){const t=process.env["GITHUB_PATH"]||"";if(t){u.issueCommand("PATH",e)}else{s.issueCommand("add-path",{},e)}process.env["PATH"]=`${e}${d.delimiter}${process.env["PATH"]}`}t.addPath=addPath;function getInput(e,t){const r=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(t&&t.required&&!r){throw new Error(`Input required and not supplied: ${e}`)}if(t&&t.trimWhitespace===false){return r}return r.trim()}t.getInput=getInput;function getMultilineInput(e,t){const r=getInput(e,t).split("\n").filter((e=>e!==""));return r}t.getMultilineInput=getMultilineInput;function getBooleanInput(e,t){const r=["true","True","TRUE"];const n=["false","False","FALSE"];const i=getInput(e,t);if(r.includes(i))return true;if(n.includes(i))return false;throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${e}\n`+`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``)}t.getBooleanInput=getBooleanInput;function setOutput(e,t){process.stdout.write(c.EOL);s.issueCommand("set-output",{name:e},t)}t.setOutput=setOutput;function setCommandEcho(e){s.issue("echo",e?"on":"off")}t.setCommandEcho=setCommandEcho;function setFailed(e){process.exitCode=g.Failure;error(e)}t.setFailed=setFailed;function isDebug(){return process.env["RUNNER_DEBUG"]==="1"}t.isDebug=isDebug;function debug(e){s.issueCommand("debug",{},e)}t.debug=debug;function error(e,t={}){s.issueCommand("error",l.toCommandProperties(t),e instanceof Error?e.toString():e)}t.error=error;function warning(e,t={}){s.issueCommand("warning",l.toCommandProperties(t),e instanceof Error?e.toString():e)}t.warning=warning;function notice(e,t={}){s.issueCommand("notice",l.toCommandProperties(t),e instanceof Error?e.toString():e)}t.notice=notice;function info(e){process.stdout.write(e+c.EOL)}t.info=info;function startGroup(e){s.issue("group",e)}t.startGroup=startGroup;function endGroup(){s.issue("endgroup")}t.endGroup=endGroup;function group(e,t){return o(this,void 0,void 0,(function*(){startGroup(e);let r;try{r=yield t()}finally{endGroup()}return r}))}t.group=group;function saveState(e,t){s.issueCommand("save-state",{name:e},t)}t.saveState=saveState;function getState(e){return process.env[`STATE_${e}`]||""}t.getState=getState;function getIDToken(e){return o(this,void 0,void 0,(function*(){return yield p.OidcClient.getIDToken(e)}))}t.getIDToken=getIDToken;var m=r(6626);Object.defineProperty(t,"summary",{enumerable:true,get:function(){return m.summary}});var b=r(6626);Object.defineProperty(t,"markdownSummary",{enumerable:true,get:function(){return b.markdownSummary}});var v=r(6690);Object.defineProperty(t,"toPosixPath",{enumerable:true,get:function(){return v.toPosixPath}});Object.defineProperty(t,"toWin32Path",{enumerable:true,get:function(){return v.toWin32Path}});Object.defineProperty(t,"toPlatformPath",{enumerable:true,get:function(){return v.toPlatformPath}})},1859:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};Object.defineProperty(t,"__esModule",{value:true});t.issueCommand=void 0;const o=a(r(7147));const s=a(r(2037));const u=r(6266);function issueCommand(e,t){const r=process.env[`GITHUB_${e}`];if(!r){throw new Error(`Unable to find environment variable for file command ${e}`)}if(!o.existsSync(r)){throw new Error(`Missing file at path: ${r}`)}o.appendFileSync(r,`${u.toCommandValue(t)}${s.EOL}`,{encoding:"utf8"})}t.issueCommand=issueCommand},2082:function(e,t,r){var n=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.OidcClient=void 0;const i=r(7616);const a=r(5724);const o=r(9362);class OidcClient{static createHttpClient(e=true,t=10){const r={allowRetries:e,maxRetries:t};return new i.HttpClient("actions/oidc-client",[new a.BearerCredentialHandler(OidcClient.getRequestToken())],r)}static getRequestToken(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable")}return e}static getIDTokenUrl(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_URL"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable")}return e}static getCall(e){var t;return n(this,void 0,void 0,(function*(){const r=OidcClient.createHttpClient();const n=yield r.getJson(e).catch((e=>{throw new Error(`Failed to get ID Token. \n \n Error Code : ${e.statusCode}\n \n Error Message: ${e.result.message}`)}));const i=(t=n.result)===null||t===void 0?void 0:t.value;if(!i){throw new Error("Response json body do not have ID Token field")}return i}))}static getIDToken(e){return n(this,void 0,void 0,(function*(){try{let t=OidcClient.getIDTokenUrl();if(e){const r=encodeURIComponent(e);t=`${t}&audience=${r}`}o.debug(`ID token url is ${t}`);const r=yield OidcClient.getCall(t);o.setSecret(r);return r}catch(e){throw new Error(`Error message: ${e.message}`)}}))}}t.OidcClient=OidcClient},6690:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};Object.defineProperty(t,"__esModule",{value:true});t.toPlatformPath=t.toWin32Path=t.toPosixPath=void 0;const o=a(r(1017));function toPosixPath(e){return e.replace(/[\\]/g,"/")}t.toPosixPath=toPosixPath;function toWin32Path(e){return e.replace(/[/]/g,"\\")}t.toWin32Path=toWin32Path;function toPlatformPath(e){return e.replace(/[/\\]/g,o.sep)}t.toPlatformPath=toPlatformPath},6626:function(e,t,r){var n=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.summary=t.markdownSummary=t.SUMMARY_DOCS_URL=t.SUMMARY_ENV_VAR=void 0;const i=r(2037);const a=r(7147);const{access:o,appendFile:s,writeFile:u}=a.promises;t.SUMMARY_ENV_VAR="GITHUB_STEP_SUMMARY";t.SUMMARY_DOCS_URL="https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary";class Summary{constructor(){this._buffer=""}filePath(){return n(this,void 0,void 0,(function*(){if(this._filePath){return this._filePath}const e=process.env[t.SUMMARY_ENV_VAR];if(!e){throw new Error(`Unable to find environment variable for $${t.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`)}try{yield o(e,a.constants.R_OK|a.constants.W_OK)}catch(t){throw new Error(`Unable to access summary file: '${e}'. Check if the file has correct read/write permissions.`)}this._filePath=e;return this._filePath}))}wrap(e,t,r={}){const n=Object.entries(r).map((([e,t])=>` ${e}="${t}"`)).join("");if(!t){return`<${e}${n}>`}return`<${e}${n}>${t}`}write(e){return n(this,void 0,void 0,(function*(){const t=!!(e===null||e===void 0?void 0:e.overwrite);const r=yield this.filePath();const n=t?u:s;yield n(r,this._buffer,{encoding:"utf8"});return this.emptyBuffer()}))}clear(){return n(this,void 0,void 0,(function*(){return this.emptyBuffer().write({overwrite:true})}))}stringify(){return this._buffer}isEmptyBuffer(){return this._buffer.length===0}emptyBuffer(){this._buffer="";return this}addRaw(e,t=false){this._buffer+=e;return t?this.addEOL():this}addEOL(){return this.addRaw(i.EOL)}addCodeBlock(e,t){const r=Object.assign({},t&&{lang:t});const n=this.wrap("pre",this.wrap("code",e),r);return this.addRaw(n).addEOL()}addList(e,t=false){const r=t?"ol":"ul";const n=e.map((e=>this.wrap("li",e))).join("");const i=this.wrap(r,n);return this.addRaw(i).addEOL()}addTable(e){const t=e.map((e=>{const t=e.map((e=>{if(typeof e==="string"){return this.wrap("td",e)}const{header:t,data:r,colspan:n,rowspan:i}=e;const a=t?"th":"td";const o=Object.assign(Object.assign({},n&&{colspan:n}),i&&{rowspan:i});return this.wrap(a,r,o)})).join("");return this.wrap("tr",t)})).join("");const r=this.wrap("table",t);return this.addRaw(r).addEOL()}addDetails(e,t){const r=this.wrap("details",this.wrap("summary",e)+t);return this.addRaw(r).addEOL()}addImage(e,t,r){const{width:n,height:i}=r||{};const a=Object.assign(Object.assign({},n&&{width:n}),i&&{height:i});const o=this.wrap("img",null,Object.assign({src:e,alt:t},a));return this.addRaw(o).addEOL()}addHeading(e,t){const r=`h${t}`;const n=["h1","h2","h3","h4","h5","h6"].includes(r)?r:"h1";const i=this.wrap(n,e);return this.addRaw(i).addEOL()}addSeparator(){const e=this.wrap("hr",null);return this.addRaw(e).addEOL()}addBreak(){const e=this.wrap("br",null);return this.addRaw(e).addEOL()}addQuote(e,t){const r=Object.assign({},t&&{cite:t});const n=this.wrap("blockquote",e,r);return this.addRaw(n).addEOL()}addLink(e,t){const r=this.wrap("a",e,{href:t});return this.addRaw(r).addEOL()}}const l=new Summary;t.markdownSummary=l;t.summary=l},6266:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t.toCommandProperties=t.toCommandValue=void 0;function toCommandValue(e){if(e===null||e===undefined){return""}else if(typeof e==="string"||e instanceof String){return e}return JSON.stringify(e)}t.toCommandValue=toCommandValue;function toCommandProperties(e){if(!Object.keys(e).length){return{}}return{title:e.title,file:e.file,line:e.startLine,endLine:e.endLine,col:e.startColumn,endColumn:e.endColumn}}t.toCommandProperties=toCommandProperties},5724:function(e,t){var r=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.PersonalAccessTokenCredentialHandler=t.BearerCredentialHandler=t.BasicCredentialHandler=void 0;class BasicCredentialHandler{constructor(e,t){this.username=e;this.password=t}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`${this.username}:${this.password}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return r(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}t.BasicCredentialHandler=BasicCredentialHandler;class BearerCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Bearer ${this.token}`}canHandleAuthentication(){return false}handleAuthentication(){return r(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}t.BearerCredentialHandler=BearerCredentialHandler;class PersonalAccessTokenCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`PAT:${this.token}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return r(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}t.PersonalAccessTokenCredentialHandler=PersonalAccessTokenCredentialHandler},7616:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};var o=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.HttpClient=t.isHttps=t.HttpClientResponse=t.HttpClientError=t.getProxyUrl=t.MediaTypes=t.Headers=t.HttpCodes=void 0;const s=a(r(3685));const u=a(r(5687));const l=a(r(8754));const c=a(r(1270));var d;(function(e){e[e["OK"]=200]="OK";e[e["MultipleChoices"]=300]="MultipleChoices";e[e["MovedPermanently"]=301]="MovedPermanently";e[e["ResourceMoved"]=302]="ResourceMoved";e[e["SeeOther"]=303]="SeeOther";e[e["NotModified"]=304]="NotModified";e[e["UseProxy"]=305]="UseProxy";e[e["SwitchProxy"]=306]="SwitchProxy";e[e["TemporaryRedirect"]=307]="TemporaryRedirect";e[e["PermanentRedirect"]=308]="PermanentRedirect";e[e["BadRequest"]=400]="BadRequest";e[e["Unauthorized"]=401]="Unauthorized";e[e["PaymentRequired"]=402]="PaymentRequired";e[e["Forbidden"]=403]="Forbidden";e[e["NotFound"]=404]="NotFound";e[e["MethodNotAllowed"]=405]="MethodNotAllowed";e[e["NotAcceptable"]=406]="NotAcceptable";e[e["ProxyAuthenticationRequired"]=407]="ProxyAuthenticationRequired";e[e["RequestTimeout"]=408]="RequestTimeout";e[e["Conflict"]=409]="Conflict";e[e["Gone"]=410]="Gone";e[e["TooManyRequests"]=429]="TooManyRequests";e[e["InternalServerError"]=500]="InternalServerError";e[e["NotImplemented"]=501]="NotImplemented";e[e["BadGateway"]=502]="BadGateway";e[e["ServiceUnavailable"]=503]="ServiceUnavailable";e[e["GatewayTimeout"]=504]="GatewayTimeout"})(d=t.HttpCodes||(t.HttpCodes={}));var h;(function(e){e["Accept"]="accept";e["ContentType"]="content-type"})(h=t.Headers||(t.Headers={}));var p;(function(e){e["ApplicationJson"]="application/json"})(p=t.MediaTypes||(t.MediaTypes={}));function getProxyUrl(e){const t=l.getProxyUrl(new URL(e));return t?t.href:""}t.getProxyUrl=getProxyUrl;const g=[d.MovedPermanently,d.ResourceMoved,d.SeeOther,d.TemporaryRedirect,d.PermanentRedirect];const m=[d.BadGateway,d.ServiceUnavailable,d.GatewayTimeout];const b=["OPTIONS","GET","DELETE","HEAD"];const v=10;const _=5;class HttpClientError extends Error{constructor(e,t){super(e);this.name="HttpClientError";this.statusCode=t;Object.setPrototypeOf(this,HttpClientError.prototype)}}t.HttpClientError=HttpClientError;class HttpClientResponse{constructor(e){this.message=e}readBody(){return o(this,void 0,void 0,(function*(){return new Promise((e=>o(this,void 0,void 0,(function*(){let t=Buffer.alloc(0);this.message.on("data",(e=>{t=Buffer.concat([t,e])}));this.message.on("end",(()=>{e(t.toString())}))}))))}))}}t.HttpClientResponse=HttpClientResponse;function isHttps(e){const t=new URL(e);return t.protocol==="https:"}t.isHttps=isHttps;class HttpClient{constructor(e,t,r){this._ignoreSslError=false;this._allowRedirects=true;this._allowRedirectDowngrade=false;this._maxRedirects=50;this._allowRetries=false;this._maxRetries=1;this._keepAlive=false;this._disposed=false;this.userAgent=e;this.handlers=t||[];this.requestOptions=r;if(r){if(r.ignoreSslError!=null){this._ignoreSslError=r.ignoreSslError}this._socketTimeout=r.socketTimeout;if(r.allowRedirects!=null){this._allowRedirects=r.allowRedirects}if(r.allowRedirectDowngrade!=null){this._allowRedirectDowngrade=r.allowRedirectDowngrade}if(r.maxRedirects!=null){this._maxRedirects=Math.max(r.maxRedirects,0)}if(r.keepAlive!=null){this._keepAlive=r.keepAlive}if(r.allowRetries!=null){this._allowRetries=r.allowRetries}if(r.maxRetries!=null){this._maxRetries=r.maxRetries}}}options(e,t){return o(this,void 0,void 0,(function*(){return this.request("OPTIONS",e,null,t||{})}))}get(e,t){return o(this,void 0,void 0,(function*(){return this.request("GET",e,null,t||{})}))}del(e,t){return o(this,void 0,void 0,(function*(){return this.request("DELETE",e,null,t||{})}))}post(e,t,r){return o(this,void 0,void 0,(function*(){return this.request("POST",e,t,r||{})}))}patch(e,t,r){return o(this,void 0,void 0,(function*(){return this.request("PATCH",e,t,r||{})}))}put(e,t,r){return o(this,void 0,void 0,(function*(){return this.request("PUT",e,t,r||{})}))}head(e,t){return o(this,void 0,void 0,(function*(){return this.request("HEAD",e,null,t||{})}))}sendStream(e,t,r,n){return o(this,void 0,void 0,(function*(){return this.request(e,t,r,n)}))}getJson(e,t={}){return o(this,void 0,void 0,(function*(){t[h.Accept]=this._getExistingOrDefaultHeader(t,h.Accept,p.ApplicationJson);const r=yield this.get(e,t);return this._processResponse(r,this.requestOptions)}))}postJson(e,t,r={}){return o(this,void 0,void 0,(function*(){const n=JSON.stringify(t,null,2);r[h.Accept]=this._getExistingOrDefaultHeader(r,h.Accept,p.ApplicationJson);r[h.ContentType]=this._getExistingOrDefaultHeader(r,h.ContentType,p.ApplicationJson);const i=yield this.post(e,n,r);return this._processResponse(i,this.requestOptions)}))}putJson(e,t,r={}){return o(this,void 0,void 0,(function*(){const n=JSON.stringify(t,null,2);r[h.Accept]=this._getExistingOrDefaultHeader(r,h.Accept,p.ApplicationJson);r[h.ContentType]=this._getExistingOrDefaultHeader(r,h.ContentType,p.ApplicationJson);const i=yield this.put(e,n,r);return this._processResponse(i,this.requestOptions)}))}patchJson(e,t,r={}){return o(this,void 0,void 0,(function*(){const n=JSON.stringify(t,null,2);r[h.Accept]=this._getExistingOrDefaultHeader(r,h.Accept,p.ApplicationJson);r[h.ContentType]=this._getExistingOrDefaultHeader(r,h.ContentType,p.ApplicationJson);const i=yield this.patch(e,n,r);return this._processResponse(i,this.requestOptions)}))}request(e,t,r,n){return o(this,void 0,void 0,(function*(){if(this._disposed){throw new Error("Client has already been disposed.")}const i=new URL(t);let a=this._prepareRequest(e,i,n);const o=this._allowRetries&&b.includes(e)?this._maxRetries+1:1;let s=0;let u;do{u=yield this.requestRaw(a,r);if(u&&u.message&&u.message.statusCode===d.Unauthorized){let e;for(const t of this.handlers){if(t.canHandleAuthentication(u)){e=t;break}}if(e){return e.handleAuthentication(this,a,r)}else{return u}}let t=this._maxRedirects;while(u.message.statusCode&&g.includes(u.message.statusCode)&&this._allowRedirects&&t>0){const o=u.message.headers["location"];if(!o){break}const s=new URL(o);if(i.protocol==="https:"&&i.protocol!==s.protocol&&!this._allowRedirectDowngrade){throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.")}yield u.readBody();if(s.hostname!==i.hostname){for(const e in n){if(e.toLowerCase()==="authorization"){delete n[e]}}}a=this._prepareRequest(e,s,n);u=yield this.requestRaw(a,r);t--}if(!u.message.statusCode||!m.includes(u.message.statusCode)){return u}s+=1;if(s{function callbackForResult(e,t){if(e){n(e)}else if(!t){n(new Error("Unknown error"))}else{r(t)}}this.requestRawWithCallback(e,t,callbackForResult)}))}))}requestRawWithCallback(e,t,r){if(typeof t==="string"){if(!e.options.headers){e.options.headers={}}e.options.headers["Content-Length"]=Buffer.byteLength(t,"utf8")}let n=false;function handleResult(e,t){if(!n){n=true;r(e,t)}}const i=e.httpModule.request(e.options,(e=>{const t=new HttpClientResponse(e);handleResult(undefined,t)}));let a;i.on("socket",(e=>{a=e}));i.setTimeout(this._socketTimeout||3*6e4,(()=>{if(a){a.end()}handleResult(new Error(`Request timeout: ${e.options.path}`))}));i.on("error",(function(e){handleResult(e)}));if(t&&typeof t==="string"){i.write(t,"utf8")}if(t&&typeof t!=="string"){t.on("close",(function(){i.end()}));t.pipe(i)}else{i.end()}}getAgent(e){const t=new URL(e);return this._getAgent(t)}_prepareRequest(e,t,r){const n={};n.parsedUrl=t;const i=n.parsedUrl.protocol==="https:";n.httpModule=i?u:s;const a=i?443:80;n.options={};n.options.host=n.parsedUrl.hostname;n.options.port=n.parsedUrl.port?parseInt(n.parsedUrl.port):a;n.options.path=(n.parsedUrl.pathname||"")+(n.parsedUrl.search||"");n.options.method=e;n.options.headers=this._mergeHeaders(r);if(this.userAgent!=null){n.options.headers["user-agent"]=this.userAgent}n.options.agent=this._getAgent(n.parsedUrl);if(this.handlers){for(const e of this.handlers){e.prepareRequest(n.options)}}return n}_mergeHeaders(e){if(this.requestOptions&&this.requestOptions.headers){return Object.assign({},lowercaseKeys(this.requestOptions.headers),lowercaseKeys(e||{}))}return lowercaseKeys(e||{})}_getExistingOrDefaultHeader(e,t,r){let n;if(this.requestOptions&&this.requestOptions.headers){n=lowercaseKeys(this.requestOptions.headers)[t]}return e[t]||n||r}_getAgent(e){let t;const r=l.getProxyUrl(e);const n=r&&r.hostname;if(this._keepAlive&&n){t=this._proxyAgent}if(this._keepAlive&&!n){t=this._agent}if(t){return t}const i=e.protocol==="https:";let a=100;if(this.requestOptions){a=this.requestOptions.maxSockets||s.globalAgent.maxSockets}if(r&&r.hostname){const e={maxSockets:a,keepAlive:this._keepAlive,proxy:Object.assign(Object.assign({},(r.username||r.password)&&{proxyAuth:`${r.username}:${r.password}`}),{host:r.hostname,port:r.port})};let n;const o=r.protocol==="https:";if(i){n=o?c.httpsOverHttps:c.httpsOverHttp}else{n=o?c.httpOverHttps:c.httpOverHttp}t=n(e);this._proxyAgent=t}if(this._keepAlive&&!t){const e={keepAlive:this._keepAlive,maxSockets:a};t=i?new u.Agent(e):new s.Agent(e);this._agent=t}if(!t){t=i?u.globalAgent:s.globalAgent}if(i&&this._ignoreSslError){t.options=Object.assign(t.options||{},{rejectUnauthorized:false})}return t}_performExponentialBackoff(e){return o(this,void 0,void 0,(function*(){e=Math.min(v,e);const t=_*Math.pow(2,e);return new Promise((e=>setTimeout((()=>e()),t)))}))}_processResponse(e,t){return o(this,void 0,void 0,(function*(){return new Promise(((r,n)=>o(this,void 0,void 0,(function*(){const i=e.message.statusCode||0;const a={statusCode:i,result:null,headers:{}};if(i===d.NotFound){r(a)}function dateTimeDeserializer(e,t){if(typeof t==="string"){const e=new Date(t);if(!isNaN(e.valueOf())){return e}}return t}let o;let s;try{s=yield e.readBody();if(s&&s.length>0){if(t&&t.deserializeDates){o=JSON.parse(s,dateTimeDeserializer)}else{o=JSON.parse(s)}a.result=o}a.headers=e.message.headers}catch(e){}if(i>299){let e;if(o&&o.message){e=o.message}else if(s&&s.length>0){e=s}else{e=`Failed request: (${i})`}const t=new HttpClientError(e,i);t.result=a.result;n(t)}else{r(a)}}))))}))}}t.HttpClient=HttpClient;const lowercaseKeys=e=>Object.keys(e).reduce(((t,r)=>(t[r.toLowerCase()]=e[r],t)),{})},8754:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t.checkBypass=t.getProxyUrl=void 0;function getProxyUrl(e){const t=e.protocol==="https:";if(checkBypass(e)){return undefined}const r=(()=>{if(t){return process.env["https_proxy"]||process.env["HTTPS_PROXY"]}else{return process.env["http_proxy"]||process.env["HTTP_PROXY"]}})();if(r){return new URL(r)}else{return undefined}}t.getProxyUrl=getProxyUrl;function checkBypass(e){if(!e.hostname){return false}const t=process.env["no_proxy"]||process.env["NO_PROXY"]||"";if(!t){return false}let r;if(e.port){r=Number(e.port)}else if(e.protocol==="http:"){r=80}else if(e.protocol==="https:"){r=443}const n=[e.hostname.toUpperCase()];if(typeof r==="number"){n.push(`${n[0]}:${r}`)}for(const e of t.split(",").map((e=>e.trim().toUpperCase())).filter((e=>e))){if(n.some((t=>t===e))){return true}}return false}t.checkBypass=checkBypass},3177:(e,t,r)=>{const{Buffer:n}=r(4300);const i=Symbol.for("BufferList");function BufferList(e){if(!(this instanceof BufferList)){return new BufferList(e)}BufferList._init.call(this,e)}BufferList._init=function _init(e){Object.defineProperty(this,i,{value:true});this._bufs=[];this.length=0;if(e){this.append(e)}};BufferList.prototype._new=function _new(e){return new BufferList(e)};BufferList.prototype._offset=function _offset(e){if(e===0){return[0,0]}let t=0;for(let r=0;rthis.length||e<0){return undefined}const t=this._offset(e);return this._bufs[t[0]][t[1]]};BufferList.prototype.slice=function slice(e,t){if(typeof e==="number"&&e<0){e+=this.length}if(typeof t==="number"&&t<0){t+=this.length}return this.copy(null,0,e,t)};BufferList.prototype.copy=function copy(e,t,r,i){if(typeof r!=="number"||r<0){r=0}if(typeof i!=="number"||i>this.length){i=this.length}if(r>=this.length){return e||n.alloc(0)}if(i<=0){return e||n.alloc(0)}const copy=!!e;const a=this._offset(r);const o=i-r;let s=o;let u=copy&&t||0;let l=a[1];if(r===0&&i===this.length){if(!copy){return this._bufs.length===1?this._bufs[0]:n.concat(this._bufs,this.length)}for(let t=0;tr){this._bufs[t].copy(e,u,l);u+=r}else{this._bufs[t].copy(e,u,l,l+s);u+=r;break}s-=r;if(l){l=0}}if(e.length>u)return e.slice(0,u);return e};BufferList.prototype.shallowSlice=function shallowSlice(e,t){e=e||0;t=typeof t!=="number"?this.length:t;if(e<0){e+=this.length}if(t<0){t+=this.length}if(e===t){return this._new()}const r=this._offset(e);const n=this._offset(t);const i=this._bufs.slice(r[0],n[0]+1);if(n[1]===0){i.pop()}else{i[i.length-1]=i[i.length-1].slice(0,n[1])}if(r[1]!==0){i[0]=i[0].slice(r[1])}return this._new(i)};BufferList.prototype.toString=function toString(e,t,r){return this.slice(t,r).toString(e)};BufferList.prototype.consume=function consume(e){e=Math.trunc(e);if(Number.isNaN(e)||e<=0)return this;while(this._bufs.length){if(e>=this._bufs[0].length){e-=this._bufs[0].length;this.length-=this._bufs[0].length;this._bufs.shift()}else{this._bufs[0]=this._bufs[0].slice(e);this.length-=e;break}}return this};BufferList.prototype.duplicate=function duplicate(){const e=this._new();for(let t=0;tthis.length?this.length:t}const i=this._offset(t);let a=i[0];let o=i[1];for(;a=e.length){const r=t.indexOf(e,o);if(r!==-1){return this._reverseOffset([a,r])}o=t.length-e.length+1}else{const t=this._reverseOffset([a,o]);if(this._match(t,e)){return t}o++}}o=0}return-1};BufferList.prototype._match=function(e,t){if(this.length-e{const n=r(5376).Duplex;const i=r(3740);const a=r(3177);function BufferListStream(e){if(!(this instanceof BufferListStream)){return new BufferListStream(e)}if(typeof e==="function"){this._callback=e;const t=function piper(e){if(this._callback){this._callback(e);this._callback=null}}.bind(this);this.on("pipe",(function onPipe(e){e.on("error",t)}));this.on("unpipe",(function onUnpipe(e){e.removeListener("error",t)}));e=null}a._init.call(this,e);n.call(this)}i(BufferListStream,n);Object.assign(BufferListStream.prototype,a.prototype);BufferListStream.prototype._new=function _new(e){return new BufferListStream(e)};BufferListStream.prototype._write=function _write(e,t,r){this._appendBuffer(e);if(typeof r==="function"){r()}};BufferListStream.prototype._read=function _read(e){if(!this.length){return this.push(null)}e=Math.min(e,this.length);this.push(this.slice(0,e));this.consume(e)};BufferListStream.prototype.end=function end(e){n.prototype.end.call(this,e);if(this._callback){this._callback(null,this.slice());this._callback=null}};BufferListStream.prototype._destroy=function _destroy(e,t){this._bufs.length=0;this.length=0;t(e)};BufferListStream.prototype._isBufferList=function _isBufferList(e){return e instanceof BufferListStream||e instanceof a||BufferListStream.isBufferList(e)};BufferListStream.isBufferList=a.isBufferList;e.exports=BufferListStream;e.exports.BufferListStream=BufferListStream;e.exports.BufferList=a},7137:(e,t,r)=>{var n=r(1269);var noop=function(){};var isRequest=function(e){return e.setHeader&&typeof e.abort==="function"};var isChildProcess=function(e){return e.stdio&&Array.isArray(e.stdio)&&e.stdio.length===3};var eos=function(e,t,r){if(typeof t==="function")return eos(e,null,t);if(!t)t={};r=n(r||noop);var i=e._writableState;var a=e._readableState;var o=t.readable||t.readable!==false&&e.readable;var s=t.writable||t.writable!==false&&e.writable;var u=false;var onlegacyfinish=function(){if(!e.writable)onfinish()};var onfinish=function(){s=false;if(!o)r.call(e)};var onend=function(){o=false;if(!s)r.call(e)};var onexit=function(t){r.call(e,t?new Error("exited with error code: "+t):null)};var onerror=function(t){r.call(e,t)};var onclose=function(){process.nextTick(onclosenexttick)};var onclosenexttick=function(){if(u)return;if(o&&!(a&&(a.ended&&!a.destroyed)))return r.call(e,new Error("premature close"));if(s&&!(i&&(i.ended&&!i.destroyed)))return r.call(e,new Error("premature close"))};var onrequest=function(){e.req.on("finish",onfinish)};if(isRequest(e)){e.on("complete",onfinish);e.on("abort",onclose);if(e.req)onrequest();else e.on("request",onrequest)}else if(s&&!i){e.on("end",onlegacyfinish);e.on("close",onlegacyfinish)}if(isChildProcess(e))e.on("exit",onexit);e.on("end",onend);e.on("finish",onfinish);if(t.error!==false)e.on("error",onerror);e.on("close",onclose);return function(){u=true;e.removeListener("complete",onfinish);e.removeListener("abort",onclose);e.removeListener("request",onrequest);if(e.req)e.req.removeListener("finish",onfinish);e.removeListener("end",onlegacyfinish);e.removeListener("close",onlegacyfinish);e.removeListener("finish",onfinish);e.removeListener("exit",onexit);e.removeListener("end",onend);e.removeListener("error",onerror);e.removeListener("close",onclose)}};e.exports=eos},2187:(e,t,r)=>{e.exports=r(7147).constants||r(2057)},3740:(e,t,r)=>{try{var n=r(3837);if(typeof n.inherits!=="function")throw"";e.exports=n.inherits}catch(t){e.exports=r(396)}},396:e=>{if(typeof Object.create==="function"){e.exports=function inherits(e,t){if(t){e.super_=t;e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:false,writable:true,configurable:true}})}}}else{e.exports=function inherits(e,t){if(t){e.super_=t;var TempCtor=function(){};TempCtor.prototype=t.prototype;e.prototype=new TempCtor;e.prototype.constructor=e}}}},1269:(e,t,r)=>{var n=r(3799);e.exports=n(once);e.exports.strict=n(onceStrict);once.proto=once((function(){Object.defineProperty(Function.prototype,"once",{value:function(){return once(this)},configurable:true});Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return onceStrict(this)},configurable:true})}));function once(e){var f=function(){if(f.called)return f.value;f.called=true;return f.value=e.apply(this,arguments)};f.called=false;return f}function onceStrict(e){var f=function(){if(f.called)throw new Error(f.onceError);f.called=true;return f.value=e.apply(this,arguments)};var t=e.name||"Function wrapped with `once`";f.onceError=t+" shouldn't be called more than once";f.called=false;return f}},9697:e=>{const t={};function createErrorType(e,r,n){if(!n){n=Error}function getMessage(e,t,n){if(typeof r==="string"){return r}else{return r(e,t,n)}}class NodeError extends n{constructor(e,t,r){super(getMessage(e,t,r))}}NodeError.prototype.name=n.name;NodeError.prototype.code=e;t[e]=NodeError}function oneOf(e,t){if(Array.isArray(e)){const r=e.length;e=e.map((e=>String(e)));if(r>2){return`one of ${t} ${e.slice(0,r-1).join(", ")}, or `+e[r-1]}else if(r===2){return`one of ${t} ${e[0]} or ${e[1]}`}else{return`of ${t} ${e[0]}`}}else{return`of ${t} ${String(e)}`}}function startsWith(e,t,r){return e.substr(!r||r<0?0:+r,t.length)===t}function endsWith(e,t,r){if(r===undefined||r>e.length){r=e.length}return e.substring(r-t.length,r)===t}function includes(e,t,r){if(typeof r!=="number"){r=0}if(r+t.length>e.length){return false}else{return e.indexOf(t,r)!==-1}}createErrorType("ERR_INVALID_OPT_VALUE",(function(e,t){return'The value "'+t+'" is invalid for option "'+e+'"'}),TypeError);createErrorType("ERR_INVALID_ARG_TYPE",(function(e,t,r){let n;if(typeof t==="string"&&startsWith(t,"not ")){n="must not be";t=t.replace(/^not /,"")}else{n="must be"}let i;if(endsWith(e," argument")){i=`The ${e} ${n} ${oneOf(t,"type")}`}else{const r=includes(e,".")?"property":"argument";i=`The "${e}" ${r} ${n} ${oneOf(t,"type")}`}i+=`. Received type ${typeof r}`;return i}),TypeError);createErrorType("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF");createErrorType("ERR_METHOD_NOT_IMPLEMENTED",(function(e){return"The "+e+" method is not implemented"}));createErrorType("ERR_STREAM_PREMATURE_CLOSE","Premature close");createErrorType("ERR_STREAM_DESTROYED",(function(e){return"Cannot call "+e+" after a stream was destroyed"}));createErrorType("ERR_MULTIPLE_CALLBACK","Callback called multiple times");createErrorType("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable");createErrorType("ERR_STREAM_WRITE_AFTER_END","write after end");createErrorType("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError);createErrorType("ERR_UNKNOWN_ENCODING",(function(e){return"Unknown encoding: "+e}),TypeError);createErrorType("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event");e.exports.q=t},651:(e,t,r)=>{var n=Object.keys||function(e){var t=[];for(var r in e){t.push(r)}return t};e.exports=Duplex;var i=r(2706);var a=r(6373);r(3740)(Duplex,i);{var o=n(a.prototype);for(var s=0;s{e.exports=PassThrough;var n=r(8047);r(3740)(PassThrough,n);function PassThrough(e){if(!(this instanceof PassThrough))return new PassThrough(e);n.call(this,e)}PassThrough.prototype._transform=function(e,t,r){r(null,e)}},2706:(e,t,r)=>{e.exports=Readable;var n;Readable.ReadableState=ReadableState;var i=r(2361).EventEmitter;var a=function EElistenerCount(e,t){return e.listeners(t).length};var o=r(6818);var s=r(4300).Buffer;var u=global.Uint8Array||function(){};function _uint8ArrayToBuffer(e){return s.from(e)}function _isUint8Array(e){return s.isBuffer(e)||e instanceof u}var l=r(3837);var c;if(l&&l.debuglog){c=l.debuglog("stream")}else{c=function debug(){}}var d=r(8606);var h=r(9861);var p=r(3254),g=p.getHighWaterMark;var m=r(9697).q,b=m.ERR_INVALID_ARG_TYPE,v=m.ERR_STREAM_PUSH_AFTER_EOF,_=m.ERR_METHOD_NOT_IMPLEMENTED,y=m.ERR_STREAM_UNSHIFT_AFTER_END_EVENT;var w;var R;var S;r(3740)(Readable,o);var E=h.errorOrDestroy;var k=["error","close","destroy","pause","resume"];function prependListener(e,t,r){if(typeof e.prependListener==="function")return e.prependListener(t,r);if(!e._events||!e._events[t])e.on(t,r);else if(Array.isArray(e._events[t]))e._events[t].unshift(r);else e._events[t]=[r,e._events[t]]}function ReadableState(e,t,i){n=n||r(651);e=e||{};if(typeof i!=="boolean")i=t instanceof n;this.objectMode=!!e.objectMode;if(i)this.objectMode=this.objectMode||!!e.readableObjectMode;this.highWaterMark=g(this,e,"readableHighWaterMark",i);this.buffer=new d;this.length=0;this.pipes=null;this.pipesCount=0;this.flowing=null;this.ended=false;this.endEmitted=false;this.reading=false;this.sync=true;this.needReadable=false;this.emittedReadable=false;this.readableListening=false;this.resumeScheduled=false;this.paused=true;this.emitClose=e.emitClose!==false;this.autoDestroy=!!e.autoDestroy;this.destroyed=false;this.defaultEncoding=e.defaultEncoding||"utf8";this.awaitDrain=0;this.readingMore=false;this.decoder=null;this.encoding=null;if(e.encoding){if(!w)w=r(1052).s;this.decoder=new w(e.encoding);this.encoding=e.encoding}}function Readable(e){n=n||r(651);if(!(this instanceof Readable))return new Readable(e);var t=this instanceof n;this._readableState=new ReadableState(e,this,t);this.readable=true;if(e){if(typeof e.read==="function")this._read=e.read;if(typeof e.destroy==="function")this._destroy=e.destroy}o.call(this)}Object.defineProperty(Readable.prototype,"destroyed",{enumerable:false,get:function get(){if(this._readableState===undefined){return false}return this._readableState.destroyed},set:function set(e){if(!this._readableState){return}this._readableState.destroyed=e}});Readable.prototype.destroy=h.destroy;Readable.prototype._undestroy=h.undestroy;Readable.prototype._destroy=function(e,t){t(e)};Readable.prototype.push=function(e,t){var r=this._readableState;var n;if(!r.objectMode){if(typeof e==="string"){t=t||r.defaultEncoding;if(t!==r.encoding){e=s.from(e,t);t=""}n=true}}else{n=true}return readableAddChunk(this,e,t,false,n)};Readable.prototype.unshift=function(e){return readableAddChunk(this,e,null,true,false)};function readableAddChunk(e,t,r,n,i){c("readableAddChunk",t);var a=e._readableState;if(t===null){a.reading=false;onEofChunk(e,a)}else{var o;if(!i)o=chunkInvalid(a,t);if(o){E(e,o)}else if(a.objectMode||t&&t.length>0){if(typeof t!=="string"&&!a.objectMode&&Object.getPrototypeOf(t)!==s.prototype){t=_uint8ArrayToBuffer(t)}if(n){if(a.endEmitted)E(e,new y);else addChunk(e,a,t,true)}else if(a.ended){E(e,new v)}else if(a.destroyed){return false}else{a.reading=false;if(a.decoder&&!r){t=a.decoder.write(t);if(a.objectMode||t.length!==0)addChunk(e,a,t,false);else maybeReadMore(e,a)}else{addChunk(e,a,t,false)}}}else if(!n){a.reading=false;maybeReadMore(e,a)}}return!a.ended&&(a.length=O){e=O}else{e--;e|=e>>>1;e|=e>>>2;e|=e>>>4;e|=e>>>8;e|=e>>>16;e++}return e}function howMuchToRead(e,t){if(e<=0||t.length===0&&t.ended)return 0;if(t.objectMode)return 1;if(e!==e){if(t.flowing&&t.length)return t.buffer.head.data.length;else return t.length}if(e>t.highWaterMark)t.highWaterMark=computeNewHighWaterMark(e);if(e<=t.length)return e;if(!t.ended){t.needReadable=true;return 0}return t.length}Readable.prototype.read=function(e){c("read",e);e=parseInt(e,10);var t=this._readableState;var r=e;if(e!==0)t.emittedReadable=false;if(e===0&&t.needReadable&&((t.highWaterMark!==0?t.length>=t.highWaterMark:t.length>0)||t.ended)){c("read: emitReadable",t.length,t.ended);if(t.length===0&&t.ended)endReadable(this);else emitReadable(this);return null}e=howMuchToRead(e,t);if(e===0&&t.ended){if(t.length===0)endReadable(this);return null}var n=t.needReadable;c("need readable",n);if(t.length===0||t.length-e0)i=fromList(e,t);else i=null;if(i===null){t.needReadable=t.length<=t.highWaterMark;e=0}else{t.length-=e;t.awaitDrain=0}if(t.length===0){if(!t.ended)t.needReadable=true;if(r!==e&&t.ended)endReadable(this)}if(i!==null)this.emit("data",i);return i};function onEofChunk(e,t){c("onEofChunk");if(t.ended)return;if(t.decoder){var r=t.decoder.end();if(r&&r.length){t.buffer.push(r);t.length+=t.objectMode?1:r.length}}t.ended=true;if(t.sync){emitReadable(e)}else{t.needReadable=false;if(!t.emittedReadable){t.emittedReadable=true;emitReadable_(e)}}}function emitReadable(e){var t=e._readableState;c("emitReadable",t.needReadable,t.emittedReadable);t.needReadable=false;if(!t.emittedReadable){c("emitReadable",t.flowing);t.emittedReadable=true;process.nextTick(emitReadable_,e)}}function emitReadable_(e){var t=e._readableState;c("emitReadable_",t.destroyed,t.length,t.ended);if(!t.destroyed&&(t.length||t.ended)){e.emit("readable");t.emittedReadable=false}t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark;flow(e)}function maybeReadMore(e,t){if(!t.readingMore){t.readingMore=true;process.nextTick(maybeReadMore_,e,t)}}function maybeReadMore_(e,t){while(!t.reading&&!t.ended&&(t.length1&&indexOf(n.pipes,e)!==-1)&&!u){c("false write response, pause",n.awaitDrain);n.awaitDrain++}r.pause()}}function onerror(t){c("onerror",t);unpipe();e.removeListener("error",onerror);if(a(e,"error")===0)E(e,t)}prependListener(e,"error",onerror);function onclose(){e.removeListener("finish",onfinish);unpipe()}e.once("close",onclose);function onfinish(){c("onfinish");e.removeListener("close",onclose);unpipe()}e.once("finish",onfinish);function unpipe(){c("unpipe");r.unpipe(e)}e.emit("pipe",r);if(!n.flowing){c("pipe resume");r.resume()}return e};function pipeOnDrain(e){return function pipeOnDrainFunctionResult(){var t=e._readableState;c("pipeOnDrain",t.awaitDrain);if(t.awaitDrain)t.awaitDrain--;if(t.awaitDrain===0&&a(e,"data")){t.flowing=true;flow(e)}}}Readable.prototype.unpipe=function(e){var t=this._readableState;var r={hasUnpiped:false};if(t.pipesCount===0)return this;if(t.pipesCount===1){if(e&&e!==t.pipes)return this;if(!e)e=t.pipes;t.pipes=null;t.pipesCount=0;t.flowing=false;if(e)e.emit("unpipe",this,r);return this}if(!e){var n=t.pipes;var i=t.pipesCount;t.pipes=null;t.pipesCount=0;t.flowing=false;for(var a=0;a0;if(n.flowing!==false)this.resume()}else if(e==="readable"){if(!n.endEmitted&&!n.readableListening){n.readableListening=n.needReadable=true;n.flowing=false;n.emittedReadable=false;c("on readable",n.length,n.reading);if(n.length){emitReadable(this)}else if(!n.reading){process.nextTick(nReadingNextTick,this)}}}return r};Readable.prototype.addListener=Readable.prototype.on;Readable.prototype.removeListener=function(e,t){var r=o.prototype.removeListener.call(this,e,t);if(e==="readable"){process.nextTick(updateReadableListening,this)}return r};Readable.prototype.removeAllListeners=function(e){var t=o.prototype.removeAllListeners.apply(this,arguments);if(e==="readable"||e===undefined){process.nextTick(updateReadableListening,this)}return t};function updateReadableListening(e){var t=e._readableState;t.readableListening=e.listenerCount("readable")>0;if(t.resumeScheduled&&!t.paused){t.flowing=true}else if(e.listenerCount("data")>0){e.resume()}}function nReadingNextTick(e){c("readable nexttick read 0");e.read(0)}Readable.prototype.resume=function(){var e=this._readableState;if(!e.flowing){c("resume");e.flowing=!e.readableListening;resume(this,e)}e.paused=false;return this};function resume(e,t){if(!t.resumeScheduled){t.resumeScheduled=true;process.nextTick(resume_,e,t)}}function resume_(e,t){c("resume",t.reading);if(!t.reading){e.read(0)}t.resumeScheduled=false;e.emit("resume");flow(e);if(t.flowing&&!t.reading)e.read(0)}Readable.prototype.pause=function(){c("call pause flowing=%j",this._readableState.flowing);if(this._readableState.flowing!==false){c("pause");this._readableState.flowing=false;this.emit("pause")}this._readableState.paused=true;return this};function flow(e){var t=e._readableState;c("flow",t.flowing);while(t.flowing&&e.read()!==null){}}Readable.prototype.wrap=function(e){var t=this;var r=this._readableState;var n=false;e.on("end",(function(){c("wrapped end");if(r.decoder&&!r.ended){var e=r.decoder.end();if(e&&e.length)t.push(e)}t.push(null)}));e.on("data",(function(i){c("wrapped data");if(r.decoder)i=r.decoder.write(i);if(r.objectMode&&(i===null||i===undefined))return;else if(!r.objectMode&&(!i||!i.length))return;var a=t.push(i);if(!a){n=true;e.pause()}}));for(var i in e){if(this[i]===undefined&&typeof e[i]==="function"){this[i]=function methodWrap(t){return function methodWrapReturnFunction(){return e[t].apply(e,arguments)}}(i)}}for(var a=0;a=t.length){if(t.decoder)r=t.buffer.join("");else if(t.buffer.length===1)r=t.buffer.first();else r=t.buffer.concat(t.length);t.buffer.clear()}else{r=t.buffer.consume(e,t.decoder)}return r}function endReadable(e){var t=e._readableState;c("endReadable",t.endEmitted);if(!t.endEmitted){t.ended=true;process.nextTick(endReadableNT,t,e)}}function endReadableNT(e,t){c("endReadableNT",e.endEmitted,e.length);if(!e.endEmitted&&e.length===0){e.endEmitted=true;t.readable=false;t.emit("end");if(e.autoDestroy){var r=t._writableState;if(!r||r.autoDestroy&&r.finished){t.destroy()}}}}if(typeof Symbol==="function"){Readable.from=function(e,t){if(S===undefined){S=r(9068)}return S(Readable,e,t)}}function indexOf(e,t){for(var r=0,n=e.length;r{e.exports=Transform;var n=r(9697).q,i=n.ERR_METHOD_NOT_IMPLEMENTED,a=n.ERR_MULTIPLE_CALLBACK,o=n.ERR_TRANSFORM_ALREADY_TRANSFORMING,s=n.ERR_TRANSFORM_WITH_LENGTH_0;var u=r(651);r(3740)(Transform,u);function afterTransform(e,t){var r=this._transformState;r.transforming=false;var n=r.writecb;if(n===null){return this.emit("error",new a)}r.writechunk=null;r.writecb=null;if(t!=null)this.push(t);n(e);var i=this._readableState;i.reading=false;if(i.needReadable||i.length{e.exports=Writable;function WriteReq(e,t,r){this.chunk=e;this.encoding=t;this.callback=r;this.next=null}function CorkedRequest(e){var t=this;this.next=null;this.entry=null;this.finish=function(){onCorkedFinish(t,e)}}var n;Writable.WritableState=WritableState;var i={deprecate:r(4450)};var a=r(6818);var o=r(4300).Buffer;var s=global.Uint8Array||function(){};function _uint8ArrayToBuffer(e){return o.from(e)}function _isUint8Array(e){return o.isBuffer(e)||e instanceof s}var u=r(9861);var l=r(3254),c=l.getHighWaterMark;var d=r(9697).q,h=d.ERR_INVALID_ARG_TYPE,p=d.ERR_METHOD_NOT_IMPLEMENTED,g=d.ERR_MULTIPLE_CALLBACK,m=d.ERR_STREAM_CANNOT_PIPE,b=d.ERR_STREAM_DESTROYED,v=d.ERR_STREAM_NULL_VALUES,_=d.ERR_STREAM_WRITE_AFTER_END,y=d.ERR_UNKNOWN_ENCODING;var w=u.errorOrDestroy;r(3740)(Writable,a);function nop(){}function WritableState(e,t,i){n=n||r(651);e=e||{};if(typeof i!=="boolean")i=t instanceof n;this.objectMode=!!e.objectMode;if(i)this.objectMode=this.objectMode||!!e.writableObjectMode;this.highWaterMark=c(this,e,"writableHighWaterMark",i);this.finalCalled=false;this.needDrain=false;this.ending=false;this.ended=false;this.finished=false;this.destroyed=false;var a=e.decodeStrings===false;this.decodeStrings=!a;this.defaultEncoding=e.defaultEncoding||"utf8";this.length=0;this.writing=false;this.corked=0;this.sync=true;this.bufferProcessing=false;this.onwrite=function(e){onwrite(t,e)};this.writecb=null;this.writelen=0;this.bufferedRequest=null;this.lastBufferedRequest=null;this.pendingcb=0;this.prefinished=false;this.errorEmitted=false;this.emitClose=e.emitClose!==false;this.autoDestroy=!!e.autoDestroy;this.bufferedRequestCount=0;this.corkedRequestsFree=new CorkedRequest(this)}WritableState.prototype.getBuffer=function getBuffer(){var e=this.bufferedRequest;var t=[];while(e){t.push(e);e=e.next}return t};(function(){try{Object.defineProperty(WritableState.prototype,"buffer",{get:i.deprecate((function writableStateBufferGetter(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer "+"instead.","DEP0003")})}catch(e){}})();var R;if(typeof Symbol==="function"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]==="function"){R=Function.prototype[Symbol.hasInstance];Object.defineProperty(Writable,Symbol.hasInstance,{value:function value(e){if(R.call(this,e))return true;if(this!==Writable)return false;return e&&e._writableState instanceof WritableState}})}else{R=function realHasInstance(e){return e instanceof this}}function Writable(e){n=n||r(651);var t=this instanceof n;if(!t&&!R.call(Writable,this))return new Writable(e);this._writableState=new WritableState(e,this,t);this.writable=true;if(e){if(typeof e.write==="function")this._write=e.write;if(typeof e.writev==="function")this._writev=e.writev;if(typeof e.destroy==="function")this._destroy=e.destroy;if(typeof e.final==="function")this._final=e.final}a.call(this)}Writable.prototype.pipe=function(){w(this,new m)};function writeAfterEnd(e,t){var r=new _;w(e,r);process.nextTick(t,r)}function validChunk(e,t,r,n){var i;if(r===null){i=new v}else if(typeof r!=="string"&&!t.objectMode){i=new h("chunk",["string","Buffer"],r)}if(i){w(e,i);process.nextTick(n,i);return false}return true}Writable.prototype.write=function(e,t,r){var n=this._writableState;var i=false;var a=!n.objectMode&&_isUint8Array(e);if(a&&!o.isBuffer(e)){e=_uint8ArrayToBuffer(e)}if(typeof t==="function"){r=t;t=null}if(a)t="buffer";else if(!t)t=n.defaultEncoding;if(typeof r!=="function")r=nop;if(n.ending)writeAfterEnd(this,r);else if(a||validChunk(this,n,e,r)){n.pendingcb++;i=writeOrBuffer(this,n,a,e,t,r)}return i};Writable.prototype.cork=function(){this._writableState.corked++};Writable.prototype.uncork=function(){var e=this._writableState;if(e.corked){e.corked--;if(!e.writing&&!e.corked&&!e.bufferProcessing&&e.bufferedRequest)clearBuffer(this,e)}};Writable.prototype.setDefaultEncoding=function setDefaultEncoding(e){if(typeof e==="string")e=e.toLowerCase();if(!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new y(e);this._writableState.defaultEncoding=e;return this};Object.defineProperty(Writable.prototype,"writableBuffer",{enumerable:false,get:function get(){return this._writableState&&this._writableState.getBuffer()}});function decodeChunk(e,t,r){if(!e.objectMode&&e.decodeStrings!==false&&typeof t==="string"){t=o.from(t,r)}return t}Object.defineProperty(Writable.prototype,"writableHighWaterMark",{enumerable:false,get:function get(){return this._writableState.highWaterMark}});function writeOrBuffer(e,t,r,n,i,a){if(!r){var o=decodeChunk(t,n,i);if(n!==o){r=true;i="buffer";n=o}}var s=t.objectMode?1:n.length;t.length+=s;var u=t.length{var n;function _defineProperty(e,t,r){if(t in e){Object.defineProperty(e,t,{value:r,enumerable:true,configurable:true,writable:true})}else{e[t]=r}return e}var i=r(5165);var a=Symbol("lastResolve");var o=Symbol("lastReject");var s=Symbol("error");var u=Symbol("ended");var l=Symbol("lastPromise");var c=Symbol("handlePromise");var d=Symbol("stream");function createIterResult(e,t){return{value:e,done:t}}function readAndResolve(e){var t=e[a];if(t!==null){var r=e[d].read();if(r!==null){e[l]=null;e[a]=null;e[o]=null;t(createIterResult(r,false))}}}function onReadable(e){process.nextTick(readAndResolve,e)}function wrapForNext(e,t){return function(r,n){e.then((function(){if(t[u]){r(createIterResult(undefined,true));return}t[c](r,n)}),n)}}var h=Object.getPrototypeOf((function(){}));var p=Object.setPrototypeOf((n={get stream(){return this[d]},next:function next(){var e=this;var t=this[s];if(t!==null){return Promise.reject(t)}if(this[u]){return Promise.resolve(createIterResult(undefined,true))}if(this[d].destroyed){return new Promise((function(t,r){process.nextTick((function(){if(e[s]){r(e[s])}else{t(createIterResult(undefined,true))}}))}))}var r=this[l];var n;if(r){n=new Promise(wrapForNext(r,this))}else{var i=this[d].read();if(i!==null){return Promise.resolve(createIterResult(i,false))}n=new Promise(this[c])}this[l]=n;return n}},_defineProperty(n,Symbol.asyncIterator,(function(){return this})),_defineProperty(n,"return",(function _return(){var e=this;return new Promise((function(t,r){e[d].destroy(null,(function(e){if(e){r(e);return}t(createIterResult(undefined,true))}))}))})),n),h);var g=function createReadableStreamAsyncIterator(e){var t;var r=Object.create(p,(t={},_defineProperty(t,d,{value:e,writable:true}),_defineProperty(t,a,{value:null,writable:true}),_defineProperty(t,o,{value:null,writable:true}),_defineProperty(t,s,{value:null,writable:true}),_defineProperty(t,u,{value:e._readableState.endEmitted,writable:true}),_defineProperty(t,c,{value:function value(e,t){var n=r[d].read();if(n){r[l]=null;r[a]=null;r[o]=null;e(createIterResult(n,false))}else{r[a]=e;r[o]=t}},writable:true}),t));r[l]=null;i(e,(function(e){if(e&&e.code!=="ERR_STREAM_PREMATURE_CLOSE"){var t=r[o];if(t!==null){r[l]=null;r[a]=null;r[o]=null;t(e)}r[s]=e;return}var n=r[a];if(n!==null){r[l]=null;r[a]=null;r[o]=null;n(createIterResult(undefined,true))}r[u]=true}));e.on("readable",onReadable.bind(null,r));return r};e.exports=g},8606:(e,t,r)=>{function ownKeys(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);if(t)n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}));r.push.apply(r,n)}return r}function _objectSpread(e){for(var t=1;t0)this.tail.next=t;else this.head=t;this.tail=t;++this.length}},{key:"unshift",value:function unshift(e){var t={data:e,next:this.head};if(this.length===0)this.tail=t;this.head=t;++this.length}},{key:"shift",value:function shift(){if(this.length===0)return;var e=this.head.data;if(this.length===1)this.head=this.tail=null;else this.head=this.head.next;--this.length;return e}},{key:"clear",value:function clear(){this.head=this.tail=null;this.length=0}},{key:"join",value:function join(e){if(this.length===0)return"";var t=this.head;var r=""+t.data;while(t=t.next){r+=e+t.data}return r}},{key:"concat",value:function concat(e){if(this.length===0)return i.alloc(0);var t=i.allocUnsafe(e>>>0);var r=this.head;var n=0;while(r){copyBuffer(r.data,t,n);n+=r.data.length;r=r.next}return t}},{key:"consume",value:function consume(e,t){var r;if(ei.length?i.length:e;if(a===i.length)n+=i;else n+=i.slice(0,e);e-=a;if(e===0){if(a===i.length){++r;if(t.next)this.head=t.next;else this.head=this.tail=null}else{this.head=t;t.data=i.slice(a)}break}++r}this.length-=r;return n}},{key:"_getBuffer",value:function _getBuffer(e){var t=i.allocUnsafe(e);var r=this.head;var n=1;r.data.copy(t);e-=r.data.length;while(r=r.next){var a=r.data;var o=e>a.length?a.length:e;a.copy(t,t.length-e,0,o);e-=o;if(e===0){if(o===a.length){++n;if(r.next)this.head=r.next;else this.head=this.tail=null}else{this.head=r;r.data=a.slice(o)}break}++n}this.length-=n;return t}},{key:s,value:function value(e,t){return o(this,_objectSpread({},t,{depth:0,customInspect:false}))}}]);return BufferList}()},9861:e=>{function destroy(e,t){var r=this;var n=this._readableState&&this._readableState.destroyed;var i=this._writableState&&this._writableState.destroyed;if(n||i){if(t){t(e)}else if(e){if(!this._writableState){process.nextTick(emitErrorNT,this,e)}else if(!this._writableState.errorEmitted){this._writableState.errorEmitted=true;process.nextTick(emitErrorNT,this,e)}}return this}if(this._readableState){this._readableState.destroyed=true}if(this._writableState){this._writableState.destroyed=true}this._destroy(e||null,(function(e){if(!t&&e){if(!r._writableState){process.nextTick(emitErrorAndCloseNT,r,e)}else if(!r._writableState.errorEmitted){r._writableState.errorEmitted=true;process.nextTick(emitErrorAndCloseNT,r,e)}else{process.nextTick(emitCloseNT,r)}}else if(t){process.nextTick(emitCloseNT,r);t(e)}else{process.nextTick(emitCloseNT,r)}}));return this}function emitErrorAndCloseNT(e,t){emitErrorNT(e,t);emitCloseNT(e)}function emitCloseNT(e){if(e._writableState&&!e._writableState.emitClose)return;if(e._readableState&&!e._readableState.emitClose)return;e.emit("close")}function undestroy(){if(this._readableState){this._readableState.destroyed=false;this._readableState.reading=false;this._readableState.ended=false;this._readableState.endEmitted=false}if(this._writableState){this._writableState.destroyed=false;this._writableState.ended=false;this._writableState.ending=false;this._writableState.finalCalled=false;this._writableState.prefinished=false;this._writableState.finished=false;this._writableState.errorEmitted=false}}function emitErrorNT(e,t){e.emit("error",t)}function errorOrDestroy(e,t){var r=e._readableState;var n=e._writableState;if(r&&r.autoDestroy||n&&n.autoDestroy)e.destroy(t);else e.emit("error",t)}e.exports={destroy:destroy,undestroy:undestroy,errorOrDestroy:errorOrDestroy}},5165:(e,t,r)=>{var n=r(9697).q.ERR_STREAM_PREMATURE_CLOSE;function once(e){var t=false;return function(){if(t)return;t=true;for(var r=arguments.length,n=new Array(r),i=0;i{function asyncGeneratorStep(e,t,r,n,i,a,o){try{var s=e[a](o);var u=s.value}catch(e){r(e);return}if(s.done){t(u)}else{Promise.resolve(u).then(n,i)}}function _asyncToGenerator(e){return function(){var t=this,r=arguments;return new Promise((function(n,i){var a=e.apply(t,r);function _next(e){asyncGeneratorStep(a,n,i,_next,_throw,"next",e)}function _throw(e){asyncGeneratorStep(a,n,i,_next,_throw,"throw",e)}_next(undefined)}))}}function ownKeys(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);if(t)n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}));r.push.apply(r,n)}return r}function _objectSpread(e){for(var t=1;t{var n;function once(e){var t=false;return function(){if(t)return;t=true;e.apply(void 0,arguments)}}var i=r(9697).q,a=i.ERR_MISSING_ARGS,o=i.ERR_STREAM_DESTROYED;function noop(e){if(e)throw e}function isRequest(e){return e.setHeader&&typeof e.abort==="function"}function destroyer(e,t,i,a){a=once(a);var s=false;e.on("close",(function(){s=true}));if(n===undefined)n=r(5165);n(e,{readable:t,writable:i},(function(e){if(e)return a(e);s=true;a()}));var u=false;return function(t){if(s)return;if(u)return;u=true;if(isRequest(e))return e.abort();if(typeof e.destroy==="function")return e.destroy();a(t||new o("pipe"))}}function call(e){e()}function pipe(e,t){return e.pipe(t)}function popCallback(e){if(!e.length)return noop;if(typeof e[e.length-1]!=="function")return noop;return e.pop()}function pipeline(){for(var e=arguments.length,t=new Array(e),r=0;r0;return destroyer(e,a,s,(function(e){if(!i)i=e;if(e)o.forEach(call);if(a)return;o.forEach(call);n(i)}))}));return t.reduce(pipe)}e.exports=pipeline},3254:(e,t,r)=>{var n=r(9697).q.ERR_INVALID_OPT_VALUE;function highWaterMarkFrom(e,t,r){return e.highWaterMark!=null?e.highWaterMark:t?e[r]:null}function getHighWaterMark(e,t,r,i){var a=highWaterMarkFrom(t,i,r);if(a!=null){if(!(isFinite(a)&&Math.floor(a)===a)||a<0){var o=i?r:"highWaterMark";throw new n(o,a)}return Math.floor(a)}return e.objectMode?16:16*1024}e.exports={getHighWaterMark:getHighWaterMark}},6818:(e,t,r)=>{e.exports=r(2781)},5376:(e,t,r)=>{var n=r(2781);if(process.env.READABLE_STREAM==="disable"&&n){e.exports=n.Readable;Object.assign(e.exports,n);e.exports.Stream=n}else{t=e.exports=r(2706);t.Stream=n||t;t.Readable=t;t.Writable=r(6373);t.Duplex=r(651);t.Transform=r(8047);t.PassThrough=r(7079);t.finished=r(5165);t.pipeline=r(4679)}},4955:(e,t,r)=>{ +import{createRequire as e}from"module";var t={7351:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};Object.defineProperty(t,"__esModule",{value:true});t.issue=t.issueCommand=void 0;const o=a(r(2037));const s=r(6321);function issueCommand(e,t,r){const n=new Command(e,t,r);process.stdout.write(n.toString()+o.EOL)}t.issueCommand=issueCommand;function issue(e,t=""){issueCommand(e,{},t)}t.issue=issue;const u="::";class Command{constructor(e,t,r){if(!e){e="missing.command"}this.command=e;this.properties=t;this.message=r}toString(){let e=u+this.command;if(this.properties&&Object.keys(this.properties).length>0){e+=" ";let t=true;for(const r in this.properties){if(this.properties.hasOwnProperty(r)){const n=this.properties[r];if(n){if(t){t=false}else{e+=","}e+=`${r}=${escapeProperty(n)}`}}}}e+=`${u}${escapeData(this.message)}`;return e}}function escapeData(e){return s.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function escapeProperty(e){return s.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}},2186:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};var o=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.getIDToken=t.getState=t.saveState=t.group=t.endGroup=t.startGroup=t.info=t.notice=t.warning=t.error=t.debug=t.isDebug=t.setFailed=t.setCommandEcho=t.setOutput=t.getBooleanInput=t.getMultilineInput=t.getInput=t.addPath=t.setSecret=t.exportVariable=t.ExitCode=void 0;const s=r(7351);const u=r(717);const l=r(6321);const c=a(r(2037));const d=a(r(1017));const h=r(5840);const p=r(8041);var g;(function(e){e[e["Success"]=0]="Success";e[e["Failure"]=1]="Failure"})(g=t.ExitCode||(t.ExitCode={}));function exportVariable(e,t){const r=l.toCommandValue(t);process.env[e]=r;const n=process.env["GITHUB_ENV"]||"";if(n){const t=`ghadelimiter_${h.v4()}`;if(e.includes(t)){throw new Error(`Unexpected input: name should not contain the delimiter "${t}"`)}if(r.includes(t)){throw new Error(`Unexpected input: value should not contain the delimiter "${t}"`)}const n=`${e}<<${t}${c.EOL}${r}${c.EOL}${t}`;u.issueCommand("ENV",n)}else{s.issueCommand("set-env",{name:e},r)}}t.exportVariable=exportVariable;function setSecret(e){s.issueCommand("add-mask",{},e)}t.setSecret=setSecret;function addPath(e){const t=process.env["GITHUB_PATH"]||"";if(t){u.issueCommand("PATH",e)}else{s.issueCommand("add-path",{},e)}process.env["PATH"]=`${e}${d.delimiter}${process.env["PATH"]}`}t.addPath=addPath;function getInput(e,t){const r=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(t&&t.required&&!r){throw new Error(`Input required and not supplied: ${e}`)}if(t&&t.trimWhitespace===false){return r}return r.trim()}t.getInput=getInput;function getMultilineInput(e,t){const r=getInput(e,t).split("\n").filter((e=>e!==""));return r}t.getMultilineInput=getMultilineInput;function getBooleanInput(e,t){const r=["true","True","TRUE"];const n=["false","False","FALSE"];const i=getInput(e,t);if(r.includes(i))return true;if(n.includes(i))return false;throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${e}\n`+`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``)}t.getBooleanInput=getBooleanInput;function setOutput(e,t){process.stdout.write(c.EOL);s.issueCommand("set-output",{name:e},t)}t.setOutput=setOutput;function setCommandEcho(e){s.issue("echo",e?"on":"off")}t.setCommandEcho=setCommandEcho;function setFailed(e){process.exitCode=g.Failure;error(e)}t.setFailed=setFailed;function isDebug(){return process.env["RUNNER_DEBUG"]==="1"}t.isDebug=isDebug;function debug(e){s.issueCommand("debug",{},e)}t.debug=debug;function error(e,t={}){s.issueCommand("error",l.toCommandProperties(t),e instanceof Error?e.toString():e)}t.error=error;function warning(e,t={}){s.issueCommand("warning",l.toCommandProperties(t),e instanceof Error?e.toString():e)}t.warning=warning;function notice(e,t={}){s.issueCommand("notice",l.toCommandProperties(t),e instanceof Error?e.toString():e)}t.notice=notice;function info(e){process.stdout.write(e+c.EOL)}t.info=info;function startGroup(e){s.issue("group",e)}t.startGroup=startGroup;function endGroup(){s.issue("endgroup")}t.endGroup=endGroup;function group(e,t){return o(this,void 0,void 0,(function*(){startGroup(e);let r;try{r=yield t()}finally{endGroup()}return r}))}t.group=group;function saveState(e,t){s.issueCommand("save-state",{name:e},t)}t.saveState=saveState;function getState(e){return process.env[`STATE_${e}`]||""}t.getState=getState;function getIDToken(e){return o(this,void 0,void 0,(function*(){return yield p.OidcClient.getIDToken(e)}))}t.getIDToken=getIDToken;var b=r(1327);Object.defineProperty(t,"summary",{enumerable:true,get:function(){return b.summary}});var m=r(1327);Object.defineProperty(t,"markdownSummary",{enumerable:true,get:function(){return m.markdownSummary}});var v=r(2981);Object.defineProperty(t,"toPosixPath",{enumerable:true,get:function(){return v.toPosixPath}});Object.defineProperty(t,"toWin32Path",{enumerable:true,get:function(){return v.toWin32Path}});Object.defineProperty(t,"toPlatformPath",{enumerable:true,get:function(){return v.toPlatformPath}})},717:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};Object.defineProperty(t,"__esModule",{value:true});t.issueCommand=void 0;const o=a(r(7147));const s=a(r(2037));const u=r(6321);function issueCommand(e,t){const r=process.env[`GITHUB_${e}`];if(!r){throw new Error(`Unable to find environment variable for file command ${e}`)}if(!o.existsSync(r)){throw new Error(`Missing file at path: ${r}`)}o.appendFileSync(r,`${u.toCommandValue(t)}${s.EOL}`,{encoding:"utf8"})}t.issueCommand=issueCommand},8041:function(e,t,r){var n=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.OidcClient=void 0;const i=r(6255);const a=r(5526);const o=r(2186);class OidcClient{static createHttpClient(e=true,t=10){const r={allowRetries:e,maxRetries:t};return new i.HttpClient("actions/oidc-client",[new a.BearerCredentialHandler(OidcClient.getRequestToken())],r)}static getRequestToken(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable")}return e}static getIDTokenUrl(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_URL"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable")}return e}static getCall(e){var t;return n(this,void 0,void 0,(function*(){const r=OidcClient.createHttpClient();const n=yield r.getJson(e).catch((e=>{throw new Error(`Failed to get ID Token. \n \n Error Code : ${e.statusCode}\n \n Error Message: ${e.result.message}`)}));const i=(t=n.result)===null||t===void 0?void 0:t.value;if(!i){throw new Error("Response json body do not have ID Token field")}return i}))}static getIDToken(e){return n(this,void 0,void 0,(function*(){try{let t=OidcClient.getIDTokenUrl();if(e){const r=encodeURIComponent(e);t=`${t}&audience=${r}`}o.debug(`ID token url is ${t}`);const r=yield OidcClient.getCall(t);o.setSecret(r);return r}catch(e){throw new Error(`Error message: ${e.message}`)}}))}}t.OidcClient=OidcClient},2981:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};Object.defineProperty(t,"__esModule",{value:true});t.toPlatformPath=t.toWin32Path=t.toPosixPath=void 0;const o=a(r(1017));function toPosixPath(e){return e.replace(/[\\]/g,"/")}t.toPosixPath=toPosixPath;function toWin32Path(e){return e.replace(/[/]/g,"\\")}t.toWin32Path=toWin32Path;function toPlatformPath(e){return e.replace(/[/\\]/g,o.sep)}t.toPlatformPath=toPlatformPath},1327:function(e,t,r){var n=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.summary=t.markdownSummary=t.SUMMARY_DOCS_URL=t.SUMMARY_ENV_VAR=void 0;const i=r(2037);const a=r(7147);const{access:o,appendFile:s,writeFile:u}=a.promises;t.SUMMARY_ENV_VAR="GITHUB_STEP_SUMMARY";t.SUMMARY_DOCS_URL="https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary";class Summary{constructor(){this._buffer=""}filePath(){return n(this,void 0,void 0,(function*(){if(this._filePath){return this._filePath}const e=process.env[t.SUMMARY_ENV_VAR];if(!e){throw new Error(`Unable to find environment variable for $${t.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`)}try{yield o(e,a.constants.R_OK|a.constants.W_OK)}catch(t){throw new Error(`Unable to access summary file: '${e}'. Check if the file has correct read/write permissions.`)}this._filePath=e;return this._filePath}))}wrap(e,t,r={}){const n=Object.entries(r).map((([e,t])=>` ${e}="${t}"`)).join("");if(!t){return`<${e}${n}>`}return`<${e}${n}>${t}`}write(e){return n(this,void 0,void 0,(function*(){const t=!!(e===null||e===void 0?void 0:e.overwrite);const r=yield this.filePath();const n=t?u:s;yield n(r,this._buffer,{encoding:"utf8"});return this.emptyBuffer()}))}clear(){return n(this,void 0,void 0,(function*(){return this.emptyBuffer().write({overwrite:true})}))}stringify(){return this._buffer}isEmptyBuffer(){return this._buffer.length===0}emptyBuffer(){this._buffer="";return this}addRaw(e,t=false){this._buffer+=e;return t?this.addEOL():this}addEOL(){return this.addRaw(i.EOL)}addCodeBlock(e,t){const r=Object.assign({},t&&{lang:t});const n=this.wrap("pre",this.wrap("code",e),r);return this.addRaw(n).addEOL()}addList(e,t=false){const r=t?"ol":"ul";const n=e.map((e=>this.wrap("li",e))).join("");const i=this.wrap(r,n);return this.addRaw(i).addEOL()}addTable(e){const t=e.map((e=>{const t=e.map((e=>{if(typeof e==="string"){return this.wrap("td",e)}const{header:t,data:r,colspan:n,rowspan:i}=e;const a=t?"th":"td";const o=Object.assign(Object.assign({},n&&{colspan:n}),i&&{rowspan:i});return this.wrap(a,r,o)})).join("");return this.wrap("tr",t)})).join("");const r=this.wrap("table",t);return this.addRaw(r).addEOL()}addDetails(e,t){const r=this.wrap("details",this.wrap("summary",e)+t);return this.addRaw(r).addEOL()}addImage(e,t,r){const{width:n,height:i}=r||{};const a=Object.assign(Object.assign({},n&&{width:n}),i&&{height:i});const o=this.wrap("img",null,Object.assign({src:e,alt:t},a));return this.addRaw(o).addEOL()}addHeading(e,t){const r=`h${t}`;const n=["h1","h2","h3","h4","h5","h6"].includes(r)?r:"h1";const i=this.wrap(n,e);return this.addRaw(i).addEOL()}addSeparator(){const e=this.wrap("hr",null);return this.addRaw(e).addEOL()}addBreak(){const e=this.wrap("br",null);return this.addRaw(e).addEOL()}addQuote(e,t){const r=Object.assign({},t&&{cite:t});const n=this.wrap("blockquote",e,r);return this.addRaw(n).addEOL()}addLink(e,t){const r=this.wrap("a",e,{href:t});return this.addRaw(r).addEOL()}}const l=new Summary;t.markdownSummary=l;t.summary=l},6321:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t.toCommandProperties=t.toCommandValue=void 0;function toCommandValue(e){if(e===null||e===undefined){return""}else if(typeof e==="string"||e instanceof String){return e}return JSON.stringify(e)}t.toCommandValue=toCommandValue;function toCommandProperties(e){if(!Object.keys(e).length){return{}}return{title:e.title,file:e.file,line:e.startLine,endLine:e.endLine,col:e.startColumn,endColumn:e.endColumn}}t.toCommandProperties=toCommandProperties},5526:function(e,t){var r=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.PersonalAccessTokenCredentialHandler=t.BearerCredentialHandler=t.BasicCredentialHandler=void 0;class BasicCredentialHandler{constructor(e,t){this.username=e;this.password=t}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`${this.username}:${this.password}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return r(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}t.BasicCredentialHandler=BasicCredentialHandler;class BearerCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Bearer ${this.token}`}canHandleAuthentication(){return false}handleAuthentication(){return r(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}t.BearerCredentialHandler=BearerCredentialHandler;class PersonalAccessTokenCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`PAT:${this.token}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return r(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}t.PersonalAccessTokenCredentialHandler=PersonalAccessTokenCredentialHandler},6255:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;Object.defineProperty(e,n,{enumerable:true,get:function(){return t[r]}})}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)if(r!=="default"&&Object.hasOwnProperty.call(e,r))n(t,e,r);i(t,e);return t};var o=this&&this.__awaiter||function(e,t,r,n){function adopt(e){return e instanceof r?e:new r((function(t){t(e)}))}return new(r||(r=Promise))((function(r,i){function fulfilled(e){try{step(n.next(e))}catch(e){i(e)}}function rejected(e){try{step(n["throw"](e))}catch(e){i(e)}}function step(e){e.done?r(e.value):adopt(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:true});t.HttpClient=t.isHttps=t.HttpClientResponse=t.HttpClientError=t.getProxyUrl=t.MediaTypes=t.Headers=t.HttpCodes=void 0;const s=a(r(3685));const u=a(r(5687));const l=a(r(9835));const c=a(r(4294));var d;(function(e){e[e["OK"]=200]="OK";e[e["MultipleChoices"]=300]="MultipleChoices";e[e["MovedPermanently"]=301]="MovedPermanently";e[e["ResourceMoved"]=302]="ResourceMoved";e[e["SeeOther"]=303]="SeeOther";e[e["NotModified"]=304]="NotModified";e[e["UseProxy"]=305]="UseProxy";e[e["SwitchProxy"]=306]="SwitchProxy";e[e["TemporaryRedirect"]=307]="TemporaryRedirect";e[e["PermanentRedirect"]=308]="PermanentRedirect";e[e["BadRequest"]=400]="BadRequest";e[e["Unauthorized"]=401]="Unauthorized";e[e["PaymentRequired"]=402]="PaymentRequired";e[e["Forbidden"]=403]="Forbidden";e[e["NotFound"]=404]="NotFound";e[e["MethodNotAllowed"]=405]="MethodNotAllowed";e[e["NotAcceptable"]=406]="NotAcceptable";e[e["ProxyAuthenticationRequired"]=407]="ProxyAuthenticationRequired";e[e["RequestTimeout"]=408]="RequestTimeout";e[e["Conflict"]=409]="Conflict";e[e["Gone"]=410]="Gone";e[e["TooManyRequests"]=429]="TooManyRequests";e[e["InternalServerError"]=500]="InternalServerError";e[e["NotImplemented"]=501]="NotImplemented";e[e["BadGateway"]=502]="BadGateway";e[e["ServiceUnavailable"]=503]="ServiceUnavailable";e[e["GatewayTimeout"]=504]="GatewayTimeout"})(d=t.HttpCodes||(t.HttpCodes={}));var h;(function(e){e["Accept"]="accept";e["ContentType"]="content-type"})(h=t.Headers||(t.Headers={}));var p;(function(e){e["ApplicationJson"]="application/json"})(p=t.MediaTypes||(t.MediaTypes={}));function getProxyUrl(e){const t=l.getProxyUrl(new URL(e));return t?t.href:""}t.getProxyUrl=getProxyUrl;const g=[d.MovedPermanently,d.ResourceMoved,d.SeeOther,d.TemporaryRedirect,d.PermanentRedirect];const b=[d.BadGateway,d.ServiceUnavailable,d.GatewayTimeout];const m=["OPTIONS","GET","DELETE","HEAD"];const v=10;const _=5;class HttpClientError extends Error{constructor(e,t){super(e);this.name="HttpClientError";this.statusCode=t;Object.setPrototypeOf(this,HttpClientError.prototype)}}t.HttpClientError=HttpClientError;class HttpClientResponse{constructor(e){this.message=e}readBody(){return o(this,void 0,void 0,(function*(){return new Promise((e=>o(this,void 0,void 0,(function*(){let t=Buffer.alloc(0);this.message.on("data",(e=>{t=Buffer.concat([t,e])}));this.message.on("end",(()=>{e(t.toString())}))}))))}))}}t.HttpClientResponse=HttpClientResponse;function isHttps(e){const t=new URL(e);return t.protocol==="https:"}t.isHttps=isHttps;class HttpClient{constructor(e,t,r){this._ignoreSslError=false;this._allowRedirects=true;this._allowRedirectDowngrade=false;this._maxRedirects=50;this._allowRetries=false;this._maxRetries=1;this._keepAlive=false;this._disposed=false;this.userAgent=e;this.handlers=t||[];this.requestOptions=r;if(r){if(r.ignoreSslError!=null){this._ignoreSslError=r.ignoreSslError}this._socketTimeout=r.socketTimeout;if(r.allowRedirects!=null){this._allowRedirects=r.allowRedirects}if(r.allowRedirectDowngrade!=null){this._allowRedirectDowngrade=r.allowRedirectDowngrade}if(r.maxRedirects!=null){this._maxRedirects=Math.max(r.maxRedirects,0)}if(r.keepAlive!=null){this._keepAlive=r.keepAlive}if(r.allowRetries!=null){this._allowRetries=r.allowRetries}if(r.maxRetries!=null){this._maxRetries=r.maxRetries}}}options(e,t){return o(this,void 0,void 0,(function*(){return this.request("OPTIONS",e,null,t||{})}))}get(e,t){return o(this,void 0,void 0,(function*(){return this.request("GET",e,null,t||{})}))}del(e,t){return o(this,void 0,void 0,(function*(){return this.request("DELETE",e,null,t||{})}))}post(e,t,r){return o(this,void 0,void 0,(function*(){return this.request("POST",e,t,r||{})}))}patch(e,t,r){return o(this,void 0,void 0,(function*(){return this.request("PATCH",e,t,r||{})}))}put(e,t,r){return o(this,void 0,void 0,(function*(){return this.request("PUT",e,t,r||{})}))}head(e,t){return o(this,void 0,void 0,(function*(){return this.request("HEAD",e,null,t||{})}))}sendStream(e,t,r,n){return o(this,void 0,void 0,(function*(){return this.request(e,t,r,n)}))}getJson(e,t={}){return o(this,void 0,void 0,(function*(){t[h.Accept]=this._getExistingOrDefaultHeader(t,h.Accept,p.ApplicationJson);const r=yield this.get(e,t);return this._processResponse(r,this.requestOptions)}))}postJson(e,t,r={}){return o(this,void 0,void 0,(function*(){const n=JSON.stringify(t,null,2);r[h.Accept]=this._getExistingOrDefaultHeader(r,h.Accept,p.ApplicationJson);r[h.ContentType]=this._getExistingOrDefaultHeader(r,h.ContentType,p.ApplicationJson);const i=yield this.post(e,n,r);return this._processResponse(i,this.requestOptions)}))}putJson(e,t,r={}){return o(this,void 0,void 0,(function*(){const n=JSON.stringify(t,null,2);r[h.Accept]=this._getExistingOrDefaultHeader(r,h.Accept,p.ApplicationJson);r[h.ContentType]=this._getExistingOrDefaultHeader(r,h.ContentType,p.ApplicationJson);const i=yield this.put(e,n,r);return this._processResponse(i,this.requestOptions)}))}patchJson(e,t,r={}){return o(this,void 0,void 0,(function*(){const n=JSON.stringify(t,null,2);r[h.Accept]=this._getExistingOrDefaultHeader(r,h.Accept,p.ApplicationJson);r[h.ContentType]=this._getExistingOrDefaultHeader(r,h.ContentType,p.ApplicationJson);const i=yield this.patch(e,n,r);return this._processResponse(i,this.requestOptions)}))}request(e,t,r,n){return o(this,void 0,void 0,(function*(){if(this._disposed){throw new Error("Client has already been disposed.")}const i=new URL(t);let a=this._prepareRequest(e,i,n);const o=this._allowRetries&&m.includes(e)?this._maxRetries+1:1;let s=0;let u;do{u=yield this.requestRaw(a,r);if(u&&u.message&&u.message.statusCode===d.Unauthorized){let e;for(const t of this.handlers){if(t.canHandleAuthentication(u)){e=t;break}}if(e){return e.handleAuthentication(this,a,r)}else{return u}}let t=this._maxRedirects;while(u.message.statusCode&&g.includes(u.message.statusCode)&&this._allowRedirects&&t>0){const o=u.message.headers["location"];if(!o){break}const s=new URL(o);if(i.protocol==="https:"&&i.protocol!==s.protocol&&!this._allowRedirectDowngrade){throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.")}yield u.readBody();if(s.hostname!==i.hostname){for(const e in n){if(e.toLowerCase()==="authorization"){delete n[e]}}}a=this._prepareRequest(e,s,n);u=yield this.requestRaw(a,r);t--}if(!u.message.statusCode||!b.includes(u.message.statusCode)){return u}s+=1;if(s{function callbackForResult(e,t){if(e){n(e)}else if(!t){n(new Error("Unknown error"))}else{r(t)}}this.requestRawWithCallback(e,t,callbackForResult)}))}))}requestRawWithCallback(e,t,r){if(typeof t==="string"){if(!e.options.headers){e.options.headers={}}e.options.headers["Content-Length"]=Buffer.byteLength(t,"utf8")}let n=false;function handleResult(e,t){if(!n){n=true;r(e,t)}}const i=e.httpModule.request(e.options,(e=>{const t=new HttpClientResponse(e);handleResult(undefined,t)}));let a;i.on("socket",(e=>{a=e}));i.setTimeout(this._socketTimeout||3*6e4,(()=>{if(a){a.end()}handleResult(new Error(`Request timeout: ${e.options.path}`))}));i.on("error",(function(e){handleResult(e)}));if(t&&typeof t==="string"){i.write(t,"utf8")}if(t&&typeof t!=="string"){t.on("close",(function(){i.end()}));t.pipe(i)}else{i.end()}}getAgent(e){const t=new URL(e);return this._getAgent(t)}_prepareRequest(e,t,r){const n={};n.parsedUrl=t;const i=n.parsedUrl.protocol==="https:";n.httpModule=i?u:s;const a=i?443:80;n.options={};n.options.host=n.parsedUrl.hostname;n.options.port=n.parsedUrl.port?parseInt(n.parsedUrl.port):a;n.options.path=(n.parsedUrl.pathname||"")+(n.parsedUrl.search||"");n.options.method=e;n.options.headers=this._mergeHeaders(r);if(this.userAgent!=null){n.options.headers["user-agent"]=this.userAgent}n.options.agent=this._getAgent(n.parsedUrl);if(this.handlers){for(const e of this.handlers){e.prepareRequest(n.options)}}return n}_mergeHeaders(e){if(this.requestOptions&&this.requestOptions.headers){return Object.assign({},lowercaseKeys(this.requestOptions.headers),lowercaseKeys(e||{}))}return lowercaseKeys(e||{})}_getExistingOrDefaultHeader(e,t,r){let n;if(this.requestOptions&&this.requestOptions.headers){n=lowercaseKeys(this.requestOptions.headers)[t]}return e[t]||n||r}_getAgent(e){let t;const r=l.getProxyUrl(e);const n=r&&r.hostname;if(this._keepAlive&&n){t=this._proxyAgent}if(this._keepAlive&&!n){t=this._agent}if(t){return t}const i=e.protocol==="https:";let a=100;if(this.requestOptions){a=this.requestOptions.maxSockets||s.globalAgent.maxSockets}if(r&&r.hostname){const e={maxSockets:a,keepAlive:this._keepAlive,proxy:Object.assign(Object.assign({},(r.username||r.password)&&{proxyAuth:`${r.username}:${r.password}`}),{host:r.hostname,port:r.port})};let n;const o=r.protocol==="https:";if(i){n=o?c.httpsOverHttps:c.httpsOverHttp}else{n=o?c.httpOverHttps:c.httpOverHttp}t=n(e);this._proxyAgent=t}if(this._keepAlive&&!t){const e={keepAlive:this._keepAlive,maxSockets:a};t=i?new u.Agent(e):new s.Agent(e);this._agent=t}if(!t){t=i?u.globalAgent:s.globalAgent}if(i&&this._ignoreSslError){t.options=Object.assign(t.options||{},{rejectUnauthorized:false})}return t}_performExponentialBackoff(e){return o(this,void 0,void 0,(function*(){e=Math.min(v,e);const t=_*Math.pow(2,e);return new Promise((e=>setTimeout((()=>e()),t)))}))}_processResponse(e,t){return o(this,void 0,void 0,(function*(){return new Promise(((r,n)=>o(this,void 0,void 0,(function*(){const i=e.message.statusCode||0;const a={statusCode:i,result:null,headers:{}};if(i===d.NotFound){r(a)}function dateTimeDeserializer(e,t){if(typeof t==="string"){const e=new Date(t);if(!isNaN(e.valueOf())){return e}}return t}let o;let s;try{s=yield e.readBody();if(s&&s.length>0){if(t&&t.deserializeDates){o=JSON.parse(s,dateTimeDeserializer)}else{o=JSON.parse(s)}a.result=o}a.headers=e.message.headers}catch(e){}if(i>299){let e;if(o&&o.message){e=o.message}else if(s&&s.length>0){e=s}else{e=`Failed request: (${i})`}const t=new HttpClientError(e,i);t.result=a.result;n(t)}else{r(a)}}))))}))}}t.HttpClient=HttpClient;const lowercaseKeys=e=>Object.keys(e).reduce(((t,r)=>(t[r.toLowerCase()]=e[r],t)),{})},9835:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t.checkBypass=t.getProxyUrl=void 0;function getProxyUrl(e){const t=e.protocol==="https:";if(checkBypass(e)){return undefined}const r=(()=>{if(t){return process.env["https_proxy"]||process.env["HTTPS_PROXY"]}else{return process.env["http_proxy"]||process.env["HTTP_PROXY"]}})();if(r){return new URL(r)}else{return undefined}}t.getProxyUrl=getProxyUrl;function checkBypass(e){if(!e.hostname){return false}const t=process.env["no_proxy"]||process.env["NO_PROXY"]||"";if(!t){return false}let r;if(e.port){r=Number(e.port)}else if(e.protocol==="http:"){r=80}else if(e.protocol==="https:"){r=443}const n=[e.hostname.toUpperCase()];if(typeof r==="number"){n.push(`${n[0]}:${r}`)}for(const e of t.split(",").map((e=>e.trim().toUpperCase())).filter((e=>e))){if(n.some((t=>t===e))){return true}}return false}t.checkBypass=checkBypass},3664:(e,t,r)=>{const{Buffer:n}=r(4300);const i=Symbol.for("BufferList");function BufferList(e){if(!(this instanceof BufferList)){return new BufferList(e)}BufferList._init.call(this,e)}BufferList._init=function _init(e){Object.defineProperty(this,i,{value:true});this._bufs=[];this.length=0;if(e){this.append(e)}};BufferList.prototype._new=function _new(e){return new BufferList(e)};BufferList.prototype._offset=function _offset(e){if(e===0){return[0,0]}let t=0;for(let r=0;rthis.length||e<0){return undefined}const t=this._offset(e);return this._bufs[t[0]][t[1]]};BufferList.prototype.slice=function slice(e,t){if(typeof e==="number"&&e<0){e+=this.length}if(typeof t==="number"&&t<0){t+=this.length}return this.copy(null,0,e,t)};BufferList.prototype.copy=function copy(e,t,r,i){if(typeof r!=="number"||r<0){r=0}if(typeof i!=="number"||i>this.length){i=this.length}if(r>=this.length){return e||n.alloc(0)}if(i<=0){return e||n.alloc(0)}const copy=!!e;const a=this._offset(r);const o=i-r;let s=o;let u=copy&&t||0;let l=a[1];if(r===0&&i===this.length){if(!copy){return this._bufs.length===1?this._bufs[0]:n.concat(this._bufs,this.length)}for(let t=0;tr){this._bufs[t].copy(e,u,l);u+=r}else{this._bufs[t].copy(e,u,l,l+s);u+=r;break}s-=r;if(l){l=0}}if(e.length>u)return e.slice(0,u);return e};BufferList.prototype.shallowSlice=function shallowSlice(e,t){e=e||0;t=typeof t!=="number"?this.length:t;if(e<0){e+=this.length}if(t<0){t+=this.length}if(e===t){return this._new()}const r=this._offset(e);const n=this._offset(t);const i=this._bufs.slice(r[0],n[0]+1);if(n[1]===0){i.pop()}else{i[i.length-1]=i[i.length-1].slice(0,n[1])}if(r[1]!==0){i[0]=i[0].slice(r[1])}return this._new(i)};BufferList.prototype.toString=function toString(e,t,r){return this.slice(t,r).toString(e)};BufferList.prototype.consume=function consume(e){e=Math.trunc(e);if(Number.isNaN(e)||e<=0)return this;while(this._bufs.length){if(e>=this._bufs[0].length){e-=this._bufs[0].length;this.length-=this._bufs[0].length;this._bufs.shift()}else{this._bufs[0]=this._bufs[0].slice(e);this.length-=e;break}}return this};BufferList.prototype.duplicate=function duplicate(){const e=this._new();for(let t=0;tthis.length?this.length:t}const i=this._offset(t);let a=i[0];let o=i[1];for(;a=e.length){const r=t.indexOf(e,o);if(r!==-1){return this._reverseOffset([a,r])}o=t.length-e.length+1}else{const t=this._reverseOffset([a,o]);if(this._match(t,e)){return t}o++}}o=0}return-1};BufferList.prototype._match=function(e,t){if(this.length-e{const n=r(1642).Duplex;const i=r(4124);const a=r(3664);function BufferListStream(e){if(!(this instanceof BufferListStream)){return new BufferListStream(e)}if(typeof e==="function"){this._callback=e;const t=function piper(e){if(this._callback){this._callback(e);this._callback=null}}.bind(this);this.on("pipe",(function onPipe(e){e.on("error",t)}));this.on("unpipe",(function onUnpipe(e){e.removeListener("error",t)}));e=null}a._init.call(this,e);n.call(this)}i(BufferListStream,n);Object.assign(BufferListStream.prototype,a.prototype);BufferListStream.prototype._new=function _new(e){return new BufferListStream(e)};BufferListStream.prototype._write=function _write(e,t,r){this._appendBuffer(e);if(typeof r==="function"){r()}};BufferListStream.prototype._read=function _read(e){if(!this.length){return this.push(null)}e=Math.min(e,this.length);this.push(this.slice(0,e));this.consume(e)};BufferListStream.prototype.end=function end(e){n.prototype.end.call(this,e);if(this._callback){this._callback(null,this.slice());this._callback=null}};BufferListStream.prototype._destroy=function _destroy(e,t){this._bufs.length=0;this.length=0;t(e)};BufferListStream.prototype._isBufferList=function _isBufferList(e){return e instanceof BufferListStream||e instanceof a||BufferListStream.isBufferList(e)};BufferListStream.isBufferList=a.isBufferList;e.exports=BufferListStream;e.exports.BufferListStream=BufferListStream;e.exports.BufferList=a},1205:(e,t,r)=>{var n=r(1223);var noop=function(){};var isRequest=function(e){return e.setHeader&&typeof e.abort==="function"};var isChildProcess=function(e){return e.stdio&&Array.isArray(e.stdio)&&e.stdio.length===3};var eos=function(e,t,r){if(typeof t==="function")return eos(e,null,t);if(!t)t={};r=n(r||noop);var i=e._writableState;var a=e._readableState;var o=t.readable||t.readable!==false&&e.readable;var s=t.writable||t.writable!==false&&e.writable;var u=false;var onlegacyfinish=function(){if(!e.writable)onfinish()};var onfinish=function(){s=false;if(!o)r.call(e)};var onend=function(){o=false;if(!s)r.call(e)};var onexit=function(t){r.call(e,t?new Error("exited with error code: "+t):null)};var onerror=function(t){r.call(e,t)};var onclose=function(){process.nextTick(onclosenexttick)};var onclosenexttick=function(){if(u)return;if(o&&!(a&&(a.ended&&!a.destroyed)))return r.call(e,new Error("premature close"));if(s&&!(i&&(i.ended&&!i.destroyed)))return r.call(e,new Error("premature close"))};var onrequest=function(){e.req.on("finish",onfinish)};if(isRequest(e)){e.on("complete",onfinish);e.on("abort",onclose);if(e.req)onrequest();else e.on("request",onrequest)}else if(s&&!i){e.on("end",onlegacyfinish);e.on("close",onlegacyfinish)}if(isChildProcess(e))e.on("exit",onexit);e.on("end",onend);e.on("finish",onfinish);if(t.error!==false)e.on("error",onerror);e.on("close",onclose);return function(){u=true;e.removeListener("complete",onfinish);e.removeListener("abort",onclose);e.removeListener("request",onrequest);if(e.req)e.req.removeListener("finish",onfinish);e.removeListener("end",onlegacyfinish);e.removeListener("close",onlegacyfinish);e.removeListener("finish",onfinish);e.removeListener("exit",onexit);e.removeListener("end",onend);e.removeListener("error",onerror);e.removeListener("close",onclose)}};e.exports=eos},3186:(e,t,r)=>{e.exports=r(7147).constants||r(2057)},4124:(e,t,r)=>{try{var n=r(3837);if(typeof n.inherits!=="function")throw"";e.exports=n.inherits}catch(t){e.exports=r(8544)}},8544:e=>{if(typeof Object.create==="function"){e.exports=function inherits(e,t){if(t){e.super_=t;e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:false,writable:true,configurable:true}})}}}else{e.exports=function inherits(e,t){if(t){e.super_=t;var TempCtor=function(){};TempCtor.prototype=t.prototype;e.prototype=new TempCtor;e.prototype.constructor=e}}}},1223:(e,t,r)=>{var n=r(2940);e.exports=n(once);e.exports.strict=n(onceStrict);once.proto=once((function(){Object.defineProperty(Function.prototype,"once",{value:function(){return once(this)},configurable:true});Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return onceStrict(this)},configurable:true})}));function once(e){var f=function(){if(f.called)return f.value;f.called=true;return f.value=e.apply(this,arguments)};f.called=false;return f}function onceStrict(e){var f=function(){if(f.called)throw new Error(f.onceError);f.called=true;return f.value=e.apply(this,arguments)};var t=e.name||"Function wrapped with `once`";f.onceError=t+" shouldn't be called more than once";f.called=false;return f}},7214:e=>{const t={};function createErrorType(e,r,n){if(!n){n=Error}function getMessage(e,t,n){if(typeof r==="string"){return r}else{return r(e,t,n)}}class NodeError extends n{constructor(e,t,r){super(getMessage(e,t,r))}}NodeError.prototype.name=n.name;NodeError.prototype.code=e;t[e]=NodeError}function oneOf(e,t){if(Array.isArray(e)){const r=e.length;e=e.map((e=>String(e)));if(r>2){return`one of ${t} ${e.slice(0,r-1).join(", ")}, or `+e[r-1]}else if(r===2){return`one of ${t} ${e[0]} or ${e[1]}`}else{return`of ${t} ${e[0]}`}}else{return`of ${t} ${String(e)}`}}function startsWith(e,t,r){return e.substr(!r||r<0?0:+r,t.length)===t}function endsWith(e,t,r){if(r===undefined||r>e.length){r=e.length}return e.substring(r-t.length,r)===t}function includes(e,t,r){if(typeof r!=="number"){r=0}if(r+t.length>e.length){return false}else{return e.indexOf(t,r)!==-1}}createErrorType("ERR_INVALID_OPT_VALUE",(function(e,t){return'The value "'+t+'" is invalid for option "'+e+'"'}),TypeError);createErrorType("ERR_INVALID_ARG_TYPE",(function(e,t,r){let n;if(typeof t==="string"&&startsWith(t,"not ")){n="must not be";t=t.replace(/^not /,"")}else{n="must be"}let i;if(endsWith(e," argument")){i=`The ${e} ${n} ${oneOf(t,"type")}`}else{const r=includes(e,".")?"property":"argument";i=`The "${e}" ${r} ${n} ${oneOf(t,"type")}`}i+=`. Received type ${typeof r}`;return i}),TypeError);createErrorType("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF");createErrorType("ERR_METHOD_NOT_IMPLEMENTED",(function(e){return"The "+e+" method is not implemented"}));createErrorType("ERR_STREAM_PREMATURE_CLOSE","Premature close");createErrorType("ERR_STREAM_DESTROYED",(function(e){return"Cannot call "+e+" after a stream was destroyed"}));createErrorType("ERR_MULTIPLE_CALLBACK","Callback called multiple times");createErrorType("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable");createErrorType("ERR_STREAM_WRITE_AFTER_END","write after end");createErrorType("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError);createErrorType("ERR_UNKNOWN_ENCODING",(function(e){return"Unknown encoding: "+e}),TypeError);createErrorType("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event");e.exports.q=t},1359:(e,t,r)=>{var n=Object.keys||function(e){var t=[];for(var r in e){t.push(r)}return t};e.exports=Duplex;var i=r(1433);var a=r(6993);r(4124)(Duplex,i);{var o=n(a.prototype);for(var s=0;s{e.exports=PassThrough;var n=r(4415);r(4124)(PassThrough,n);function PassThrough(e){if(!(this instanceof PassThrough))return new PassThrough(e);n.call(this,e)}PassThrough.prototype._transform=function(e,t,r){r(null,e)}},1433:(e,t,r)=>{e.exports=Readable;var n;Readable.ReadableState=ReadableState;var i=r(2361).EventEmitter;var a=function EElistenerCount(e,t){return e.listeners(t).length};var o=r(2387);var s=r(4300).Buffer;var u=global.Uint8Array||function(){};function _uint8ArrayToBuffer(e){return s.from(e)}function _isUint8Array(e){return s.isBuffer(e)||e instanceof u}var l=r(3837);var c;if(l&&l.debuglog){c=l.debuglog("stream")}else{c=function debug(){}}var d=r(2746);var h=r(7049);var p=r(9948),g=p.getHighWaterMark;var b=r(7214).q,m=b.ERR_INVALID_ARG_TYPE,v=b.ERR_STREAM_PUSH_AFTER_EOF,_=b.ERR_METHOD_NOT_IMPLEMENTED,y=b.ERR_STREAM_UNSHIFT_AFTER_END_EVENT;var w;var R;var S;r(4124)(Readable,o);var E=h.errorOrDestroy;var k=["error","close","destroy","pause","resume"];function prependListener(e,t,r){if(typeof e.prependListener==="function")return e.prependListener(t,r);if(!e._events||!e._events[t])e.on(t,r);else if(Array.isArray(e._events[t]))e._events[t].unshift(r);else e._events[t]=[r,e._events[t]]}function ReadableState(e,t,i){n=n||r(1359);e=e||{};if(typeof i!=="boolean")i=t instanceof n;this.objectMode=!!e.objectMode;if(i)this.objectMode=this.objectMode||!!e.readableObjectMode;this.highWaterMark=g(this,e,"readableHighWaterMark",i);this.buffer=new d;this.length=0;this.pipes=null;this.pipesCount=0;this.flowing=null;this.ended=false;this.endEmitted=false;this.reading=false;this.sync=true;this.needReadable=false;this.emittedReadable=false;this.readableListening=false;this.resumeScheduled=false;this.paused=true;this.emitClose=e.emitClose!==false;this.autoDestroy=!!e.autoDestroy;this.destroyed=false;this.defaultEncoding=e.defaultEncoding||"utf8";this.awaitDrain=0;this.readingMore=false;this.decoder=null;this.encoding=null;if(e.encoding){if(!w)w=r(4841).s;this.decoder=new w(e.encoding);this.encoding=e.encoding}}function Readable(e){n=n||r(1359);if(!(this instanceof Readable))return new Readable(e);var t=this instanceof n;this._readableState=new ReadableState(e,this,t);this.readable=true;if(e){if(typeof e.read==="function")this._read=e.read;if(typeof e.destroy==="function")this._destroy=e.destroy}o.call(this)}Object.defineProperty(Readable.prototype,"destroyed",{enumerable:false,get:function get(){if(this._readableState===undefined){return false}return this._readableState.destroyed},set:function set(e){if(!this._readableState){return}this._readableState.destroyed=e}});Readable.prototype.destroy=h.destroy;Readable.prototype._undestroy=h.undestroy;Readable.prototype._destroy=function(e,t){t(e)};Readable.prototype.push=function(e,t){var r=this._readableState;var n;if(!r.objectMode){if(typeof e==="string"){t=t||r.defaultEncoding;if(t!==r.encoding){e=s.from(e,t);t=""}n=true}}else{n=true}return readableAddChunk(this,e,t,false,n)};Readable.prototype.unshift=function(e){return readableAddChunk(this,e,null,true,false)};function readableAddChunk(e,t,r,n,i){c("readableAddChunk",t);var a=e._readableState;if(t===null){a.reading=false;onEofChunk(e,a)}else{var o;if(!i)o=chunkInvalid(a,t);if(o){E(e,o)}else if(a.objectMode||t&&t.length>0){if(typeof t!=="string"&&!a.objectMode&&Object.getPrototypeOf(t)!==s.prototype){t=_uint8ArrayToBuffer(t)}if(n){if(a.endEmitted)E(e,new y);else addChunk(e,a,t,true)}else if(a.ended){E(e,new v)}else if(a.destroyed){return false}else{a.reading=false;if(a.decoder&&!r){t=a.decoder.write(t);if(a.objectMode||t.length!==0)addChunk(e,a,t,false);else maybeReadMore(e,a)}else{addChunk(e,a,t,false)}}}else if(!n){a.reading=false;maybeReadMore(e,a)}}return!a.ended&&(a.length=O){e=O}else{e--;e|=e>>>1;e|=e>>>2;e|=e>>>4;e|=e>>>8;e|=e>>>16;e++}return e}function howMuchToRead(e,t){if(e<=0||t.length===0&&t.ended)return 0;if(t.objectMode)return 1;if(e!==e){if(t.flowing&&t.length)return t.buffer.head.data.length;else return t.length}if(e>t.highWaterMark)t.highWaterMark=computeNewHighWaterMark(e);if(e<=t.length)return e;if(!t.ended){t.needReadable=true;return 0}return t.length}Readable.prototype.read=function(e){c("read",e);e=parseInt(e,10);var t=this._readableState;var r=e;if(e!==0)t.emittedReadable=false;if(e===0&&t.needReadable&&((t.highWaterMark!==0?t.length>=t.highWaterMark:t.length>0)||t.ended)){c("read: emitReadable",t.length,t.ended);if(t.length===0&&t.ended)endReadable(this);else emitReadable(this);return null}e=howMuchToRead(e,t);if(e===0&&t.ended){if(t.length===0)endReadable(this);return null}var n=t.needReadable;c("need readable",n);if(t.length===0||t.length-e0)i=fromList(e,t);else i=null;if(i===null){t.needReadable=t.length<=t.highWaterMark;e=0}else{t.length-=e;t.awaitDrain=0}if(t.length===0){if(!t.ended)t.needReadable=true;if(r!==e&&t.ended)endReadable(this)}if(i!==null)this.emit("data",i);return i};function onEofChunk(e,t){c("onEofChunk");if(t.ended)return;if(t.decoder){var r=t.decoder.end();if(r&&r.length){t.buffer.push(r);t.length+=t.objectMode?1:r.length}}t.ended=true;if(t.sync){emitReadable(e)}else{t.needReadable=false;if(!t.emittedReadable){t.emittedReadable=true;emitReadable_(e)}}}function emitReadable(e){var t=e._readableState;c("emitReadable",t.needReadable,t.emittedReadable);t.needReadable=false;if(!t.emittedReadable){c("emitReadable",t.flowing);t.emittedReadable=true;process.nextTick(emitReadable_,e)}}function emitReadable_(e){var t=e._readableState;c("emitReadable_",t.destroyed,t.length,t.ended);if(!t.destroyed&&(t.length||t.ended)){e.emit("readable");t.emittedReadable=false}t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark;flow(e)}function maybeReadMore(e,t){if(!t.readingMore){t.readingMore=true;process.nextTick(maybeReadMore_,e,t)}}function maybeReadMore_(e,t){while(!t.reading&&!t.ended&&(t.length1&&indexOf(n.pipes,e)!==-1)&&!u){c("false write response, pause",n.awaitDrain);n.awaitDrain++}r.pause()}}function onerror(t){c("onerror",t);unpipe();e.removeListener("error",onerror);if(a(e,"error")===0)E(e,t)}prependListener(e,"error",onerror);function onclose(){e.removeListener("finish",onfinish);unpipe()}e.once("close",onclose);function onfinish(){c("onfinish");e.removeListener("close",onclose);unpipe()}e.once("finish",onfinish);function unpipe(){c("unpipe");r.unpipe(e)}e.emit("pipe",r);if(!n.flowing){c("pipe resume");r.resume()}return e};function pipeOnDrain(e){return function pipeOnDrainFunctionResult(){var t=e._readableState;c("pipeOnDrain",t.awaitDrain);if(t.awaitDrain)t.awaitDrain--;if(t.awaitDrain===0&&a(e,"data")){t.flowing=true;flow(e)}}}Readable.prototype.unpipe=function(e){var t=this._readableState;var r={hasUnpiped:false};if(t.pipesCount===0)return this;if(t.pipesCount===1){if(e&&e!==t.pipes)return this;if(!e)e=t.pipes;t.pipes=null;t.pipesCount=0;t.flowing=false;if(e)e.emit("unpipe",this,r);return this}if(!e){var n=t.pipes;var i=t.pipesCount;t.pipes=null;t.pipesCount=0;t.flowing=false;for(var a=0;a0;if(n.flowing!==false)this.resume()}else if(e==="readable"){if(!n.endEmitted&&!n.readableListening){n.readableListening=n.needReadable=true;n.flowing=false;n.emittedReadable=false;c("on readable",n.length,n.reading);if(n.length){emitReadable(this)}else if(!n.reading){process.nextTick(nReadingNextTick,this)}}}return r};Readable.prototype.addListener=Readable.prototype.on;Readable.prototype.removeListener=function(e,t){var r=o.prototype.removeListener.call(this,e,t);if(e==="readable"){process.nextTick(updateReadableListening,this)}return r};Readable.prototype.removeAllListeners=function(e){var t=o.prototype.removeAllListeners.apply(this,arguments);if(e==="readable"||e===undefined){process.nextTick(updateReadableListening,this)}return t};function updateReadableListening(e){var t=e._readableState;t.readableListening=e.listenerCount("readable")>0;if(t.resumeScheduled&&!t.paused){t.flowing=true}else if(e.listenerCount("data")>0){e.resume()}}function nReadingNextTick(e){c("readable nexttick read 0");e.read(0)}Readable.prototype.resume=function(){var e=this._readableState;if(!e.flowing){c("resume");e.flowing=!e.readableListening;resume(this,e)}e.paused=false;return this};function resume(e,t){if(!t.resumeScheduled){t.resumeScheduled=true;process.nextTick(resume_,e,t)}}function resume_(e,t){c("resume",t.reading);if(!t.reading){e.read(0)}t.resumeScheduled=false;e.emit("resume");flow(e);if(t.flowing&&!t.reading)e.read(0)}Readable.prototype.pause=function(){c("call pause flowing=%j",this._readableState.flowing);if(this._readableState.flowing!==false){c("pause");this._readableState.flowing=false;this.emit("pause")}this._readableState.paused=true;return this};function flow(e){var t=e._readableState;c("flow",t.flowing);while(t.flowing&&e.read()!==null){}}Readable.prototype.wrap=function(e){var t=this;var r=this._readableState;var n=false;e.on("end",(function(){c("wrapped end");if(r.decoder&&!r.ended){var e=r.decoder.end();if(e&&e.length)t.push(e)}t.push(null)}));e.on("data",(function(i){c("wrapped data");if(r.decoder)i=r.decoder.write(i);if(r.objectMode&&(i===null||i===undefined))return;else if(!r.objectMode&&(!i||!i.length))return;var a=t.push(i);if(!a){n=true;e.pause()}}));for(var i in e){if(this[i]===undefined&&typeof e[i]==="function"){this[i]=function methodWrap(t){return function methodWrapReturnFunction(){return e[t].apply(e,arguments)}}(i)}}for(var a=0;a=t.length){if(t.decoder)r=t.buffer.join("");else if(t.buffer.length===1)r=t.buffer.first();else r=t.buffer.concat(t.length);t.buffer.clear()}else{r=t.buffer.consume(e,t.decoder)}return r}function endReadable(e){var t=e._readableState;c("endReadable",t.endEmitted);if(!t.endEmitted){t.ended=true;process.nextTick(endReadableNT,t,e)}}function endReadableNT(e,t){c("endReadableNT",e.endEmitted,e.length);if(!e.endEmitted&&e.length===0){e.endEmitted=true;t.readable=false;t.emit("end");if(e.autoDestroy){var r=t._writableState;if(!r||r.autoDestroy&&r.finished){t.destroy()}}}}if(typeof Symbol==="function"){Readable.from=function(e,t){if(S===undefined){S=r(9082)}return S(Readable,e,t)}}function indexOf(e,t){for(var r=0,n=e.length;r{e.exports=Transform;var n=r(7214).q,i=n.ERR_METHOD_NOT_IMPLEMENTED,a=n.ERR_MULTIPLE_CALLBACK,o=n.ERR_TRANSFORM_ALREADY_TRANSFORMING,s=n.ERR_TRANSFORM_WITH_LENGTH_0;var u=r(1359);r(4124)(Transform,u);function afterTransform(e,t){var r=this._transformState;r.transforming=false;var n=r.writecb;if(n===null){return this.emit("error",new a)}r.writechunk=null;r.writecb=null;if(t!=null)this.push(t);n(e);var i=this._readableState;i.reading=false;if(i.needReadable||i.length{e.exports=Writable;function WriteReq(e,t,r){this.chunk=e;this.encoding=t;this.callback=r;this.next=null}function CorkedRequest(e){var t=this;this.next=null;this.entry=null;this.finish=function(){onCorkedFinish(t,e)}}var n;Writable.WritableState=WritableState;var i={deprecate:r(5278)};var a=r(2387);var o=r(4300).Buffer;var s=global.Uint8Array||function(){};function _uint8ArrayToBuffer(e){return o.from(e)}function _isUint8Array(e){return o.isBuffer(e)||e instanceof s}var u=r(7049);var l=r(9948),c=l.getHighWaterMark;var d=r(7214).q,h=d.ERR_INVALID_ARG_TYPE,p=d.ERR_METHOD_NOT_IMPLEMENTED,g=d.ERR_MULTIPLE_CALLBACK,b=d.ERR_STREAM_CANNOT_PIPE,m=d.ERR_STREAM_DESTROYED,v=d.ERR_STREAM_NULL_VALUES,_=d.ERR_STREAM_WRITE_AFTER_END,y=d.ERR_UNKNOWN_ENCODING;var w=u.errorOrDestroy;r(4124)(Writable,a);function nop(){}function WritableState(e,t,i){n=n||r(1359);e=e||{};if(typeof i!=="boolean")i=t instanceof n;this.objectMode=!!e.objectMode;if(i)this.objectMode=this.objectMode||!!e.writableObjectMode;this.highWaterMark=c(this,e,"writableHighWaterMark",i);this.finalCalled=false;this.needDrain=false;this.ending=false;this.ended=false;this.finished=false;this.destroyed=false;var a=e.decodeStrings===false;this.decodeStrings=!a;this.defaultEncoding=e.defaultEncoding||"utf8";this.length=0;this.writing=false;this.corked=0;this.sync=true;this.bufferProcessing=false;this.onwrite=function(e){onwrite(t,e)};this.writecb=null;this.writelen=0;this.bufferedRequest=null;this.lastBufferedRequest=null;this.pendingcb=0;this.prefinished=false;this.errorEmitted=false;this.emitClose=e.emitClose!==false;this.autoDestroy=!!e.autoDestroy;this.bufferedRequestCount=0;this.corkedRequestsFree=new CorkedRequest(this)}WritableState.prototype.getBuffer=function getBuffer(){var e=this.bufferedRequest;var t=[];while(e){t.push(e);e=e.next}return t};(function(){try{Object.defineProperty(WritableState.prototype,"buffer",{get:i.deprecate((function writableStateBufferGetter(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer "+"instead.","DEP0003")})}catch(e){}})();var R;if(typeof Symbol==="function"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]==="function"){R=Function.prototype[Symbol.hasInstance];Object.defineProperty(Writable,Symbol.hasInstance,{value:function value(e){if(R.call(this,e))return true;if(this!==Writable)return false;return e&&e._writableState instanceof WritableState}})}else{R=function realHasInstance(e){return e instanceof this}}function Writable(e){n=n||r(1359);var t=this instanceof n;if(!t&&!R.call(Writable,this))return new Writable(e);this._writableState=new WritableState(e,this,t);this.writable=true;if(e){if(typeof e.write==="function")this._write=e.write;if(typeof e.writev==="function")this._writev=e.writev;if(typeof e.destroy==="function")this._destroy=e.destroy;if(typeof e.final==="function")this._final=e.final}a.call(this)}Writable.prototype.pipe=function(){w(this,new b)};function writeAfterEnd(e,t){var r=new _;w(e,r);process.nextTick(t,r)}function validChunk(e,t,r,n){var i;if(r===null){i=new v}else if(typeof r!=="string"&&!t.objectMode){i=new h("chunk",["string","Buffer"],r)}if(i){w(e,i);process.nextTick(n,i);return false}return true}Writable.prototype.write=function(e,t,r){var n=this._writableState;var i=false;var a=!n.objectMode&&_isUint8Array(e);if(a&&!o.isBuffer(e)){e=_uint8ArrayToBuffer(e)}if(typeof t==="function"){r=t;t=null}if(a)t="buffer";else if(!t)t=n.defaultEncoding;if(typeof r!=="function")r=nop;if(n.ending)writeAfterEnd(this,r);else if(a||validChunk(this,n,e,r)){n.pendingcb++;i=writeOrBuffer(this,n,a,e,t,r)}return i};Writable.prototype.cork=function(){this._writableState.corked++};Writable.prototype.uncork=function(){var e=this._writableState;if(e.corked){e.corked--;if(!e.writing&&!e.corked&&!e.bufferProcessing&&e.bufferedRequest)clearBuffer(this,e)}};Writable.prototype.setDefaultEncoding=function setDefaultEncoding(e){if(typeof e==="string")e=e.toLowerCase();if(!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new y(e);this._writableState.defaultEncoding=e;return this};Object.defineProperty(Writable.prototype,"writableBuffer",{enumerable:false,get:function get(){return this._writableState&&this._writableState.getBuffer()}});function decodeChunk(e,t,r){if(!e.objectMode&&e.decodeStrings!==false&&typeof t==="string"){t=o.from(t,r)}return t}Object.defineProperty(Writable.prototype,"writableHighWaterMark",{enumerable:false,get:function get(){return this._writableState.highWaterMark}});function writeOrBuffer(e,t,r,n,i,a){if(!r){var o=decodeChunk(t,n,i);if(n!==o){r=true;i="buffer";n=o}}var s=t.objectMode?1:n.length;t.length+=s;var u=t.length{var n;function _defineProperty(e,t,r){if(t in e){Object.defineProperty(e,t,{value:r,enumerable:true,configurable:true,writable:true})}else{e[t]=r}return e}var i=r(6080);var a=Symbol("lastResolve");var o=Symbol("lastReject");var s=Symbol("error");var u=Symbol("ended");var l=Symbol("lastPromise");var c=Symbol("handlePromise");var d=Symbol("stream");function createIterResult(e,t){return{value:e,done:t}}function readAndResolve(e){var t=e[a];if(t!==null){var r=e[d].read();if(r!==null){e[l]=null;e[a]=null;e[o]=null;t(createIterResult(r,false))}}}function onReadable(e){process.nextTick(readAndResolve,e)}function wrapForNext(e,t){return function(r,n){e.then((function(){if(t[u]){r(createIterResult(undefined,true));return}t[c](r,n)}),n)}}var h=Object.getPrototypeOf((function(){}));var p=Object.setPrototypeOf((n={get stream(){return this[d]},next:function next(){var e=this;var t=this[s];if(t!==null){return Promise.reject(t)}if(this[u]){return Promise.resolve(createIterResult(undefined,true))}if(this[d].destroyed){return new Promise((function(t,r){process.nextTick((function(){if(e[s]){r(e[s])}else{t(createIterResult(undefined,true))}}))}))}var r=this[l];var n;if(r){n=new Promise(wrapForNext(r,this))}else{var i=this[d].read();if(i!==null){return Promise.resolve(createIterResult(i,false))}n=new Promise(this[c])}this[l]=n;return n}},_defineProperty(n,Symbol.asyncIterator,(function(){return this})),_defineProperty(n,"return",(function _return(){var e=this;return new Promise((function(t,r){e[d].destroy(null,(function(e){if(e){r(e);return}t(createIterResult(undefined,true))}))}))})),n),h);var g=function createReadableStreamAsyncIterator(e){var t;var r=Object.create(p,(t={},_defineProperty(t,d,{value:e,writable:true}),_defineProperty(t,a,{value:null,writable:true}),_defineProperty(t,o,{value:null,writable:true}),_defineProperty(t,s,{value:null,writable:true}),_defineProperty(t,u,{value:e._readableState.endEmitted,writable:true}),_defineProperty(t,c,{value:function value(e,t){var n=r[d].read();if(n){r[l]=null;r[a]=null;r[o]=null;e(createIterResult(n,false))}else{r[a]=e;r[o]=t}},writable:true}),t));r[l]=null;i(e,(function(e){if(e&&e.code!=="ERR_STREAM_PREMATURE_CLOSE"){var t=r[o];if(t!==null){r[l]=null;r[a]=null;r[o]=null;t(e)}r[s]=e;return}var n=r[a];if(n!==null){r[l]=null;r[a]=null;r[o]=null;n(createIterResult(undefined,true))}r[u]=true}));e.on("readable",onReadable.bind(null,r));return r};e.exports=g},2746:(e,t,r)=>{function ownKeys(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);if(t)n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}));r.push.apply(r,n)}return r}function _objectSpread(e){for(var t=1;t0)this.tail.next=t;else this.head=t;this.tail=t;++this.length}},{key:"unshift",value:function unshift(e){var t={data:e,next:this.head};if(this.length===0)this.tail=t;this.head=t;++this.length}},{key:"shift",value:function shift(){if(this.length===0)return;var e=this.head.data;if(this.length===1)this.head=this.tail=null;else this.head=this.head.next;--this.length;return e}},{key:"clear",value:function clear(){this.head=this.tail=null;this.length=0}},{key:"join",value:function join(e){if(this.length===0)return"";var t=this.head;var r=""+t.data;while(t=t.next){r+=e+t.data}return r}},{key:"concat",value:function concat(e){if(this.length===0)return i.alloc(0);var t=i.allocUnsafe(e>>>0);var r=this.head;var n=0;while(r){copyBuffer(r.data,t,n);n+=r.data.length;r=r.next}return t}},{key:"consume",value:function consume(e,t){var r;if(ei.length?i.length:e;if(a===i.length)n+=i;else n+=i.slice(0,e);e-=a;if(e===0){if(a===i.length){++r;if(t.next)this.head=t.next;else this.head=this.tail=null}else{this.head=t;t.data=i.slice(a)}break}++r}this.length-=r;return n}},{key:"_getBuffer",value:function _getBuffer(e){var t=i.allocUnsafe(e);var r=this.head;var n=1;r.data.copy(t);e-=r.data.length;while(r=r.next){var a=r.data;var o=e>a.length?a.length:e;a.copy(t,t.length-e,0,o);e-=o;if(e===0){if(o===a.length){++n;if(r.next)this.head=r.next;else this.head=this.tail=null}else{this.head=r;r.data=a.slice(o)}break}++n}this.length-=n;return t}},{key:s,value:function value(e,t){return o(this,_objectSpread({},t,{depth:0,customInspect:false}))}}]);return BufferList}()},7049:e=>{function destroy(e,t){var r=this;var n=this._readableState&&this._readableState.destroyed;var i=this._writableState&&this._writableState.destroyed;if(n||i){if(t){t(e)}else if(e){if(!this._writableState){process.nextTick(emitErrorNT,this,e)}else if(!this._writableState.errorEmitted){this._writableState.errorEmitted=true;process.nextTick(emitErrorNT,this,e)}}return this}if(this._readableState){this._readableState.destroyed=true}if(this._writableState){this._writableState.destroyed=true}this._destroy(e||null,(function(e){if(!t&&e){if(!r._writableState){process.nextTick(emitErrorAndCloseNT,r,e)}else if(!r._writableState.errorEmitted){r._writableState.errorEmitted=true;process.nextTick(emitErrorAndCloseNT,r,e)}else{process.nextTick(emitCloseNT,r)}}else if(t){process.nextTick(emitCloseNT,r);t(e)}else{process.nextTick(emitCloseNT,r)}}));return this}function emitErrorAndCloseNT(e,t){emitErrorNT(e,t);emitCloseNT(e)}function emitCloseNT(e){if(e._writableState&&!e._writableState.emitClose)return;if(e._readableState&&!e._readableState.emitClose)return;e.emit("close")}function undestroy(){if(this._readableState){this._readableState.destroyed=false;this._readableState.reading=false;this._readableState.ended=false;this._readableState.endEmitted=false}if(this._writableState){this._writableState.destroyed=false;this._writableState.ended=false;this._writableState.ending=false;this._writableState.finalCalled=false;this._writableState.prefinished=false;this._writableState.finished=false;this._writableState.errorEmitted=false}}function emitErrorNT(e,t){e.emit("error",t)}function errorOrDestroy(e,t){var r=e._readableState;var n=e._writableState;if(r&&r.autoDestroy||n&&n.autoDestroy)e.destroy(t);else e.emit("error",t)}e.exports={destroy:destroy,undestroy:undestroy,errorOrDestroy:errorOrDestroy}},6080:(e,t,r)=>{var n=r(7214).q.ERR_STREAM_PREMATURE_CLOSE;function once(e){var t=false;return function(){if(t)return;t=true;for(var r=arguments.length,n=new Array(r),i=0;i{function asyncGeneratorStep(e,t,r,n,i,a,o){try{var s=e[a](o);var u=s.value}catch(e){r(e);return}if(s.done){t(u)}else{Promise.resolve(u).then(n,i)}}function _asyncToGenerator(e){return function(){var t=this,r=arguments;return new Promise((function(n,i){var a=e.apply(t,r);function _next(e){asyncGeneratorStep(a,n,i,_next,_throw,"next",e)}function _throw(e){asyncGeneratorStep(a,n,i,_next,_throw,"throw",e)}_next(undefined)}))}}function ownKeys(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);if(t)n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}));r.push.apply(r,n)}return r}function _objectSpread(e){for(var t=1;t{var n;function once(e){var t=false;return function(){if(t)return;t=true;e.apply(void 0,arguments)}}var i=r(7214).q,a=i.ERR_MISSING_ARGS,o=i.ERR_STREAM_DESTROYED;function noop(e){if(e)throw e}function isRequest(e){return e.setHeader&&typeof e.abort==="function"}function destroyer(e,t,i,a){a=once(a);var s=false;e.on("close",(function(){s=true}));if(n===undefined)n=r(6080);n(e,{readable:t,writable:i},(function(e){if(e)return a(e);s=true;a()}));var u=false;return function(t){if(s)return;if(u)return;u=true;if(isRequest(e))return e.abort();if(typeof e.destroy==="function")return e.destroy();a(t||new o("pipe"))}}function call(e){e()}function pipe(e,t){return e.pipe(t)}function popCallback(e){if(!e.length)return noop;if(typeof e[e.length-1]!=="function")return noop;return e.pop()}function pipeline(){for(var e=arguments.length,t=new Array(e),r=0;r0;return destroyer(e,a,s,(function(e){if(!i)i=e;if(e)o.forEach(call);if(a)return;o.forEach(call);n(i)}))}));return t.reduce(pipe)}e.exports=pipeline},9948:(e,t,r)=>{var n=r(7214).q.ERR_INVALID_OPT_VALUE;function highWaterMarkFrom(e,t,r){return e.highWaterMark!=null?e.highWaterMark:t?e[r]:null}function getHighWaterMark(e,t,r,i){var a=highWaterMarkFrom(t,i,r);if(a!=null){if(!(isFinite(a)&&Math.floor(a)===a)||a<0){var o=i?r:"highWaterMark";throw new n(o,a)}return Math.floor(a)}return e.objectMode?16:16*1024}e.exports={getHighWaterMark:getHighWaterMark}},2387:(e,t,r)=>{e.exports=r(2781)},1642:(e,t,r)=>{var n=r(2781);if(process.env.READABLE_STREAM==="disable"&&n){e.exports=n.Readable;Object.assign(e.exports,n);e.exports.Stream=n}else{t=e.exports=r(1433);t.Stream=n||t;t.Readable=t;t.Writable=r(6993);t.Duplex=r(1359);t.Transform=r(4415);t.PassThrough=r(1542);t.finished=r(6080);t.pipeline=r(6989)}},1867:(e,t,r)=>{ /*! safe-buffer. MIT License. Feross Aboukhadijeh */ -var n=r(4300);var i=n.Buffer;function copyProps(e,t){for(var r in e){t[r]=e[r]}}if(i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow){e.exports=n}else{copyProps(n,t);t.Buffer=SafeBuffer}function SafeBuffer(e,t,r){return i(e,t,r)}SafeBuffer.prototype=Object.create(i.prototype);copyProps(i,SafeBuffer);SafeBuffer.from=function(e,t,r){if(typeof e==="number"){throw new TypeError("Argument must not be a number")}return i(e,t,r)};SafeBuffer.alloc=function(e,t,r){if(typeof e!=="number"){throw new TypeError("Argument must be a number")}var n=i(e);if(t!==undefined){if(typeof r==="string"){n.fill(t,r)}else{n.fill(t)}}else{n.fill(0)}return n};SafeBuffer.allocUnsafe=function(e){if(typeof e!=="number"){throw new TypeError("Argument must be a number")}return i(e)};SafeBuffer.allocUnsafeSlow=function(e){if(typeof e!=="number"){throw new TypeError("Argument must be a number")}return n.SlowBuffer(e)}},1052:(e,t,r)=>{var n=r(4955).Buffer;var i=n.isEncoding||function(e){e=""+e;switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return true;default:return false}};function _normalizeEncoding(e){if(!e)return"utf8";var t;while(true){switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase();t=true}}}function normalizeEncoding(e){var t=_normalizeEncoding(e);if(typeof t!=="string"&&(n.isEncoding===i||!i(e)))throw new Error("Unknown encoding: "+e);return t||e}t.s=StringDecoder;function StringDecoder(e){this.encoding=normalizeEncoding(e);var t;switch(this.encoding){case"utf16le":this.text=utf16Text;this.end=utf16End;t=4;break;case"utf8":this.fillLast=utf8FillLast;t=4;break;case"base64":this.text=base64Text;this.end=base64End;t=3;break;default:this.write=simpleWrite;this.end=simpleEnd;return}this.lastNeed=0;this.lastTotal=0;this.lastChar=n.allocUnsafe(t)}StringDecoder.prototype.write=function(e){if(e.length===0)return"";var t;var r;if(this.lastNeed){t=this.fillLast(e);if(t===undefined)return"";r=this.lastNeed;this.lastNeed=0}else{r=0}if(r>5===6)return 2;else if(e>>4===14)return 3;else if(e>>3===30)return 4;return e>>6===2?-1:-2}function utf8CheckIncomplete(e,t,r){var n=t.length-1;if(n=0){if(i>0)e.lastNeed=i-1;return i}if(--n=0){if(i>0)e.lastNeed=i-2;return i}if(--n=0){if(i>0){if(i===2)i=0;else e.lastNeed=i-3}return i}return 0}function utf8CheckExtraBytes(e,t,r){if((t[0]&192)!==128){e.lastNeed=0;return"�"}if(e.lastNeed>1&&t.length>1){if((t[1]&192)!==128){e.lastNeed=1;return"�"}if(e.lastNeed>2&&t.length>2){if((t[2]&192)!==128){e.lastNeed=2;return"�"}}}}function utf8FillLast(e){var t=this.lastTotal-this.lastNeed;var r=utf8CheckExtraBytes(this,e,t);if(r!==undefined)return r;if(this.lastNeed<=e.length){e.copy(this.lastChar,t,0,this.lastNeed);return this.lastChar.toString(this.encoding,0,this.lastTotal)}e.copy(this.lastChar,t,0,e.length);this.lastNeed-=e.length}function utf8Text(e,t){var r=utf8CheckIncomplete(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=r;var n=e.length-(r-this.lastNeed);e.copy(this.lastChar,0,n);return e.toString("utf8",t,n)}function utf8End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed)return t+"�";return t}function utf16Text(e,t){if((e.length-t)%2===0){var r=e.toString("utf16le",t);if(r){var n=r.charCodeAt(r.length-1);if(n>=55296&&n<=56319){this.lastNeed=2;this.lastTotal=4;this.lastChar[0]=e[e.length-2];this.lastChar[1]=e[e.length-1];return r.slice(0,-1)}}return r}this.lastNeed=1;this.lastTotal=2;this.lastChar[0]=e[e.length-1];return e.toString("utf16le",t,e.length-1)}function utf16End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,r)}return t}function base64Text(e,t){var r=(e.length-t)%3;if(r===0)return e.toString("base64",t);this.lastNeed=3-r;this.lastTotal=3;if(r===1){this.lastChar[0]=e[e.length-1]}else{this.lastChar[0]=e[e.length-2];this.lastChar[1]=e[e.length-1]}return e.toString("base64",t,e.length-r)}function base64End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed)return t+this.lastChar.toString("base64",0,3-this.lastNeed);return t}function simpleWrite(e){return e.toString(this.encoding)}function simpleEnd(e){return e&&e.length?this.write(e):""}},8598:(e,t,r)=>{var n=r(3837);var i=r(2032);var a=r(6392);var o=r(5376).Writable;var s=r(5376).PassThrough;var noop=function(){};var overflow=function(e){e&=511;return e&&512-e};var emptyStream=function(e,t){var r=new Source(e,t);r.end();return r};var mixinPax=function(e,t){if(t.path)e.name=t.path;if(t.linkpath)e.linkname=t.linkpath;if(t.size)e.size=parseInt(t.size,10);e.pax=t;return e};var Source=function(e,t){this._parent=e;this.offset=t;s.call(this,{autoDestroy:false})};n.inherits(Source,s);Source.prototype.destroy=function(e){this._parent.destroy(e)};var Extract=function(e){if(!(this instanceof Extract))return new Extract(e);o.call(this,e);e=e||{};this._offset=0;this._buffer=i();this._missing=0;this._partial=false;this._onparse=noop;this._header=null;this._stream=null;this._overflow=null;this._cb=null;this._locked=false;this._destroyed=false;this._pax=null;this._paxGlobal=null;this._gnuLongPath=null;this._gnuLongLinkPath=null;var t=this;var r=t._buffer;var oncontinue=function(){t._continue()};var onunlock=function(e){t._locked=false;if(e)return t.destroy(e);if(!t._stream)oncontinue()};var onstreamend=function(){t._stream=null;var e=overflow(t._header.size);if(e)t._parse(e,ondrain);else t._parse(512,onheader);if(!t._locked)oncontinue()};var ondrain=function(){t._buffer.consume(overflow(t._header.size));t._parse(512,onheader);oncontinue()};var onpaxglobalheader=function(){var e=t._header.size;t._paxGlobal=a.decodePax(r.slice(0,e));r.consume(e);onstreamend()};var onpaxheader=function(){var e=t._header.size;t._pax=a.decodePax(r.slice(0,e));if(t._paxGlobal)t._pax=Object.assign({},t._paxGlobal,t._pax);r.consume(e);onstreamend()};var ongnulongpath=function(){var n=t._header.size;this._gnuLongPath=a.decodeLongPath(r.slice(0,n),e.filenameEncoding);r.consume(n);onstreamend()};var ongnulonglinkpath=function(){var n=t._header.size;this._gnuLongLinkPath=a.decodeLongPath(r.slice(0,n),e.filenameEncoding);r.consume(n);onstreamend()};var onheader=function(){var n=t._offset;var i;try{i=t._header=a.decode(r.slice(0,512),e.filenameEncoding,e.allowUnknownFormat)}catch(e){t.emit("error",e)}r.consume(512);if(!i){t._parse(512,onheader);oncontinue();return}if(i.type==="gnu-long-path"){t._parse(i.size,ongnulongpath);oncontinue();return}if(i.type==="gnu-long-link-path"){t._parse(i.size,ongnulonglinkpath);oncontinue();return}if(i.type==="pax-global-header"){t._parse(i.size,onpaxglobalheader);oncontinue();return}if(i.type==="pax-header"){t._parse(i.size,onpaxheader);oncontinue();return}if(t._gnuLongPath){i.name=t._gnuLongPath;t._gnuLongPath=null}if(t._gnuLongLinkPath){i.linkname=t._gnuLongLinkPath;t._gnuLongLinkPath=null}if(t._pax){t._header=i=mixinPax(i,t._pax);t._pax=null}t._locked=true;if(!i.size||i.type==="directory"){t._parse(512,onheader);t.emit("entry",i,emptyStream(t,n),onunlock);return}t._stream=new Source(t,n);t.emit("entry",i,t._stream,onunlock);t._parse(i.size,onstreamend);oncontinue()};this._onheader=onheader;this._parse(512,onheader)};n.inherits(Extract,o);Extract.prototype.destroy=function(e){if(this._destroyed)return;this._destroyed=true;if(e)this.emit("error",e);this.emit("close");if(this._stream)this._stream.emit("close")};Extract.prototype._parse=function(e,t){if(this._destroyed)return;this._offset+=e;this._missing=e;if(t===this._onheader)this._partial=false;this._onparse=t};Extract.prototype._continue=function(){if(this._destroyed)return;var e=this._cb;this._cb=noop;if(this._overflow)this._write(this._overflow,undefined,e);else e()};Extract.prototype._write=function(e,t,r){if(this._destroyed)return;var n=this._stream;var i=this._buffer;var a=this._missing;if(e.length)this._partial=true;if(e.lengtha){o=e.slice(a);e=e.slice(0,a)}if(n)n.end(e);else i.append(e);this._overflow=o;this._onparse()};Extract.prototype._final=function(e){if(this._partial)return this.destroy(new Error("Unexpected end of data"));e()};e.exports=Extract},6392:(e,t)=>{var r=Buffer.alloc;var n="0000000000000000000";var i="7777777777777777777";var a="0".charCodeAt(0);var o=Buffer.from("ustar\0","binary");var s=Buffer.from("00","binary");var u=Buffer.from("ustar ","binary");var l=Buffer.from(" \0","binary");var c=parseInt("7777",8);var d=257;var h=263;var clamp=function(e,t,r){if(typeof e!=="number")return r;e=~~e;if(e>=t)return t;if(e>=0)return e;e+=t;if(e>=0)return e;return 0};var toType=function(e){switch(e){case 0:return"file";case 1:return"link";case 2:return"symlink";case 3:return"character-device";case 4:return"block-device";case 5:return"directory";case 6:return"fifo";case 7:return"contiguous-file";case 72:return"pax-header";case 55:return"pax-global-header";case 27:return"gnu-long-link-path";case 28:case 30:return"gnu-long-path"}return null};var toTypeflag=function(e){switch(e){case"file":return 0;case"link":return 1;case"symlink":return 2;case"character-device":return 3;case"block-device":return 4;case"directory":return 5;case"fifo":return 6;case"contiguous-file":return 7;case"pax-header":return 72}return 0};var indexOf=function(e,t,r,n){for(;rt)return i.slice(0,t)+" ";else return n.slice(0,t-e.length)+e+" "};function parse256(e){var t;if(e[0]===128)t=true;else if(e[0]===255)t=false;else return null;var r=[];for(var n=e.length-1;n>0;n--){var i=e[n];if(t)r.push(i);else r.push(255-i)}var a=0;var o=r.length;for(n=0;n=Math.pow(10,r))r++;return t+r+e};t.decodeLongPath=function(e,t){return decodeStr(e,0,e.length,t)};t.encodePax=function(e){var t="";if(e.name)t+=addLength(" path="+e.name+"\n");if(e.linkname)t+=addLength(" linkpath="+e.linkname+"\n");var r=e.pax;if(r){for(var n in r){t+=addLength(" "+n+"="+r[n]+"\n")}}return Buffer.from(t)};t.decodePax=function(e){var t={};while(e.length){var r=0;while(r100){var u=n.indexOf("/");if(u===-1)return null;i+=i?"/"+n.slice(0,u):n.slice(0,u);n=n.slice(u+1)}if(Buffer.byteLength(n)>100||Buffer.byteLength(i)>155)return null;if(e.linkname&&Buffer.byteLength(e.linkname)>100)return null;t.write(n);t.write(encodeOct(e.mode&c,6),100);t.write(encodeOct(e.uid,6),108);t.write(encodeOct(e.gid,6),116);t.write(encodeOct(e.size,11),124);t.write(encodeOct(e.mtime.getTime()/1e3|0,11),136);t[156]=a+toTypeflag(e.type);if(e.linkname)t.write(e.linkname,157);o.copy(t,d);s.copy(t,h);if(e.uname)t.write(e.uname,265);if(e.gname)t.write(e.gname,297);t.write(encodeOct(e.devmajor||0,6),329);t.write(encodeOct(e.devminor||0,6),337);if(i)t.write(i,345);t.write(encodeOct(cksum(t),6),148);return t};t.decode=function(e,t,r){var n=e[156]===0?0:e[156]-a;var i=decodeStr(e,0,100,t);var s=decodeOct(e,100,8);var c=decodeOct(e,108,8);var p=decodeOct(e,116,8);var g=decodeOct(e,124,12);var m=decodeOct(e,136,12);var b=toType(n);var v=e[157]===0?null:decodeStr(e,157,100,t);var _=decodeStr(e,265,32);var y=decodeStr(e,297,32);var w=decodeOct(e,329,8);var R=decodeOct(e,337,8);var S=cksum(e);if(S===8*32)return null;if(S!==decodeOct(e,148,8))throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");if(o.compare(e,d,d+6)===0){if(e[345])i=decodeStr(e,345,155,t)+"/"+i}else if(u.compare(e,d,d+6)===0&&l.compare(e,h,h+2)===0){}else{if(!r){throw new Error("Invalid tar header: unknown format.")}}if(n===0&&i&&i[i.length-1]==="/")n=5;return{name:i,mode:s,uid:c,gid:p,size:g,mtime:new Date(1e3*m),type:b,linkname:v,uname:_,gname:y,devmajor:w,devminor:R}}},438:(e,t,r)=>{t.extract=r(8598);t.pack=r(2867)},2867:(e,t,r)=>{var n=r(2187);var i=r(7137);var a=r(3740);var o=Buffer.alloc;var s=r(5376).Readable;var u=r(5376).Writable;var l=r(1576).StringDecoder;var c=r(6392);var d=parseInt("755",8);var h=parseInt("644",8);var p=o(1024);var noop=function(){};var overflow=function(e,t){t&=511;if(t)e.push(p.slice(0,512-t))};function modeToType(e){switch(e&n.S_IFMT){case n.S_IFBLK:return"block-device";case n.S_IFCHR:return"character-device";case n.S_IFDIR:return"directory";case n.S_IFIFO:return"fifo";case n.S_IFLNK:return"symlink"}return"file"}var Sink=function(e){u.call(this);this.written=0;this._to=e;this._destroyed=false};a(Sink,u);Sink.prototype._write=function(e,t,r){this.written+=e.length;if(this._to.push(e))return r();this._to._drain=r};Sink.prototype.destroy=function(){if(this._destroyed)return;this._destroyed=true;this.emit("close")};var LinkSink=function(){u.call(this);this.linkname="";this._decoder=new l("utf-8");this._destroyed=false};a(LinkSink,u);LinkSink.prototype._write=function(e,t,r){this.linkname+=this._decoder.write(e);r()};LinkSink.prototype.destroy=function(){if(this._destroyed)return;this._destroyed=true;this.emit("close")};var Void=function(){u.call(this);this._destroyed=false};a(Void,u);Void.prototype._write=function(e,t,r){r(new Error("No body allowed for this entry"))};Void.prototype.destroy=function(){if(this._destroyed)return;this._destroyed=true;this.emit("close")};var Pack=function(e){if(!(this instanceof Pack))return new Pack(e);s.call(this,e);this._drain=noop;this._finalized=false;this._finalizing=false;this._destroyed=false;this._stream=null};a(Pack,s);Pack.prototype.entry=function(e,t,r){if(this._stream)throw new Error("already piping an entry");if(this._finalized||this._destroyed)return;if(typeof t==="function"){r=t;t=null}if(!r)r=noop;var n=this;if(!e.size||e.type==="symlink")e.size=0;if(!e.type)e.type=modeToType(e.mode);if(!e.mode)e.mode=e.type==="directory"?d:h;if(!e.uid)e.uid=0;if(!e.gid)e.gid=0;if(!e.mtime)e.mtime=new Date;if(typeof t==="string")t=Buffer.from(t);if(Buffer.isBuffer(t)){e.size=t.length;this._encode(e);var a=this.push(t);overflow(n,e.size);if(a)process.nextTick(r);else this._drain=r;return new Void}if(e.type==="symlink"&&!e.linkname){var o=new LinkSink;i(o,(function(t){if(t){n.destroy();return r(t)}e.linkname=o.linkname;n._encode(e);r()}));return o}this._encode(e);if(e.type!=="file"&&e.type!=="contiguous-file"){process.nextTick(r);return new Void}var s=new Sink(this);this._stream=s;i(s,(function(t){n._stream=null;if(t){n.destroy();return r(t)}if(s.written!==e.size){n.destroy();return r(new Error("size mismatch"))}overflow(n,e.size);if(n._finalizing)n.finalize();r()}));return s};Pack.prototype.finalize=function(){if(this._stream){this._finalizing=true;return}if(this._finalized)return;this._finalized=true;this.push(p);this.push(null)};Pack.prototype.destroy=function(e){if(this._destroyed)return;this._destroyed=true;if(e)this.emit("error",e);this.emit("close");if(this._stream&&this._stream.destroy)this._stream.destroy()};Pack.prototype._encode=function(e){if(!e.pax){var t=c.encode(e);if(t){this.push(t);return}}this._encodePax(e)};Pack.prototype._encodePax=function(e){var t=c.encodePax({name:e.name,linkname:e.linkname,pax:e.pax});var r={name:"PaxHeader",mode:e.mode,uid:e.uid,gid:e.gid,size:t.length,mtime:e.mtime,type:"pax-header",linkname:e.linkname&&"PaxHeader",uname:e.uname,gname:e.gname,devmajor:e.devmajor,devminor:e.devminor};this.push(c.encode(r));this.push(t);overflow(this,t.length);r.size=e.size;r.type=e.type;this.push(c.encode(r))};Pack.prototype._read=function(e){var t=this._drain;this._drain=noop;t()};e.exports=Pack},1270:(e,t,r)=>{e.exports=r(4218)},4218:(e,t,r)=>{var n=r(1808);var i=r(4404);var a=r(3685);var o=r(5687);var s=r(2361);var u=r(9491);var l=r(3837);t.httpOverHttp=httpOverHttp;t.httpsOverHttp=httpsOverHttp;t.httpOverHttps=httpOverHttps;t.httpsOverHttps=httpsOverHttps;function httpOverHttp(e){var t=new TunnelingAgent(e);t.request=a.request;return t}function httpsOverHttp(e){var t=new TunnelingAgent(e);t.request=a.request;t.createSocket=createSecureSocket;t.defaultPort=443;return t}function httpOverHttps(e){var t=new TunnelingAgent(e);t.request=o.request;return t}function httpsOverHttps(e){var t=new TunnelingAgent(e);t.request=o.request;t.createSocket=createSecureSocket;t.defaultPort=443;return t}function TunnelingAgent(e){var t=this;t.options=e||{};t.proxyOptions=t.options.proxy||{};t.maxSockets=t.options.maxSockets||a.Agent.defaultMaxSockets;t.requests=[];t.sockets=[];t.on("free",(function onFree(e,r,n,i){var a=toOptions(r,n,i);for(var o=0,s=t.requests.length;o=this.maxSockets){i.requests.push(a);return}i.createSocket(a,(function(t){t.on("free",onFree);t.on("close",onCloseOrRemove);t.on("agentRemove",onCloseOrRemove);e.onSocket(t);function onFree(){i.emit("free",t,a)}function onCloseOrRemove(e){i.removeSocket(t);t.removeListener("free",onFree);t.removeListener("close",onCloseOrRemove);t.removeListener("agentRemove",onCloseOrRemove)}}))};TunnelingAgent.prototype.createSocket=function createSocket(e,t){var r=this;var n={};r.sockets.push(n);var i=mergeOptions({},r.proxyOptions,{method:"CONNECT",path:e.host+":"+e.port,agent:false,headers:{host:e.host+":"+e.port}});if(e.localAddress){i.localAddress=e.localAddress}if(i.proxyAuth){i.headers=i.headers||{};i.headers["Proxy-Authorization"]="Basic "+new Buffer(i.proxyAuth).toString("base64")}c("making CONNECT request");var a=r.request(i);a.useChunkedEncodingByDefault=false;a.once("response",onResponse);a.once("upgrade",onUpgrade);a.once("connect",onConnect);a.once("error",onError);a.end();function onResponse(e){e.upgrade=true}function onUpgrade(e,t,r){process.nextTick((function(){onConnect(e,t,r)}))}function onConnect(i,o,s){a.removeAllListeners();o.removeAllListeners();if(i.statusCode!==200){c("tunneling socket could not be established, statusCode=%d",i.statusCode);o.destroy();var u=new Error("tunneling socket could not be established, "+"statusCode="+i.statusCode);u.code="ECONNRESET";e.request.emit("error",u);r.removeSocket(n);return}if(s.length>0){c("got illegal response body from proxy");o.destroy();var u=new Error("got illegal response body from proxy");u.code="ECONNRESET";e.request.emit("error",u);r.removeSocket(n);return}c("tunneling connection has established");r.sockets[r.sockets.indexOf(n)]=o;return t(o)}function onError(t){a.removeAllListeners();c("tunneling socket could not be established, cause=%s\n",t.message,t.stack);var i=new Error("tunneling socket could not be established, "+"cause="+t.message);i.code="ECONNRESET";e.request.emit("error",i);r.removeSocket(n)}};TunnelingAgent.prototype.removeSocket=function removeSocket(e){var t=this.sockets.indexOf(e);if(t===-1){return}this.sockets.splice(t,1);var r=this.requests.shift();if(r){this.createSocket(r,(function(e){r.request.onSocket(e)}))}};function createSecureSocket(e,t){var r=this;TunnelingAgent.prototype.createSocket.call(r,e,(function(n){var a=e.request.getHeader("host");var o=mergeOptions({},r.options,{socket:n,servername:a?a.replace(/:.*$/,""):e.host});var s=i.connect(0,o);r.sockets[r.sockets.indexOf(n)]=s;t(s)}))}function toOptions(e,t,r){if(typeof e==="string"){return{host:e,port:t,localAddress:r}}return e}function mergeOptions(e){for(var t=1,r=arguments.length;t{e.exports=r(3837).deprecate},6470:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});Object.defineProperty(t,"v1",{enumerable:true,get:function(){return n.default}});Object.defineProperty(t,"v3",{enumerable:true,get:function(){return i.default}});Object.defineProperty(t,"v4",{enumerable:true,get:function(){return a.default}});Object.defineProperty(t,"v5",{enumerable:true,get:function(){return o.default}});Object.defineProperty(t,"NIL",{enumerable:true,get:function(){return s.default}});Object.defineProperty(t,"version",{enumerable:true,get:function(){return u.default}});Object.defineProperty(t,"validate",{enumerable:true,get:function(){return l.default}});Object.defineProperty(t,"stringify",{enumerable:true,get:function(){return c.default}});Object.defineProperty(t,"parse",{enumerable:true,get:function(){return d.default}});var n=_interopRequireDefault(r(6074));var i=_interopRequireDefault(r(4239));var a=_interopRequireDefault(r(6686));var o=_interopRequireDefault(r(4352));var s=_interopRequireDefault(r(7800));var u=_interopRequireDefault(r(7066));var l=_interopRequireDefault(r(8701));var c=_interopRequireDefault(r(4976));var d=_interopRequireDefault(r(6305));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}},2539:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function md5(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return n.default.createHash("md5").update(e).digest()}var i=md5;t["default"]=i},7800:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var r="00000000-0000-0000-0000-000000000000";t["default"]=r},6305:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(8701));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function parse(e){if(!(0,n.default)(e)){throw TypeError("Invalid UUID")}let t;const r=new Uint8Array(16);r[0]=(t=parseInt(e.slice(0,8),16))>>>24;r[1]=t>>>16&255;r[2]=t>>>8&255;r[3]=t&255;r[4]=(t=parseInt(e.slice(9,13),16))>>>8;r[5]=t&255;r[6]=(t=parseInt(e.slice(14,18),16))>>>8;r[7]=t&255;r[8]=(t=parseInt(e.slice(19,23),16))>>>8;r[9]=t&255;r[10]=(t=parseInt(e.slice(24,36),16))/1099511627776&255;r[11]=t/4294967296&255;r[12]=t>>>24&255;r[13]=t>>>16&255;r[14]=t>>>8&255;r[15]=t&255;return r}var i=parse;t["default"]=i},4464:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var r=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;t["default"]=r},716:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=rng;var n=_interopRequireDefault(r(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const i=new Uint8Array(256);let a=i.length;function rng(){if(a>i.length-16){n.default.randomFillSync(i);a=0}return i.slice(a,a+=16)}},4157:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function sha1(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return n.default.createHash("sha1").update(e).digest()}var i=sha1;t["default"]=i},4976:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(8701));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const i=[];for(let e=0;e<256;++e){i.push((e+256).toString(16).substr(1))}function stringify(e,t=0){const r=(i[e[t+0]]+i[e[t+1]]+i[e[t+2]]+i[e[t+3]]+"-"+i[e[t+4]]+i[e[t+5]]+"-"+i[e[t+6]]+i[e[t+7]]+"-"+i[e[t+8]]+i[e[t+9]]+"-"+i[e[t+10]]+i[e[t+11]]+i[e[t+12]]+i[e[t+13]]+i[e[t+14]]+i[e[t+15]]).toLowerCase();if(!(0,n.default)(r)){throw TypeError("Stringified UUID is invalid")}return r}var a=stringify;t["default"]=a},6074:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(716));var i=_interopRequireDefault(r(4976));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}let a;let o;let s=0;let u=0;function v1(e,t,r){let l=t&&r||0;const c=t||new Array(16);e=e||{};let d=e.node||a;let h=e.clockseq!==undefined?e.clockseq:o;if(d==null||h==null){const t=e.random||(e.rng||n.default)();if(d==null){d=a=[t[0]|1,t[1],t[2],t[3],t[4],t[5]]}if(h==null){h=o=(t[6]<<8|t[7])&16383}}let p=e.msecs!==undefined?e.msecs:Date.now();let g=e.nsecs!==undefined?e.nsecs:u+1;const m=p-s+(g-u)/1e4;if(m<0&&e.clockseq===undefined){h=h+1&16383}if((m<0||p>s)&&e.nsecs===undefined){g=0}if(g>=1e4){throw new Error("uuid.v1(): Can't create more than 10M uuids/sec")}s=p;u=g;o=h;p+=122192928e5;const b=((p&268435455)*1e4+g)%4294967296;c[l++]=b>>>24&255;c[l++]=b>>>16&255;c[l++]=b>>>8&255;c[l++]=b&255;const v=p/4294967296*1e4&268435455;c[l++]=v>>>8&255;c[l++]=v&255;c[l++]=v>>>24&15|16;c[l++]=v>>>16&255;c[l++]=h>>>8|128;c[l++]=h&255;for(let e=0;e<6;++e){c[l+e]=d[e]}return t||(0,i.default)(c)}var l=v1;t["default"]=l},4239:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(2060));var i=_interopRequireDefault(r(2539));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const a=(0,n.default)("v3",48,i.default);var o=a;t["default"]=o},2060:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=_default;t.URL=t.DNS=void 0;var n=_interopRequireDefault(r(4976));var i=_interopRequireDefault(r(6305));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function stringToBytes(e){e=unescape(encodeURIComponent(e));const t=[];for(let r=0;r{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(716));var i=_interopRequireDefault(r(4976));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function v4(e,t,r){e=e||{};const a=e.random||(e.rng||n.default)();a[6]=a[6]&15|64;a[8]=a[8]&63|128;if(t){r=r||0;for(let e=0;e<16;++e){t[r+e]=a[e]}return t}return(0,i.default)(a)}var a=v4;t["default"]=a},4352:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(2060));var i=_interopRequireDefault(r(4157));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const a=(0,n.default)("v5",80,i.default);var o=a;t["default"]=o},8701:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(4464));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function validate(e){return typeof e==="string"&&n.default.test(e)}var i=validate;t["default"]=i},7066:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(8701));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function version(e){if(!(0,n.default)(e)){throw TypeError("Invalid UUID")}return parseInt(e.substr(14,1),16)}var i=version;t["default"]=i},3799:e=>{e.exports=wrappy;function wrappy(e,t){if(e&&t)return wrappy(e)(t);if(typeof e!=="function")throw new TypeError("need wrapper function");Object.keys(e).forEach((function(t){wrapper[t]=e[t]}));return wrapper;function wrapper(){var t=new Array(arguments.length);for(var r=0;r{t.exports=e(import.meta.url)("assert")},4300:t=>{t.exports=e(import.meta.url)("buffer")},2057:t=>{t.exports=e(import.meta.url)("constants")},6113:t=>{t.exports=e(import.meta.url)("crypto")},2361:t=>{t.exports=e(import.meta.url)("events")},7147:t=>{t.exports=e(import.meta.url)("fs")},3685:t=>{t.exports=e(import.meta.url)("http")},5687:t=>{t.exports=e(import.meta.url)("https")},1808:t=>{t.exports=e(import.meta.url)("net")},7718:t=>{t.exports=e(import.meta.url)("node:child_process")},7561:t=>{t.exports=e(import.meta.url)("node:fs")},7742:t=>{t.exports=e(import.meta.url)("node:process")},4492:t=>{t.exports=e(import.meta.url)("node:stream")},5628:t=>{t.exports=e(import.meta.url)("node:zlib")},2037:t=>{t.exports=e(import.meta.url)("os")},1017:t=>{t.exports=e(import.meta.url)("path")},2781:t=>{t.exports=e(import.meta.url)("stream")},1576:t=>{t.exports=e(import.meta.url)("string_decoder")},4404:t=>{t.exports=e(import.meta.url)("tls")},3837:t=>{t.exports=e(import.meta.url)("util")},2889:(e,t,r)=>{r.a(e,(async e=>{var t=r(7718);var n=r(7742);var i=r(4492);var a=r(7561);var o=r(5628);var s=r(438);var u=r(9362);const l=u.getInput("container",{required:true});const c=JSON.parse(u.getInput("error-log-paths",{required:true}));const d=u.getInput("log-tarball-prefix",{required:true});const h=JSON.parse(u.getInput("tests",{required:true}));try{if(t.spawnSync("docker",["run","--name","base","-v",`${n.cwd()}/build.tar.zst:/build.tar.zst`,"--workdir","/__w/leap/leap",l,"tar","--zstd","-xf","/build.tar.zst"],{stdio:"inherit"}).status)throw new Error("Failed to create base container");if(t.spawnSync("docker",["commit","base","baseimage"],{stdio:"inherit"}).status)throw new Error("Failed to create base image");if(t.spawnSync("docker",["rm","base"],{stdio:"inherit"}).status)throw new Error("Failed to remove base container");let e=[];h.forEach((r=>{e.push(new Promise((e=>{t.spawn("docker",["run","--name",r,"--init","baseimage","bash","-c",`cd build; ctest --output-on-failure -R '^${r}$'`],{stdio:"inherit"}).on("close",(t=>e(t)))})))}));const r=await Promise.all(e);for(let e=0;e{if(!e.name.startsWith(`__w/leap/leap/build`)){t.on("end",(()=>r()));t.resume();return}e.name=e.name.substring(`__w/leap/leap/`.length);if(e.name!=="build/"&&c.filter((t=>e.name.startsWith(t))).length===0){t.on("end",(()=>r()));t.resume();return}t.pipe(l.entry(e,r))})).on("finish",(()=>{l.finalize()}));t.spawn("docker",["export",h[e]]).stdout.pipe(n);i.promises.pipeline(l,o.createGzip(),a.createWriteStream(`${d}-${h[e]}-logs.tar.gz`))}}catch(e){u.setFailed(`Uncaught exception ${e.message}`)}e()}),1)}};var r={};function __nccwpck_require__(e){var n=r[e];if(n!==undefined){return n.exports}var i=r[e]={exports:{}};var a=true;try{t[e].call(i.exports,i,i.exports,__nccwpck_require__);a=false}finally{if(a)delete r[e]}return i.exports}(()=>{var e=typeof Symbol==="function"?Symbol("webpack then"):"__webpack_then__";var t=typeof Symbol==="function"?Symbol("webpack exports"):"__webpack_exports__";var completeQueue=e=>{if(e){e.forEach((e=>e.r--));e.forEach((e=>e.r--?e.r++:e()))}};var completeFunction=e=>!--e.r&&e();var queueFunction=(e,t)=>e?e.push(t):completeFunction(t);var wrapDeps=r=>r.map((r=>{if(r!==null&&typeof r==="object"){if(r[e])return r;if(r.then){var n=[];r.then((e=>{i[t]=e;completeQueue(n);n=0}));var i={};i[e]=(e,t)=>(queueFunction(n,e),r["catch"](t));return i}}var a={};a[e]=e=>completeFunction(e);a[t]=r;return a}));__nccwpck_require__.a=(r,n,i)=>{var a=i&&[];var o=r.exports;var s;var u;var l;var c=true;var d=false;var whenAll=(t,r,n)=>{if(d)return;d=true;r.r+=t.length;t.map(((t,i)=>t[e](r,n)));d=false};var h=new Promise(((e,t)=>{l=t;u=()=>(e(o),completeQueue(a),a=0)}));h[t]=o;h[e]=(e,t)=>{if(c){return completeFunction(e)}if(s)whenAll(s,e,t);queueFunction(a,e);h["catch"](t)};r.exports=h;n((e=>{if(!e)return u();s=wrapDeps(e);var r,n;var i=new Promise(((e,i)=>{r=()=>e(n=s.map((e=>e[t])));r.r=0;whenAll(s,r,i)}));return r.r?i:n})).then(u,l);c=false}})();if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=new URL(".",import.meta.url).pathname.slice(import.meta.url.match(/^file:\/\/\/\w:/)?1:0,-1)+"/";var n=__nccwpck_require__(2889);n=await n; \ No newline at end of file +var n=r(4300);var i=n.Buffer;function copyProps(e,t){for(var r in e){t[r]=e[r]}}if(i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow){e.exports=n}else{copyProps(n,t);t.Buffer=SafeBuffer}function SafeBuffer(e,t,r){return i(e,t,r)}SafeBuffer.prototype=Object.create(i.prototype);copyProps(i,SafeBuffer);SafeBuffer.from=function(e,t,r){if(typeof e==="number"){throw new TypeError("Argument must not be a number")}return i(e,t,r)};SafeBuffer.alloc=function(e,t,r){if(typeof e!=="number"){throw new TypeError("Argument must be a number")}var n=i(e);if(t!==undefined){if(typeof r==="string"){n.fill(t,r)}else{n.fill(t)}}else{n.fill(0)}return n};SafeBuffer.allocUnsafe=function(e){if(typeof e!=="number"){throw new TypeError("Argument must be a number")}return i(e)};SafeBuffer.allocUnsafeSlow=function(e){if(typeof e!=="number"){throw new TypeError("Argument must be a number")}return n.SlowBuffer(e)}},4841:(e,t,r)=>{var n=r(1867).Buffer;var i=n.isEncoding||function(e){e=""+e;switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return true;default:return false}};function _normalizeEncoding(e){if(!e)return"utf8";var t;while(true){switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase();t=true}}}function normalizeEncoding(e){var t=_normalizeEncoding(e);if(typeof t!=="string"&&(n.isEncoding===i||!i(e)))throw new Error("Unknown encoding: "+e);return t||e}t.s=StringDecoder;function StringDecoder(e){this.encoding=normalizeEncoding(e);var t;switch(this.encoding){case"utf16le":this.text=utf16Text;this.end=utf16End;t=4;break;case"utf8":this.fillLast=utf8FillLast;t=4;break;case"base64":this.text=base64Text;this.end=base64End;t=3;break;default:this.write=simpleWrite;this.end=simpleEnd;return}this.lastNeed=0;this.lastTotal=0;this.lastChar=n.allocUnsafe(t)}StringDecoder.prototype.write=function(e){if(e.length===0)return"";var t;var r;if(this.lastNeed){t=this.fillLast(e);if(t===undefined)return"";r=this.lastNeed;this.lastNeed=0}else{r=0}if(r>5===6)return 2;else if(e>>4===14)return 3;else if(e>>3===30)return 4;return e>>6===2?-1:-2}function utf8CheckIncomplete(e,t,r){var n=t.length-1;if(n=0){if(i>0)e.lastNeed=i-1;return i}if(--n=0){if(i>0)e.lastNeed=i-2;return i}if(--n=0){if(i>0){if(i===2)i=0;else e.lastNeed=i-3}return i}return 0}function utf8CheckExtraBytes(e,t,r){if((t[0]&192)!==128){e.lastNeed=0;return"�"}if(e.lastNeed>1&&t.length>1){if((t[1]&192)!==128){e.lastNeed=1;return"�"}if(e.lastNeed>2&&t.length>2){if((t[2]&192)!==128){e.lastNeed=2;return"�"}}}}function utf8FillLast(e){var t=this.lastTotal-this.lastNeed;var r=utf8CheckExtraBytes(this,e,t);if(r!==undefined)return r;if(this.lastNeed<=e.length){e.copy(this.lastChar,t,0,this.lastNeed);return this.lastChar.toString(this.encoding,0,this.lastTotal)}e.copy(this.lastChar,t,0,e.length);this.lastNeed-=e.length}function utf8Text(e,t){var r=utf8CheckIncomplete(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=r;var n=e.length-(r-this.lastNeed);e.copy(this.lastChar,0,n);return e.toString("utf8",t,n)}function utf8End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed)return t+"�";return t}function utf16Text(e,t){if((e.length-t)%2===0){var r=e.toString("utf16le",t);if(r){var n=r.charCodeAt(r.length-1);if(n>=55296&&n<=56319){this.lastNeed=2;this.lastTotal=4;this.lastChar[0]=e[e.length-2];this.lastChar[1]=e[e.length-1];return r.slice(0,-1)}}return r}this.lastNeed=1;this.lastTotal=2;this.lastChar[0]=e[e.length-1];return e.toString("utf16le",t,e.length-1)}function utf16End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,r)}return t}function base64Text(e,t){var r=(e.length-t)%3;if(r===0)return e.toString("base64",t);this.lastNeed=3-r;this.lastTotal=3;if(r===1){this.lastChar[0]=e[e.length-1]}else{this.lastChar[0]=e[e.length-2];this.lastChar[1]=e[e.length-1]}return e.toString("base64",t,e.length-r)}function base64End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed)return t+this.lastChar.toString("base64",0,3-this.lastNeed);return t}function simpleWrite(e){return e.toString(this.encoding)}function simpleEnd(e){return e&&e.length?this.write(e):""}},7882:(e,t,r)=>{var n=r(3837);var i=r(336);var a=r(8860);var o=r(1642).Writable;var s=r(1642).PassThrough;var noop=function(){};var overflow=function(e){e&=511;return e&&512-e};var emptyStream=function(e,t){var r=new Source(e,t);r.end();return r};var mixinPax=function(e,t){if(t.path)e.name=t.path;if(t.linkpath)e.linkname=t.linkpath;if(t.size)e.size=parseInt(t.size,10);e.pax=t;return e};var Source=function(e,t){this._parent=e;this.offset=t;s.call(this,{autoDestroy:false})};n.inherits(Source,s);Source.prototype.destroy=function(e){this._parent.destroy(e)};var Extract=function(e){if(!(this instanceof Extract))return new Extract(e);o.call(this,e);e=e||{};this._offset=0;this._buffer=i();this._missing=0;this._partial=false;this._onparse=noop;this._header=null;this._stream=null;this._overflow=null;this._cb=null;this._locked=false;this._destroyed=false;this._pax=null;this._paxGlobal=null;this._gnuLongPath=null;this._gnuLongLinkPath=null;var t=this;var r=t._buffer;var oncontinue=function(){t._continue()};var onunlock=function(e){t._locked=false;if(e)return t.destroy(e);if(!t._stream)oncontinue()};var onstreamend=function(){t._stream=null;var e=overflow(t._header.size);if(e)t._parse(e,ondrain);else t._parse(512,onheader);if(!t._locked)oncontinue()};var ondrain=function(){t._buffer.consume(overflow(t._header.size));t._parse(512,onheader);oncontinue()};var onpaxglobalheader=function(){var e=t._header.size;t._paxGlobal=a.decodePax(r.slice(0,e));r.consume(e);onstreamend()};var onpaxheader=function(){var e=t._header.size;t._pax=a.decodePax(r.slice(0,e));if(t._paxGlobal)t._pax=Object.assign({},t._paxGlobal,t._pax);r.consume(e);onstreamend()};var ongnulongpath=function(){var n=t._header.size;this._gnuLongPath=a.decodeLongPath(r.slice(0,n),e.filenameEncoding);r.consume(n);onstreamend()};var ongnulonglinkpath=function(){var n=t._header.size;this._gnuLongLinkPath=a.decodeLongPath(r.slice(0,n),e.filenameEncoding);r.consume(n);onstreamend()};var onheader=function(){var n=t._offset;var i;try{i=t._header=a.decode(r.slice(0,512),e.filenameEncoding,e.allowUnknownFormat)}catch(e){t.emit("error",e)}r.consume(512);if(!i){t._parse(512,onheader);oncontinue();return}if(i.type==="gnu-long-path"){t._parse(i.size,ongnulongpath);oncontinue();return}if(i.type==="gnu-long-link-path"){t._parse(i.size,ongnulonglinkpath);oncontinue();return}if(i.type==="pax-global-header"){t._parse(i.size,onpaxglobalheader);oncontinue();return}if(i.type==="pax-header"){t._parse(i.size,onpaxheader);oncontinue();return}if(t._gnuLongPath){i.name=t._gnuLongPath;t._gnuLongPath=null}if(t._gnuLongLinkPath){i.linkname=t._gnuLongLinkPath;t._gnuLongLinkPath=null}if(t._pax){t._header=i=mixinPax(i,t._pax);t._pax=null}t._locked=true;if(!i.size||i.type==="directory"){t._parse(512,onheader);t.emit("entry",i,emptyStream(t,n),onunlock);return}t._stream=new Source(t,n);t.emit("entry",i,t._stream,onunlock);t._parse(i.size,onstreamend);oncontinue()};this._onheader=onheader;this._parse(512,onheader)};n.inherits(Extract,o);Extract.prototype.destroy=function(e){if(this._destroyed)return;this._destroyed=true;if(e)this.emit("error",e);this.emit("close");if(this._stream)this._stream.emit("close")};Extract.prototype._parse=function(e,t){if(this._destroyed)return;this._offset+=e;this._missing=e;if(t===this._onheader)this._partial=false;this._onparse=t};Extract.prototype._continue=function(){if(this._destroyed)return;var e=this._cb;this._cb=noop;if(this._overflow)this._write(this._overflow,undefined,e);else e()};Extract.prototype._write=function(e,t,r){if(this._destroyed)return;var n=this._stream;var i=this._buffer;var a=this._missing;if(e.length)this._partial=true;if(e.lengtha){o=e.slice(a);e=e.slice(0,a)}if(n)n.end(e);else i.append(e);this._overflow=o;this._onparse()};Extract.prototype._final=function(e){if(this._partial)return this.destroy(new Error("Unexpected end of data"));e()};e.exports=Extract},8860:(e,t)=>{var r=Buffer.alloc;var n="0000000000000000000";var i="7777777777777777777";var a="0".charCodeAt(0);var o=Buffer.from("ustar\0","binary");var s=Buffer.from("00","binary");var u=Buffer.from("ustar ","binary");var l=Buffer.from(" \0","binary");var c=parseInt("7777",8);var d=257;var h=263;var clamp=function(e,t,r){if(typeof e!=="number")return r;e=~~e;if(e>=t)return t;if(e>=0)return e;e+=t;if(e>=0)return e;return 0};var toType=function(e){switch(e){case 0:return"file";case 1:return"link";case 2:return"symlink";case 3:return"character-device";case 4:return"block-device";case 5:return"directory";case 6:return"fifo";case 7:return"contiguous-file";case 72:return"pax-header";case 55:return"pax-global-header";case 27:return"gnu-long-link-path";case 28:case 30:return"gnu-long-path"}return null};var toTypeflag=function(e){switch(e){case"file":return 0;case"link":return 1;case"symlink":return 2;case"character-device":return 3;case"block-device":return 4;case"directory":return 5;case"fifo":return 6;case"contiguous-file":return 7;case"pax-header":return 72}return 0};var indexOf=function(e,t,r,n){for(;rt)return i.slice(0,t)+" ";else return n.slice(0,t-e.length)+e+" "};function parse256(e){var t;if(e[0]===128)t=true;else if(e[0]===255)t=false;else return null;var r=[];for(var n=e.length-1;n>0;n--){var i=e[n];if(t)r.push(i);else r.push(255-i)}var a=0;var o=r.length;for(n=0;n=Math.pow(10,r))r++;return t+r+e};t.decodeLongPath=function(e,t){return decodeStr(e,0,e.length,t)};t.encodePax=function(e){var t="";if(e.name)t+=addLength(" path="+e.name+"\n");if(e.linkname)t+=addLength(" linkpath="+e.linkname+"\n");var r=e.pax;if(r){for(var n in r){t+=addLength(" "+n+"="+r[n]+"\n")}}return Buffer.from(t)};t.decodePax=function(e){var t={};while(e.length){var r=0;while(r100){var u=n.indexOf("/");if(u===-1)return null;i+=i?"/"+n.slice(0,u):n.slice(0,u);n=n.slice(u+1)}if(Buffer.byteLength(n)>100||Buffer.byteLength(i)>155)return null;if(e.linkname&&Buffer.byteLength(e.linkname)>100)return null;t.write(n);t.write(encodeOct(e.mode&c,6),100);t.write(encodeOct(e.uid,6),108);t.write(encodeOct(e.gid,6),116);t.write(encodeOct(e.size,11),124);t.write(encodeOct(e.mtime.getTime()/1e3|0,11),136);t[156]=a+toTypeflag(e.type);if(e.linkname)t.write(e.linkname,157);o.copy(t,d);s.copy(t,h);if(e.uname)t.write(e.uname,265);if(e.gname)t.write(e.gname,297);t.write(encodeOct(e.devmajor||0,6),329);t.write(encodeOct(e.devminor||0,6),337);if(i)t.write(i,345);t.write(encodeOct(cksum(t),6),148);return t};t.decode=function(e,t,r){var n=e[156]===0?0:e[156]-a;var i=decodeStr(e,0,100,t);var s=decodeOct(e,100,8);var c=decodeOct(e,108,8);var p=decodeOct(e,116,8);var g=decodeOct(e,124,12);var b=decodeOct(e,136,12);var m=toType(n);var v=e[157]===0?null:decodeStr(e,157,100,t);var _=decodeStr(e,265,32);var y=decodeStr(e,297,32);var w=decodeOct(e,329,8);var R=decodeOct(e,337,8);var S=cksum(e);if(S===8*32)return null;if(S!==decodeOct(e,148,8))throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");if(o.compare(e,d,d+6)===0){if(e[345])i=decodeStr(e,345,155,t)+"/"+i}else if(u.compare(e,d,d+6)===0&&l.compare(e,h,h+2)===0){}else{if(!r){throw new Error("Invalid tar header: unknown format.")}}if(n===0&&i&&i[i.length-1]==="/")n=5;return{name:i,mode:s,uid:c,gid:p,size:g,mtime:new Date(1e3*b),type:m,linkname:v,uname:_,gname:y,devmajor:w,devminor:R}}},2283:(e,t,r)=>{t.extract=r(7882);t.pack=r(4930)},4930:(e,t,r)=>{var n=r(3186);var i=r(1205);var a=r(4124);var o=Buffer.alloc;var s=r(1642).Readable;var u=r(1642).Writable;var l=r(1576).StringDecoder;var c=r(8860);var d=parseInt("755",8);var h=parseInt("644",8);var p=o(1024);var noop=function(){};var overflow=function(e,t){t&=511;if(t)e.push(p.slice(0,512-t))};function modeToType(e){switch(e&n.S_IFMT){case n.S_IFBLK:return"block-device";case n.S_IFCHR:return"character-device";case n.S_IFDIR:return"directory";case n.S_IFIFO:return"fifo";case n.S_IFLNK:return"symlink"}return"file"}var Sink=function(e){u.call(this);this.written=0;this._to=e;this._destroyed=false};a(Sink,u);Sink.prototype._write=function(e,t,r){this.written+=e.length;if(this._to.push(e))return r();this._to._drain=r};Sink.prototype.destroy=function(){if(this._destroyed)return;this._destroyed=true;this.emit("close")};var LinkSink=function(){u.call(this);this.linkname="";this._decoder=new l("utf-8");this._destroyed=false};a(LinkSink,u);LinkSink.prototype._write=function(e,t,r){this.linkname+=this._decoder.write(e);r()};LinkSink.prototype.destroy=function(){if(this._destroyed)return;this._destroyed=true;this.emit("close")};var Void=function(){u.call(this);this._destroyed=false};a(Void,u);Void.prototype._write=function(e,t,r){r(new Error("No body allowed for this entry"))};Void.prototype.destroy=function(){if(this._destroyed)return;this._destroyed=true;this.emit("close")};var Pack=function(e){if(!(this instanceof Pack))return new Pack(e);s.call(this,e);this._drain=noop;this._finalized=false;this._finalizing=false;this._destroyed=false;this._stream=null};a(Pack,s);Pack.prototype.entry=function(e,t,r){if(this._stream)throw new Error("already piping an entry");if(this._finalized||this._destroyed)return;if(typeof t==="function"){r=t;t=null}if(!r)r=noop;var n=this;if(!e.size||e.type==="symlink")e.size=0;if(!e.type)e.type=modeToType(e.mode);if(!e.mode)e.mode=e.type==="directory"?d:h;if(!e.uid)e.uid=0;if(!e.gid)e.gid=0;if(!e.mtime)e.mtime=new Date;if(typeof t==="string")t=Buffer.from(t);if(Buffer.isBuffer(t)){e.size=t.length;this._encode(e);var a=this.push(t);overflow(n,e.size);if(a)process.nextTick(r);else this._drain=r;return new Void}if(e.type==="symlink"&&!e.linkname){var o=new LinkSink;i(o,(function(t){if(t){n.destroy();return r(t)}e.linkname=o.linkname;n._encode(e);r()}));return o}this._encode(e);if(e.type!=="file"&&e.type!=="contiguous-file"){process.nextTick(r);return new Void}var s=new Sink(this);this._stream=s;i(s,(function(t){n._stream=null;if(t){n.destroy();return r(t)}if(s.written!==e.size){n.destroy();return r(new Error("size mismatch"))}overflow(n,e.size);if(n._finalizing)n.finalize();r()}));return s};Pack.prototype.finalize=function(){if(this._stream){this._finalizing=true;return}if(this._finalized)return;this._finalized=true;this.push(p);this.push(null)};Pack.prototype.destroy=function(e){if(this._destroyed)return;this._destroyed=true;if(e)this.emit("error",e);this.emit("close");if(this._stream&&this._stream.destroy)this._stream.destroy()};Pack.prototype._encode=function(e){if(!e.pax){var t=c.encode(e);if(t){this.push(t);return}}this._encodePax(e)};Pack.prototype._encodePax=function(e){var t=c.encodePax({name:e.name,linkname:e.linkname,pax:e.pax});var r={name:"PaxHeader",mode:e.mode,uid:e.uid,gid:e.gid,size:t.length,mtime:e.mtime,type:"pax-header",linkname:e.linkname&&"PaxHeader",uname:e.uname,gname:e.gname,devmajor:e.devmajor,devminor:e.devminor};this.push(c.encode(r));this.push(t);overflow(this,t.length);r.size=e.size;r.type=e.type;this.push(c.encode(r))};Pack.prototype._read=function(e){var t=this._drain;this._drain=noop;t()};e.exports=Pack},4294:(e,t,r)=>{e.exports=r(4219)},4219:(e,t,r)=>{var n=r(1808);var i=r(4404);var a=r(3685);var o=r(5687);var s=r(2361);var u=r(9491);var l=r(3837);t.httpOverHttp=httpOverHttp;t.httpsOverHttp=httpsOverHttp;t.httpOverHttps=httpOverHttps;t.httpsOverHttps=httpsOverHttps;function httpOverHttp(e){var t=new TunnelingAgent(e);t.request=a.request;return t}function httpsOverHttp(e){var t=new TunnelingAgent(e);t.request=a.request;t.createSocket=createSecureSocket;t.defaultPort=443;return t}function httpOverHttps(e){var t=new TunnelingAgent(e);t.request=o.request;return t}function httpsOverHttps(e){var t=new TunnelingAgent(e);t.request=o.request;t.createSocket=createSecureSocket;t.defaultPort=443;return t}function TunnelingAgent(e){var t=this;t.options=e||{};t.proxyOptions=t.options.proxy||{};t.maxSockets=t.options.maxSockets||a.Agent.defaultMaxSockets;t.requests=[];t.sockets=[];t.on("free",(function onFree(e,r,n,i){var a=toOptions(r,n,i);for(var o=0,s=t.requests.length;o=this.maxSockets){i.requests.push(a);return}i.createSocket(a,(function(t){t.on("free",onFree);t.on("close",onCloseOrRemove);t.on("agentRemove",onCloseOrRemove);e.onSocket(t);function onFree(){i.emit("free",t,a)}function onCloseOrRemove(e){i.removeSocket(t);t.removeListener("free",onFree);t.removeListener("close",onCloseOrRemove);t.removeListener("agentRemove",onCloseOrRemove)}}))};TunnelingAgent.prototype.createSocket=function createSocket(e,t){var r=this;var n={};r.sockets.push(n);var i=mergeOptions({},r.proxyOptions,{method:"CONNECT",path:e.host+":"+e.port,agent:false,headers:{host:e.host+":"+e.port}});if(e.localAddress){i.localAddress=e.localAddress}if(i.proxyAuth){i.headers=i.headers||{};i.headers["Proxy-Authorization"]="Basic "+new Buffer(i.proxyAuth).toString("base64")}c("making CONNECT request");var a=r.request(i);a.useChunkedEncodingByDefault=false;a.once("response",onResponse);a.once("upgrade",onUpgrade);a.once("connect",onConnect);a.once("error",onError);a.end();function onResponse(e){e.upgrade=true}function onUpgrade(e,t,r){process.nextTick((function(){onConnect(e,t,r)}))}function onConnect(i,o,s){a.removeAllListeners();o.removeAllListeners();if(i.statusCode!==200){c("tunneling socket could not be established, statusCode=%d",i.statusCode);o.destroy();var u=new Error("tunneling socket could not be established, "+"statusCode="+i.statusCode);u.code="ECONNRESET";e.request.emit("error",u);r.removeSocket(n);return}if(s.length>0){c("got illegal response body from proxy");o.destroy();var u=new Error("got illegal response body from proxy");u.code="ECONNRESET";e.request.emit("error",u);r.removeSocket(n);return}c("tunneling connection has established");r.sockets[r.sockets.indexOf(n)]=o;return t(o)}function onError(t){a.removeAllListeners();c("tunneling socket could not be established, cause=%s\n",t.message,t.stack);var i=new Error("tunneling socket could not be established, "+"cause="+t.message);i.code="ECONNRESET";e.request.emit("error",i);r.removeSocket(n)}};TunnelingAgent.prototype.removeSocket=function removeSocket(e){var t=this.sockets.indexOf(e);if(t===-1){return}this.sockets.splice(t,1);var r=this.requests.shift();if(r){this.createSocket(r,(function(e){r.request.onSocket(e)}))}};function createSecureSocket(e,t){var r=this;TunnelingAgent.prototype.createSocket.call(r,e,(function(n){var a=e.request.getHeader("host");var o=mergeOptions({},r.options,{socket:n,servername:a?a.replace(/:.*$/,""):e.host});var s=i.connect(0,o);r.sockets[r.sockets.indexOf(n)]=s;t(s)}))}function toOptions(e,t,r){if(typeof e==="string"){return{host:e,port:t,localAddress:r}}return e}function mergeOptions(e){for(var t=1,r=arguments.length;t{e.exports=r(3837).deprecate},5840:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});Object.defineProperty(t,"v1",{enumerable:true,get:function(){return n.default}});Object.defineProperty(t,"v3",{enumerable:true,get:function(){return i.default}});Object.defineProperty(t,"v4",{enumerable:true,get:function(){return a.default}});Object.defineProperty(t,"v5",{enumerable:true,get:function(){return o.default}});Object.defineProperty(t,"NIL",{enumerable:true,get:function(){return s.default}});Object.defineProperty(t,"version",{enumerable:true,get:function(){return u.default}});Object.defineProperty(t,"validate",{enumerable:true,get:function(){return l.default}});Object.defineProperty(t,"stringify",{enumerable:true,get:function(){return c.default}});Object.defineProperty(t,"parse",{enumerable:true,get:function(){return d.default}});var n=_interopRequireDefault(r(8628));var i=_interopRequireDefault(r(6409));var a=_interopRequireDefault(r(5122));var o=_interopRequireDefault(r(9120));var s=_interopRequireDefault(r(5332));var u=_interopRequireDefault(r(1595));var l=_interopRequireDefault(r(6900));var c=_interopRequireDefault(r(8950));var d=_interopRequireDefault(r(4848));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}},4569:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function md5(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return n.default.createHash("md5").update(e).digest()}var i=md5;t["default"]=i},5332:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var r="00000000-0000-0000-0000-000000000000";t["default"]=r},4848:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6900));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function parse(e){if(!(0,n.default)(e)){throw TypeError("Invalid UUID")}let t;const r=new Uint8Array(16);r[0]=(t=parseInt(e.slice(0,8),16))>>>24;r[1]=t>>>16&255;r[2]=t>>>8&255;r[3]=t&255;r[4]=(t=parseInt(e.slice(9,13),16))>>>8;r[5]=t&255;r[6]=(t=parseInt(e.slice(14,18),16))>>>8;r[7]=t&255;r[8]=(t=parseInt(e.slice(19,23),16))>>>8;r[9]=t&255;r[10]=(t=parseInt(e.slice(24,36),16))/1099511627776&255;r[11]=t/4294967296&255;r[12]=t>>>24&255;r[13]=t>>>16&255;r[14]=t>>>8&255;r[15]=t&255;return r}var i=parse;t["default"]=i},814:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var r=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;t["default"]=r},807:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=rng;var n=_interopRequireDefault(r(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const i=new Uint8Array(256);let a=i.length;function rng(){if(a>i.length-16){n.default.randomFillSync(i);a=0}return i.slice(a,a+=16)}},5274:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function sha1(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return n.default.createHash("sha1").update(e).digest()}var i=sha1;t["default"]=i},8950:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6900));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const i=[];for(let e=0;e<256;++e){i.push((e+256).toString(16).substr(1))}function stringify(e,t=0){const r=(i[e[t+0]]+i[e[t+1]]+i[e[t+2]]+i[e[t+3]]+"-"+i[e[t+4]]+i[e[t+5]]+"-"+i[e[t+6]]+i[e[t+7]]+"-"+i[e[t+8]]+i[e[t+9]]+"-"+i[e[t+10]]+i[e[t+11]]+i[e[t+12]]+i[e[t+13]]+i[e[t+14]]+i[e[t+15]]).toLowerCase();if(!(0,n.default)(r)){throw TypeError("Stringified UUID is invalid")}return r}var a=stringify;t["default"]=a},8628:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(807));var i=_interopRequireDefault(r(8950));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}let a;let o;let s=0;let u=0;function v1(e,t,r){let l=t&&r||0;const c=t||new Array(16);e=e||{};let d=e.node||a;let h=e.clockseq!==undefined?e.clockseq:o;if(d==null||h==null){const t=e.random||(e.rng||n.default)();if(d==null){d=a=[t[0]|1,t[1],t[2],t[3],t[4],t[5]]}if(h==null){h=o=(t[6]<<8|t[7])&16383}}let p=e.msecs!==undefined?e.msecs:Date.now();let g=e.nsecs!==undefined?e.nsecs:u+1;const b=p-s+(g-u)/1e4;if(b<0&&e.clockseq===undefined){h=h+1&16383}if((b<0||p>s)&&e.nsecs===undefined){g=0}if(g>=1e4){throw new Error("uuid.v1(): Can't create more than 10M uuids/sec")}s=p;u=g;o=h;p+=122192928e5;const m=((p&268435455)*1e4+g)%4294967296;c[l++]=m>>>24&255;c[l++]=m>>>16&255;c[l++]=m>>>8&255;c[l++]=m&255;const v=p/4294967296*1e4&268435455;c[l++]=v>>>8&255;c[l++]=v&255;c[l++]=v>>>24&15|16;c[l++]=v>>>16&255;c[l++]=h>>>8|128;c[l++]=h&255;for(let e=0;e<6;++e){c[l+e]=d[e]}return t||(0,i.default)(c)}var l=v1;t["default"]=l},6409:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(5998));var i=_interopRequireDefault(r(4569));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const a=(0,n.default)("v3",48,i.default);var o=a;t["default"]=o},5998:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=_default;t.URL=t.DNS=void 0;var n=_interopRequireDefault(r(8950));var i=_interopRequireDefault(r(4848));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function stringToBytes(e){e=unescape(encodeURIComponent(e));const t=[];for(let r=0;r{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(807));var i=_interopRequireDefault(r(8950));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function v4(e,t,r){e=e||{};const a=e.random||(e.rng||n.default)();a[6]=a[6]&15|64;a[8]=a[8]&63|128;if(t){r=r||0;for(let e=0;e<16;++e){t[r+e]=a[e]}return t}return(0,i.default)(a)}var a=v4;t["default"]=a},9120:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(5998));var i=_interopRequireDefault(r(5274));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const a=(0,n.default)("v5",80,i.default);var o=a;t["default"]=o},6900:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(814));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function validate(e){return typeof e==="string"&&n.default.test(e)}var i=validate;t["default"]=i},1595:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t["default"]=void 0;var n=_interopRequireDefault(r(6900));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function version(e){if(!(0,n.default)(e)){throw TypeError("Invalid UUID")}return parseInt(e.substr(14,1),16)}var i=version;t["default"]=i},2940:e=>{e.exports=wrappy;function wrappy(e,t){if(e&&t)return wrappy(e)(t);if(typeof e!=="function")throw new TypeError("need wrapper function");Object.keys(e).forEach((function(t){wrapper[t]=e[t]}));return wrapper;function wrapper(){var t=new Array(arguments.length);for(var r=0;r{t.exports=e(import.meta.url)("assert")},4300:t=>{t.exports=e(import.meta.url)("buffer")},2057:t=>{t.exports=e(import.meta.url)("constants")},6113:t=>{t.exports=e(import.meta.url)("crypto")},2361:t=>{t.exports=e(import.meta.url)("events")},7147:t=>{t.exports=e(import.meta.url)("fs")},3685:t=>{t.exports=e(import.meta.url)("http")},5687:t=>{t.exports=e(import.meta.url)("https")},1808:t=>{t.exports=e(import.meta.url)("net")},7718:t=>{t.exports=e(import.meta.url)("node:child_process")},7561:t=>{t.exports=e(import.meta.url)("node:fs")},7742:t=>{t.exports=e(import.meta.url)("node:process")},4492:t=>{t.exports=e(import.meta.url)("node:stream")},5628:t=>{t.exports=e(import.meta.url)("node:zlib")},2037:t=>{t.exports=e(import.meta.url)("os")},1017:t=>{t.exports=e(import.meta.url)("path")},2781:t=>{t.exports=e(import.meta.url)("stream")},1576:t=>{t.exports=e(import.meta.url)("string_decoder")},4404:t=>{t.exports=e(import.meta.url)("tls")},3837:t=>{t.exports=e(import.meta.url)("util")},6955:(e,t,r)=>{r.a(e,(async e=>{var t=r(7718);var n=r(7742);var i=r(4492);var a=r(7561);var o=r(5628);var s=r(2283);var u=r(2186);const l=u.getInput("container",{required:true});const c=JSON.parse(u.getInput("error-log-paths",{required:true}));const d=u.getInput("log-tarball-prefix",{required:true});const h=u.getInput("tests-label",{required:true});try{if(t.spawnSync("docker",["run","--name","base","-v",`${n.cwd()}/build.tar.zst:/build.tar.zst`,"--workdir","/__w/leap/leap",l,"sh","-c","zstdcat /build.tar.zst | tar x"],{stdio:"inherit"}).status)throw new Error("Failed to create base container");if(t.spawnSync("docker",["commit","base","baseimage"],{stdio:"inherit"}).status)throw new Error("Failed to create base image");if(t.spawnSync("docker",["rm","base"],{stdio:"inherit"}).status)throw new Error("Failed to remove base container");const e=t.spawnSync("docker",["run","--rm","baseimage","bash","-e","-o","pipefail","-c",`cd build; ctest -L '${h}' --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]'`]);if(e.status)throw new Error("Failed to discover tests with label");const r=JSON.parse(e.stdout);let p=[];r.forEach((e=>{p.push(new Promise((r=>{t.spawn("docker",["run","--name",e,"--init","baseimage","bash","-c",`cd build; ctest --output-on-failure -R '^${e}$'`],{stdio:"inherit"}).on("close",(e=>r(e)))})))}));const g=await Promise.all(p);for(let e=0;e{if(!e.name.startsWith(`__w/leap/leap/build`)){t.on("end",(()=>r()));t.resume();return}e.name=e.name.substring(`__w/leap/leap/`.length);if(e.name!=="build/"&&c.filter((t=>e.name.startsWith(t))).length===0){t.on("end",(()=>r()));t.resume();return}t.pipe(l.entry(e,r))})).on("finish",(()=>{l.finalize()}));t.spawn("docker",["export",r[e]]).stdout.pipe(n);i.promises.pipeline(l,o.createGzip(),a.createWriteStream(`${d}-${r[e]}-logs.tar.gz`))}}catch(e){u.setFailed(`Uncaught exception ${e.message}`)}e()}),1)}};var r={};function __nccwpck_require__(e){var n=r[e];if(n!==undefined){return n.exports}var i=r[e]={exports:{}};var a=true;try{t[e].call(i.exports,i,i.exports,__nccwpck_require__);a=false}finally{if(a)delete r[e]}return i.exports}(()=>{var e=typeof Symbol==="function"?Symbol("webpack then"):"__webpack_then__";var t=typeof Symbol==="function"?Symbol("webpack exports"):"__webpack_exports__";var completeQueue=e=>{if(e){e.forEach((e=>e.r--));e.forEach((e=>e.r--?e.r++:e()))}};var completeFunction=e=>!--e.r&&e();var queueFunction=(e,t)=>e?e.push(t):completeFunction(t);var wrapDeps=r=>r.map((r=>{if(r!==null&&typeof r==="object"){if(r[e])return r;if(r.then){var n=[];r.then((e=>{i[t]=e;completeQueue(n);n=0}));var i={};i[e]=(e,t)=>(queueFunction(n,e),r["catch"](t));return i}}var a={};a[e]=e=>completeFunction(e);a[t]=r;return a}));__nccwpck_require__.a=(r,n,i)=>{var a=i&&[];var o=r.exports;var s;var u;var l;var c=true;var d=false;var whenAll=(t,r,n)=>{if(d)return;d=true;r.r+=t.length;t.map(((t,i)=>t[e](r,n)));d=false};var h=new Promise(((e,t)=>{l=t;u=()=>(e(o),completeQueue(a),a=0)}));h[t]=o;h[e]=(e,t)=>{if(c){return completeFunction(e)}if(s)whenAll(s,e,t);queueFunction(a,e);h["catch"](t)};r.exports=h;n((e=>{if(!e)return u();s=wrapDeps(e);var r,n;var i=new Promise(((e,i)=>{r=()=>e(n=s.map((e=>e[t])));r.r=0;whenAll(s,r,i)}));return r.r?i:n})).then(u,l);c=false}})();if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=new URL(".",import.meta.url).pathname.slice(import.meta.url.match(/^file:\/\/\/\w:/)?1:0,-1)+"/";var n=__nccwpck_require__(6955);n=await n; \ No newline at end of file diff --git a/.github/actions/parallel-ctest-containers/main.mjs b/.github/actions/parallel-ctest-containers/main.mjs index 61ca9d59d0..ed7b99ede6 100644 --- a/.github/actions/parallel-ctest-containers/main.mjs +++ b/.github/actions/parallel-ctest-containers/main.mjs @@ -9,16 +9,22 @@ import core from '@actions/core' const container = core.getInput('container', {required: true}); const error_log_paths = JSON.parse(core.getInput('error-log-paths', {required: true})); const log_tarball_prefix = core.getInput('log-tarball-prefix', {required: true}); -const tests = JSON.parse(core.getInput('tests', {required: true})); +const tests_label = core.getInput('tests-label', {required: true}); try { - if(child_process.spawnSync("docker", ["run", "--name", "base", "-v", `${process.cwd()}/build.tar.zst:/build.tar.zst`, "--workdir", "/__w/leap/leap", container, "tar", "--zstd", "-xf", "/build.tar.zst"], {stdio:"inherit"}).status) + if(child_process.spawnSync("docker", ["run", "--name", "base", "-v", `${process.cwd()}/build.tar.zst:/build.tar.zst`, "--workdir", "/__w/leap/leap", container, "sh", "-c", "zstdcat /build.tar.zst | tar x"], {stdio:"inherit"}).status) throw new Error("Failed to create base container"); if(child_process.spawnSync("docker", ["commit", "base", "baseimage"], {stdio:"inherit"}).status) throw new Error("Failed to create base image"); if(child_process.spawnSync("docker", ["rm", "base"], {stdio:"inherit"}).status) throw new Error("Failed to remove base container"); + // the correct approach is by far "--show-only=json-v1" and then pluck out .tests[].name; but that doesn't work on U18's cmake 3.10 since it lacks json-v1 output + const test_query_result = child_process.spawnSync("docker", ["run", "--rm", "baseimage", "bash", "-e", "-o", "pipefail", "-c", `cd build; ctest -L '${tests_label}' --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]'`]); + if(test_query_result.status) + throw new Error("Failed to discover tests with label") + const tests = JSON.parse(test_query_result.stdout); + let subprocesses = []; tests.forEach(t => { subprocesses.push(new Promise(resolve => { diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b95d924124..6fd38bae5e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -65,9 +65,6 @@ jobs: fail-fast: false matrix: platform: [ubuntu18, ubuntu20, ubuntu22] - outputs: - np-tests: ${{steps.build.outputs.np-tests}} - lr-tests: ${{steps.build.outputs.lr-tests}} runs-on: ["self-hosted", "enf-x86-beefy"] container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}} steps: @@ -83,9 +80,6 @@ jobs: cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -GNinja .. ninja - # the correct approach is by far "--show-only=json-v1 | jq '.tests[].name' | jq -sc" but that doesn't work on U18's cmake 3.10 since it lacks json-v1 - echo ::set-output name=np-tests::$(ctest -L "nonparallelizable_tests" --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]') - echo ::set-output name=lr-tests::$(ctest -L "long_running_tests" --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]') tar -pc -C .. --exclude "*.o" build | zstd --long -T0 -9 > ../build.tar.zst - name: Upload builddir uses: AntelopeIO/upload-artifact-large-chunks-action@v1 @@ -165,7 +159,7 @@ jobs: container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}} error-log-paths: '["build/etc", "build/var", "build/leap-ignition-wd"]' log-tarball-prefix: ${{matrix.platform}} - tests: ${{needs.Build.outputs.np-tests}} + tests-label: nonparallelizable_tests - name: Upload logs from failed tests uses: actions/upload-artifact@v3 if: failure() @@ -194,7 +188,7 @@ jobs: container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}} error-log-paths: '["build/etc", "build/var", "build/leap-ignition-wd"]' log-tarball-prefix: ${{matrix.platform}} - tests: ${{needs.Build.outputs.lr-tests}} + tests-label: long_running_tests - name: Upload logs from failed tests uses: actions/upload-artifact@v3 if: failure() From 5c38a6d8d8d7079b3a355830e459d1358db7614e Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Thu, 15 Sep 2022 14:58:49 -0400 Subject: [PATCH 053/111] only give package write permission to single job that requires it --- .github/workflows/build.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6fd38bae5e..bc268c1a36 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ on: type: boolean permissions: - packages: write + packages: read contents: read defaults: @@ -44,6 +44,9 @@ jobs: matrix: platform: ${{fromJSON(needs.d.outputs.missing-platforms)}} runs-on: ["self-hosted", "enf-x86-beefy"] + permissions: + packages: write + contents: read steps: - name: Login to Container Registry uses: docker/login-action@v2 From 85cab27623c5e78ed95ccbf074970653148b21d7 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Wed, 14 Sep 2022 17:27:34 -0400 Subject: [PATCH 054/111] enable CI testing on more platform combinations --- .github/workflows/build.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bc268c1a36..460e20d073 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -122,7 +122,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu20] + platform: [ubuntu20, ubuntu22] runs-on: ["self-hosted", "enf-x86-hightier"] container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}} steps: @@ -137,6 +137,9 @@ jobs: run: | # https://github.com/actions/runner/issues/2033 -- need this because of full version label test looking at git revs chown -R $(id -u):$(id -g) $PWD + # jammy's boost 1.74 can stumble on an EXDEV via copy_file_range() it doesn't have a fallback for; re-eval once moving to std::filesystem + export TMPDIR="$PWD/tmp" + mkdir -p $TMPDIR zstdcat build.tar.zst | tar x cd build ctest --output-on-failure -j $(nproc) -LE "(nonparallelizable_tests|long_running_tests)" @@ -148,7 +151,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu20] + platform: [ubuntu18, ubuntu20, ubuntu22] runs-on: ["self-hosted", "enf-x86-midtier"] steps: - uses: actions/checkout@v3 @@ -177,7 +180,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu20] + platform: [ubuntu18, ubuntu20, ubuntu22] runs-on: ["self-hosted", "enf-x86-lowtier"] steps: - uses: actions/checkout@v3 From eaeaec0278691c241a624b18542fe0e27982b0f4 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 15 Sep 2022 18:22:02 -0500 Subject: [PATCH 055/111] GH-174 Do not apply 3-strike rule when subjective billing is disabled or if read-only transaction. --- plugins/producer_plugin/producer_plugin.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 83ad30326e..6a42f4d879 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1915,8 +1915,12 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, { auto start = fc::time_point::now(); + bool disable_subjective_enforcement = (persist_until_expired && _disable_subjective_api_billing) + || (!persist_until_expired && _disable_subjective_p2p_billing) + || trx->read_only; + auto first_auth = trx->packed_trx()->get_transaction().first_authorizer(); - if( _account_fails.failure_limit( first_auth ) ) { + if( !disable_subjective_enforcement && _account_fails.failure_limit( first_auth ) ) { if( next ) { auto except_ptr = std::static_pointer_cast( std::make_shared( FC_LOG_MESSAGE( error, "transaction ${id} exceeded failure limit for account ${a}", @@ -1933,9 +1937,7 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, if( max_trx_time.count() < 0 ) max_trx_time = fc::microseconds::maximum(); bool disable_subjective_billing = ( _pending_block_mode == pending_block_mode::producing ) - || ( persist_until_expired && _disable_subjective_api_billing ) - || ( !persist_until_expired && _disable_subjective_p2p_billing ) - || trx->read_only; + || disable_subjective_enforcement; int64_t sub_bill = 0; if( !disable_subjective_billing ) From b47f3f5635741295af8ca263877e02eccd488823 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 15 Sep 2022 18:53:18 -0500 Subject: [PATCH 056/111] GH-174 Do not track failures when subjective enforcement disabled otherwise it can affect trxs outside of those failures --- plugins/producer_plugin/producer_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 6a42f4d879..640beb2522 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1980,7 +1980,8 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline, fc_dlog( _trx_failed_trace_log, "Failed ${c} trx, auth: ${a}, prev billed: ${p}us, ran: ${r}us, id: ${id}", ("c", failure_code)("a", first_auth)("p", prev_billed_cpu_time_us) ( "r", end - start )( "id", trx->id() ) ); - _account_fails.add( first_auth, failure_code ); + if( !disable_subjective_enforcement ) + _account_fails.add( first_auth, failure_code ); } if( next ) { if( return_failure_trace ) { From dfbe904db7a359f6f8ec1116ac8c545727386edc Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 16 Sep 2022 07:26:54 -0500 Subject: [PATCH 057/111] GH-109 No reason to store expiration --- .../chain/unapplied_transaction_queue.hpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp index 8e4aa23fae..28547943fd 100644 --- a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp +++ b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp @@ -32,12 +32,12 @@ using next_func_t = std::functionid(); } + fc::time_point_sec expiration()const { return trx_meta->packed_trx()->expiration(); } unapplied_transaction(const unapplied_transaction&) = delete; unapplied_transaction() = delete; @@ -61,7 +61,7 @@ class unapplied_transaction_queue { const_mem_fun >, ordered_non_unique< tag, member >, - ordered_non_unique< tag, member > + ordered_non_unique< tag, const_mem_fun > > > unapplied_trx_queue_type; @@ -101,7 +101,7 @@ class unapplied_transaction_queue { auto& persisted_by_expiry = queue.get(); while( !persisted_by_expiry.empty() ) { const auto& itr = persisted_by_expiry.begin(); - if( itr->expiry > pending_block_time ) { + if( itr->expiration() > pending_block_time ) { break; } if( deadline <= fc::time_point::now() ) { @@ -146,8 +146,7 @@ class unapplied_transaction_queue { const block_state_ptr& bsptr = *ritr; for( auto itr = bsptr->trxs_metas().begin(), end = bsptr->trxs_metas().end(); itr != end; ++itr ) { const auto& trx = *itr; - fc::time_point expiry = trx->packed_trx()->expiration(); - auto insert_itr = queue.insert( { trx, expiry, trx_enum_type::forked } ); + auto insert_itr = queue.insert( { trx, trx_enum_type::forked } ); if( insert_itr.second ) added( insert_itr.first ); } } @@ -155,8 +154,7 @@ class unapplied_transaction_queue { void add_aborted( deque aborted_trxs ) { for( auto& trx : aborted_trxs ) { - fc::time_point expiry = trx->packed_trx()->expiration(); - auto insert_itr = queue.insert( { std::move( trx ), expiry, trx_enum_type::aborted } ); + auto insert_itr = queue.insert( { std::move( trx ), trx_enum_type::aborted } ); if( insert_itr.second ) added( insert_itr.first ); } } @@ -164,8 +162,7 @@ class unapplied_transaction_queue { void add_persisted( const transaction_metadata_ptr& trx ) { auto itr = queue.get().find( trx->id() ); if( itr == queue.get().end() ) { - fc::time_point expiry = trx->packed_trx()->expiration(); - auto insert_itr = queue.insert( { trx, expiry, trx_enum_type::persisted } ); + auto insert_itr = queue.insert( { trx, trx_enum_type::persisted } ); if( insert_itr.second ) added( insert_itr.first ); } else if( itr->trx_type != trx_enum_type::persisted ) { if (itr->trx_type == trx_enum_type::incoming || itr->trx_type == trx_enum_type::incoming_persisted) @@ -180,9 +177,8 @@ class unapplied_transaction_queue { void add_incoming( const transaction_metadata_ptr& trx, bool persist_until_expired, bool return_failure_trace, next_func_t next ) { auto itr = queue.get().find( trx->id() ); if( itr == queue.get().end() ) { - fc::time_point expiry = trx->packed_trx()->expiration(); auto insert_itr = queue.insert( - { trx, expiry, persist_until_expired ? trx_enum_type::incoming_persisted : trx_enum_type::incoming, return_failure_trace, std::move( next ) } ); + { trx, persist_until_expired ? trx_enum_type::incoming_persisted : trx_enum_type::incoming, return_failure_trace, std::move( next ) } ); if( insert_itr.second ) added( insert_itr.first ); } else { if( itr->trx_meta == trx ) return; // same trx meta pointer From b767da350e71dbd710d0bcc76fa05e32d60005fa Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 16 Sep 2022 08:57:51 -0500 Subject: [PATCH 058/111] GH-109 Add lower_bound(trx_id) --- .../chain/unapplied_transaction_queue.hpp | 6 ++++ .../unapplied_transaction_queue_tests.cpp | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp index 28547943fd..5020b08b28 100644 --- a/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp +++ b/libraries/chain/include/eosio/chain/unapplied_transaction_queue.hpp @@ -204,6 +204,12 @@ class unapplied_transaction_queue { iterator incoming_begin() { return queue.get().lower_bound( trx_enum_type::incoming_persisted ); } iterator incoming_end() { return queue.get().end(); } // if changed to upper_bound, verify usage performance + iterator lower_bound( const transaction_id_type& id ) { + auto itr = queue.get().find( id ); + if( itr == queue.get().end() ) return queue.get().end(); + return queue.project(itr); + } + /// caller's responsibility to call next() if applicable iterator erase( iterator itr ) { removed( itr ); diff --git a/unittests/unapplied_transaction_queue_tests.cpp b/unittests/unapplied_transaction_queue_tests.cpp index 3b95218eff..a18d9c50e4 100644 --- a/unittests/unapplied_transaction_queue_tests.cpp +++ b/unittests/unapplied_transaction_queue_tests.cpp @@ -78,6 +78,17 @@ auto create_test_block_state( deque trx_metas ) { return bsp; } +// given a current itr make sure expected number of items are iterated over +void verify_order( unapplied_transaction_queue& q, unapplied_transaction_queue::iterator itr, size_t expected ) { + size_t size = 0; + std::set ids; + for( ; itr != q.end(); ++itr, ++size ) { + ids.insert( itr->id() ); + } + BOOST_TEST( size == expected ); + BOOST_TEST( ids.size() == expected ); +} + BOOST_AUTO_TEST_CASE( unapplied_transaction_queue_test ) try { unapplied_transaction_queue q; @@ -260,41 +271,64 @@ BOOST_AUTO_TEST_CASE( unapplied_transaction_queue_test ) try { q.add_persisted( trx8 ); q.add_aborted( { trx18, trx19 } ); q.add_forked( { bs6, bs5, bs4 } ); + // verify order + verify_order( q, q.begin(), 17 ); + verify_order( q, q.lower_bound(trx16->id()), 17 ); + // verify type order BOOST_CHECK( q.size() == 17 ); BOOST_REQUIRE( next( q ) == trx16 ); BOOST_CHECK( q.size() == 16 ); + verify_order( q, q.lower_bound(trx8->id()), 16 ); BOOST_REQUIRE( next( q ) == trx8 ); BOOST_CHECK( q.size() == 15 ); + verify_order( q, q.lower_bound(trx1->id()), 15 ); BOOST_REQUIRE( next( q ) == trx1 ); BOOST_CHECK( q.size() == 14 ); + verify_order( q, q.lower_bound(trx2->id()), 14 ); BOOST_REQUIRE( next( q ) == trx2 ); BOOST_CHECK( q.size() == 13 ); + verify_order( q, q.lower_bound(trx3->id()), 13 ); + verify_order( q, q.lower_bound(trx15->id()), 5 ); BOOST_REQUIRE_EQUAL( next( q ), trx3 ); BOOST_CHECK( q.size() == 12 ); + verify_order( q, q.lower_bound(trx4->id()), 12 ); BOOST_REQUIRE( next( q ) == trx4 ); BOOST_CHECK( q.size() == 11 ); + verify_order( q, q.lower_bound(trx5->id()), 11 ); BOOST_REQUIRE( next( q ) == trx5 ); BOOST_CHECK( q.size() == 10 ); + verify_order( q, q.lower_bound(trx6->id()), 10 ); + verify_order( q, q.lower_bound(trx15->id()), 5 ); BOOST_REQUIRE( next( q ) == trx6 ); BOOST_CHECK( q.size() == 9 ); + verify_order( q, q.lower_bound(trx7->id()), 9 ); BOOST_REQUIRE( next( q ) == trx7 ); BOOST_CHECK( q.size() == 8 ); + verify_order( q, q.lower_bound(trx11->id()), 8 ); BOOST_REQUIRE( next( q ) == trx11 ); BOOST_CHECK( q.size() == 7 ); + verify_order( q, q.lower_bound(trx12->id()), 7 ); BOOST_REQUIRE_EQUAL( next( q ), trx12 ); BOOST_CHECK( q.size() == 6 ); + verify_order( q, q.lower_bound(trx13->id()), 6 ); BOOST_REQUIRE( next( q ) == trx13 ); BOOST_CHECK( q.size() == 5 ); + verify_order( q, q.lower_bound(trx15->id()), 5 ); BOOST_REQUIRE( next( q ) == trx15 ); BOOST_CHECK( q.size() == 4 ); + verify_order( q, q.lower_bound(trx9->id()), 4 ); BOOST_REQUIRE( next( q ) == trx9 ); BOOST_CHECK( q.size() == 3 ); + verify_order( q, q.lower_bound(trx14->id()), 3 ); BOOST_REQUIRE( next( q ) == trx14 ); BOOST_CHECK( q.size() == 2 ); + verify_order( q, q.lower_bound(trx18->id()), 2 ); BOOST_REQUIRE( next( q ) == trx18 ); BOOST_CHECK( q.size() == 1 ); + verify_order( q, q.lower_bound(trx19->id()), 1 ); BOOST_REQUIRE( next( q ) == trx19 ); BOOST_CHECK( q.size() == 0 ); + verify_order( q, q.lower_bound(trx19->id()), 0 ); BOOST_REQUIRE( next( q ) == nullptr ); BOOST_CHECK( q.empty() ); From 20b3fe654cf0fbaac9b31295a468332dc2660f1c Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Fri, 16 Sep 2022 11:44:15 -0400 Subject: [PATCH 059/111] pinned_build.sh: make relative path work --- scripts/pinned_build.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/pinned_build.sh b/scripts/pinned_build.sh index 7f96484945..15159851ab 100755 --- a/scripts/pinned_build.sh +++ b/scripts/pinned_build.sh @@ -25,7 +25,8 @@ if [ $# -eq 0 ] || [ -z "$1" ] fi CORE_SYM=EOS -DEP_DIR=$1 +# CMAKE_C_COMPILER requires absolute path +DEP_DIR=`realpath $1` LEAP_DIR=$2 JOBS=$3 CLANG_VER=11.0.1 @@ -49,7 +50,8 @@ popdir() { echo ${D} D=`eval echo $D | head -n1 | cut -d " " -f1` - if [[ ${D} != ${EXPECTED} ]]; then + # -ef compares absolute paths + if ! [[ ${D} -ef ${EXPECTED} ]]; then echo "Directory is not where expected EXPECTED=${EXPECTED} at ${D}" exit 1 fi From 7a064a58cea20f099878b2f06c3dd61ee97e7993 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Sat, 17 Sep 2022 10:03:22 -0500 Subject: [PATCH 060/111] GH-109 Add /v1/chain/get_unapplied_transactions endpoint to producer_api_plugin --- .../producer_api_plugin.cpp | 13 +++- .../eosio/producer_plugin/producer_plugin.hpp | 33 ++++++++- plugins/producer_plugin/producer_plugin.cpp | 72 +++++++++++++++++++ tests/plugin_http_api_test.py | 20 ++++++ 4 files changed, 135 insertions(+), 3 deletions(-) diff --git a/plugins/producer_api_plugin/producer_api_plugin.cpp b/plugins/producer_api_plugin/producer_api_plugin.cpp index 023e7bcb00..634c7da8cd 100644 --- a/plugins/producer_api_plugin/producer_api_plugin.cpp +++ b/plugins/producer_api_plugin/producer_api_plugin.cpp @@ -29,10 +29,11 @@ struct async_result_visitor : public fc::visitor { #define CALL_WITH_400(api_name, api_handle, call_name, INVOKE, http_response_code) \ {std::string("/v1/" #api_name "/" #call_name), \ - [&api_handle](string, string body, url_response_callback cb) mutable { \ + [&api_handle, http_max_response_time](string, string body, url_response_callback cb) mutable { \ try { \ + auto deadline = fc::time_point::now() + http_max_response_time; \ INVOKE \ - cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ + cb(http_response_code, deadline, fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -65,6 +66,10 @@ struct async_result_visitor : public fc::visitor { auto params = parse_params(body);\ auto result = api_handle.call_name(std::move(params)); +#define INVOKE_R_R_D(api_handle, call_name, in_param) \ + auto params = parse_params(body);\ + auto result = api_handle.call_name(std::move(params), deadline); + #define INVOKE_R_V(api_handle, call_name) \ body = parse_params(body); \ auto result = api_handle.call_name(); @@ -87,6 +92,8 @@ void producer_api_plugin::plugin_startup() { ilog("starting producer_api_plugin"); // lifetime of plugin is lifetime of application auto& producer = app().get_plugin(); + auto& http = app().get_plugin(); + fc::microseconds http_max_response_time = http.get_max_response_time(); app().get_plugin().add_api({ CALL_WITH_400(producer, producer, pause, @@ -122,6 +129,8 @@ void producer_api_plugin::plugin_startup() { producer_plugin::get_supported_protocol_features_params), 201), CALL_WITH_400(producer, producer, get_account_ram_corrections, INVOKE_R_R(producer, get_account_ram_corrections, producer_plugin::get_account_ram_corrections_params), 201), + CALL_WITH_400(producer, producer, get_unapplied_transactions, + INVOKE_R_R_D(producer, get_unapplied_transactions, producer_plugin::get_unapplied_transactions_params), 200), }, appbase::priority::medium_high); } diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp index b9b31fbf6c..2ee1f132f6 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp @@ -114,7 +114,35 @@ class producer_plugin : public appbase::plugin { get_account_ram_corrections_result get_account_ram_corrections( const get_account_ram_corrections_params& params ) const; - void log_failed_transaction(const transaction_id_type& trx_id, const chain::packed_transaction_ptr& packed_trx_ptr, const char* reason) const; + struct get_unapplied_transactions_params { + string lower_bound; /// transaction id + std::optional limit = 100; + std::optional time_limit_ms; // defaults to 10ms + }; + + struct unapplied_trx { + transaction_id_type trx_id; + fc::time_point_sec expiration; + string trx_type; // eosio::chain::trx_enum_type values or "read_only" + account_name first_auth; + account_name first_receiver; + action_name first_action; + uint16_t total_actions = 0; + uint32_t billed_cpu_time_us = 0; + size_t size = 0; + }; + + struct get_unapplied_transactions_result { + size_t size = 0; + size_t incoming_size = 0; + std::vector trxs; + string more; ///< fill lower_bound with trx id to fetch next set of transactions + }; + + get_unapplied_transactions_result get_unapplied_transactions( const get_unapplied_transactions_params& params, const fc::time_point& deadline ) const; + + + void log_failed_transaction(const transaction_id_type& trx_id, const chain::packed_transaction_ptr& packed_trx_ptr, const char* reason) const; private: std::shared_ptr my; @@ -131,3 +159,6 @@ FC_REFLECT(eosio::producer_plugin::scheduled_protocol_feature_activations, (prot FC_REFLECT(eosio::producer_plugin::get_supported_protocol_features_params, (exclude_disabled)(exclude_unactivatable)) FC_REFLECT(eosio::producer_plugin::get_account_ram_corrections_params, (lower_bound)(upper_bound)(limit)(reverse)) FC_REFLECT(eosio::producer_plugin::get_account_ram_corrections_result, (rows)(more)) +FC_REFLECT(eosio::producer_plugin::get_unapplied_transactions_params, (lower_bound)(limit)(time_limit_ms)) +FC_REFLECT(eosio::producer_plugin::unapplied_trx, (trx_id)(expiration)(trx_type)(first_auth)(first_receiver)(first_action)(total_actions)(billed_cpu_time_us)(size)) +FC_REFLECT(eosio::producer_plugin::get_unapplied_transactions_result, (size)(incoming_size)(trxs)(more)) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 640beb2522..8e4ebdf9d7 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1438,6 +1438,78 @@ producer_plugin::get_account_ram_corrections( const get_account_ram_corrections_ return result; } +producer_plugin::get_unapplied_transactions_result +producer_plugin::get_unapplied_transactions( const get_unapplied_transactions_params& p, const fc::time_point& deadline ) const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + + auto& ua = my->_unapplied_transactions; + + auto itr = ([&](){ + if (!p.lower_bound.empty()) { + try { + auto trx_id = transaction_id_type( p.lower_bound ); + return ua.lower_bound( trx_id ); + } catch( ... ) { + return ua.end(); + } + } else { + return ua.begin(); + } + })(); + + auto get_trx_type = [&](trx_enum_type t, bool read_only) { + if( read_only ) return "read_only"; + switch( t ) { + case trx_enum_type::unknown: + return "unknown"; + case trx_enum_type::persisted: + return "persisted"; + case trx_enum_type::forked: + return "forked"; + case trx_enum_type::aborted: + return "aborted"; + case trx_enum_type::incoming: + return "incoming"; + } + return "unknown type"; + }; + + get_unapplied_transactions_result result; + result.size = ua.size(); + result.incoming_size = ua.incoming_size(); + + uint32_t remaining = p.limit ? *p.limit : std::numeric_limits::max(); + while (itr != ua.end() && remaining > 0 && params_deadline > fc::time_point::now()) { + FC_CHECK_DEADLINE(deadline); + auto& r = result.trxs.emplace_back(); + r.trx_id = itr->id(); + r.expiration = itr->expiration(); + const auto& pt = itr->trx_meta->packed_trx(); + r.trx_type = get_trx_type( itr->trx_type, itr->trx_meta->read_only ); + r.first_auth = pt->get_transaction().first_authorizer(); + const auto& actions = pt->get_transaction().actions; + if( !actions.empty() ) { + r.first_receiver = actions[0].account; + r.first_action = actions[0].name; + } + r.total_actions = pt->get_transaction().total_actions(); + r.billed_cpu_time_us = itr->trx_meta->billed_cpu_time_us; + r.size = pt->get_estimated_size(); + + ++itr; + remaining--; + } + + if (itr != ua.end()) { + result.more = itr->id(); + } + + return result; +} + + std::optional producer_plugin_impl::calculate_next_block_time(const account_name& producer_name, const block_timestamp_type& current_block_time) const { chain::controller& chain = chain_plug->chain(); const auto& hbs = chain.head_block_state(); diff --git a/tests/plugin_http_api_test.py b/tests/plugin_http_api_test.py index 474fd0e83a..4739ec3823 100755 --- a/tests/plugin_http_api_test.py +++ b/tests/plugin_http_api_test.py @@ -1161,6 +1161,26 @@ def test_ProducerApi(self) : ret_json = Utils.runCmdReturnJson(valid_cmd) self.assertIn("rows", ret_json) + # get_unapplied_transactions with empty parameter + default_cmd = cmd_base + "get_unapplied_transactions" + ret_json = Utils.runCmdReturnJson(default_cmd) + self.assertIn("size", ret_json) + self.assertIn("incoming_size", ret_json) + # get_unapplied_transactions with empty content parameter + empty_content_cmd = default_cmd + self.http_post_str + self.empty_content_str + ret_json = Utils.runCmdReturnJson(empty_content_cmd) + self.assertIn("size", ret_json) + self.assertIn("incoming_size", ret_json) + # get_unapplied_transactions with invalid parameter + invalid_cmd = default_cmd + self.http_post_str + self.http_post_invalid_param + ret_json = Utils.runCmdReturnJson(invalid_cmd) + self.assertEqual(ret_json["code"], 400) + self.assertEqual(ret_json["error"]["code"], 3200006) + # get_unapplied_transactions with valid parameter + valid_cmd = default_cmd + self.http_post_str + ("'{\"lower_bound\":\"\", \"limit\":1, \"time_limit_ms\":500}'") + ret_json = Utils.runCmdReturnJson(valid_cmd) + self.assertIn("trxs", ret_json) + # test all wallet api def test_WalletApi(self) : cmd_base = self.base_wallet_cmd_str + "wallet/" From c7edfc6796312f4378a170c06c133b287bcac625 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Sat, 17 Sep 2022 12:39:48 -0500 Subject: [PATCH 061/111] GH-178 Allow longer time for node to sync up after fork --- tests/trx_finality_status_forked_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/trx_finality_status_forked_test.py b/tests/trx_finality_status_forked_test.py index 5e2b218f17..e9786abb25 100755 --- a/tests/trx_finality_status_forked_test.py +++ b/tests/trx_finality_status_forked_test.py @@ -245,13 +245,13 @@ def getState(status): "ERROR: The way the test is designed, the transaction should be added to a block that has a higher number than it was in originally before it was forked out." + \ f"\n\noriginal in block state: {json.dumps(originalInBlockState, indent=1)}\n\nafter fork in block state: {json.dumps(afterForkInBlockState, indent=1)}" - assert prodNodes[1].waitForBlock(afterForkInBlockState["block_number"], blockType=BlockType.lib), \ + assert prodNodes[1].waitForBlock(afterForkInBlockState["block_number"], timeout=120, blockType=BlockType.lib), \ f"ERROR: Block never finalized.\n\nprod 0 info: {json.dumps(prodNodes[0].getInfo(), indent=1)}\n\nprod 1 info: {json.dumps(prodNodes[1].getInfo(), indent=1)}" + \ f"\n\nafter fork in block state: {json.dumps(afterForkInBlockState, indent=1)}" retStatus = prodNodes[1].getTransactionStatus(transId) if afterForkBlockId != retStatus["block_id"]: # might have been forked out, if so wait for new block to become LIB - assert prodNodes[1].waitForBlock(retStatus["block_number"], blockType=BlockType.lib), \ + assert prodNodes[1].waitForBlock(retStatus["block_number"], timeout=120, blockType=BlockType.lib), \ f"ERROR: Block never finalized.\n\nprod 0 info: {json.dumps(prodNodes[0].getInfo(), indent=1)}\n\nprod 1 info: {json.dumps(prodNodes[1].getInfo(), indent=1)}" + \ f"\n\nafter fork in block state: {json.dumps(afterForkInBlockState, indent=1)}" From f548d3698b6d3fa71c785c50818abf299f90184e Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Sat, 17 Sep 2022 13:37:12 -0700 Subject: [PATCH 062/111] added get_unapplied_transactions to openapi docs --- .../producer_api_plugin/producer.swagger.yaml | 647 +++++++++++------- 1 file changed, 389 insertions(+), 258 deletions(-) diff --git a/plugins/producer_api_plugin/producer.swagger.yaml b/plugins/producer_api_plugin/producer.swagger.yaml index aea863a798..f7d235c593 100644 --- a/plugins/producer_api_plugin/producer.swagger.yaml +++ b/plugins/producer_api_plugin/producer.swagger.yaml @@ -6,7 +6,7 @@ info: name: MIT url: https://opensource.org/licenses/MIT contact: - url: https://eos.io + url: https://eosnetwork.com tags: - name: eosio servers: @@ -30,259 +30,162 @@ paths: /producer/pause: post: summary: pause - description: Pause producer node + description: Pause producer node. Takes no arguments returns no values. operationId: pause - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: boolean - description: "returns status" + $ref: '#/component/schema/OK' /producer/resume: post: summary: resume - description: Resume producer node + description: Resume producer node. Takes no arguments returns no values. operationId: resume - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - description: Resumes activity for producer responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' /producer/paused: post: summary: paused - description: Retreives paused status for producer node + description: Retreives paused status for producer node. Takes no arguments returns no values. operationId: paused - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: boolean - description: True if producer is paused, false otherwise + $ref: '#/component/schema/OK' /producer/get_runtime_options: post: summary: get_runtime_options - description: Retreives run time options for producer node + description: Retreives run time options for producer node. Only `incoming_defer_ratio` is a floating point number the other return values are signed integers. operationId: get_runtime_options - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: object - description: Returns run time options set for the producer - properties: - max_transaction_time: - type: integer - description: Max transaction time - max_irreversible_block_age: - type: integer - description: Max irreversible block age - produce_time_offset_us: - type: integer - description: Time offset - last_block_time_offset_us: - type: integer - description: Last block time offset - max_scheduled_transaction_time_per_block_ms: - type: integer - description: Max scheduled transaction time per block in ms - subjective_cpu_leeway_us: - type: integer - description: Subjective CPU leeway - incoming_defer_ratio: - type: integer - description: Incoming defer ration + $ref: '#/component/schema/Runtime_Options' + /producer/update_runtime_options: post: summary: update_runtime_options - description: Update run time options for producer node + description: Update run time options for producer node. May post any of the runtime options in combination or along. Only `incoming_defer_ratio` is a floating point number the other values are signed integers. operationId: update_runtime_options - parameters: [] requestBody: content: application/json: schema: - type: object - required: - - options - properties: - options: - type: object - description: Defines the run time options to set for the producer - properties: - max_transaction_time: - type: integer - description: Max transaction time - max_irreversible_block_age: - type: integer - description: Max irreversible block age - produce_time_offset_us: - type: integer - description: Time offset - last_block_time_offset_us: - type: integer - description: Last block time offset - max_scheduled_transaction_time_per_block_ms: - type: integer - description: Max scheduled transaction time per block in ms - subjective_cpu_leeway_us: - type: integer - description: Subjective CPU leeway - incoming_defer_ratio: - type: integer - description: Incoming defer ration + $ref: '#/component/schema/Runtime_Options' responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' /producer/get_greylist: post: summary: get_greylist - description: Retreives the greylist for producer node + description: Retreives the greylist for producer node. operationId: get_greylist - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: - type: array - description: List of account names stored in the greylist - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + type: object + properties: + accounts: + type: array + description: Array of account names stored in the greylist + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" /producer/add_greylist_accounts: post: summary: add_greylist_accounts - description: Adds accounts to grey list for producer node + description: Adds accounts to grey list for producer node. At least one account is required. operationId: add_greylist_accounts - parameters: [] requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - properties: - accounts: - type: array - description: List of account names to add - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + accounts: + type: array + description: List of account names to add + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/remove_greylist_accounts: post: summary: remove_greylist_accounts - description: Removes accounts from greylist for producer node + description: Removes accounts from greylist for producer node. At least one account is required. operationId: remove_greylist_accounts - parameters: [] requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - properties: - accounts: - type: array - description: List of account names to remove - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + accounts: + type: array + description: List of account names to remove + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - type: array - description: List of account names stored in the greylist - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - + $ref: '#/component/schema/OK' + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/get_whitelist_blacklist: post: summary: get_whitelist_blacklist - description: Retreives the white list and black list for producer node + description: Retreives the white list and black list for producer node. A json object containing whitelist and blacklist information. `actor_whitelist` , `actor_blacklist`, `contract_whitelist`, `contract_blacklist` are represented by an array of Names. `action_blacklist` is an array of tuples consisting of Name and Action. `key_blacklist` is an array of Public Keys. Name is a string represeting a NamePrivileged or NameBasic or NameBid or NameCatchAll operationId: get_whitelist_blacklist - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: schema: type: object - description: Defines the actor whitelist and blacklist, the contract whitelist and blacklist, the action blacklist and key blacklist properties: actor_whitelist: type: array @@ -317,106 +220,105 @@ paths: /producer/set_whitelist_blacklist: post: summary: set_whitelist_blacklist - description: Sets the white list and black list for producer node + description: Defines the whitelist and blacklist for a producer node. Takes a json object containing whitelist and blacklist information. At least one of actor_whitelist, actor_blacklist, contract_whitelist, contract_blacklist, action_blacklist, and key_blacklist is required. `actor_whitelist` , `actor_blacklist`, `contract_whitelist`, `contract_blacklist` take an array of Names. `action_blacklist` is an array of tuples consisting of Name and Action. `key_blacklist` is an array of Public Keys. Name is a string represeting a NamePrivileged or NameBasic or NameBid or NameCatchAll operationId: set_whitelist_blacklist - parameters: [] + required: true requestBody: content: application/json: schema: type: object - required: - - params properties: - params: - type: object - description: Defines the actor whitelist and blacklist, the contract whitelist and blacklist, the action blacklist and key blacklist - properties: - actor_whitelist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - actor_blacklist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - contract_whitelist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - contract_blacklist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - action_blacklist: - type: array - items: - type: array - description: Array of two string values, the account name as the first and action name as the second - items: - allOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/CppSignature.yaml" - key_blacklist: - type: array - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/KeyType.yaml" - + actor_whitelist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + actor_blacklist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + contract_whitelist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + contract_blacklist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + action_blacklist: + type: array + items: + type: array + description: Array of two string values, the account name as the first and action name as the second + items: + anyOf: + - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + - $ref: "https://eosio.github.io/schemata/v2.0/oas/CppSignature.yaml" + key_blacklist: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/KeyType.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' + + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' + /producer/create_snapshot: post: summary: create_snapshot - description: Creates a snapshot for producer node + description: Creates a snapshot for producer node. Returns error when unable to create snapshot. operationId: create_snapshot - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - required: - - next - properties: - next: - type: object - description: Defines the snapshot to be created - properties: - snapshot_name: - type: string - description: The name of the snapshot - head_block_id: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" - - responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + type: object + properties: + head_block_id: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + head_block_num: + type: integer + descripiton: Highest block number on the chain + example: 5102 + head_block_time: + type: string + description: Highest block unix timestamp + example: 2020-11-16T00:00:00.000 + version: + type: integer + description: version number + example: 6 + snapshot_name: + type: string + description: The path and file name of the snapshot + example: /home/me/nodes/node-name/snapshots/snapshot-0000999f99999f9f999f99f99ff9999f999f9fff99ff99ffff9f9f9fff9f9999.bin + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/get_integrity_hash: post: summary: get_integrity_hash description: Retreives the integrity hash for producer node operationId: get_integrity_hash - parameters: [] - requestBody: - content: - application/json: - schema: - type: object - properties: {} responses: - "200": + "201": description: OK content: application/json: @@ -424,74 +326,303 @@ paths: type: object description: Defines the integrity hash information details properties: - integrity_hash: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" head_block_id: $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + integrity_hash: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" /producer/schedule_protocol_feature_activations: post: summary: schedule_protocol_feature_activations - description: Schedule protocol feature activation for producer node + description: Schedule protocol feature activation for producer node. Note some features may require pre-activation. Will return error for duplicate requests or when feature required pre-activation. operationId: schedule_protocol_feature_activations - parameters: [] requestBody: content: application/json: schema: type: object - required: - - schedule properties: - schedule: - type: object - properties: - protocol_features_to_activate: - type: array - description: List of protocol features to activate - items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" - + protocol_features_to_activate: + type: array + description: List of protocol features to activate + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" responses: - "200": + "201": description: OK content: application/json: schema: - description: Returns Nothing + $ref: '#/component/schema/OK' + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' /producer/get_supported_protocol_features: post: summary: get_supported_protocol_features - description: Retreives supported protocol features for producer node + description: Retreives supported protocol features for producer node. Pass filters in as part of the request body. operationId: get_supported_protocol_features - parameters: [] requestBody: content: application/json: schema: type: object - required: - - params properties: - params: + exclude_disabled: + type: boolean + description: Exclude disabled protocol features + exclude_unactivatable: + type: boolean + description: Exclude unactivatable protocol features + example: false + responses: + "201": + description: OK + content: + application/json: + schema: + type: array + description: Variant type, an array of strings with the supported protocol features + items: type: object - description: Defines filters based on which to return the supported protocol features properties: - exclude_disabled: - type: boolean - description: Exclude disabled protocol features - exclude_unactivatable: - type: boolean - description: Exclude unactivatable protocol features + feature_digest: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + subjective_restrictions: + type: object + properties: + enabled: + type: boolean + example: true + preactivation_required: + type: boolean + example: true + earliest_allowed_activation_time: + type: string + example: "1970-01-01T00:00:00.000" + description_digest: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + dependancies: + type: array + items: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + protocol_feature_type: + type: string + example: "builtin" + specification: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + + /producer/get_account_ram_corrections: + post: + summary: get_account_ram_corrections + description: Retreives accounts with ram corrections. + operationId: get_account_ram_corrections + requestBody: + content: + application/json: + schema: + type: object + properties: + lower_bound: + type: int + description: lowest account key + upper_bound: + type: int + description: highest account key + limit: + type: int + description: number of rows to scans + example: 10 + reverse: + type: boolean + description: direction of search + example: false + responses: + "201": + description: OK + content: + application/json: + schema: + type: object + properties: + rows: + type: array + items: + type: string + + /producer/producer/get_unapplied_transactions: + post: + summary: get_unapplied_transactions + description: Get Unapplied Transactions. No required parameters. + operationId: get_unapplied_transactions + requestBody: + content: + application/json: + schema: + type: object + properties: + limit: + type: int + description: number of transactions to return, defaults to 4,294,967,295 + example: 2 + lower_bound: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + time_limit_ms: + type: int + description: defaults to 10ms + example: 10 responses: "200": description: OK content: application/json: schema: - type: array - description: Variant type, an array of strings with the supported protocol features - items: - type: string + type: object + properties: + size: + type: integer + example: 12428 + incoming_size: + type: integer + example: 4475 + trxs: + type: array + items: + type: object + properties: + trx_id: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + expiration: + type: string + example: "2022-09-17T16:30:16" + trx_type: + type: string + example: "aborted" + first_auth: + type: string + example: "jkbsg.wam" + first_receiver: + type: string + example: "m.federation" + first_action: + type: string + example: "mine" + total_actions: + type: integer + example: 1 + billed_cpu_time_us: + type: integer + example: 504 + size: + type: integer + example: 934 + more: + $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + "400": + description: client error + content: + application/json: + schema: + $ref: '#/component/schema/Error' + +component: + schema: + Error: + type: object + properties: + code: + type: integer + description: http return code + example: 400 + message: + type: string + description: summary of error + example: Invalid Request + error: + type: object + description: details on the error + properties: + code: + type: integer + description: internal error code + example: 3200006 + name: + type: string + description: name of error + example: invalid_http_request + what: + type: string + description: prettier version of error name + example: invalid http request + details: + type: array + description: list of additional information for debugging + items: + type: object + properties: + message: + type: string + description: debugging message + example: Unable to parse valid input from POST body + file: + type: string + description: file where error was thrown + example: http_plugin.hpp + line_number: + type: integer + description: line number in file where error was thrown + example: 246 + method: + type: string + description: function executed when error occured + example: parse_params + OK: + type: object + properties: + result: + type: string + description: status + example: ok + Runtime_Options: + type: object + properties: + max_transaction_time: + type: integer + description: Max transaction time + example: 100 + max_irreversible_block_age: + type: integer + description: Max irreversible block age + example: -1 + produce_time_offset_us: + type: integer + description: Time offset + example: -100000 + last_block_time_offset_us: + type: integer + description: Last block time offset + example: -200000 + max_scheduled_transaction_time_per_block_ms: + type: integer + description: Max scheduled transaction time per block in ms + example: 100 + incoming_defer_ratio: + type: string + description: Incoming defer ration, parsed to double + example: "1.00000000000000000" + greylist_limit: + type: integer + description: limit on number of Names supported by greylist + example: 1000 From 9718e528024c7f71b18805b2593fd90142bd68b0 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Sun, 18 Sep 2022 22:43:14 -0400 Subject: [PATCH 063/111] label new issues with 'triage' label and add them to org project --- .github/workflows/label_new_issues.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/label_new_issues.yaml diff --git a/.github/workflows/label_new_issues.yaml b/.github/workflows/label_new_issues.yaml new file mode 100644 index 0000000000..79753dbccc --- /dev/null +++ b/.github/workflows/label_new_issues.yaml @@ -0,0 +1,17 @@ +name: Label New Issue + +on: + issues: + types: opened + +jobs: + label_new_issue: + uses: AntelopeIO/issue-project-labeler-workflow/.github/workflows/issue-project-labeler.yaml@v1 + with: + issue-id: ${{github.event.issue.node_id}} + label: triage + org-project: 'Team Backlog' + project-field: Status=Todo + secrets: + token: ${{secrets.ENFCIBOT_REPO_AND_PROJECTS}} + From 18d7287461021dcfe710af061de3c5f7199dd13d Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:40:08 -0400 Subject: [PATCH 064/111] make ship recovery logging be at info level --- libraries/state_history/include/eosio/state_history/log.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/state_history/include/eosio/state_history/log.hpp b/libraries/state_history/include/eosio/state_history/log.hpp index d0c7a356f9..40fb5b95fa 100644 --- a/libraries/state_history/include/eosio/state_history/log.hpp +++ b/libraries/state_history/include/eosio/state_history/log.hpp @@ -296,7 +296,7 @@ class state_history_log { break; pos = pos + state_history_log_header_serial_size + header.payload_size + sizeof(suffix); if (!(++num_found % 10000)) { - dlog("${num_found} blocks found, log pos = ${pos}", ("num_found", num_found)("pos", pos)); + ilog("${num_found} blocks found, log pos = ${pos}", ("num_found", num_found)("pos", pos)); } } log.flush(); @@ -390,7 +390,7 @@ class state_history_log { index.skip(-sizeof(uint64_t)); if (!(remaining % 10000)) - dlog("${remaining} blocks remaining, log pos = ${pos}", ("num_found", remaining)("pos", pos)); + ilog("${remaining} blocks remaining, log pos = ${pos}", ("num_found", remaining)("pos", pos)); } } From 84f6fed4baa67ba53d71ad2312127b8bb4f6e428 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Wed, 21 Sep 2022 07:26:37 -0700 Subject: [PATCH 065/111] updated schema references to eosnetwork host --- plugins/chain_api_plugin/chain.swagger.yaml | 96 +++++++++---------- plugins/net_api_plugin/net.swagger.yaml | 32 +++---- .../producer_api_plugin/producer.swagger.yaml | 54 +++++------ .../test_control.swagger.yaml | 2 +- .../trace_api_plugin/trace_api.swagger.yaml | 4 +- 5 files changed, 94 insertions(+), 94 deletions(-) diff --git a/plugins/chain_api_plugin/chain.swagger.yaml b/plugins/chain_api_plugin/chain.swagger.yaml index 28063b4cc8..dc743cdfc0 100644 --- a/plugins/chain_api_plugin/chain.swagger.yaml +++ b/plugins/chain_api_plugin/chain.swagger.yaml @@ -37,14 +37,14 @@ paths: - account_name properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" responses: "200": description: OK content: application/json: schema: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Account.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Account.yaml" /get_block: post: description: Returns an object containing various details about a specific block on the blockchain. @@ -66,7 +66,7 @@ paths: content: application/json: schema: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Block.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Block.yaml" /get_block_info: post: description: Similar to `get_block` but returns a fixed-size smaller subset of the block data. @@ -100,7 +100,7 @@ paths: content: application/json: schema: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Info.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Info.yaml" /push_transaction: post: @@ -116,7 +116,7 @@ paths: type: array description: array of signatures required to authorize transaction items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Signature.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Signature.yaml" compression: type: boolean description: Compression used, usually false @@ -148,7 +148,7 @@ paths: type: array description: array of signatures required to authorize transaction items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Signature.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Signature.yaml" compression: type: boolean description: Compression used, usually false @@ -177,7 +177,7 @@ paths: schema: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Transaction.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Transaction.yaml" responses: "200": description: OK @@ -208,7 +208,7 @@ paths: content: application/json: schema: - $ref: "https://eosio.github.io/schemata/v2.0/oas/BlockHeaderState.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockHeaderState.yaml" /get_abi: post: @@ -223,14 +223,14 @@ paths: - account_name properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" responses: "200": description: OK content: application/json: schema: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Abi.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Abi.yaml" /get_currency_balance: post: description: Retrieves the current balance @@ -246,11 +246,11 @@ paths: - symbol properties: code: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" account: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" symbol: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Symbol.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Symbol.yaml" responses: "200": @@ -260,7 +260,7 @@ paths: schema: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Symbol.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Symbol.yaml" /get_currency_stats: post: @@ -273,9 +273,9 @@ paths: type: object properties: code: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" symbol: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Symbol.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Symbol.yaml" responses: "200": @@ -299,12 +299,12 @@ paths: - available_keys properties: transaction: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Transaction.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Transaction.yaml" available_keys: type: array description: Provide the available keys items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/PublicKey.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/PublicKey.yaml" responses: "200": description: OK @@ -356,17 +356,17 @@ paths: type: array nullable: true items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/ProducerSchedule.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/ProducerSchedule.yaml" pending: type: array nullable: true items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/ProducerSchedule.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/ProducerSchedule.yaml" proposed: type: array nullable: true items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/ProducerSchedule.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/ProducerSchedule.yaml" /get_raw_code_and_abi: @@ -382,7 +382,7 @@ paths: - account_name properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" responses: "200": @@ -393,7 +393,7 @@ paths: type: object properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" wasm: type: string description: base64 encoded wasm @@ -412,7 +412,7 @@ paths: type: object properties: lower_bound: - $ref: "https://eosio.github.io/schemata/v2.0/oas/DateTimeSeconds.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/DateTimeSeconds.yaml" limit: description: The maximum number of transactions to return type: integer @@ -430,7 +430,7 @@ paths: transactions: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Transaction.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Transaction.yaml" /get_table_by_scope: @@ -481,9 +481,9 @@ paths: rows: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/TableScope.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/TableScope.yaml" more: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" /get_table_rows: post: @@ -563,9 +563,9 @@ paths: - args properties: code: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" action: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" args: type: object description: json object of the action parameters that will be serialized. @@ -579,7 +579,7 @@ paths: type: object properties: binargs: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Hex.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Hex.yaml" /abi_bin_to_json: post: @@ -597,11 +597,11 @@ paths: - binargs properties: code: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" action: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" binargs: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Hex.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Hex.yaml" responses: "200": description: OK @@ -624,7 +624,7 @@ paths: - code_as_wasm properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" code_as_wasm: type: integer default: 1 @@ -639,15 +639,15 @@ paths: title: GetCodeResponse.yaml properties: name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" code_hash: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" wast: type: string wasm: type: string abi: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Abi.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Abi.yaml" /get_raw_abi: post: @@ -662,7 +662,7 @@ paths: - account_name properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" responses: "200": description: OK @@ -672,12 +672,12 @@ paths: type: object properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" code_hash: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" abi_hash: allOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" abi: type: string @@ -741,13 +741,13 @@ paths: description: List of authorizing accounts and/or actor/permissions items: anyOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Authority.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Authority.yaml" keys: type: array description: List of authorizing keys items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/PublicKey.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/PublicKey.yaml" responses: "200": description: OK @@ -773,13 +773,13 @@ paths: - threshold properties: account_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" permission_name: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" authorizer: oneOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/PublicKey.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Authority.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/PublicKey.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Authority.yaml" weight: type: "integer" description: the weight that this authorizer adds to satisfy the permission diff --git a/plugins/net_api_plugin/net.swagger.yaml b/plugins/net_api_plugin/net.swagger.yaml index 4bba46ef39..2c895a1604 100644 --- a/plugins/net_api_plugin/net.swagger.yaml +++ b/plugins/net_api_plugin/net.swagger.yaml @@ -61,17 +61,17 @@ paths: description: Incremental value above a computed base type: integer chain_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' node_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' key: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/PublicKey.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/PublicKey.yaml' time: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/DateTimeSeconds.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/DateTimeSeconds.yaml' token: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' sig: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Signature.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Signature.yaml' p2p_address: description: IP address or URL of the peer type: string @@ -79,12 +79,12 @@ paths: description: Last irreversible block number type: integer last_irreversible_block_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' head_num: description: Head number type: integer head_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' os: description: Operating system name type: string @@ -190,17 +190,17 @@ paths: description: Incremental value above a computed base type: integer chain_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' node_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' key: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/PublicKey.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/PublicKey.yaml' time: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/DateTimeSeconds.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/DateTimeSeconds.yaml' token: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' sig: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Signature.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Signature.yaml' p2p_address: description: IP address or URL of the peer type: string @@ -208,12 +208,12 @@ paths: description: Last irreversible block number type: integer last_irreversible_block_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' head_num: description: Head number type: integer head_id: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml' os: description: Operating system name type: string diff --git a/plugins/producer_api_plugin/producer.swagger.yaml b/plugins/producer_api_plugin/producer.swagger.yaml index f7d235c593..2942309d57 100644 --- a/plugins/producer_api_plugin/producer.swagger.yaml +++ b/plugins/producer_api_plugin/producer.swagger.yaml @@ -111,7 +111,7 @@ paths: type: array description: Array of account names stored in the greylist items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" /producer/add_greylist_accounts: post: @@ -128,7 +128,7 @@ paths: type: array description: List of account names to add items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" responses: "201": @@ -158,7 +158,7 @@ paths: type: array description: List of account names to remove items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" responses: "201": @@ -190,19 +190,19 @@ paths: actor_whitelist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" actor_blacklist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" contract_whitelist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" contract_blacklist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" action_blacklist: type: array items: @@ -210,12 +210,12 @@ paths: description: Array of two string values, the account name as the first and action name as the second items: allOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/CppSignature.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/CppSignature.yaml" key_blacklist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/KeyType.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/KeyType.yaml" /producer/set_whitelist_blacklist: post: @@ -232,19 +232,19 @@ paths: actor_whitelist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" actor_blacklist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" contract_whitelist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" contract_blacklist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" action_blacklist: type: array items: @@ -252,12 +252,12 @@ paths: description: Array of two string values, the account name as the first and action name as the second items: anyOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/Name.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/CppSignature.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Name.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/CppSignature.yaml" key_blacklist: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/KeyType.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/KeyType.yaml" responses: "201": description: OK @@ -287,7 +287,7 @@ paths: type: object properties: head_block_id: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" head_block_num: type: integer descripiton: Highest block number on the chain @@ -327,9 +327,9 @@ paths: description: Defines the integrity hash information details properties: head_block_id: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" integrity_hash: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" /producer/schedule_protocol_feature_activations: post: @@ -346,7 +346,7 @@ paths: type: array description: List of protocol features to activate items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" responses: "201": description: OK @@ -391,7 +391,7 @@ paths: type: object properties: feature_digest: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" subjective_restrictions: type: object properties: @@ -405,11 +405,11 @@ paths: type: string example: "1970-01-01T00:00:00.000" description_digest: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" dependancies: type: array items: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" protocol_feature_type: type: string example: "builtin" @@ -478,7 +478,7 @@ paths: description: number of transactions to return, defaults to 4,294,967,295 example: 2 lower_bound: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" time_limit_ms: type: int description: defaults to 10ms @@ -503,7 +503,7 @@ paths: type: object properties: trx_id: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" expiration: type: string example: "2022-09-17T16:30:16" @@ -529,7 +529,7 @@ paths: type: integer example: 934 more: - $ref: "https://eosio.github.io/schemata/v2.0/oas/Sha256.yaml" + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" "400": description: client error content: diff --git a/plugins/test_control_api_plugin/test_control.swagger.yaml b/plugins/test_control_api_plugin/test_control.swagger.yaml index 906fe76ea8..df0d07cdf1 100644 --- a/plugins/test_control_api_plugin/test_control.swagger.yaml +++ b/plugins/test_control_api_plugin/test_control.swagger.yaml @@ -44,7 +44,7 @@ paths: type: object properties: producer: - $ref: 'https://eosio.github.io/schemata/v2.0/oas/Name.yaml' + $ref: 'https://docs.eosnetwork.com/openapi/v2.0/Name.yaml' where_in_sequence: type: integer based_on_lib: diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index 2c5f5dc78e..c1ad3694c5 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -44,8 +44,8 @@ paths: application/json: schema: oneOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/BlockTraceV0.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/BlockTraceV1.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV0.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV1.yaml" "400": description: Error - requested block number is invalid (not a number, larger than max int) "404": From 3b57d5a258bb5e9bddb35d862da8a5b292ee5d3e Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 21 Sep 2022 10:48:13 -0500 Subject: [PATCH 066/111] GH-139 Update cleos to return an error code on failed trx processing similar to before --return-failure-trace was added. --- .../eosio/chain_plugin/chain_plugin.hpp | 4 +- programs/cleos/main.cpp | 40 ++++++++++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index 9f5a523a12..9b408e70e0 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -441,7 +441,7 @@ class read_only { get_scheduled_transactions_result get_scheduled_transactions( const get_scheduled_transactions_params& params ) const; struct compute_transaction_results { chain::transaction_id_type transaction_id; - fc::variant processed; + fc::variant processed; // "processed" is expected JSON for trxs in cleos }; struct compute_transaction_params { @@ -666,7 +666,7 @@ class read_write { using push_transaction_params = fc::variant_object; struct push_transaction_results { chain::transaction_id_type transaction_id; - fc::variant processed; + fc::variant processed; // "processed" is expected JSON for trxs in cleos }; void push_transaction(const push_transaction_params& params, chain::plugin_interface::next_function next); diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 178109a0b5..896eaf33f4 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -188,6 +188,7 @@ bool print_request = false; bool print_response = false; bool no_auto_keosd = false; bool verbose = false; +int return_code = 0; uint8_t tx_max_cpu_usage = 0; uint32_t tx_max_net_usage = 0; @@ -538,6 +539,31 @@ void print_action_tree( const fc::variant& action ) { } } +int get_return_code( const fc::variant& result ) { + // if a trx with a processed, then check to see if it failed execution for return value + int r = 0; + if (result.is_object() && result.get_object().contains("processed")) { + const auto& processed = result["processed"]; + if( processed.get_object().contains( "except" ) ) { + try { + auto soft_except = processed["except"].as>(); + if( soft_except ) { + auto code = soft_except->code(); + if( code > std::numeric_limits::max() ) { + r = 1; + } else { + r = static_cast( code ); + } + } + if( r == 0 ) r = 1; + } catch( ... ) { + r = 1; + } + } + } + return r; +} + void print_result( const fc::variant& result ) { try { if (result.is_object() && result.get_object().contains("processed")) { const auto& processed = result["processed"]; @@ -600,6 +626,7 @@ void send_actions(std::vector&& actions, packed_transaction::comp out << jsonstr; out.close(); } + return_code = get_return_code( result ); if( tx_print_json ) { if (jsonstr.length() == 0) { jsonstr = fc::json::to_pretty_string( result ); @@ -624,6 +651,7 @@ void send_transaction( signed_transaction& trx, packed_transaction::compression_ out << jsonstr; out.close(); } + return_code = get_return_code( result ); if( tx_print_json ) { if (jsonstr.length() == 0) { jsonstr = fc::json::to_pretty_string( result ); @@ -4136,14 +4164,16 @@ int main( int argc, char** argv ) { } return 1; } catch ( const std::bad_alloc& ) { - elog("bad alloc"); + elog("bad alloc"); + return 1; } catch( const boost::interprocess::bad_alloc& ) { - elog("bad alloc"); + elog("bad alloc"); + return 1; } catch (const fc::exception& e) { - return handle_error(e); + return handle_error(e); } catch (const std::exception& e) { - return handle_error(fc::std_exception_wrapper::from_current_exception(e)); + return handle_error(fc::std_exception_wrapper::from_current_exception(e)); } - return 0; + return return_code; } From ea7e3a34ea6f2497320070112f025e264f5f0c1c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 21 Sep 2022 13:12:55 -0500 Subject: [PATCH 067/111] GH-139 Fix for setting error code when no error actually happened. --- programs/cleos/main.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 896eaf33f4..572c2a6c5b 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -545,19 +545,22 @@ int get_return_code( const fc::variant& result ) { if (result.is_object() && result.get_object().contains("processed")) { const auto& processed = result["processed"]; if( processed.get_object().contains( "except" ) ) { - try { - auto soft_except = processed["except"].as>(); - if( soft_except ) { - auto code = soft_except->code(); - if( code > std::numeric_limits::max() ) { - r = 1; - } else { - r = static_cast( code ); + const auto& except = processed["except"]; + if( except.is_object() ) { + try { + auto soft_except = except.as>(); + if( soft_except ) { + auto code = soft_except->code(); + if( code > std::numeric_limits::max() ) { + r = 1; + } else { + r = static_cast( code ); + } + if( r == 0 ) r = 1; } + } catch( ... ) { + r = 1; } - if( r == 0 ) r = 1; - } catch( ... ) { - r = 1; } } } From 04a831e77ab4c935cedc82ab93683ef150bfb93f Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 21 Sep 2022 14:48:59 -0500 Subject: [PATCH 068/111] GH-139 On cleos failure capture both stderr and stdout in output as some tests are expecting to find errors in the trace. --- tests/Node.py | 2 +- tests/prod_preactivation_test.py | 5 +++-- tests/testUtils.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/Node.py b/tests/Node.py index bc133bedd1..dbc9f50f60 100644 --- a/tests/Node.py +++ b/tests/Node.py @@ -776,7 +776,7 @@ def publishContract(self, account, contractDir, wasmFile, abiFile, waitForTransB if shouldFail: if trans["processed"]["except"] != None: retMap={} - retMap["returncode"]=0 + retMap["returncode"]=1 retMap["cmd"]=cmd retMap["output"]=bytes(str(trans),'utf-8') return retMap diff --git a/tests/prod_preactivation_test.py b/tests/prod_preactivation_test.py index 406366dacd..2930caf46f 100755 --- a/tests/prod_preactivation_test.py +++ b/tests/prod_preactivation_test.py @@ -112,8 +112,9 @@ Print("publish a new bios contract %s should fails because env.is_feature_activated unresolveable" % (contractDir)) retMap = node0.publishContract("eosio", contractDir, wasmFile, abiFile, True, shouldFail=True) - if retMap["output"].decode("utf-8").find("unresolveable") < 0: - errorExit("bios contract not result in expected unresolveable error") + outPut = retMap["output"].decode("utf-8") + if outPut.find("unresolveable") < 0: + errorExit(f"bios contract not result in expected unresolveable error: {outPut}") secwait = 30 Print("Wait for node 1 to produce...") diff --git a/tests/testUtils.py b/tests/testUtils.py index e4fa9ec599..8af001722e 100755 --- a/tests/testUtils.py +++ b/tests/testUtils.py @@ -205,7 +205,8 @@ def checkDelayedOutput(popen, cmd, ignoreError=False): Utils.checkOutputFileWrite(start, cmd, output, error) if popen.returncode != 0 and not ignoreError: Utils.Print("ERROR: %s" % error) - raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=error) + # for now just include both stderr and stdout in output + raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=error+" "+output) return output.decode("utf-8") @staticmethod From 89466843df10169cf3e098e8a1c8e68834d56349 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 21 Sep 2022 15:06:54 -0500 Subject: [PATCH 069/111] GH-139 stdout,stderr are byte arrays --- tests/testUtils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testUtils.py b/tests/testUtils.py index 8af001722e..55c225d530 100755 --- a/tests/testUtils.py +++ b/tests/testUtils.py @@ -205,8 +205,8 @@ def checkDelayedOutput(popen, cmd, ignoreError=False): Utils.checkOutputFileWrite(start, cmd, output, error) if popen.returncode != 0 and not ignoreError: Utils.Print("ERROR: %s" % error) - # for now just include both stderr and stdout in output - raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=error+" "+output) + # for now just include both stderr and stdout in output, python 3.5+ supports both a stdout and stderr attributes + raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=error+bytes(" ", 'utf-8')+output) return output.decode("utf-8") @staticmethod From 77d4029a12364b53b3e0e7bad39cef740f7687f3 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Wed, 21 Sep 2022 22:24:39 -0400 Subject: [PATCH 070/111] add missing incoming_persisted in get_trx_type --- plugins/producer_plugin/producer_plugin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 8e4ebdf9d7..52bf9dad1a 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -1470,6 +1470,8 @@ producer_plugin::get_unapplied_transactions( const get_unapplied_transactions_pa return "forked"; case trx_enum_type::aborted: return "aborted"; + case trx_enum_type::incoming_persisted: + return "incoming_persisted"; case trx_enum_type::incoming: return "incoming"; } From 79d74aca1bd1087687c2ed303cd0b694b5b38377 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Wed, 21 Sep 2022 22:36:05 -0400 Subject: [PATCH 071/111] remove elog when ship thread exits --- libraries/state_history/include/eosio/state_history/log.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/state_history/include/eosio/state_history/log.hpp b/libraries/state_history/include/eosio/state_history/log.hpp index bf546de137..05f64ed45d 100644 --- a/libraries/state_history/include/eosio/state_history/log.hpp +++ b/libraries/state_history/include/eosio/state_history/log.hpp @@ -141,7 +141,6 @@ class state_history_log { eptr = std::current_exception(); write_thread_has_exception = true; } - elog("${name} thread ended", ("name", this->name)); }); } From 8282cd5a90790fc4bede127b486ad876686a7834 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 21 Sep 2022 22:48:38 -0500 Subject: [PATCH 072/111] GH-139 verify is an object before get_object --- programs/cleos/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 572c2a6c5b..3781f91bc7 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -544,7 +544,7 @@ int get_return_code( const fc::variant& result ) { int r = 0; if (result.is_object() && result.get_object().contains("processed")) { const auto& processed = result["processed"]; - if( processed.get_object().contains( "except" ) ) { + if( processed.is_object() && processed.get_object().contains( "except" ) ) { const auto& except = processed["except"]; if( except.is_object() ) { try { From 8aca9cbd17112eb4bc4f7442fcee3e177adb010a Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 13:57:13 -0400 Subject: [PATCH 073/111] replace EOSIO refs with Antelope if applicable :doc --- .../00_build-unsupported-os.md | 2 +- docs/00_install/01_build-from-source/index.md | 2 +- docs/00_install/index.md | 14 +++++++------- .../02_node-setups/00_producing-node.md | 8 ++++---- .../02_node-setups/01_non-producing-node.md | 8 ++++---- .../00_local-single-node-testnet.md | 4 ++-- .../01_local-multi-node-testnet.md | 8 ++++---- .../03_development-environment/index.md | 2 +- .../01_nodeos/03_plugins/chain_plugin/index.md | 2 +- .../01_nodeos/03_plugins/login_plugin/index.md | 2 +- .../03_plugins/producer_plugin/index.md | 4 ++-- ...10_how-to-fast-start-without-old-history.md | 2 +- ...ow-to-replay-or-resync-with-full-history.md | 2 +- ...how-to-create-snapshot-with-full-history.md | 2 +- ...ow-to-restore-snapshot-with-full-history.md | 2 +- .../03_plugins/trace_api_plugin/index.md | 8 ++++---- docs/01_nodeos/06_logging/index.md | 4 ++-- .../07_concepts/05_storage-and-read-modes.md | 6 +++--- .../07_concepts/10_context-free-data/index.md | 2 +- docs/01_nodeos/08_troubleshooting/index.md | 4 ++-- docs/01_nodeos/index.md | 6 +++--- .../02_how-to-guides/how-to-create-a-wallet.md | 2 +- .../how-to-create-an-account.md | 10 +++++----- .../how-to-create-key-pairs.md | 6 +++--- .../how-to-delegate-CPU-resource.md | 6 +++--- .../how-to-delegate-net-resource.md | 6 +++--- .../how-to-deploy-a-smart-contract.md | 2 +- .../how-to-get-account-information.md | 10 +++++----- .../how-to-get-block-information.md | 4 ++-- .../how-to-get-transaction-information.md | 6 +++--- .../02_how-to-guides/how-to-import-a-key.md | 4 ++-- .../how-to-list-all-key-pairs.md | 4 ++-- .../03_command-reference/create/account.md | 2 +- .../03_command-reference/net/connect.md | 2 +- .../03_command-reference/net/disconnect.md | 2 +- .../02_cleos/03_command-reference/net/peers.md | 2 +- .../03_command-reference/net/status.md | 2 +- .../03_command-reference/set/set-account.md | 2 +- docs/02_cleos/04_troubleshooting.md | 2 +- docs/02_cleos/index.md | 6 +++--- docs/03_keosd/index.md | 4 ++-- docs/10_utilities/index.md | 6 +++--- docs/index.md | 18 +++++++++--------- 43 files changed, 101 insertions(+), 101 deletions(-) diff --git a/docs/00_install/01_build-from-source/00_build-unsupported-os.md b/docs/00_install/01_build-from-source/00_build-unsupported-os.md index a9988c0215..e5cffe252d 100644 --- a/docs/00_install/01_build-from-source/00_build-unsupported-os.md +++ b/docs/00_install/01_build-from-source/00_build-unsupported-os.md @@ -1,5 +1,5 @@ --- -content_title: Build EOSIO from Source on Other Unix-based OS +content_title: Build Antelope from Source on Other Unix-based OS --- **Please keep in mind that instructions for building from source on other unsupported operating systems provided here should be considered experimental and provided AS-IS on a best-effort basis and may not be fully featured.** diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index d2a817d01b..7cffd45e4a 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -1,5 +1,5 @@ --- -content_title: Build EOSIO from Source +content_title: Build Antelope from Source --- The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests. diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 23a61b3271..1d711083d3 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -1,26 +1,26 @@ --- -content_title: EOSIO Software Installation +content_title: Antelope Software Installation --- -The best way to install and use the EOSIO software is to build it from source: +The best way to install and use the Antelope software is to build it from source: -* [Build EOSIO from Source](01_build-from-source/index.md) +* [Build Antelope from Source](01_build-from-source/index.md) ## Supported Operating Systems -EOSIO currently supports the following operating systems: +Antelope currently supports the following operating systems: 1. Ubuntu 18.04 2. Ubuntu 20.04 3. Ubuntu 22.04 [[info | Note]] -| It may be possible to build and install EOSIO on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported. +| It may be possible to build and install Antelope on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported. -* [Build EOSIO on Other Unix-based Systems](01_build-from-source/00_build-unsupported-os.md) +* [Build Antelope on Other Unix-based Systems](01_build-from-source/00_build-unsupported-os.md) ## Docker Utilities for Node Execution (D.U.N.E.) -If you are using different operating system or prefer not to build EOSIO from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring EOSIO and doing contract development pretty much instantly +If you are using different operating system or prefer not to build Antelope from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring Antelope and doing contract development pretty much instantly * [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/eosnetworkfoundation/DUNE) diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index 7bb7d2a2ba..edcc593276 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -7,15 +7,15 @@ content_title: Producing Node Setup ## Goal -This section describes how to set up a producing node within the EOSIO network. A producing node, as its name implies, is a node that is configured to produce blocks in an `EOSIO` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). +This section describes how to set up a producing node within the Antelope network. A producing node, as its name implies, is a node that is configured to produce blocks in an `Antelope` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) -[//]: # ( If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -53,7 +53,7 @@ producer-name = youraccount You will need to set the private key for your producer. The public key should have an authority for the producer account defined above. `signature-provider` is defined with a 3-field tuple: -* `public-key` - A valid EOSIO public key in form of a string. +* `public-key` - A valid Antelope public key in form of a string. * `provider-spec` - It's a string formatted like `:` * `provider-type` - KEY or KEOSD diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index b85a014c34..b0e5c9cc31 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -4,15 +4,15 @@ content_title: Non-producing Node Setup ## Goal -This section describes how to set up a non-producing node within the EOSIO network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `EOSIO` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. +This section describes how to set up a non-producing node within the Antelope network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `Antelope` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT NEXT LINK CONTAINS A BROKEN LINK ) -[//]: # ( If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -41,4 +41,4 @@ nodeos ... --p2p-peer-address=106.10.42.238:9876 ### 2. Enable one or more available plugins -Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the EOSIO RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. +Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the Antelope RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index 4b0f8d1b56..a55d817774 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -12,11 +12,11 @@ This section describes how to set up a single-node blockchain configuration runn ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # (THIS IS A COMMENT, NEXT LINK HAS BROKEN LINK) -[//]: # (If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) +[//]: # (If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 698f0414de..52a7c8dfb8 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -10,7 +10,7 @@ This section describes how to set up a multi-node blockchain configuration runni ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -20,7 +20,7 @@ Open four "terminal" windows and perform the following steps: 1. [Start the Wallet Manager](#1-start-the-wallet-manager) 2. [Create a Default Wallet](#2-create-a-default-wallet) -3. [Loading the EOSIO Key](#3-loading-the-eosio-key) +3. [Loading the Antelope Key](#3-loading-the-eosio-key) 4. [Start the First Producer Node](#4-start-the-first-producer-node) 5. [Start the Second Producer Node](#5-start-the-second-producer-node) 6. [Get Nodes Info](#6-get-nodes-info) @@ -66,7 +66,7 @@ Without password imported keys will not be retrievable. `keosd` will generate some status output in its window. We will continue to use this second window for subsequent `cleos` commands. -### 3. Loading the EOSIO Key +### 3. Loading the Antelope Key The private blockchain launched in the steps above is created with a default initial key which must be loaded into the wallet. @@ -90,7 +90,7 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node -The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the EOSIO binaries. +The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the Antelope binaries. To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index 9305397d45..4ed1302c63 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -23,7 +23,7 @@ Try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundatio ## Third-Party Testnets -The following third-party testnets are available for testing EOSIO dApps and smart contracts: +The following third-party testnets are available for testing Antelope dApps and smart contracts: * Jungle Testnet [monitor](https://monitor.jungletestnet.io/), [website](https://jungletestnet.io/) * [CryptoKylin Testnet](https://www.cryptokylin.io/) diff --git a/docs/01_nodeos/03_plugins/chain_plugin/index.md b/docs/01_nodeos/03_plugins/chain_plugin/index.md index 9da5921080..1d284edffa 100644 --- a/docs/01_nodeos/03_plugins/chain_plugin/index.md +++ b/docs/01_nodeos/03_plugins/chain_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `chain_plugin` is a core plugin required to process and aggregate chain data on an EOSIO node. +The `chain_plugin` is a core plugin required to process and aggregate chain data on an Antelope node. ## Usage diff --git a/docs/01_nodeos/03_plugins/login_plugin/index.md b/docs/01_nodeos/03_plugins/login_plugin/index.md index 68df9d4c1e..09ebf2be74 100644 --- a/docs/01_nodeos/03_plugins/login_plugin/index.md +++ b/docs/01_nodeos/03_plugins/login_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `login_plugin` supports the concept of applications authenticating with the EOSIO blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. +The `login_plugin` supports the concept of applications authenticating with the Antelope blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. ## Usage diff --git a/docs/01_nodeos/03_plugins/producer_plugin/index.md b/docs/01_nodeos/03_plugins/producer_plugin/index.md index 66e1b0077f..6fce1fd71f 100644 --- a/docs/01_nodeos/03_plugins/producer_plugin/index.md +++ b/docs/01_nodeos/03_plugins/producer_plugin/index.md @@ -49,7 +49,7 @@ Config Options for eosio::producer_plugin: = Where: is a string form of - a vaild EOSIO public + a vaild Antelope public key is a string in the @@ -59,7 +59,7 @@ Config Options for eosio::producer_plugin: is KEY, or KEOSD KEY: is a string form of - a valid EOSIO + a valid Antelope private key which maps to the provided public key diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md index 962b9e711c..43c9536410 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md @@ -8,7 +8,7 @@ This procedure records the current chain state and future history, without previ ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md index 9f0a7308f0..8b29bf6919 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md @@ -8,7 +8,7 @@ This procedure records the entire chain history. ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md index 19d69e9c28..a81bfe15f5 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure creates a database containing the chain state, with full history ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md index 52e3b27e5e..364b2f91f7 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure restores an existing snapshot with full history, so the node can ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md index 74d1215ec0..b9822780fd 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md @@ -5,11 +5,11 @@ The `trace_api_plugin` provides a consumer-focused long-term API for retrieving ## Purpose -While integrating applications such as block explorers and exchanges with an EOSIO blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: +While integrating applications such as block explorers and exchanges with an Antelope blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: * A transcript of retired actions and related metadata * A consumer-focused long-term API to retrieve blocks -* Maintainable resource commitments at the EOSIO nodes +* Maintainable resource commitments at the Antelope nodes Therefore, one crucial goal of the `trace_api_plugin` is to improve the maintenance of node resources (file system, disk space, memory used, etc.). This goal is different from the existing `history_plugin` which provides far more configurable filtering and querying capabilities, or the existing `state_history_plugin` which provides a binary streaming interface to access structural chain data, action data, as well as state deltas. @@ -101,7 +101,7 @@ nodeos ... --plugin eosio::chain_plugin [options] \ ## Configuration Example -Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some EOSIO reference contracts: +Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some Antelope reference contracts: ```sh nodeos --data-dir data_dir --config-dir config_dir --trace-dir traces_dir @@ -191,7 +191,7 @@ If resource usage cannot be effectively managed via the `trace-minimum-irreversi ## Manual Maintenance -The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed EOSIO system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). +The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed Antelope system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). [[info | For node operators]] | Node operators can take full control over the lifetime of the historical data available in their nodes via the `trace-api-plugin` and the `trace-minimum-irreversible-history-blocks` and `trace-minimum-uncompressed-irreversible-history-blocks` options in conjunction with any external filesystem resource manager. diff --git a/docs/01_nodeos/06_logging/index.md b/docs/01_nodeos/06_logging/index.md index 8a7670e7fb..910db0928a 100644 --- a/docs/01_nodeos/06_logging/index.md +++ b/docs/01_nodeos/06_logging/index.md @@ -6,7 +6,7 @@ Logging for `nodeos` is controlled by the `logging.json` file. CLI options can b ## Appenders -The logging library built into EOSIO supports two appender types: +The logging library built into Antelope supports two appender types: - [Console](#console) - [GELF](#gelf) (Graylog Extended Log Format) @@ -74,7 +74,7 @@ Example: ## Loggers -The logging library built into EOSIO currently supports the following loggers: +The logging library built into Antelope currently supports the following loggers: - `default` - the default logger, always enabled. - `net_plugin_impl` - detailed logging for the net plugin. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index c942a3bcb2..0965fdf298 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -2,7 +2,7 @@ content_title: Storage and Read Modes --- -The EOSIO platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) +The Antelope platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) ## Blockchain State and Storage @@ -15,9 +15,9 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain * The `pending block` is an in memory block containing transactions as they are processed and pushed into the block; this will/may eventually become the head block. If the `nodeos` instance is the producing node, the pending block is distributed to other `nodeos` instances. * Outside the chain state, block data is cached in RAM until it becomes final/irreversible; especifically the signed block itself. After the last irreversible block (LIB) catches up to the block, that block is then retrieved from the irreversible blocks log. -## EOSIO Interfaces +## Antelope Interfaces -EOSIO provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +Antelope provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API diff --git a/docs/01_nodeos/07_concepts/10_context-free-data/index.md b/docs/01_nodeos/07_concepts/10_context-free-data/index.md index 0a31072bcb..5ee2aeebba 100644 --- a/docs/01_nodeos/07_concepts/10_context-free-data/index.md +++ b/docs/01_nodeos/07_concepts/10_context-free-data/index.md @@ -4,7 +4,7 @@ link_text: Context-Free Data --- ## Overview -The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, EOSIO blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. +The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, Antelope blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. ## Concept The goal of context-free data is to allow blockchain applications the option to store non-essential information within a transaction. Some examples of context-free data include: diff --git a/docs/01_nodeos/08_troubleshooting/index.md b/docs/01_nodeos/08_troubleshooting/index.md index 7aa22031d8..2d813a018b 100644 --- a/docs/01_nodeos/08_troubleshooting/index.md +++ b/docs/01_nodeos/08_troubleshooting/index.md @@ -28,7 +28,7 @@ Command Line Options for eosio::chain_plugin: Start `nodeos` with `--shared-memory-size-mb 1024`. A 1 GB shared memory file allows approximately half a million transactions. -### What version of EOSIO am I running/connecting to? +### What version of Antelope am I running/connecting to? If defaults can be used, then `cleos get info` will output a block that contains a field called `server_version`. If your `nodeos` is not using the defaults, then you need to know the URL of the `nodeos`. In that case, use the following with your `nodeos` URL: @@ -44,4 +44,4 @@ cleos --url http://localhost:8888 get info | grep server_version ### Error 3070000: WASM Exception Error -If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. +If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an Antelope-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. diff --git a/docs/01_nodeos/index.md b/docs/01_nodeos/index.md index 9877dc16a9..c31e5f3a82 100644 --- a/docs/01_nodeos/index.md +++ b/docs/01_nodeos/index.md @@ -4,11 +4,11 @@ content_title: Nodeos ## Introduction -`nodeos` is the core service daemon that runs on every EOSIO node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. +`nodeos` is the core service daemon that runs on every Antelope node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. ## Installation -`nodeos` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [EOSIO Software Installation](../00_install/index.md) section. +`nodeos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [Antelope Software Installation](../00_install/index.md) section. ## Explore @@ -23,4 +23,4 @@ Navigate the sections below to configure and use `nodeos`. * [Troubleshooting](08_troubleshooting/index.md) - Common `nodeos` troubleshooting questions. [[info | Access Node]] -| A local or remote EOSIO access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. +| A local or remote Antelope access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md index 06e3ff199b..a69e76c768 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. * Understand [Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) in the protocol documents. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md index 1fd79840ff..69030e4477 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to create a new EOSIO blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. +This how-to guide provides instructions on how to create a new Antelope blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. The example in this how-to guide creates a new account named **bob**, authorized by the default system account **eosio**, using the `cleos` CLI tool. @@ -10,8 +10,8 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about [EOSIO Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) +| The cleos tool is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install the cleos tool. +* Learn about [Antelope Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) * Learn about Asymmetric Cryptography - [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) pairs. * Create public/private keypairs for the `owner` and `active` permissions of an account. @@ -34,7 +34,7 @@ cleos create account eosio bob EOS87TQktA5RVse2EguhztfQVEh6XXxBmgkU8b4Y5YnGvtYAo * `bob` = the name of the new account conforming to [account naming conventions](/protocol-guides/04_accounts_and_permissions.md#2-accounts) * `EOS87TQ...AoLGNN` = the owner public key or permission level for the new account (**required**) [[info | Note]] -| To create a new account in the EOSIO blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created EOSIO blockchain, the default system account used to create a new account is **eosio**. +| To create a new account in the Antelope blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created Antelope blockchain, the default system account used to create a new account is **eosio**. **Example Output** @@ -46,4 +46,4 @@ warning: transaction executed locally, but may not be confirmed by the network y ### Summary -By following these instructions, you are able to create a new EOSIO account in your blockchain environment. +By following these instructions, you are able to create a new Antelope account in your blockchain environment. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md index e3e298aefe..16615039c5 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md @@ -1,14 +1,14 @@ ## Overview -This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in an Antelope blockchain. ## Before you begin Make sure you meet the following requirements: * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about asymmetric cryptography (public and private keypair) in the context of an EOSIO blockchain. +| The cleos tool is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install the cleos tool. +* Learn about asymmetric cryptography (public and private keypair) in the context of an Antelope blockchain. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 00d977278a..65003d0e2e 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. -* Understand [CPU bandwidth](/glossary.md#cpu) in an EOSIO blockchain. -* Understand [NET bandwidth](/glossary.md#net) in an EOSIO blockchain. +* Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. +* Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index c3bd8d8bd8..6db305abdb 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. -* Understand [NET bandwidth](/glossary.md#net) in an EOSIO blockchain. -* Understand [CPU bandwidth](/glossary.md#cpu) in an EOSIO blockchain. +* Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. +* Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md index 32fcce2c00..c7f0bfb18d 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md +++ b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md @@ -1,6 +1,6 @@ ## Goal -Deploy an EOSIO contract +Deploy an Antelope contract ## Before you begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md index 1213c0ac51..79d320a8aa 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md @@ -1,15 +1,15 @@ ## Overview -This how-to guide provides instructions on how to query infomation of an EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. +This how-to guide provides instructions on how to query infomation of an Antelope account. The example in this how-to guide retrieves information of the `eosio` account. ## Before you begin * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +| The cleos tool is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install the cleos tool. -* Acquire functional understanding of [EOSIO Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) +* Acquire functional understanding of [Antelope Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) ## Command Reference @@ -28,7 +28,7 @@ cleos get account eosio ``` **Where**: -* `eosio` = The name of the default system account in the EOSIO blockchain. +* `eosio` = The name of the default system account in the Antelope blockchain. **Example Output** @@ -53,4 +53,4 @@ cpu bandwidth: ``` [[info | Account Fields]] -| Depending on the EOSIO network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. +| Depending on the Antelope network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md index 216413ed1e..9914cc40b1 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md @@ -10,10 +10,10 @@ Make sure to meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what a [block](/glossary.md#block) is and its role in the blockchain. -* Understand the [block lifecycle](/protocol-guides/01_consensus_protocol.md#5-block-lifecycle) in the EOSIO consensus protocol. +* Understand the [block lifecycle](/protocol-guides/01_consensus_protocol.md#5-block-lifecycle) in the Antelope consensus protocol. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md index 717d6b225a..e40a2e2225 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to retrieve infomation of an EOSIO transaction using a transaction ID. +This how-to guide provides instructions on how to retrieve infomation of an Antelope transaction using a transaction ID. The example in this how-to retrieves transaction information associated with the creation of the account **bob**. @@ -9,8 +9,8 @@ The example in this how-to retrieves transaction information associated with the Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand how transactions work in an EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](/protocol-guides/02_transactions_protocol.md) section. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. +* Understand how transactions work in an Antelope blockchain. For more information on transactions, see the [Transactions Protocol](/protocol-guides/02_transactions_protocol.md) section. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md index d2cf0d0f4c..cf17414d4b 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md +++ b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an Antelope blockchain. ## Before you Begin @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet import`](../03_command-reference/wallet/import.md) command. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) is. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md index 2241458075..afcf1956c3 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an Antelope blockchain. The example in this how-to guide displays all public keys and public/private key pairs stored within the existing default wallet. @@ -13,7 +13,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet`](../03_command-reference/wallet/index.md) commands. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) is. ## Command Reference diff --git a/docs/02_cleos/03_command-reference/create/account.md b/docs/02_cleos/03_command-reference/create/account.md index 976c986f56..2dce43ba81 100755 --- a/docs/02_cleos/03_command-reference/create/account.md +++ b/docs/02_cleos/03_command-reference/create/account.md @@ -30,7 +30,7 @@ Options: ``` ## Command -A set of EOSIO keys is required to create an account. The EOSIO keys can be generated by using `cleos create key`. +A set of Antelope keys is required to create an account. The Antelope keys can be generated by using `cleos create key`. ```sh cleos create account inita tester EOS4toFS3YXEQCkuuw1aqDLrtHim86Gz9u3hBdcBw5KNPZcursVHq EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA diff --git a/docs/02_cleos/03_command-reference/net/connect.md b/docs/02_cleos/03_command-reference/net/connect.md index 646762cf1d..777a9c4852 100755 --- a/docs/02_cleos/03_command-reference/net/connect.md +++ b/docs/02_cleos/03_command-reference/net/connect.md @@ -30,7 +30,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/disconnect.md b/docs/02_cleos/03_command-reference/net/disconnect.md index d375c4b239..1cd269e83b 100755 --- a/docs/02_cleos/03_command-reference/net/disconnect.md +++ b/docs/02_cleos/03_command-reference/net/disconnect.md @@ -28,7 +28,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/peers.md b/docs/02_cleos/03_command-reference/net/peers.md index 359f89f792..39bdc5190e 100644 --- a/docs/02_cleos/03_command-reference/net/peers.md +++ b/docs/02_cleos/03_command-reference/net/peers.md @@ -27,7 +27,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/status.md b/docs/02_cleos/03_command-reference/net/status.md index 4ed8a84bd0..5a179e1705 100644 --- a/docs/02_cleos/03_command-reference/net/status.md +++ b/docs/02_cleos/03_command-reference/net/status.md @@ -30,7 +30,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/set/set-account.md b/docs/02_cleos/03_command-reference/set/set-account.md index 304db1bb0d..a06a4383eb 100644 --- a/docs/02_cleos/03_command-reference/set/set-account.md +++ b/docs/02_cleos/03_command-reference/set/set-account.md @@ -2,7 +2,7 @@ set parameters dealing with account permissions [[info | JSON input]] -| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the EOSIO software. +| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the Antelope software. ## Positionals - `account` _TEXT_ - The account to set/delete a permission authority for diff --git a/docs/02_cleos/04_troubleshooting.md b/docs/02_cleos/04_troubleshooting.md index 63250119e9..68a673b4f3 100644 --- a/docs/02_cleos/04_troubleshooting.md +++ b/docs/02_cleos/04_troubleshooting.md @@ -20,4 +20,4 @@ Replace API_ENDPOINT and PORT with your remote `nodeos` API endpoint detail ## "Missing Authorizations" -That means you are not using the required authorizations. Most likely you are not using correct EOSIO account or permission level to sign the transaction +That means you are not using the required authorizations. Most likely you are not using correct Antelope account or permission level to sign the transaction diff --git a/docs/02_cleos/index.md b/docs/02_cleos/index.md index fbe3ca8d30..c0d320ad80 100644 --- a/docs/02_cleos/index.md +++ b/docs/02_cleos/index.md @@ -4,11 +4,11 @@ content_title: Cleos ## Introduction -`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test EOSIO smart contracts. +`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test Antelope smart contracts. ## Installation -`cleos` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [EOSIO Software Installation](../00_install/index.md) section. +`cleos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Using Cleos @@ -23,7 +23,7 @@ cleos --help ``` ```console -Command Line Interface to EOSIO Client +Command Line Interface to Antelope Client Usage: cleos [OPTIONS] SUBCOMMAND Options: diff --git a/docs/03_keosd/index.md b/docs/03_keosd/index.md index cfd45cb9de..7142237112 100644 --- a/docs/03_keosd/index.md +++ b/docs/03_keosd/index.md @@ -8,11 +8,11 @@ content_title: Keosd ## Installation -`keosd` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [EOSIO Software Installation](../00_install/index.md) section. +`keosd` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Operation When a wallet is unlocked with the corresponding password, `cleos` can request `keosd` to sign a transaction with the appropriate private keys. Also, `keosd` provides support for hardware-based wallets such as Secure Encalve and YubiHSM. [[info | Audience]] -| `keosd` is intended to be used by EOSIO developers only. +| `keosd` is intended to be used by Antelope developers only. diff --git a/docs/10_utilities/index.md b/docs/10_utilities/index.md index 747c95cb72..35e014ffb2 100644 --- a/docs/10_utilities/index.md +++ b/docs/10_utilities/index.md @@ -1,9 +1,9 @@ --- -content_title: EOSIO Utilities -link_text: EOSIO Utilities +content_title: Antelope Utilities +link_text: Antelope Utilities --- -This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other EOSIO software: +This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other Antelope software: * [eosio-blocklog](eosio-blocklog.md) - Low-level utility for node operators to interact with block log files. * [trace_api_util](trace_api_util.md) - Low-level utility for performing tasks associated with the [Trace API](../01_nodeos/03_plugins/trace_api_plugin/index.md). diff --git a/docs/index.md b/docs/index.md index 0e98757754..cad35b6b99 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,23 +1,23 @@ --- -content_title: EOSIO Overview +content_title: Antelope Overview --- -EOSIO is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. EOSIO comes with a number of programs. The primary ones included in EOSIO are the following: +Antelope is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. Antelope comes with a number of programs. The primary ones included in Antelope are the following: * [Nodeos](01_nodeos/index.md) - Core service daemon that runs a node for block production, API endpoints, or local development. * [Cleos](02_cleos/index.md) - Command line interface to interact with the blockchain (via `nodeos`) and manage wallets (via `keosd`). -* [Keosd](03_keosd/index.md) - Component that manages EOSIO keys in wallets and provides a secure enclave for digital signing. +* [Keosd](03_keosd/index.md) - Component that manages Antelope keys in wallets and provides a secure enclave for digital signing. The basic relationship between these components is illustrated in the diagram below. -![EOSIO components](mandel_components.png) +![Antelope components](mandel_components.png) -Additional EOSIO Resources: -* [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. +Additional Antelope Resources: +* [Antelope Utilities](10_utilities/index.md) - Utilities that complement the Antelope software. [//]: # (THIS IS A COMMENT REMOVING BROKEN LINKS) -[//]: # (Upgrade-Guide-20_upgrade-guide/index.md-EOSIO-version/protocol-upgrade-guide.) -[//]: # (Release Notes 30_release-notes/index.md - All release notes for this EOSIO version.) +[//]: # (Upgrade-Guide-20_upgrade-guide/index.md-antelope-version/protocol-upgrade-guide.) +[//]: # (Release Notes 30_release-notes/index.md - All release notes for this Antelope version.) [[info | What's Next?]] -| [Install the EOSIO Software](00_install/index.md) before exploring the sections above. +| [Install the Antelope Software](00_install/index.md) before exploring the sections above. From 1a4791202056c9f79b36e07b0865bfc5d9e8dee8 Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 15:47:48 -0400 Subject: [PATCH 074/111] fix existing docs.eosnetwork.com links :doc --- docs/01_nodeos/03_plugins/net_api_plugin/index.md | 2 +- docs/01_nodeos/07_concepts/05_storage-and-read-modes.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/01_nodeos/03_plugins/net_api_plugin/index.md b/docs/01_nodeos/03_plugins/net_api_plugin/index.md index 658e643a0a..af16d5c918 100644 --- a/docs/01_nodeos/03_plugins/net_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/net_api_plugin/index.md @@ -8,7 +8,7 @@ The `net_api_plugin` provides four RPC API endpoints: * connections * status -See [Net API Reference Documentation](https://docs.eosnetwork.com/reference/mandel-plugins/net_api.html). +See [Net API Reference Documentation](https://docs.eosnetwork.com/leap-plugins/latest/net.api/). [[caution | Caution]] | This plugin exposes endpoints that allow management of p2p connections. Running this plugin on a publicly accessible node is not recommended as it can be exploited. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index 0965fdf298..8fb138d5f3 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -17,7 +17,7 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain ## Antelope Interfaces -Antelope provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +Antelope provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/cdt/latest/reference/Files/) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API From 013ed372535ae182fa3d597350e7aa3cb409b063 Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 16:07:17 -0400 Subject: [PATCH 075/111] curate github and eosnetwork.com links :doc --- docs/00_install/01_build-from-source/00_build-unsupported-os.md | 2 +- docs/00_install/01_build-from-source/index.md | 2 +- docs/00_install/index.md | 2 +- docs/01_nodeos/02_usage/03_development-environment/index.md | 2 +- docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md | 2 +- docs/01_nodeos/index.md | 2 +- docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md | 2 +- docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md | 2 +- docs/02_cleos/index.md | 2 +- docs/03_keosd/index.md | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/00_install/01_build-from-source/00_build-unsupported-os.md b/docs/00_install/01_build-from-source/00_build-unsupported-os.md index e5cffe252d..e0d3c19331 100644 --- a/docs/00_install/01_build-from-source/00_build-unsupported-os.md +++ b/docs/00_install/01_build-from-source/00_build-unsupported-os.md @@ -6,7 +6,7 @@ content_title: Build Antelope from Source on Other Unix-based OS ### Using DUNE -For the official multi-platform support try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) which runs in an ubuntu image via a docker container. +For the official multi-platform support try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) which runs in an ubuntu image via a docker container. **A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes. diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 7cffd45e4a..b2a4a63513 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -6,7 +6,7 @@ The shell scripts previously recommended for building the software have been rem ### Using DUNE -As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) for the easiest way to get started, and for multi-platform support. +As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started, and for multi-platform support. ### Building From Source diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 1d711083d3..4e9bf6eff2 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -23,4 +23,4 @@ Antelope currently supports the following operating systems: If you are using different operating system or prefer not to build Antelope from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring Antelope and doing contract development pretty much instantly -* [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/eosnetworkfoundation/DUNE) +* [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/AntelopeIO/DUNE) diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index 4ed1302c63..f5efbeef4f 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -19,7 +19,7 @@ While this option can technically be used for smart contract development, it may ## Official Testing Node -Try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) for the easiest way to get started, and for multi-platform support. +Try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started, and for multi-platform support. ## Third-Party Testnets diff --git a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md index efbb5a0204..8b784d0a34 100644 --- a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md +++ b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md @@ -4,7 +4,7 @@ The `txn_test_gen_plugin` is used for transaction test purposes. [[info | For More Information]] -For more information, check the [txn_test_gen_plugin/README.md](https://github.com/eosnetworkfoundation/mandel/tree/main/plugins/txn_test_gen_plugin) on the EOSIO/eos repository. +For more information, check the [txn_test_gen_plugin/README.md](https://github.com/AntelopeIO/leap/tree/main/plugins/txn_test_gen_plugin) on the `AntelopeIO/leap` repository. ## Usage diff --git a/docs/01_nodeos/index.md b/docs/01_nodeos/index.md index c31e5f3a82..51d749230e 100644 --- a/docs/01_nodeos/index.md +++ b/docs/01_nodeos/index.md @@ -8,7 +8,7 @@ content_title: Nodeos ## Installation -`nodeos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [Antelope Software Installation](../00_install/index.md) section. +`nodeos` is distributed as part of the [Antelope software suite](https://github.com/AntelopeIO/leap). To install `nodeos`, visit the [Antelope Software Installation](../00_install/index.md) section. ## Explore diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 65003d0e2e..ab15bdbfe2 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -12,7 +12,7 @@ Make sure you meet the following requirements: [[info | Note]] | `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. -* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. +* Ensure the reference system contracts from [`reference-contracts`](https://github.com/AntelopeIO/reference-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. * Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. * Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index 6db305abdb..c009cb31ca 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -12,7 +12,7 @@ Make sure you meet the following requirements: [[info | Note]] | `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. -* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. +* Ensure the reference system contracts from [`reference-contracts`](https://github.com/AntelopeIO/reference-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. * Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. * Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. diff --git a/docs/02_cleos/index.md b/docs/02_cleos/index.md index c0d320ad80..e779146036 100644 --- a/docs/02_cleos/index.md +++ b/docs/02_cleos/index.md @@ -8,7 +8,7 @@ content_title: Cleos ## Installation -`cleos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [Antelope Software Installation](../00_install/index.md) section. +`cleos` is distributed as part of the [Antelope software suite](https://github.com/AntelopeIO/leap). To install `cleos` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Using Cleos diff --git a/docs/03_keosd/index.md b/docs/03_keosd/index.md index 7142237112..69bcdcd487 100644 --- a/docs/03_keosd/index.md +++ b/docs/03_keosd/index.md @@ -8,7 +8,7 @@ content_title: Keosd ## Installation -`keosd` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [Antelope Software Installation](../00_install/index.md) section. +`keosd` is distributed as part of the [Antelope software suite](https://github.com/AntelopeIO/leap). To install `keosd` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Operation From 6aae754d9c3e9032f5ae6e8df79bee3ad582a001 Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 17:28:56 -0400 Subject: [PATCH 076/111] replace applicable eosio refs to antelope :doc --- docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md | 2 +- .../02_usage/02_node-setups/01_non-producing-node.md | 2 +- .../00_local-single-node-testnet.md | 2 +- .../03_development-environment/01_local-multi-node-testnet.md | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index edcc593276..d53636153e 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -15,7 +15,7 @@ This section describes how to set up a producing node within the Antelope networ * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) -[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-antelope-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index b0e5c9cc31..87c0f69493 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -12,7 +12,7 @@ This section describes how to set up a non-producing node within the Antelope ne * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT NEXT LINK CONTAINS A BROKEN LINK ) -[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-antelope-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index a55d817774..e94c037d02 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -16,7 +16,7 @@ This section describes how to set up a single-node blockchain configuration runn * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # (THIS IS A COMMENT, NEXT LINK HAS BROKEN LINK) -[//]: # (If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) +[//]: # (If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-antelope-binaries.md .) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 52a7c8dfb8..e14591bb26 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -20,7 +20,7 @@ Open four "terminal" windows and perform the following steps: 1. [Start the Wallet Manager](#1-start-the-wallet-manager) 2. [Create a Default Wallet](#2-create-a-default-wallet) -3. [Loading the Antelope Key](#3-loading-the-eosio-key) +3. [Loading the Antelope Key](#3-loading-the-antelope-key) 4. [Start the First Producer Node](#4-start-the-first-producer-node) 5. [Start the Second Producer Node](#5-start-the-second-producer-node) 6. [Get Nodes Info](#6-get-nodes-info) @@ -90,7 +90,9 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node + To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: From 2c7a00408b20e0639f06b27f849240671774a513 Mon Sep 17 00:00:00 2001 From: Luis Date: Thu, 22 Sep 2022 01:22:58 -0400 Subject: [PATCH 077/111] make html comment MDX-compatible for doc6s parsing :doc --- .../01_local-multi-node-testnet.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index e14591bb26..30d2b4a1d0 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -90,9 +90,8 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node - +[//]: # (don't render for now) +[//]: # (The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the Antelope binaries.) To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: From ced38878781ee8c45ab077b1e74532599a828fea Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 22 Sep 2022 07:01:05 -0500 Subject: [PATCH 078/111] GH-139 remove unneeded optional --- programs/cleos/main.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 3781f91bc7..9f41194956 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -548,16 +548,14 @@ int get_return_code( const fc::variant& result ) { const auto& except = processed["except"]; if( except.is_object() ) { try { - auto soft_except = except.as>(); - if( soft_except ) { - auto code = soft_except->code(); - if( code > std::numeric_limits::max() ) { - r = 1; - } else { - r = static_cast( code ); - } - if( r == 0 ) r = 1; + auto soft_except = except.as(); + auto code = soft_except.code(); + if( code > std::numeric_limits::max() ) { + r = 1; + } else { + r = static_cast( code ); } + if( r == 0 ) r = 1; } catch( ... ) { r = 1; } From bf53b6334c6ef34b2f7d5d980c6175df5ac555cf Mon Sep 17 00:00:00 2001 From: Luis Date: Thu, 22 Sep 2022 09:50:07 -0400 Subject: [PATCH 079/111] add manual links to plugins API reference --- .../03_plugins/chain_api_plugin/api-reference/index.md | 2 +- .../03_plugins/db_size_api_plugin/api-reference/index.md | 2 +- docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md | 2 +- .../03_plugins/producer_api_plugin/api-reference/index.md | 2 +- .../03_plugins/trace_api_plugin/api-reference/index.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md index 6451c70868..f49aa2c390 100644 --- a/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Chain API Reference](https://docs.eosnetwork.com/leap-plugins/latest/chain.api/) diff --git a/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md index 6451c70868..7b7810fe72 100644 --- a/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[DB Size API Reference](https://docs.eosnetwork.com/leap-plugins/latest/db_size.api/) diff --git a/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md index 6451c70868..842ba652eb 100644 --- a/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Net API Reference](https://docs.eosnetwork.com/leap-plugins/latest/net.api/) diff --git a/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md index 6451c70868..80bcc0b7fd 100644 --- a/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Producer API Reference](https://docs.eosnetwork.com/leap-plugins/latest/producer.api/) diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md index 6451c70868..07a171ca7d 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Trace API Reference](https://docs.eosnetwork.com/leap-plugins/latest/trace.api/) From f12be2fdec830af97d831f866fde879cf49221a6 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 22 Sep 2022 13:14:15 -0500 Subject: [PATCH 080/111] bump version to 3.1.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d8d419c72..64c1d2b7b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set( CXX_STANDARD_REQUIRED ON) set(VERSION_MAJOR 3) set(VERSION_MINOR 1) -set(VERSION_PATCH 0) +set(VERSION_PATCH 1) #set(VERSION_SUFFIX rc4) if(VERSION_SUFFIX) From 746cc81f298a7a3d112e71fa2ef0243dc052f28e Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Thu, 22 Sep 2022 14:46:28 -0400 Subject: [PATCH 081/111] tar --ignore-failed-read on uploaded failure logs --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4c387c50d2..167ac1e85d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -150,7 +150,7 @@ jobs: ctest --output-on-failure -L "nonparallelizable_tests" - name: Bundle logs from failed tests if: failure() - run: tar -czf ${{matrix.platform}}-serial-logs.tar.gz build/var build/etc build/leap-ignition-wd + run: tar --ignore-failed-read -czf ${{matrix.platform}}-serial-logs.tar.gz build/var build/etc build/leap-ignition-wd - name: Upload logs from failed tests uses: actions/upload-artifact@v3 if: failure() @@ -183,7 +183,7 @@ jobs: ctest --output-on-failure -R ${{matrix.test-name}} - name: Bundle logs from failed tests if: failure() - run: tar -czf ${{matrix.platform}}-${{matrix.test-name}}-logs.tar.gz build/var build/etc build/leap-ignition-wd + run: tar --ignore-failed-read -czf ${{matrix.platform}}-${{matrix.test-name}}-logs.tar.gz build/var build/etc build/leap-ignition-wd - name: Upload logs from failed tests uses: actions/upload-artifact@v3 if: failure() From b888d9a3b305af17f3cf56fb98bc5ff9a4a35d2d Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 22 Sep 2022 18:34:00 -0500 Subject: [PATCH 082/111] GH-139 Use Python 3.5+ feature of capturing stderr in CalledProcessError --- tests/TestHarness/Cluster.py | 6 +++--- tests/TestHarness/Node.py | 18 +++++++++--------- tests/TestHarness/WalletMgr.py | 12 +++++++----- tests/TestHarness/testUtils.py | 5 ++--- tests/cli_test.py | 6 ++++-- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/tests/TestHarness/Cluster.py b/tests/TestHarness/Cluster.py index 37313ffe90..4c0e0d248f 100644 --- a/tests/TestHarness/Cluster.py +++ b/tests/TestHarness/Cluster.py @@ -624,7 +624,7 @@ def getClientVersion(fullVersion=False): verStr=m.group(1) return verStr except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Exception during client version query. %s" % (msg)) raise @@ -666,7 +666,7 @@ def createAccountKeys(count): if Utils.Debug: Utils.Print("name: %s, key(owner): ['%s', '%s], key(active): ['%s', '%s']" % (name, ownerPublic, ownerPrivate, activePublic, activePrivate)) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Exception during key creation. %s" % (msg)) break @@ -1353,7 +1353,7 @@ def myFunc(): psOut=Utils.checkOutput(cmd.split()) return psOut except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: call of \"%s\" failed. %s" % (cmd, msg)) return None return None diff --git a/tests/TestHarness/Node.py b/tests/TestHarness/Node.py index 6016f3b292..6d99cb1644 100644 --- a/tests/TestHarness/Node.py +++ b/tests/TestHarness/Node.py @@ -177,7 +177,7 @@ def stdinAndCheckOutput(cmd, subcommand): outs,errs=popen.communicate(input=subcommand.encode("utf-8")) ret=popen.wait() except subprocess.CalledProcessError as ex: - msg=ex.output + msg=ex.stderr return (ex.returncode, msg, None) return (ret, outs, errs) @@ -580,7 +580,7 @@ def transferFunds(self, source, destination, amountStr, memo="memo", force=False self.trackCmdTransaction(trans, reportStatus=reportStatus) except subprocess.CalledProcessError as ex: end=time.perf_counter() - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Exception during funds transfer. cmd Duration: %.3f sec. %s" % (end-start, msg)) if exitOnError: Utils.cmdError("could not transfer \"%s\" from %s to %s" % (amountStr, source, destination)) @@ -604,7 +604,7 @@ def transferFundsAsync(self, source, destination, amountStr, memo="memo", force= Utils.Print("cmd Duration: %.3f sec" % (end-start)) except subprocess.CalledProcessError as ex: end=time.perf_counter() - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Exception during spawn of funds transfer. cmd Duration: %.3f sec. %s" % (end-start, msg)) if exitOnError: Utils.cmdError("could not transfer \"%s\" from %s to %s" % (amountStr, source, destination)) @@ -764,7 +764,7 @@ def getAccountCodeHash(self, account): return m.group(1) except subprocess.CalledProcessError as ex: end=time.perf_counter() - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Exception during code hash retrieval. cmd Duration: %.3f sec. %s" % (end-start, msg)) return None @@ -786,7 +786,7 @@ def publishContract(self, account, contractDir, wasmFile, abiFile, waitForTransB except subprocess.CalledProcessError as ex: if not shouldFail: end=time.perf_counter() - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Exception during set contract. cmd Duration: %.3f sec. %s" % (end-start, msg)) return None else: @@ -865,7 +865,7 @@ def pushTransaction(self, trans, opts="", silentErrors=False, permissions=None): Utils.Print("cmd Duration: %.3f sec" % (end-start)) return (Node.getTransStatus(retTrans) == 'executed', retTrans) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") if not silentErrors: end=time.perf_counter() Utils.Print("ERROR: Exception during push transaction. cmd Duration=%.3f sec. %s" % (end - start, msg)) @@ -893,7 +893,7 @@ def pushMessage(self, account, action, data, opts, silentErrors=False, signature Utils.Print("cmd Duration: %.3f sec" % (end-start)) return (Node.getTransStatus(trans) == 'executed' if expectTrxTrace else True, trans) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") if not silentErrors: end=time.perf_counter() Utils.Print("ERROR: Exception during push message. cmd Duration=%.3f sec. %s" % (end - start, msg)) @@ -994,7 +994,7 @@ def processCleosCmd(self, cmd, cmdDesc, silentErrors=True, exitOnError=False, ex except subprocess.CalledProcessError as ex: if not silentErrors: end=time.perf_counter() - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") errorMsg="Exception during \"%s\". Exception message: %s. cmd Duration=%.3f sec. %s" % (cmdDesc, msg, end-start, exitMsg) if exitOnError: Utils.cmdError(errorMsg) @@ -1040,7 +1040,7 @@ def processCurlCmd(self, resource, command, payload, silentErrors=True, exitOnEr except subprocess.CalledProcessError as ex: if not silentErrors: end=time.perf_counter() - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") errorMsg="Exception during \"%s\". %s. cmd Duration=%.3f sec." % (cmd, msg, end-start) if exitOnError: Utils.cmdError(errorMsg) diff --git a/tests/TestHarness/WalletMgr.py b/tests/TestHarness/WalletMgr.py index a64cb89f2f..143caf829a 100644 --- a/tests/TestHarness/WalletMgr.py +++ b/tests/TestHarness/WalletMgr.py @@ -95,6 +95,8 @@ def launch(self): psOut=Utils.checkOutput(pgrepCmd.split()) if Utils.Debug: Utils.Print("Launched %s. {%s}" % (Utils.EosWalletName, psOut)) except subprocess.CalledProcessError as ex: + Utils.Print(f"STDOUT: {ex.output}") + Utils.Print(f"STDERR: {ex.stderr}") Utils.errorExit("Failed to launch the wallet manager") return True @@ -131,7 +133,7 @@ def create(self, name, accounts=None, exitOnError=True): time.sleep(delay) continue - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") errorMsg="ERROR: Failed to create wallet - %s. %s" % (name, msg) if exitOnError: Utils.errorExit("%s" % (errorMsg)) @@ -170,7 +172,7 @@ def importKey(self, account, wallet, ignoreDupKeyWarning=False): try: Utils.checkOutput(cmd.split()) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") if warningMsg in msg: if not ignoreDupKeyWarning: Utils.Print("WARNING: This key is already imported into the wallet.") @@ -187,7 +189,7 @@ def importKey(self, account, wallet, ignoreDupKeyWarning=False): try: Utils.checkOutput(cmd.split()) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") if warningMsg in msg: if not ignoreDupKeyWarning: Utils.Print("WARNING: This key is already imported into the wallet.") @@ -237,7 +239,7 @@ def getOpenWallets(self): try: retStr=Utils.checkOutput(cmd.split()) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Failed to open wallets. %s" % (msg)) return False @@ -259,7 +261,7 @@ def getKeys(self, wallet): try: retStr=Utils.checkOutput(cmd.split()) except subprocess.CalledProcessError as ex: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") Utils.Print("ERROR: Failed to get keys. %s" % (msg)) return False m=p.findall(retStr) diff --git a/tests/TestHarness/testUtils.py b/tests/TestHarness/testUtils.py index 5b9690756b..24dfc9d4fc 100755 --- a/tests/TestHarness/testUtils.py +++ b/tests/TestHarness/testUtils.py @@ -204,9 +204,8 @@ def checkDelayedOutput(popen, cmd, ignoreError=False): (output,error)=popen.communicate() Utils.checkOutputFileWrite(start, cmd, output, error) if popen.returncode != 0 and not ignoreError: - Utils.Print("ERROR: %s" % error) # for now just include both stderr and stdout in output, python 3.5+ supports both a stdout and stderr attributes - raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=error+bytes(" ", 'utf-8')+output) + raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=output, stderr=error) return output.decode("utf-8") @staticmethod @@ -397,7 +396,7 @@ def getBlockLog(blockLogLocation, blockLogAction=BlockLogAction.return_blocks, o if throwException: raise if not silentErrors: - msg=ex.output.decode("utf-8") + msg=ex.stderr.decode("utf-8") errorMsg="Exception during \"%s\". %s" % (cmd, msg) if exitOnError: Utils.cmdError(errorMsg) diff --git a/tests/cli_test.py b/tests/cli_test.py index 9ca2a0d697..33be05e9e5 100755 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -119,7 +119,8 @@ def cleos_sign_test(): outs,errs=popen.communicate() popen.wait() except subprocess.CalledProcessError as ex: - print(ex.output) + print(f"STDOUT: {ex.output}") + print(f"STDERR: {ex.stderr}") # make sure fields are unpacked assert(b'"expiration": "2019-08-01T07:15:49"' in errs) assert(b'"ref_block_num": 34881' in errs) @@ -145,7 +146,8 @@ def processCleosCommand(cmd): outs, errs = popen.communicate() popen.wait() except subprocess.CalledProcessError as ex: - print(ex.output) + print(f"STDOUT: {ex.output}") + print(f"STDERR: {ex.stderr}") return outs, errs def cleos_abi_file_test(): From 885d8faba1325336a09e84b03baac734162936e3 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 22 Sep 2022 18:39:54 -0500 Subject: [PATCH 083/111] GH-139 Use Python 3.5+ feature of capturing stderr in CalledProcessError --- tests/TestHarness/Node.py | 4 +--- tests/TestHarness/testUtils.py | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/TestHarness/Node.py b/tests/TestHarness/Node.py index 6d99cb1644..c8d4dc421c 100644 --- a/tests/TestHarness/Node.py +++ b/tests/TestHarness/Node.py @@ -794,9 +794,7 @@ def publishContract(self, account, contractDir, wasmFile, abiFile, waitForTransB retMap["returncode"]=ex.returncode retMap["cmd"]=ex.cmd retMap["output"]=ex.output - # commented below as they are available only in Python3.5 and above - # retMap["stdout"]=ex.stdout - # retMap["stderr"]=ex.stderr + retMap["stderr"]=ex.stderr return retMap if shouldFail: diff --git a/tests/TestHarness/testUtils.py b/tests/TestHarness/testUtils.py index 24dfc9d4fc..2cbe58650c 100755 --- a/tests/TestHarness/testUtils.py +++ b/tests/TestHarness/testUtils.py @@ -204,7 +204,6 @@ def checkDelayedOutput(popen, cmd, ignoreError=False): (output,error)=popen.communicate() Utils.checkOutputFileWrite(start, cmd, output, error) if popen.returncode != 0 and not ignoreError: - # for now just include both stderr and stdout in output, python 3.5+ supports both a stdout and stderr attributes raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=output, stderr=error) return output.decode("utf-8") From 1cc2fce50fb523cf3150d15a7d6f6b6c8e46873e Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 23 Sep 2022 07:30:08 -0500 Subject: [PATCH 084/111] GH-217 Remove debug print causing log spam --- tests/testUtils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testUtils.py b/tests/testUtils.py index 55c225d530..8df95a65f6 100755 --- a/tests/testUtils.py +++ b/tests/testUtils.py @@ -204,7 +204,6 @@ def checkDelayedOutput(popen, cmd, ignoreError=False): (output,error)=popen.communicate() Utils.checkOutputFileWrite(start, cmd, output, error) if popen.returncode != 0 and not ignoreError: - Utils.Print("ERROR: %s" % error) # for now just include both stderr and stdout in output, python 3.5+ supports both a stdout and stderr attributes raise subprocess.CalledProcessError(returncode=popen.returncode, cmd=cmd, output=error+bytes(" ", 'utf-8')+output) return output.decode("utf-8") From 57fa42d8162fbafc687d3511c138f52cf94879b7 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 23 Sep 2022 07:30:36 -0500 Subject: [PATCH 085/111] GH-217 transferFunds returns None on failure --- tests/nodeos_retry_transaction_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nodeos_retry_transaction_test.py b/tests/nodeos_retry_transaction_test.py index 2764ae51bd..03730c8f7a 100755 --- a/tests/nodeos_retry_transaction_test.py +++ b/tests/nodeos_retry_transaction_test.py @@ -181,7 +181,7 @@ overdrawTransferAmount = "1001.0000 {0}".format(CORE_SYMBOL) Print("Transfer funds %s from account %s to %s" % (overdrawTransferAmount, overdrawAccount.name, cluster.eosioAccount.name)) overdrawtrans = node.transferFunds(overdrawAccount, cluster.eosioAccount, overdrawTransferAmount, "test overdraw transfer", exitOnError=False, reportStatus=False, retry=1) - assert "overdrawn balance" in str(overdrawtrans), "ERROR: Overdraw transaction attempt should have failed with overdrawn balance." + assert overdrawtrans is None, f"ERROR: Overdraw transaction attempt should have failed with overdrawn balance: {overdrawtrans}" def cacheTransIdInBlock(transId, transToBlock, node): global lastIrreversibleBlockNum From a73b5236e6f13a0a9b18ca0fafe5f4958320bdb2 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 23 Sep 2022 08:58:11 -0500 Subject: [PATCH 086/111] GH-186 Log std::exception for http calls at debug level. --- plugins/http_plugin/http_plugin.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index 6e91cf0020..e896f0ab60 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -515,9 +515,8 @@ class http_plugin_impl : public std::enable_shared_from_this { } catch (std::exception& e) { error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, e.what())), verbose_http_errors)}; cb( 500, fc::time_point::maximum(), fc::variant( results )); - fc_elog( logger(), "STD Exception encountered while processing ${api}.${call}", - ("api", api_name)( "call", call_name ) ); - fc_dlog( logger(), "Exception Details: ${e}", ("e", e.what()) ); + fc_dlog( logger(), "STD Exception encountered while processing ${api}.${call}: ${e}", + ("api", api_name)("call", call_name)("e", e.what()) ); } catch (...) { error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, "Unknown Exception" )), verbose_http_errors)}; From 6393c079952cc94e0d20e570b7090c6de66d6259 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Fri, 23 Sep 2022 08:04:29 -0700 Subject: [PATCH 087/111] Updated docs for openapi /v1/trace_api - updated description with notes on options needed at startup - updated json returns for 400,404, and 500 - added get_transaction_trace method --- .../trace_api_plugin/trace_api.swagger.yaml | 177 +++++++++++++++++- 1 file changed, 175 insertions(+), 2 deletions(-) diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index c1ad3694c5..19f549533a 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -6,7 +6,7 @@ info: name: MIT url: https://opensource.org/licenses/MIT contact: - url: https://eos.io + url: https://eosnetwork.com servers: - url: '{protocol}://{host}:{port}/v1/' variables: @@ -24,7 +24,7 @@ components: paths: /trace_api/get_block: post: - description: Returns a block trace object containing retired actions and related metadata. + description: Returns a block trace object containing retired actions and related metadata. Must specifiy one option `trace-rpc-abi` or `no-trace-abis`. These options are provided at nodeos startup on the command line or in config.ini file. Configuration option `trace-rpc-abi` There must be at least one ABI specified OR the flag trace-no-abis must be used. ABIs are specified as "Key=Value" pairs in the form = Where can be an absolute path to a file containing a valid JSON-encoded ABI a relative path from `data-dir` to a file containing a valid JSON-encoded ABI. Configuration option `trace-no-abis` use to indicate that the RPC responses will not use ABIs operationId: get_block requestBody: content: @@ -48,7 +48,180 @@ paths: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV1.yaml" "400": description: Error - requested block number is invalid (not a number, larger than max int) + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string "404": description: Error - requested data not present on node + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string "500": description: Error - exceptional condition while processing get_block; e.g. corrupt files + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 500 + message: + type: string + example: "Trace API encountered an Error which it cannot recover from. Please resolve the error and relaunch the process" + error: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string + + /trace_api/get_transaction_trace: + post: + description: foo + optionationId: get_transaction_trace + requestBody: + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + description: Proviade a transaction id + responses: + "200": + description: ok + "400": + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string + "404": + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string + "500": + description: Error - exceptional condition while processing get_block; e.g. corrupt files + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 500 + message: + type: string + example: "Trace API encountered an Error which it cannot recover from. Please resolve the error and relaunch the process" + error: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string From 8827ce38a4c777925cfe44116a2a35fa2ff83dd0 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Fri, 23 Sep 2022 08:24:57 -0700 Subject: [PATCH 088/111] updated trace_api openapi docs - updated return schema for get_block - updated description for get_transaction_trace --- .../trace_api_plugin/trace_api.swagger.yaml | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index 19f549533a..0bd3b97e43 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -43,9 +43,22 @@ paths: content: application/json: schema: - oneOf: - - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV0.yaml" - - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV1.yaml" + type: object + properties: + id: + type: string + number: + type: integer + previous_id: + type: string + status: + type: string + enum: ["irreversible", "pending"] + example: pending + timestamp: + type: string + producer: + type: string "400": description: Error - requested block number is invalid (not a number, larger than max int) content: @@ -130,7 +143,7 @@ paths: /trace_api/get_transaction_trace: post: - description: foo + description: Does a scan of the trace files looking for the transaction optionationId: get_transaction_trace requestBody: content: @@ -145,7 +158,9 @@ paths: description: Proviade a transaction id responses: "200": - description: ok + content: + application/json: + schema: "400": content: application/json: From 239bb348d103d9f792903505ab22e3bbf529decc Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Fri, 23 Sep 2022 12:50:54 -0400 Subject: [PATCH 089/111] always run the long running tests -- including for PRs --- .github/workflows/build.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 460e20d073..912a438500 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -7,10 +7,6 @@ on: - "release/*" pull_request: workflow_dispatch: - inputs: - run-lr-tests: - description: 'Run long running tests' - type: boolean permissions: packages: read @@ -176,7 +172,7 @@ jobs: lr-tests: name: LR Tests needs: [d, Build] - if: always() && needs.Build.result == 'success' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || inputs.run-lr-tests) + if: always() && needs.Build.result == 'success' strategy: fail-fast: false matrix: From fa87b159edb77dee82d08bde0ffd9d58e0177ed4 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Fri, 23 Sep 2022 12:24:40 -0700 Subject: [PATCH 090/111] updated schema for trace_api openapi - Added new component schemas - ERROR_DETAILS - TRACE - TRANSACTION_HEADER - TRANSACTION_TRACE - BLOCK_TRACE - updated 4xx errors with shared ERROR_DETAILS component - verification and updates for schema returned for get_block - verifcation and updates for schema returned for get_transaction --- .../trace_api_plugin/trace_api.swagger.yaml | 282 ++++++++++++------ 1 file changed, 187 insertions(+), 95 deletions(-) diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index 0bd3b97e43..1531dae149 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -1,6 +1,7 @@ openapi: 3.0.0 info: title: Trace API + description: This plubing must specifiy one option `trace-rpc-abi` or `no-trace-abis`. These options are provided at nodeos startup on the command line or in config.ini file. Configuration option `trace-rpc-abi` There must be at least one ABI specified OR the flag trace-no-abis must be used. ABIs are specified as "Key=Value" pairs in the form = Where can be an absolute path to a file containing a valid JSON-encoded ABI a relative path from `data-dir` to a file containing a valid JSON-encoded ABI. Configuration option `trace-no-abis` use to indicate that the RPC responses version: 1.0.0 license: name: MIT @@ -21,10 +22,13 @@ servers: default: "8080" components: schemas: {} +security: + - {} paths: /trace_api/get_block: post: - description: Returns a block trace object containing retired actions and related metadata. Must specifiy one option `trace-rpc-abi` or `no-trace-abis`. These options are provided at nodeos startup on the command line or in config.ini file. Configuration option `trace-rpc-abi` There must be at least one ABI specified OR the flag trace-no-abis must be used. ABIs are specified as "Key=Value" pairs in the form = Where can be an absolute path to a file containing a valid JSON-encoded ABI a relative path from `data-dir` to a file containing a valid JSON-encoded ABI. Configuration option `trace-no-abis` use to indicate that the RPC responses will not use ABIs + summary: get block + description: Returns a block trace object containing retired actions and related metadata. operationId: get_block requestBody: content: @@ -43,22 +47,7 @@ paths: content: application/json: schema: - type: object - properties: - id: - type: string - number: - type: integer - previous_id: - type: string - status: - type: string - enum: ["irreversible", "pending"] - example: pending - timestamp: - type: string - producer: - type: string + $ref: "#/component/schema/BLOCK_TRACE" "400": description: Error - requested block number is invalid (not a number, larger than max int) content: @@ -73,19 +62,7 @@ paths: type: string example: "bad or missing block_num" error: - type: object - properties: - code: - type: integer - example: 0 - name: - type: string - what: - type: string - details: - type: array - items: - type: string + $ref: "#/component/schema/ERROR_DETAILS" "404": description: Error - requested data not present on node content: @@ -100,19 +77,7 @@ paths: type: string example: "bad or missing block_num" error: - type: object - properties: - code: - type: integer - example: 0 - name: - type: string - what: - type: string - details: - type: array - items: - type: string + $ref: "#/component/schema/ERROR_DETAILS" "500": description: Error - exceptional condition while processing get_block; e.g. corrupt files content: @@ -127,22 +92,11 @@ paths: type: string example: "Trace API encountered an Error which it cannot recover from. Please resolve the error and relaunch the process" error: - type: object - properties: - code: - type: integer - example: 0 - name: - type: string - what: - type: string - details: - type: array - items: - type: string + $ref: "#/component/schema/ERROR_DETAILS" /trace_api/get_transaction_trace: post: + summary: transaction trace description: Does a scan of the trace files looking for the transaction optionationId: get_transaction_trace requestBody: @@ -161,7 +115,9 @@ paths: content: application/json: schema: + $ref: "#/component/schema/TRANSACTION_TRACE" "400": + description: Error - requested block number is invalid (not a number, larger than max int) content: application/json: schema: @@ -174,20 +130,9 @@ paths: type: string example: "bad or missing block_num" error: - type: object - properties: - code: - type: integer - example: 0 - name: - type: string - what: - type: string - details: - type: array - items: - type: string + $ref: "#/component/schema/ERROR_DETAILS" "404": + description: Error - requested data not present on node content: application/json: schema: @@ -200,19 +145,7 @@ paths: type: string example: "bad or missing block_num" error: - type: object - properties: - code: - type: integer - example: 0 - name: - type: string - what: - type: string - details: - type: array - items: - type: string + $ref: "#/component/schema/ERROR_DETAILS" "500": description: Error - exceptional condition while processing get_block; e.g. corrupt files content: @@ -227,16 +160,175 @@ paths: type: string example: "Trace API encountered an Error which it cannot recover from. Please resolve the error and relaunch the process" error: - type: object - properties: - code: - type: integer - example: 0 - name: - type: string - what: - type: string - details: - type: array - items: - type: string + $ref: "#/component/schema/ERROR_DETAILS" +component: + schema: + TRACE: + type: object + properties: + global_squence: + type: integer + example: 669 + receiver: + type: string + example: myproducer + account: + type: string + example: esio.token + action: + type: string + example: transfer + authorization: + type: array + items: + type: object + properties: + account: + type: string + example: myaccount + permission: + type: string + example: active + data: + type: string + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + return_value: + type: string + example: "" + params: + type: object + properties: + from: + type: string + example: eosio + to: + type: string + example: myproducer + quantity: + type: string + example: "10.000 SYS" + memo: + type: string + example: "first transfer" + TRANSACTION_HEADER: + type: object + properties: + expiration: + type: string + example: "2019-06-18T00:00:00" + ref_block_num: + type: integer + example: 25 + ref_block_prefix: + type: integer + example: 61809694 + max_net_usage_words: + type: integer + example: 0 + max_cpu_usage_ms: + type: integer + example: 0 + delay_sec: + type: integer + example: 0 + TRANSACTION_TRACE: + type: object + properties: + id: + type: string + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + block_num: + type: integer + example: 31 + block_time: + type: string + example: "2019-06-18T00:00:00" + producer_block_id: + type: string + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + actions: + type: array + items: + $ref: "#/component/schema/TRACE" + status: + type: string + example: executed + cpu_usage_us: + type: integer + example: 669 + net_usage_words: + type: integer + example: 6 + signatures: + type: array + items: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/CppSignature.yaml" + transaction_header: + type: object + $ref: "#/component/schema/TRANSACTION_HEADER" + BLOCK_TRACE: + type: object + properties: + id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + number: + type: integer + example: 31 + previous_id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + status: + type: string + enum: + - "irreversible" + - "executed" + - "pending" + example: executed + timestamp: + type: string + example: "2019-06-18T00:00:00" + producer: + type: string + example: myproducer + transaction_mroot: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + action_mroot: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + schedule_version: + type: integer + example: 1 + transactions: + type: array + items: + type: object + properties: + id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + block_num: + type: integer + example: 31 + block_time: + type: string + example: "2019-06-18T00:00:00" + producer_block_id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + actions: + type: array + items: + $ref: "#/component/schema/TRACE" + transaction_header: + type: object + $ref: "#/component/schema/TRANSACTION_HEADER" + ERROR_DETAILS: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string From 31e631473baa563051e284bea1bd51bc4ae4385d Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Fri, 23 Sep 2022 13:09:00 -0700 Subject: [PATCH 091/111] updated trace_api openapi documentation - added trace_transcation method - added new component types - ERROR_DETAILS - TRACE - TRANSACTION_HEADER - TRANSACTION_TRACE - BLOCK_TRACE - updated return schema for both get_block and get_transaction --- .../trace_api_plugin/trace_api.swagger.yaml | 288 +++++++++++++++++- 1 file changed, 284 insertions(+), 4 deletions(-) diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index 2c5f5dc78e..1531dae149 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -1,12 +1,13 @@ openapi: 3.0.0 info: title: Trace API + description: This plubing must specifiy one option `trace-rpc-abi` or `no-trace-abis`. These options are provided at nodeos startup on the command line or in config.ini file. Configuration option `trace-rpc-abi` There must be at least one ABI specified OR the flag trace-no-abis must be used. ABIs are specified as "Key=Value" pairs in the form = Where can be an absolute path to a file containing a valid JSON-encoded ABI a relative path from `data-dir` to a file containing a valid JSON-encoded ABI. Configuration option `trace-no-abis` use to indicate that the RPC responses version: 1.0.0 license: name: MIT url: https://opensource.org/licenses/MIT contact: - url: https://eos.io + url: https://eosnetwork.com servers: - url: '{protocol}://{host}:{port}/v1/' variables: @@ -21,9 +22,12 @@ servers: default: "8080" components: schemas: {} +security: + - {} paths: /trace_api/get_block: post: + summary: get block description: Returns a block trace object containing retired actions and related metadata. operationId: get_block requestBody: @@ -43,12 +47,288 @@ paths: content: application/json: schema: - oneOf: - - $ref: "https://eosio.github.io/schemata/v2.0/oas/BlockTraceV0.yaml" - - $ref: "https://eosio.github.io/schemata/v2.0/oas/BlockTraceV1.yaml" + $ref: "#/component/schema/BLOCK_TRACE" "400": description: Error - requested block number is invalid (not a number, larger than max int) + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + $ref: "#/component/schema/ERROR_DETAILS" + "404": + description: Error - requested data not present on node + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + $ref: "#/component/schema/ERROR_DETAILS" + "500": + description: Error - exceptional condition while processing get_block; e.g. corrupt files + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 500 + message: + type: string + example: "Trace API encountered an Error which it cannot recover from. Please resolve the error and relaunch the process" + error: + $ref: "#/component/schema/ERROR_DETAILS" + + /trace_api/get_transaction_trace: + post: + summary: transaction trace + description: Does a scan of the trace files looking for the transaction + optionationId: get_transaction_trace + requestBody: + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + description: Proviade a transaction id + responses: + "200": + content: + application/json: + schema: + $ref: "#/component/schema/TRANSACTION_TRACE" + "400": + description: Error - requested block number is invalid (not a number, larger than max int) + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + $ref: "#/component/schema/ERROR_DETAILS" "404": description: Error - requested data not present on node + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 400 + message: + type: string + example: "bad or missing block_num" + error: + $ref: "#/component/schema/ERROR_DETAILS" "500": description: Error - exceptional condition while processing get_block; e.g. corrupt files + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 500 + message: + type: string + example: "Trace API encountered an Error which it cannot recover from. Please resolve the error and relaunch the process" + error: + $ref: "#/component/schema/ERROR_DETAILS" +component: + schema: + TRACE: + type: object + properties: + global_squence: + type: integer + example: 669 + receiver: + type: string + example: myproducer + account: + type: string + example: esio.token + action: + type: string + example: transfer + authorization: + type: array + items: + type: object + properties: + account: + type: string + example: myaccount + permission: + type: string + example: active + data: + type: string + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + return_value: + type: string + example: "" + params: + type: object + properties: + from: + type: string + example: eosio + to: + type: string + example: myproducer + quantity: + type: string + example: "10.000 SYS" + memo: + type: string + example: "first transfer" + TRANSACTION_HEADER: + type: object + properties: + expiration: + type: string + example: "2019-06-18T00:00:00" + ref_block_num: + type: integer + example: 25 + ref_block_prefix: + type: integer + example: 61809694 + max_net_usage_words: + type: integer + example: 0 + max_cpu_usage_ms: + type: integer + example: 0 + delay_sec: + type: integer + example: 0 + TRANSACTION_TRACE: + type: object + properties: + id: + type: string + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + block_num: + type: integer + example: 31 + block_time: + type: string + example: "2019-06-18T00:00:00" + producer_block_id: + type: string + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + actions: + type: array + items: + $ref: "#/component/schema/TRACE" + status: + type: string + example: executed + cpu_usage_us: + type: integer + example: 669 + net_usage_words: + type: integer + example: 6 + signatures: + type: array + items: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/CppSignature.yaml" + transaction_header: + type: object + $ref: "#/component/schema/TRANSACTION_HEADER" + BLOCK_TRACE: + type: object + properties: + id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + number: + type: integer + example: 31 + previous_id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + status: + type: string + enum: + - "irreversible" + - "executed" + - "pending" + example: executed + timestamp: + type: string + example: "2019-06-18T00:00:00" + producer: + type: string + example: myproducer + transaction_mroot: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + action_mroot: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + schedule_version: + type: integer + example: 1 + transactions: + type: array + items: + type: object + properties: + id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + block_num: + type: integer + example: 31 + block_time: + type: string + example: "2019-06-18T00:00:00" + producer_block_id: + $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" + actions: + type: array + items: + $ref: "#/component/schema/TRACE" + transaction_header: + type: object + $ref: "#/component/schema/TRANSACTION_HEADER" + ERROR_DETAILS: + type: object + properties: + code: + type: integer + example: 0 + name: + type: string + what: + type: string + details: + type: array + items: + type: string From 68b25435575d5688aff49a3e157eb1704d1b4145 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Sat, 24 Sep 2022 08:52:04 -0500 Subject: [PATCH 092/111] GH-223 Remove hard-coded Test succeeded message --- tests/nodeos_contrl_c_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nodeos_contrl_c_test.py b/tests/nodeos_contrl_c_test.py index 7a873fafed..9c86dd4c2d 100755 --- a/tests/nodeos_contrl_c_test.py +++ b/tests/nodeos_contrl_c_test.py @@ -112,7 +112,7 @@ errorExit("Failed to kill the seed node") finally: - TestHelper.shutdown(cluster, walletMgr, testSuccessful=True, killEosInstances=True, killWallet=True, keepLogs=True, cleanRun=True, dumpErrorDetails=True) + TestHelper.shutdown(cluster, walletMgr, testSuccessful=testSuccessful, killEosInstances=True, killWallet=True, keepLogs=True, cleanRun=True, dumpErrorDetails=True) errorCode = 0 if testSuccessful else 1 exit(errorCode) \ No newline at end of file From f2d077f70f017d7da5fe931984d1c19f0ed9b716 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Sat, 24 Sep 2022 08:52:56 -0500 Subject: [PATCH 093/111] GH-223 Wait for system init transaction to make it into a block. A test failed because it attempted to use the system contract before it was init-ed. --- tests/Cluster.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Cluster.py b/tests/Cluster.py index db3842da09..24f48e9cbd 100644 --- a/tests/Cluster.py +++ b/tests/Cluster.py @@ -1328,6 +1328,11 @@ def bootstrap(self, biosNode, totalNodes, prodCount, totalProducers, pfSetupPoli data="{\"version\":0,\"core\":\"4,%s\"}" % (CORE_SYMBOL) opts="--permission %s@active" % (eosioAccount.name) trans=biosNode.pushMessage(eosioAccount.name, action, data, opts) + transId=Node.getTransId(trans[1]) + Utils.Print("Wait for system init transaction to be in a block.") + if not biosNode.waitForTransInBlock(transId): + Utils.Print("ERROR: Failed to validate transaction %s in block on server port %d." % (transId, biosNode.port)) + return None Utils.Print("Cluster bootstrap done.") From 05099f957ad32b572f2b255ac20ee5e7da8ea4b6 Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Wed, 29 Jun 2022 22:29:11 -0400 Subject: [PATCH 094/111] docs cleanup --- .../00_install-prebuilt-binaries.md | 71 ---- .../01_download-eosio-source.md | 31 -- .../02_build-eosio-binaries.md | 18 - .../03_install-eosio-binaries.md | 24 -- .../04_test-eosio-binaries.md | 15 - .../01_shell-scripts/05_uninstall-eosio.md | 13 - .../01_shell-scripts/index.md | 17 - .../02_manual-build/00_eosio-dependencies.md | 45 --- .../03_platforms/amazon_linux-2.md | 92 ----- .../03_platforms/centos-7.7.md | 100 ----- .../02_manual-build/03_platforms/index.md | 8 - .../03_platforms/macos-10.14.md | 74 ---- .../03_platforms/ubuntu-18.04.md | 92 ----- .../02_manual-build/index.md | 28 -- docs/00_install/01_build-from-source/index.md | 58 ++- docs/00_install/index.md | 22 +- .../02_node-setups/00_producing-node.md | 8 +- .../02_node-setups/01_non-producing-node.md | 8 +- .../00_local-single-node-testnet.md | 4 +- .../01_local-multi-node-testnet.md | 23 +- .../03_development-environment/index.md | 6 +- .../03_plugins/chain_plugin/index.md | 2 +- .../03_plugins/login_plugin/index.md | 2 +- .../03_plugins/producer_plugin/index.md | 4 +- ...0_how-to-fast-start-without-old-history.md | 2 +- ...w-to-replay-or-resync-with-full-history.md | 2 +- ...ow-to-create-snapshot-with-full-history.md | 2 +- ...w-to-restore-snapshot-with-full-history.md | 2 +- .../03_plugins/state_history_plugin/index.md | 5 - .../03_plugins/trace_api_plugin/index.md | 8 +- .../03_plugins/txn_test_gen_plugin/index.md | 2 +- docs/01_nodeos/06_logging/index.md | 4 +- .../07_concepts/05_storage-and-read-modes.md | 6 +- .../07_concepts/10_context-free-data/index.md | 2 +- docs/01_nodeos/08_troubleshooting/index.md | 4 +- docs/01_nodeos/09_deprecation-notices.md | 3 - docs/01_nodeos/index.md | 7 +- .../how-to-create-a-wallet.md | 2 +- .../how-to-create-an-account.md | 10 +- .../how-to-create-key-pairs.md | 6 +- .../how-to-delegate-CPU-resource.md | 8 +- .../how-to-delegate-net-resource.md | 8 +- .../how-to-deploy-a-smart-contract.md | 2 +- .../how-to-get-account-information.md | 10 +- .../how-to-get-block-information.md | 4 +- .../how-to-get-transaction-information.md | 6 +- .../02_how-to-guides/how-to-import-a-key.md | 4 +- .../how-to-list-all-key-pairs.md | 4 +- .../03_command-reference/create/account.md | 2 +- .../03_command-reference/net/connect.md | 2 +- .../03_command-reference/net/disconnect.md | 2 +- .../03_command-reference/net/peers.md | 2 +- .../03_command-reference/net/status.md | 2 +- .../03_command-reference/set/set-account.md | 2 +- docs/02_cleos/04_troubleshooting.md | 2 +- docs/02_cleos/index.md | 6 +- docs/03_keosd/index.md | 4 +- docs/10_utilities/index.md | 6 +- docs/20_upgrade-guide/79_2.0-upgrade-guide.md | 3 - docs/20_upgrade-guide/81_1.8-upgrade-guide.md | 132 ------ docs/20_upgrade-guide/index.md | 52 --- docs/30_release-notes/87_v2.0.12.md | 4 - docs/30_release-notes/88_v2.0.11.md | 21 - docs/30_release-notes/89_v2.0.10.md | 41 -- docs/30_release-notes/90_v2.0.9.md | 17 - docs/30_release-notes/91_v2.0.8.md | 59 --- docs/30_release-notes/92_v2.0.7.md | 30 -- docs/30_release-notes/93_v2.0.6.md | 74 ---- docs/30_release-notes/94_v2.0.5.md | 65 --- docs/30_release-notes/95_v2.0.4.md | 88 ---- docs/30_release-notes/96_v2.0.3.md | 29 -- docs/30_release-notes/97_v2.0.2.md | 46 --- docs/30_release-notes/98_v2.0.1.md | 37 -- docs/30_release-notes/99_v2.0.0.md | 377 ------------------ docs/30_release-notes/index.md | 28 -- docs/index.md | 22 +- ...o_components.png => mandel_components.png} | Bin 77 files changed, 166 insertions(+), 1867 deletions(-) delete mode 100644 docs/00_install/00_install-prebuilt-binaries.md delete mode 100644 docs/00_install/01_build-from-source/01_shell-scripts/01_download-eosio-source.md delete mode 100644 docs/00_install/01_build-from-source/01_shell-scripts/02_build-eosio-binaries.md delete mode 100644 docs/00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md delete mode 100644 docs/00_install/01_build-from-source/01_shell-scripts/04_test-eosio-binaries.md delete mode 100644 docs/00_install/01_build-from-source/01_shell-scripts/05_uninstall-eosio.md delete mode 100644 docs/00_install/01_build-from-source/01_shell-scripts/index.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/00_eosio-dependencies.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/03_platforms/amazon_linux-2.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/03_platforms/centos-7.7.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/03_platforms/index.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/03_platforms/macos-10.14.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/03_platforms/ubuntu-18.04.md delete mode 100644 docs/00_install/01_build-from-source/02_manual-build/index.md delete mode 100644 docs/01_nodeos/09_deprecation-notices.md delete mode 100644 docs/20_upgrade-guide/79_2.0-upgrade-guide.md delete mode 100644 docs/20_upgrade-guide/81_1.8-upgrade-guide.md delete mode 100644 docs/20_upgrade-guide/index.md delete mode 100644 docs/30_release-notes/87_v2.0.12.md delete mode 100644 docs/30_release-notes/88_v2.0.11.md delete mode 100644 docs/30_release-notes/89_v2.0.10.md delete mode 100644 docs/30_release-notes/90_v2.0.9.md delete mode 100644 docs/30_release-notes/91_v2.0.8.md delete mode 100644 docs/30_release-notes/92_v2.0.7.md delete mode 100644 docs/30_release-notes/93_v2.0.6.md delete mode 100644 docs/30_release-notes/94_v2.0.5.md delete mode 100644 docs/30_release-notes/95_v2.0.4.md delete mode 100644 docs/30_release-notes/96_v2.0.3.md delete mode 100644 docs/30_release-notes/97_v2.0.2.md delete mode 100644 docs/30_release-notes/98_v2.0.1.md delete mode 100644 docs/30_release-notes/99_v2.0.0.md delete mode 100644 docs/30_release-notes/index.md rename docs/{eosio_components.png => mandel_components.png} (100%) diff --git a/docs/00_install/00_install-prebuilt-binaries.md b/docs/00_install/00_install-prebuilt-binaries.md deleted file mode 100644 index 6888d6b6f2..0000000000 --- a/docs/00_install/00_install-prebuilt-binaries.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -content_title: Install Prebuilt Binaries ---- - -[[info | Previous Builds]] -| If you have previously installed EOSIO from source using shell scripts, you must first run the [Uninstall Script](01_build-from-source/01_shell-scripts/05_uninstall-eosio.md) before installing any prebuilt binaries on the same OS. - -## Prebuilt Binaries - -Prebuilt EOSIO software packages are available for the operating systems below. Find and follow the instructions for your OS: - -### Mac OS X: - -#### Mac OS X Brew Install -```sh -brew tap eosio/eosio -brew install eosio -``` -#### Mac OS X Brew Uninstall -```sh -brew remove eosio -``` - -### Ubuntu Linux: - -#### Ubuntu 18.04 Package Install -```sh -wget https://github.com/eosio/eos/releases/download/v2.0.13/eosio_2.0.13-1-ubuntu-18.04_amd64.deb -sudo apt install ./eosio_2.0.13-1-ubuntu-18.04_amd64.deb -``` -#### Ubuntu 16.04 Package Install -```sh -wget https://github.com/eosio/eos/releases/download/v2.0.13/eosio_2.0.13-1-ubuntu-16.04_amd64.deb -sudo apt install ./eosio_2.0.13-1-ubuntu-16.04_amd64.deb -``` -#### Ubuntu Package Uninstall -```sh -sudo apt remove eosio -``` - -### RPM-based (CentOS, Amazon Linux, etc.): - -#### RPM Package Install -```sh -wget https://github.com/eosio/eos/releases/download/v2.0.13/eosio-2.0.13-1.el7.x86_64.rpm -sudo yum install ./eosio-2.0.13-1.el7.x86_64.rpm -``` -#### RPM Package Uninstall -```sh -sudo yum remove eosio -``` - -## Location of EOSIO binaries - -After installing the prebuilt packages, the actual EOSIO binaries will be located under: -* `/usr/opt/eosio//bin` (Linux-based); or -* `/usr/local/Cellar/eosio//bin` (MacOS) - -where `version-string` is the EOSIO version that was installed. - -Also, soft links for each EOSIO program (`nodeos`, `cleos`, `keosd`, etc.) will be created under `usr/bin` or `usr/local/bin` to allow them to be executed from any directory. - -## Previous Versions - -To install previous versions of the EOSIO prebuilt binaries: - -1. Browse to https://github.com/EOSIO/eos/tags and select the actual version of the EOSIO software you need to install. - -2. Scroll down past the `Release Notes` and download the package or archive that you need for your OS. - -3. Follow the instructions on the first paragraph above to install the selected prebuilt binaries on the given OS. diff --git a/docs/00_install/01_build-from-source/01_shell-scripts/01_download-eosio-source.md b/docs/00_install/01_build-from-source/01_shell-scripts/01_download-eosio-source.md deleted file mode 100644 index 18f436899b..0000000000 --- a/docs/00_install/01_build-from-source/01_shell-scripts/01_download-eosio-source.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -content_title: Download EOSIO Source ---- - -To download the EOSIO source code, clone the `eos` repo and its submodules. It is adviced to create a home `eosio` folder first and download all the EOSIO related software there: - -```sh -mkdir -p ~/eosio && cd ~/eosio -git clone --recursive https://github.com/EOSIO/eos -``` - -## Update Submodules - -If a repository is cloned without the `--recursive` flag, the submodules *must* be updated before starting the build process: - -```sh -cd ~/eosio/eos -git submodule update --init --recursive -``` - -## Pull Changes - -When pulling changes, especially after switching branches, the submodules *must* also be updated. This can be achieved with the `git submodule` command as above, or using `git pull` directly: - -```sh -[git checkout ] (optional) -git pull --recurse-submodules -``` - -[[info | What's Next?]] -| [Build EOSIO binaries](02_build-eosio-binaries.md) diff --git a/docs/00_install/01_build-from-source/01_shell-scripts/02_build-eosio-binaries.md b/docs/00_install/01_build-from-source/01_shell-scripts/02_build-eosio-binaries.md deleted file mode 100644 index 9f550793ad..0000000000 --- a/docs/00_install/01_build-from-source/01_shell-scripts/02_build-eosio-binaries.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -content_title: Build EOSIO Binaries ---- - -[[info | Shell Scripts]] -| The build script is one of various automated shell scripts provided in the EOSIO repository for building, installing, and optionally uninstalling the EOSIO software and its dependencies. They are available in the `eos/scripts` folder. - -The build script first installs all dependencies and then builds EOSIO. The script supports these [Operating Systems](../../index.md#supported-operating-systems). To run it, first change to the `~/eosio/eos` folder, then launch the script: - -```sh -cd ~/eosio/eos -./scripts/eosio_build.sh -``` - -The build process writes temporary content to the `eos/build` folder. After building, the program binaries can be found at `eos/build/programs`. - -[[info | What's Next?]] -| [Installing EOSIO](03_install-eosio-binaries.md) is strongly recommended after building from source as it makes local development significantly more friendly. diff --git a/docs/00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md b/docs/00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md deleted file mode 100644 index dfc8e8d9d1..0000000000 --- a/docs/00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -content_title: Install EOSIO Binaries ---- - -## EOSIO install script - -For ease of contract development, content can be installed at the `/usr/local` folder using the `eosio_install.sh` script within the `eos/scripts` folder. Adequate permission is required to install on system folders: - -```sh -cd ~/eosio/eos -./scripts/eosio_install.sh -``` - -## EOSIO manual install - -In lieu of the `eosio_install.sh` script, you can install the EOSIO binaries directly by invoking `make install` within the `eos/build` folder. Again, adequate permission is required to install on system folders: - -```sh -cd ~/eosio/eos/build -make install -``` - -[[info | What's Next?]] -| Configure and use [Nodeos](../../../01_nodeos/index.md), or optionally [Test the EOSIO binaries](04_test-eosio-binaries.md). diff --git a/docs/00_install/01_build-from-source/01_shell-scripts/04_test-eosio-binaries.md b/docs/00_install/01_build-from-source/01_shell-scripts/04_test-eosio-binaries.md deleted file mode 100644 index 3a34bf8cee..0000000000 --- a/docs/00_install/01_build-from-source/01_shell-scripts/04_test-eosio-binaries.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -content_title: Test EOSIO Binaries ---- - -Optionally, a set of tests can be run against your build to perform some basic validation of the EOSIO software installation. - -To run the test suite after building, run: - -```sh -cd ~/eosio/eos/build -make test -``` - -[[info | What's Next?]] -| Configure and use [Nodeos](../../../01_nodeos/index.md). diff --git a/docs/00_install/01_build-from-source/01_shell-scripts/05_uninstall-eosio.md b/docs/00_install/01_build-from-source/01_shell-scripts/05_uninstall-eosio.md deleted file mode 100644 index 7b8ca8e831..0000000000 --- a/docs/00_install/01_build-from-source/01_shell-scripts/05_uninstall-eosio.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -content_title: Uninstall EOSIO ---- - -If you have previously built EOSIO from source and now wish to install the prebuilt binaries, or to build from source again, it is recommended to run the `eosio_uninstall.sh` script within the `eos/scripts` folder: - -```sh -cd ~/eosio/eos -./scripts/eosio_uninstall.sh -``` - -[[info | Uninstall Dependencies]] -| The uninstall script will also prompt the user to uninstall EOSIO dependencies. This is recommended if installing prebuilt EOSIO binaries or building EOSIO for the first time. diff --git a/docs/00_install/01_build-from-source/01_shell-scripts/index.md b/docs/00_install/01_build-from-source/01_shell-scripts/index.md deleted file mode 100644 index 6e1f1ffbbe..0000000000 --- a/docs/00_install/01_build-from-source/01_shell-scripts/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -content_title: Shell Scripts ---- - -[[info | Did you know?]] -| Shell scripts automate the process of building, installing, testing, and uninstalling the EOSIO software and dependencies. - -To build EOSIO from the source code using shell scripts, visit the sections below: - -1. [Download EOSIO Source](01_download-eosio-source.md) -2. [Build EOSIO Binaries](02_build-eosio-binaries.md) -3. [Install EOSIO Binaries](03_install-eosio-binaries.md) -4. [Test EOSIO Binaries](04_test-eosio-binaries.md) -5. [Uninstall EOSIO](05_uninstall-eosio.md) - -[[info | Building EOSIO is for Advanced Developers]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](../../00_install-prebuilt-binaries.md) instead of building from source. diff --git a/docs/00_install/01_build-from-source/02_manual-build/00_eosio-dependencies.md b/docs/00_install/01_build-from-source/02_manual-build/00_eosio-dependencies.md deleted file mode 100644 index fa119af890..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/00_eosio-dependencies.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -content_title: EOSIO Software Dependencies ---- - -The EOSIO software requires specific software dependencies to build the EOSIO binaries. These dependencies can be built from source or installed from binaries directly. Dependencies can be pinned to a specific version release or unpinned to the current version, usually the latest one. The main EOSIO dependencies hosted outside the EOSIO repos are: - -* Clang - the C++17 compliant compiler used by EOSIO -* CMake - the build system used by EOSIO -* Boost - the C++ Boost library used by EOSIO -* OpenSSL - the secure communications (and crypto) library -* LLVM - the LLVM compiler/toolchain infrastructure - -Other dependencies are either inside the EOSIO repo, such as the `secp256k1` elliptic curve DSA library, or they are otherwise used for testing or housekeeping purposes, such as: - -* automake, autoconf, autotools -* doxygen, graphviz -* python2, python3 -* bzip2, zlib -* etc. - -## Pinned Dependencies - -To guarantee interoperability across different EOSIO software releases, developers may opt to reproduce the exact "pinned" dependency binaries used in-house. Block producers may want to install and run the EOSIO software built with these pinned dependencies for portability and stability reasons. Pinned dependencies are usually built from source. - -## Unpinned Dependencies - -Regular users or application developers may prefer installing unpinned versions of the EOSIO dependencies. These correspond to the latest or otherwise stable versions of the dependencies. The main advantage of unpinned dependencies is reduced installation times and perhaps better performance. Pinned dependencies are typically installed from binaries. - -## Automatic Installation of Dependencies - -EOSIO dependencies can be built or installed automatically from the [Build Script](../01_shell-scripts/02_build-eosio-binaries.md) when building EOSIO from source. To build the pinned dependencies, the optional `-P` parameter can be specified when invoking the script. Otherwise, the unpinned dependencies will be installed instead, with the exception of `boost` and `cmake` which are always pinned: - -```sh -cd ~/eosio/eos -./scripts/eosio_build.sh [-P] -``` - -### Unupported Platforms - -EOSIO dependencies can also be built and installed manually by reproducing the same commands invoked by the [Build Script](../01_shell-scripts/02_build-eosio-binaries.md). The actual commands can be generated from the script directly by exporting specific environment variables and CLI parameters to the script when invoked: - -```sh -cd ~/eosio/eos -export VERBOSE=true && export DRYRUN=true && ./scripts/eosio_build.sh -y [-P] -``` diff --git a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/amazon_linux-2.md b/docs/00_install/01_build-from-source/02_manual-build/03_platforms/amazon_linux-2.md deleted file mode 100644 index 21d69ed950..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/amazon_linux-2.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -content_title: Amazon Linux 2 ---- - -This section contains shell commands to manually download, build, install, test, and uninstall EOSIO and dependencies on Amazon Linux 2. - -[[info | Building EOSIO is for Advanced Developers]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](../../../00_install-prebuilt-binaries.md) instead of building from source. - -Select a task below, then copy/paste the shell commands to a Unix terminal to execute: - -* [Download EOSIO Repository](#download-eosio-repository) -* [Install EOSIO Dependencies](#install-eosio-dependencies) -* [Build EOSIO](#build-eosio) -* [Install EOSIO](#install-eosio) -* [Test EOSIO](#test-eosio) -* [Uninstall EOSIO](#uninstall-eosio) - -[[info | Building EOSIO on another OS?]] -| Visit the [Build EOSIO from Source](../../index.md) section. - -## Download EOSIO Repository -These commands set the EOSIO directories, install git, and clone the EOSIO repository. -```sh -# set EOSIO directories -export EOSIO_LOCATION=~/eosio/eos -export EOSIO_INSTALL_LOCATION=$EOSIO_LOCATION/../install -mkdir -p $EOSIO_INSTALL_LOCATION -# install git -yum update -y && yum install -y git -# clone EOSIO repository -git clone https://github.com/EOSIO/eos.git $EOSIO_LOCATION -cd $EOSIO_LOCATION && git submodule update --init --recursive -``` - -## Install EOSIO Dependencies -These commands install the EOSIO software dependencies. Make sure to [Download the EOSIO Repository](#download-eosio-repository) first and set the EOSIO directories. -```sh -# install dependencies -yum install -y which sudo procps-ng util-linux autoconf automake \ - libtool make bzip2 bzip2-devel openssl-devel gmp-devel libstdc++ libcurl-devel \ - libusbx-devel python3 python3-devel python-devel libedit-devel doxygen \ - graphviz clang patch llvm-devel llvm-static vim-common jq -# build cmake -export PATH=$EOSIO_INSTALL_LOCATION/bin:$PATH -cd $EOSIO_INSTALL_LOCATION && curl -LO https://cmake.org/files/v3.13/cmake-3.13.2.tar.gz && \ - tar -xzf cmake-3.13.2.tar.gz && \ - cd cmake-3.13.2 && \ - ./bootstrap --prefix=$EOSIO_INSTALL_LOCATION && \ - make -j$(nproc) && \ - make install && \ - rm -rf $EOSIO_INSTALL_LOCATION/cmake-3.13.2.tar.gz $EOSIO_INSTALL_LOCATION/cmake-3.13.2 -# build boost -cd $EOSIO_INSTALL_LOCATION && curl -LO https://boostorg.jfrog.io/artifactory/main/release/1.71.0/source/boost_1_71_0.tar.bz2 && \ - tar -xjf boost_1_71_0.tar.bz2 && \ - cd boost_1_71_0 && \ - ./bootstrap.sh --prefix=$EOSIO_INSTALL_LOCATION && \ - ./b2 --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -q -j$(nproc) install && \ - rm -rf $EOSIO_INSTALL_LOCATION/boost_1_71_0.tar.bz2 $EOSIO_INSTALL_LOCATION/boost_1_71_0 -``` - -## Build EOSIO -These commands build the EOSIO software on the specified OS. Make sure to [Install EOSIO Dependencies](#install-eosio-dependencies) first. - -[[caution | `EOSIO_BUILD_LOCATION` environment variable]] -| Do NOT change this variable. It is set for convenience only. It should always be set to the `build` folder within the cloned repository. - -```sh -export EOSIO_BUILD_LOCATION=$EOSIO_LOCATION/build -mkdir -p $EOSIO_BUILD_LOCATION -cd $EOSIO_BUILD_LOCATION && $EOSIO_INSTALL_LOCATION/bin/cmake -DCMAKE_BUILD_TYPE='Release' -DCMAKE_CXX_COMPILER='clang++' -DCMAKE_C_COMPILER='clang' -DCMAKE_INSTALL_PREFIX=$EOSIO_INSTALL_LOCATION $EOSIO_LOCATION -cd $EOSIO_BUILD_LOCATION && make -j$(nproc) -``` - -## Install EOSIO -This command installs the EOSIO software on the specified OS. Make sure to [Build EOSIO](#build-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && make install -``` - -## Test EOSIO -These commands validate the EOSIO software installation on the specified OS. This task is optional but recommended. Make sure to [Install EOSIO](#install-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && make test -``` - -## Uninstall EOSIO -These commands uninstall the EOSIO software from the specified OS. -```sh -xargs rm < $EOSIO_BUILD_LOCATION/install_manifest.txt -rm -rf $EOSIO_BUILD_LOCATION -``` diff --git a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/centos-7.7.md b/docs/00_install/01_build-from-source/02_manual-build/03_platforms/centos-7.7.md deleted file mode 100644 index 8a7fdbd5ae..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/centos-7.7.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -content_title: Centos 7.7 ---- - -This section contains shell commands to manually download, build, install, test, and uninstall EOSIO and dependencies on Centos 7.7. - -[[info | Building EOSIO is for Advanced Developers]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](../../../00_install-prebuilt-binaries.md) instead of building from source. - -Select a task below, then copy/paste the shell commands to a Unix terminal to execute: - -* [Download EOSIO Repository](#download-eosio-repository) -* [Install EOSIO Dependencies](#install-eosio-dependencies) -* [Build EOSIO](#build-eosio) -* [Install EOSIO](#install-eosio) -* [Test EOSIO](#test-eosio) -* [Uninstall EOSIO](#uninstall-eosio) - -[[info | Building EOSIO on another OS?]] -| Visit the [Build EOSIO from Source](../../index.md) section. - -## Download EOSIO Repository -These commands set the EOSIO directories, install git, and clone the EOSIO repository. -```sh -# set EOSIO directories -export EOSIO_LOCATION=~/eosio/eos -export EOSIO_INSTALL_LOCATION=$EOSIO_LOCATION/../install -mkdir -p $EOSIO_INSTALL_LOCATION -# install git -yum update -y && yum install -y git -# clone EOSIO repository -git clone https://github.com/EOSIO/eos.git $EOSIO_LOCATION -cd $EOSIO_LOCATION && git submodule update --init --recursive -``` - -## Install EOSIO Dependencies -These commands install the EOSIO software dependencies. Make sure to [Download the EOSIO Repository](#download-eosio-repository) first and set the EOSIO directories. -```sh -# install dependencies -yum update -y && \ - yum install -y epel-release && \ - yum --enablerepo=extras install -y centos-release-scl && \ - yum --enablerepo=extras install -y devtoolset-8 && \ - yum --enablerepo=extras install -y which git autoconf automake libtool make bzip2 doxygen \ - graphviz bzip2-devel openssl-devel gmp-devel ocaml \ - python python-devel rh-python36 file libusbx-devel \ - libcurl-devel patch vim-common jq llvm-toolset-7.0-llvm-devel llvm-toolset-7.0-llvm-static -# build cmake -export PATH=$EOSIO_INSTALL_LOCATION/bin:$PATH -cd $EOSIO_INSTALL_LOCATION && curl -LO https://cmake.org/files/v3.13/cmake-3.13.2.tar.gz && \ - source /opt/rh/devtoolset-8/enable && \ - tar -xzf cmake-3.13.2.tar.gz && \ - cd cmake-3.13.2 && \ - ./bootstrap --prefix=$EOSIO_INSTALL_LOCATION && \ - make -j$(nproc) && \ - make install && \ - rm -rf $EOSIO_INSTALL_LOCATION/cmake-3.13.2.tar.gz $EOSIO_INSTALL_LOCATION/cmake-3.13.2 -# apply clang patch -cp -f $EOSIO_LOCATION/scripts/clang-devtoolset8-support.patch /tmp/clang-devtoolset8-support.patch -# build boost -cd $EOSIO_INSTALL_LOCATION && curl -LO https://boostorg.jfrog.io/artifactory/main/release/1.71.0/source/boost_1_71_0.tar.bz2 && \ - source /opt/rh/devtoolset-8/enable && \ - tar -xjf boost_1_71_0.tar.bz2 && \ - cd boost_1_71_0 && \ - ./bootstrap.sh --prefix=$EOSIO_INSTALL_LOCATION && \ - ./b2 --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -q -j$(nproc) install && \ - rm -rf $EOSIO_INSTALL_LOCATION/boost_1_71_0.tar.bz2 $EOSIO_INSTALL_LOCATION/boost_1_71_0 -``` - -## Build EOSIO -These commands build the EOSIO software on the specified OS. Make sure to [Install EOSIO Dependencies](#install-eosio-dependencies) first. - -[[caution | `EOSIO_BUILD_LOCATION` environment variable]] -| Do NOT change this variable. It is set for convenience only. It should always be set to the `build` folder within the cloned repository. - -```sh -export EOSIO_BUILD_LOCATION=$EOSIO_LOCATION/build -mkdir -p $EOSIO_BUILD_LOCATION -cd $EOSIO_BUILD_LOCATION && source /opt/rh/devtoolset-8/enable && cmake -DCMAKE_BUILD_TYPE='Release' -DLLVM_DIR='/opt/rh/llvm-toolset-7.0/root/usr/lib64/cmake/llvm' -DCMAKE_INSTALL_PREFIX=$EOSIO_INSTALL_LOCATION $EOSIO_LOCATION -cd $EOSIO_BUILD_LOCATION && make -j$(nproc) -``` - -## Install EOSIO -This command installs the EOSIO software on the specified OS. Make sure to [Build EOSIO](#build-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && make install -``` - -## Test EOSIO -These commands validate the EOSIO software installation on the specified OS. This task is optional but recommended. Make sure to [Install EOSIO](#install-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && source /opt/rh/rh-python36/enable && make test -``` - -## Uninstall EOSIO -These commands uninstall the EOSIO software from the specified OS. -```sh -xargs rm < $EOSIO_BUILD_LOCATION/install_manifest.txt -rm -rf $EOSIO_BUILD_LOCATION -``` diff --git a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/index.md b/docs/00_install/01_build-from-source/02_manual-build/03_platforms/index.md deleted file mode 100644 index 4058c091e5..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -content_title: Platforms ---- - -* [Amazon Linux 2](amazon_linux-2.md) -* [CentOS 7.7](centos-7.7.md) -* [MacOS 10.14](macos-10.14.md) -* [Ubuntu 18.04](ubuntu-18.04.md) diff --git a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/macos-10.14.md b/docs/00_install/01_build-from-source/02_manual-build/03_platforms/macos-10.14.md deleted file mode 100644 index 15e58cc106..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/macos-10.14.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -content_title: MacOS 10.14 ---- - -This section contains shell commands to manually download, build, install, test, and uninstall EOSIO and dependencies on MacOS 10.14. - -[[info | Building EOSIO is for Advanced Developers]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](../../../00_install-prebuilt-binaries.md) instead of building from source. - -Select a task below, then copy/paste the shell commands to a Unix terminal to execute: - -* [Download EOSIO Repository](#download-eosio-repository) -* [Install EOSIO Dependencies](#install-eosio-dependencies) -* [Build EOSIO](#build-eosio) -* [Install EOSIO](#install-eosio) -* [Test EOSIO](#test-eosio) -* [Uninstall EOSIO](#uninstall-eosio) - -[[info | Building EOSIO on another OS?]] -| Visit the [Build EOSIO from Source](../../index.md) section. - -## Download EOSIO Repository -These commands set the EOSIO directories, install git, and clone the EOSIO repository. -```sh -# set EOSIO directories -export EOSIO_LOCATION=~/eosio/eos -export EOSIO_INSTALL_LOCATION=$EOSIO_LOCATION/../install -mkdir -p $EOSIO_INSTALL_LOCATION -# install git -brew update && brew install git -# clone EOSIO repository -git clone https://github.com/EOSIO/eos.git $EOSIO_LOCATION -cd $EOSIO_LOCATION && git submodule update --init --recursive -``` - -## Install EOSIO Dependencies -These commands install the EOSIO software dependencies. Make sure to [Download the EOSIO Repository](#download-eosio-repository) first and set the EOSIO directories. -```sh -# install dependencies -brew install cmake python libtool libusb graphviz automake wget gmp pkgconfig doxygen openssl@1.1 jq boost || : -export PATH=$EOSIO_INSTALL_LOCATION/bin:$PATH -``` - -## Build EOSIO -These commands build the EOSIO software on the specified OS. Make sure to [Install EOSIO Dependencies](#install-eosio-dependencies) first. - -[[caution | `EOSIO_BUILD_LOCATION` environment variable]] -| Do NOT change this variable. It is set for convenience only. It should always be set to the `build` folder within the cloned repository. - -```sh -export EOSIO_BUILD_LOCATION=$EOSIO_LOCATION/build -mkdir -p $EOSIO_BUILD_LOCATION -cd $EOSIO_BUILD_LOCATION && cmake -DCMAKE_BUILD_TYPE='Release' -DCMAKE_INSTALL_PREFIX=$EOSIO_INSTALL_LOCATION $EOSIO_LOCATION -cd $EOSIO_BUILD_LOCATION && make -j$(getconf _NPROCESSORS_ONLN) -``` - -## Install EOSIO -This command installs the EOSIO software on the specified OS. Make sure to [Build EOSIO](#build-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && make install -``` - -## Test EOSIO -These commands validate the EOSIO software installation on the specified OS. This task is optional but recommended. Make sure to [Install EOSIO](#install-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && make test -``` - -## Uninstall EOSIO -These commands uninstall the EOSIO software from the specified OS. -```sh -xargs rm < $EOSIO_BUILD_LOCATION/install_manifest.txt -rm -rf $EOSIO_BUILD_LOCATION -``` diff --git a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/ubuntu-18.04.md b/docs/00_install/01_build-from-source/02_manual-build/03_platforms/ubuntu-18.04.md deleted file mode 100644 index 49717b5f10..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/03_platforms/ubuntu-18.04.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -content_title: Ubuntu 18.04 ---- - -This section contains shell commands to manually download, build, install, test, and uninstall EOSIO and dependencies on Ubuntu 18.04. - -[[info | Building EOSIO is for Advanced Developers]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](../../../00_install-prebuilt-binaries.md) instead of building from source. - -Select a task below, then copy/paste the shell commands to a Unix terminal to execute: - -* [Download EOSIO Repository](#download-eosio-repository) -* [Install EOSIO Dependencies](#install-eosio-dependencies) -* [Build EOSIO](#build-eosio) -* [Install EOSIO](#install-eosio) -* [Test EOSIO](#test-eosio) -* [Uninstall EOSIO](#uninstall-eosio) - -[[info | Building EOSIO on another OS?]] -| Visit the [Build EOSIO from Source](../../index.md) section. - -## Download EOSIO Repository -These commands set the EOSIO directories, install git, and clone the EOSIO repository. -```sh -# set EOSIO directories -export EOSIO_LOCATION=~/eosio/eos -export EOSIO_INSTALL_LOCATION=$EOSIO_LOCATION/../install -mkdir -p $EOSIO_INSTALL_LOCATION -# install git -apt-get update && apt-get upgrade -y && DEBIAN_FRONTEND=noninteractive apt-get install -y git -# clone EOSIO repository -git clone https://github.com/EOSIO/eos.git $EOSIO_LOCATION -cd $EOSIO_LOCATION && git submodule update --init --recursive -``` - -## Install EOSIO Dependencies -These commands install the EOSIO software dependencies. Make sure to [Download the EOSIO Repository](#download-eosio-repository) first and set the EOSIO directories. -```sh -# install dependencies -apt-get install -y make bzip2 automake libbz2-dev libssl-dev doxygen graphviz libgmp3-dev \ - autotools-dev python2.7 python2.7-dev python3 python3-dev \ - autoconf libtool curl zlib1g-dev sudo ruby libusb-1.0-0-dev \ - libcurl4-gnutls-dev pkg-config patch llvm-7-dev clang-7 vim-common jq -# build cmake -export PATH=$EOSIO_INSTALL_LOCATION/bin:$PATH -cd $EOSIO_INSTALL_LOCATION && curl -LO https://cmake.org/files/v3.13/cmake-3.13.2.tar.gz && \ - tar -xzf cmake-3.13.2.tar.gz && \ - cd cmake-3.13.2 && \ - ./bootstrap --prefix=$EOSIO_INSTALL_LOCATION && \ - make -j$(nproc) && \ - make install && \ - rm -rf $EOSIO_INSTALL_LOCATION/cmake-3.13.2.tar.gz $EOSIO_INSTALL_LOCATION/cmake-3.13.2 -# build boost -cd $EOSIO_INSTALL_LOCATION && curl -LO https://boostorg.jfrog.io/artifactory/main/release/1.71.0/source/boost_1_71_0.tar.bz2 && \ - tar -xjf boost_1_71_0.tar.bz2 && \ - cd boost_1_71_0 && \ - ./bootstrap.sh --prefix=$EOSIO_INSTALL_LOCATION && \ - ./b2 --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -q -j$(nproc) install && \ - rm -rf $EOSIO_INSTALL_LOCATION/boost_1_71_0.tar.bz2 $EOSIO_INSTALL_LOCATION/boost_1_71_0 -``` - -## Build EOSIO -These commands build the EOSIO software on the specified OS. Make sure to [Install EOSIO Dependencies](#install-eosio-dependencies) first. - -[[caution | `EOSIO_BUILD_LOCATION` environment variable]] -| Do NOT change this variable. It is set for convenience only. It should always be set to the `build` folder within the cloned repository. - -```sh -export EOSIO_BUILD_LOCATION=$EOSIO_LOCATION/build -mkdir -p $EOSIO_BUILD_LOCATION -cd $EOSIO_BUILD_LOCATION && cmake -DCMAKE_BUILD_TYPE='Release' -DCMAKE_CXX_COMPILER='clang++-7' -DCMAKE_C_COMPILER='clang-7' -DLLVM_DIR='/usr/lib/llvm-7/lib/cmake/llvm' -DCMAKE_INSTALL_PREFIX=$EOSIO_INSTALL_LOCATION $EOSIO_LOCATION -cd $EOSIO_BUILD_LOCATION && make -j$(nproc) -``` - -## Install EOSIO -This command installs the EOSIO software on the specified OS. Make sure to [Build EOSIO](#build-eosio) first. -```sh -cd $EOSIO_BUILD_LOCATION && make install -``` - -## Test EOSIO -These commands validate the EOSIO software installation on the specified OS. Make sure to [Install EOSIO](#install-eosio) first. (**Note**: This task is optional but recommended.) -```sh -cd $EOSIO_BUILD_LOCATION && make test -``` - -## Uninstall EOSIO -These commands uninstall the EOSIO software from the specified OS. -```sh -xargs rm < $EOSIO_BUILD_LOCATION/install_manifest.txt -rm -rf $EOSIO_BUILD_LOCATION -``` diff --git a/docs/00_install/01_build-from-source/02_manual-build/index.md b/docs/00_install/01_build-from-source/02_manual-build/index.md deleted file mode 100644 index 0852795c3f..0000000000 --- a/docs/00_install/01_build-from-source/02_manual-build/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -content_title: EOSIO Manual Build ---- - -[[info | Manual Builds are for Advanced Developers]] -| These manual instructions are intended for advanced developers. The [Shell Scripts](../01_shell-scripts/index.md) should be the preferred method to build EOSIO from source. If the script fails or your platform is not supported, continue with the instructions below. - -## EOSIO Dependencies - -When performing a manual build, it is necessary to install specific software packages that the EOSIO software depends on. To learn more about these dependencies, visit the [EOSIO Software Dependencies](00_eosio-dependencies.md) section. - -## Platforms - -Shell commands are available to manually download, build, install, test, and uninstall the EOSIO software and dependencies for these [platforms](03_platforms/index.md). - -## Out-of-source Builds - -While building dependencies and EOSIO binaries, out-of-source builds are also supported. Refer to the `cmake` help for more information. - -## Other Compilers - -To override `clang`'s default compiler toolchain, add these flags to the `cmake` command within the above instructions: - -`-DCMAKE_CXX_COMPILER=/path/to/c++ -DCMAKE_C_COMPILER=/path/to/cc` - -## Debug Builds - -For a debug build, add `-DCMAKE_BUILD_TYPE=Debug`. Other common build types include `Release` and `RelWithDebInfo`. diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 03f3db858f..7e9bdfbc44 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -1,14 +1,56 @@ --- -content_title: Build EOSIO from Source +content_title: Build Mandel from Source --- -[[info | Building EOSIO is for Advanced Developers]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](../00_install-prebuilt-binaries.md) instead of building from source. +The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests. -EOSIO can be built on several platforms using different build methods. Advanced users may opt to build EOSIO using our shell scripts. Node operators or block producers who wish to deploy a public node, may prefer our manual build instructions. +## Building Mandel -* [Shell Scripts](01_shell-scripts/index.md) - Suitable for the majority of developers, these scripts build on Mac OS and many flavors of Linux. -* [Manual Build](02_manual-build/index.md) - Suitable for those platforms that may be hostile to the shell scripts or for operators who need more control over their builds. +``` +git submodule update --init --recursive +mkdir build +cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make -j $(nproc) +``` -[[info | EOSIO Installation Recommended]] -| After building EOSIO successfully, it is highly recommended to install the EOSIO binaries from their default build directory. This copies the EOSIO binaries to a central location, such as `/usr/local/bin`, or `~/eosio/x.y/bin`, where `x.y` is the EOSIO release version. +We support the following CMake options: +``` +-DCMAKE_CXX_COMPILER_LAUNCHER=ccache Speed up builds +-DCMAKE_C_COMPILER_LAUNCHER=ccache Speed up builds +-DCMAKE_BUILD_TYPE=DEBUG Debug builds +-DDISABLE_WASM_SPEC_TESTS=yes Speed up builds and skip many tests +-DCMAKE_INSTALL_PREFIX=/foo/bar Where to install to +-DENABLE_OC=no Disable OC support; useful when this repo is used + as a library +-GNinja Use ninja instead of make + (faster on high-core-count machines) +``` + +I highly recommend the ccache options. They don't speed up the first clean build, but they speed up future clean builds after the first build. + +### Running tests + +``` +cd build + +# Runs parallelizable tests in parallel. This runs much faster when +# -DDISABLE_WASM_SPEC_TESTS=yes is used. +ctest -j $(nproc) -LE "nonparallelizable_tests|long_running_tests" -E "full-version-label-test|release-build-test|print-build-info-test" + +# These tests can't run in parallel. +ctest -L "nonparallelizable_tests" + +# These tests can't run in parallel. They also take a long time to run. +ctest -L "long_running_tests" +``` + +## Other Compilers + +To override `clang`'s default compiler toolchain, add these flags to the `cmake` command within the above instructions: + +`-DCMAKE_CXX_COMPILER=/path/to/c++ -DCMAKE_C_COMPILER=/path/to/cc` + +## Debug Builds + +For a debug build, add `-DCMAKE_BUILD_TYPE=Debug`. Other common build types include `Release` and `RelWithDebInfo`. diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 3153b2547c..7ed71bdcdb 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -1,24 +1,18 @@ --- -content_title: EOSIO Software Installation +content_title: Mandel Software Installation --- -There are various ways to install and use the EOSIO software: +The best way to install and use the Mandel software is to build it from source: -* [Install EOSIO Prebuilt Binaries](00_install-prebuilt-binaries.md) -* [Build EOSIO from Source](01_build-from-source/index.md) - -[[info]] -| If you are new to EOSIO, it is recommended that you install the [EOSIO Prebuilt Binaries](00_install-prebuilt-binaries.md), then proceed to the [Getting Started](https://developers.eos.io/eosio-home/docs/) section of the [EOSIO Developer Portal](https://developers.eos.io/). If you are an advanced developer, a block producer, or no binaries are available for your platform, you may need to [Build EOSIO from source](01_build-from-source/index.md) instead. +* [Build Mandel from Source](01_build-from-source/index.md) ## Supported Operating Systems -EOSIO currently supports the following operating systems: +Mandel currently supports the following operating systems: -1. Amazon Linux 2 -2. CentOS 7 -3. Ubuntu 16.04 -4. Ubuntu 18.04 -5. MacOS 10.14 (Mojave) +1. Ubuntu 18.04 +2. Ubuntu 20.04 +3. Ubuntu 22.04 [[info | Note]] -| It may be possible to install EOSIO on other Unix-based operating systems. This is not officially supported, though. +| It may be possible to install Mandel on other Unix-based operating systems. This is not officially supported, though. diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index f9555ba262..d6950fc4c7 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -7,12 +7,12 @@ content_title: Producing Node Setup ## Goal -This section describes how to set up a producing node within the EOSIO network. A producing node, as its name implies, is a node that is configured to produce blocks in an `EOSIO` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). +This section describes how to set up a producing node within the Mandel network. A producing node, as its name implies, is a node that is configured to produce blocks in an `Mandel` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the Mandel software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built Mandel using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps @@ -49,7 +49,7 @@ producer-name = youraccount You will need to set the private key for your producer. The public key should have an authority for the producer account defined above. `signature-provider` is defined with a 3-field tuple: -* `public-key` - A valid EOSIO public key in form of a string. +* `public-key` - A valid Mandel public key in form of a string. * `provider-spec` - It's a string formatted like : * `provider-type` - KEY or KEOSD diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index 77365ef18f..6ad52526e1 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -4,12 +4,12 @@ content_title: Non-producing Node Setup ## Goal -This section describes how to set up a non-producing node within the EOSIO network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `EOSIO` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. +This section describes how to set up a non-producing node within the Mandel network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `Mandel` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the Mandel software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built Mandel using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps @@ -37,4 +37,4 @@ nodeos ... --p2p-peer-address=106.10.42.238:9876 ### 2. Enable one or more available plugins -Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the EOSIO RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. +Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the Mandel RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index 53ca22048c..f1e7f8be2a 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -12,8 +12,8 @@ This section describes how to set up a single-node blockchain configuration runn ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the Mandel software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built Mandel using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 7f94e88b81..2794ad9c79 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -10,20 +10,23 @@ This section describes how to set up a multi-node blockchain configuration runni ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the Mandel software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps Open four "terminal" windows and perform the following steps: -1. [Start the Wallet Manager](#1-start-the-wallet-manager) -2. [Create a Default Wallet](#2-create-a-default-wallet) -3. [Loading the EOSIO Key](#3-loading-the-eosio-key) -4. [Start the First Producer Node](#4-start-the-first-producer-node) -5. [Start the Second Producer Node](#5-start-the-second-producer-node) -6. [Get Nodes Info](#6-get-nodes-info) +- [Goal](#goal) +- [Before you begin](#before-you-begin) +- [Steps](#steps) + - [1. Start the Wallet Manager](#1-start-the-wallet-manager) + - [2. Create a Default Wallet](#2-create-a-default-wallet) + - [3. Loading the Mandel Key](#3-loading-the-mandel-key) + - [4. Start the First Producer Node](#4-start-the-first-producer-node) + - [5. Start the Second Producer Node](#5-start-the-second-producer-node) + - [6. Get Nodes Info](#6-get-nodes-info) ### 1. Start the Wallet Manager @@ -66,7 +69,7 @@ Without password imported keys will not be retrievable. `keosd` will generate some status output in its window. We will continue to use this second window for subsequent `cleos` commands. -### 3. Loading the EOSIO Key +### 3. Loading the Mandel Key The private blockchain launched in the steps above is created with a default initial key which must be loaded into the wallet. @@ -90,7 +93,7 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node -The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the EOSIO binaries. +The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the Mandel binaries. To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index f7cfa8f882..c09829aba9 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -15,17 +15,17 @@ This is the go-to option for smart contract developers, aspiring Block Producers While this option can technically be used for smart contract development, it may be overkill. This is most beneficial for those who are working on aspects of core development, such as benchmarking, optimization and experimentation. It's also a good option for hands-on learning and concept proofing. * [Configure Nodeos as a Local Two-Node Testnet](01_local-multi-node-testnet.md) -* [Configure Nodeos as a Local 21-Node Testnet](https://github.com/EOSIO/eos/blob/master/tutorials/bios-boot-tutorial/README.md) +* [Configure Nodeos as a Local 21-Node Testnet](https://github.com/eosnetworkfoundation/mandel/tree/main/tutorials/bios-boot-tutorial) ## Official Testnet -The official testnet is available for testing EOSIO dApps and smart contracts: +The official testnet is available for testing Mandel dApps and smart contracts: * [testnet.eos.io](https://testnet.eos.io/) ## Third-Party Testnets -The following third-party testnets are available for testing EOSIO dApps and smart contracts: +The following third-party testnets are available for testing Mandel dApps and smart contracts: * Jungle Testnet [monitor](https://monitor.jungletestnet.io/), [website](https://jungletestnet.io/) * [CryptoKylin Testnet](https://www.cryptokylin.io/) diff --git a/docs/01_nodeos/03_plugins/chain_plugin/index.md b/docs/01_nodeos/03_plugins/chain_plugin/index.md index 9da5921080..3815ef6346 100644 --- a/docs/01_nodeos/03_plugins/chain_plugin/index.md +++ b/docs/01_nodeos/03_plugins/chain_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `chain_plugin` is a core plugin required to process and aggregate chain data on an EOSIO node. +The `chain_plugin` is a core plugin required to process and aggregate chain data on a Mandel node. ## Usage diff --git a/docs/01_nodeos/03_plugins/login_plugin/index.md b/docs/01_nodeos/03_plugins/login_plugin/index.md index 68df9d4c1e..74d0b2a205 100644 --- a/docs/01_nodeos/03_plugins/login_plugin/index.md +++ b/docs/01_nodeos/03_plugins/login_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `login_plugin` supports the concept of applications authenticating with the EOSIO blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. +The `login_plugin` supports the concept of applications authenticating with the Mandel blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. ## Usage diff --git a/docs/01_nodeos/03_plugins/producer_plugin/index.md b/docs/01_nodeos/03_plugins/producer_plugin/index.md index 14b5be24ba..ac6475e761 100644 --- a/docs/01_nodeos/03_plugins/producer_plugin/index.md +++ b/docs/01_nodeos/03_plugins/producer_plugin/index.md @@ -49,7 +49,7 @@ Config Options for eosio::producer_plugin: = Where: is a string form of - a vaild EOSIO public + a vaild Mandel public key is a string in the @@ -59,7 +59,7 @@ Config Options for eosio::producer_plugin: is KEY, or KEOSD KEY: is a string form of - a valid EOSIO + a valid Mandel private key which maps to the provided public key diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md index 4e1f534483..facd99cbac 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md @@ -8,7 +8,7 @@ This procedure records the current chain state and future history, without previ ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Mandel is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md index 9f0a7308f0..b1ada13126 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md @@ -8,7 +8,7 @@ This procedure records the entire chain history. ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Mandel is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md index 19d69e9c28..712b48c7a5 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure creates a database containing the chain state, with full history ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Mandel is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md index 6eb2e76db4..582ea6b6c2 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure restores an existing snapshot with full history, so the node can ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Mandel is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/index.md b/docs/01_nodeos/03_plugins/state_history_plugin/index.md index 4ee27384f5..44d8c40c27 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/index.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/index.md @@ -48,11 +48,6 @@ Config Options for eosio::state_history_plugin: ## Examples -### history-tools - - * [Source code](https://github.com/EOSIO/history-tools/) - * [Documentation](https://eosio.github.io/history-tools/) - ## Dependencies * [`chain_plugin`](../chain_plugin/index.md) diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md index 74d1215ec0..696a397709 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md @@ -5,11 +5,11 @@ The `trace_api_plugin` provides a consumer-focused long-term API for retrieving ## Purpose -While integrating applications such as block explorers and exchanges with an EOSIO blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: +While integrating applications such as block explorers and exchanges with a Mandel blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: * A transcript of retired actions and related metadata * A consumer-focused long-term API to retrieve blocks -* Maintainable resource commitments at the EOSIO nodes +* Maintainable resource commitments at the Mandel nodes Therefore, one crucial goal of the `trace_api_plugin` is to improve the maintenance of node resources (file system, disk space, memory used, etc.). This goal is different from the existing `history_plugin` which provides far more configurable filtering and querying capabilities, or the existing `state_history_plugin` which provides a binary streaming interface to access structural chain data, action data, as well as state deltas. @@ -101,7 +101,7 @@ nodeos ... --plugin eosio::chain_plugin [options] \ ## Configuration Example -Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some EOSIO reference contracts: +Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some Mandel reference contracts: ```sh nodeos --data-dir data_dir --config-dir config_dir --trace-dir traces_dir @@ -191,7 +191,7 @@ If resource usage cannot be effectively managed via the `trace-minimum-irreversi ## Manual Maintenance -The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed EOSIO system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). +The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed Mandel system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). [[info | For node operators]] | Node operators can take full control over the lifetime of the historical data available in their nodes via the `trace-api-plugin` and the `trace-minimum-irreversible-history-blocks` and `trace-minimum-uncompressed-irreversible-history-blocks` options in conjunction with any external filesystem resource manager. diff --git a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md index bca53fba1c..9150e4fd1b 100644 --- a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md +++ b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md @@ -4,7 +4,7 @@ The `txn_test_gen_plugin` is used for transaction test purposes. [[info | For More Information]] -For more information, check the [txn_test_gen_plugin/README.md](https://github.com/EOSIO/eos/blob/develop/plugins/txn_test_gen_plugin/README.md) on the EOSIO/eos repository. +For more information, check the [txn_test_gen_plugin/README.md](https://github.com/eosnetworkfoundation/mandel/tree/main/plugins/txn_test_gen_plugin) on the Mandel/eos repository. ## Usage diff --git a/docs/01_nodeos/06_logging/index.md b/docs/01_nodeos/06_logging/index.md index 8a7670e7fb..0b1fdb8c7d 100644 --- a/docs/01_nodeos/06_logging/index.md +++ b/docs/01_nodeos/06_logging/index.md @@ -6,7 +6,7 @@ Logging for `nodeos` is controlled by the `logging.json` file. CLI options can b ## Appenders -The logging library built into EOSIO supports two appender types: +The logging library built into Mandel supports two appender types: - [Console](#console) - [GELF](#gelf) (Graylog Extended Log Format) @@ -74,7 +74,7 @@ Example: ## Loggers -The logging library built into EOSIO currently supports the following loggers: +The logging library built into Mandel currently supports the following loggers: - `default` - the default logger, always enabled. - `net_plugin_impl` - detailed logging for the net plugin. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index df2a872729..b682285906 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -2,7 +2,7 @@ content_title: Storage and Read Modes --- -The EOSIO platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) +The Mandel platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) ## Blockchain State and Storage @@ -15,9 +15,9 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain * The `pending block` is an in memory block containing transactions as they are processed and pushed into the block; this will/may eventually become the head block. If the `nodeos` instance is the producing node, the pending block is distributed to other `nodeos` instances. * Outside the chain state, block data is cached in RAM until it becomes final/irreversible; especifically the signed block itself. After the last irreversible block (LIB) catches up to the block, that block is then retrieved from the irreversible blocks log. -## EOSIO Interfaces +## Mandel Interfaces -EOSIO provides a set of [services](../../) and [interfaces](https://developers.eos.io/manuals/eosio.cdt/latest/files) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +Mandel provides a set of [services](../../) and [interfaces](https://developers.eos.io/manuals/eosio.cdt/latest/files) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API diff --git a/docs/01_nodeos/07_concepts/10_context-free-data/index.md b/docs/01_nodeos/07_concepts/10_context-free-data/index.md index 0a31072bcb..cb894d55ee 100644 --- a/docs/01_nodeos/07_concepts/10_context-free-data/index.md +++ b/docs/01_nodeos/07_concepts/10_context-free-data/index.md @@ -4,7 +4,7 @@ link_text: Context-Free Data --- ## Overview -The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, EOSIO blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. +The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, Mandel blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. ## Concept The goal of context-free data is to allow blockchain applications the option to store non-essential information within a transaction. Some examples of context-free data include: diff --git a/docs/01_nodeos/08_troubleshooting/index.md b/docs/01_nodeos/08_troubleshooting/index.md index 409ca6c371..be225e3070 100644 --- a/docs/01_nodeos/08_troubleshooting/index.md +++ b/docs/01_nodeos/08_troubleshooting/index.md @@ -28,7 +28,7 @@ Command Line Options for eosio::chain_plugin: Start `nodeos` with `--shared-memory-size-mb 1024`. A 1 GB shared memory file allows approximately half a million transactions. -### What version of EOSIO am I running/connecting to? +### What version of Mandel am I running/connecting to? If defaults can be used, then `cleos get info` will output a block that contains a field called `server_version`. If your `nodeos` is not using the defaults, then you need to know the URL of the `nodeos`. In that case, use the following with your `nodeos` URL: @@ -44,4 +44,4 @@ cleos --url http://localhost:8888 get info | grep server_version ### Error 3070000: WASM Exception Error -If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). +If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot a Mandel-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). diff --git a/docs/01_nodeos/09_deprecation-notices.md b/docs/01_nodeos/09_deprecation-notices.md deleted file mode 100644 index ab7f356582..0000000000 --- a/docs/01_nodeos/09_deprecation-notices.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -link: https://github.com/EOSIO/eos/issues/7597 ---- diff --git a/docs/01_nodeos/index.md b/docs/01_nodeos/index.md index 7fac253202..21b8e045a1 100644 --- a/docs/01_nodeos/index.md +++ b/docs/01_nodeos/index.md @@ -4,11 +4,11 @@ content_title: Nodeos ## Introduction -`nodeos` is the core service daemon that runs on every EOSIO node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. +`nodeos` is the core service daemon that runs on every Mandel node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. ## Installation -`nodeos` is distributed as part of the [EOSIO software suite](https://github.com/EOSIO/eos/blob/master/README.md). To install `nodeos`, visit the [EOSIO Software Installation](../00_install/index.md) section. +`nodeos` is distributed as part of the [Mandel software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [Mandel Software Installation](../00_install/index.md) section. ## Explore @@ -21,7 +21,6 @@ Navigate the sections below to configure and use `nodeos`. * [Logging](06_logging/index.md) - Logging config/usage, loggers, appenders, logging levels. * [Concepts](07_concepts/index.md) - `nodeos` concepts, explainers, implementation aspects. * [Troubleshooting](08_troubleshooting/index.md) - Common `nodeos` troubleshooting questions. -* [Deprecation Notices](https://github.com/EOSIO/eos/issues/7597) - Lists `nodeos` deprecated functionality. [[info | Access Node]] -| A local or remote EOSIO access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. +| A local or remote Mandel access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md index 4973217f16..f5a6528f0b 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. * Understand [Accounts and Permissions](https://developers.eos.io/welcome/latest/protocol-guides/accounts_and_permissions) in the protocol documents. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md index 20fc565847..528c500a37 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to create a new EOSIO blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. +This how-to guide provides instructions on how to create a new Mandel blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. The example in this how-to guide creates a new account named **bob**, authorized by the default system account **eosio**, using the `cleos` CLI tool. @@ -10,8 +10,8 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about [EOSIO Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) +| The cleos tool is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install the cleos tool. +* Learn about [Mandel Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) * Learn about Asymmetric Cryptography - [public key](https://developers.eos.io/welcome/v2.1/glossary/index#public-key) and [private key](https://developers.eos.io/welcome/v2.1/glossary/index#private-key) pairs. * Create public/private keypairs for the `owner` and `active` permissions of an account. @@ -34,7 +34,7 @@ cleos create account eosio bob EOS87TQktA5RVse2EguhztfQVEh6XXxBmgkU8b4Y5YnGvtYAo * `bob` = the name of the new account conforming to [account naming conventions](https://developers.eos.io/welcome/v2.1/protocol-guides/accounts_and_permissions#2-accounts) * `EOS87TQ...AoLGNN` = the owner public key or permission level for the new account (**required**) [[info | Note]] -| To create a new account in the EOSIO blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created EOSIO blockchain, the default system account used to create a new account is **eosio**. +| To create a new account in the Mandel blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created Mandel blockchain, the default system account used to create a new account is **eosio**. **Example Output** @@ -46,4 +46,4 @@ warning: transaction executed locally, but may not be confirmed by the network y ### Summary -By following these instructions, you are able to create a new EOSIO account in your blockchain environment. +By following these instructions, you are able to create a new Mandel account in your blockchain environment. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md index e3e298aefe..385fc6b017 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md @@ -1,14 +1,14 @@ ## Overview -This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in a Mandel blockchain. ## Before you begin Make sure you meet the following requirements: * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about asymmetric cryptography (public and private keypair) in the context of an EOSIO blockchain. +| The cleos tool is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install the cleos tool. +* Learn about asymmetric cryptography (public and private keypair) in the context of a Mandel blockchain. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 5345bd83f6..606209e3d6 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. -* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/EOSIO/eosio.contracts) repository is deployed and used to manage system resources. +* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in an EOSIO blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in an EOSIO blockchain. +* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a Mandel blockchain. +* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a Mandel blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index 118c36ba13..51ec81b0b9 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. -* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/EOSIO/eosio.contracts) repository is deployed and used to manage system resources. +* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in an EOSIO blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in an EOSIO blockchain. +* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a Mandel blockchain. +* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a Mandel blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md index 32fcce2c00..ccb970fbf2 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md +++ b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md @@ -1,6 +1,6 @@ ## Goal -Deploy an EOSIO contract +Deploy a Mandel contract ## Before you begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md index 7dc5f686d0..fabf5045fe 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md @@ -1,15 +1,15 @@ ## Overview -This how-to guide provides instructions on how to query infomation of an EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. +This how-to guide provides instructions on how to query infomation of a Mandel account. The example in this how-to guide retrieves information of the `eosio` account. ## Before you begin * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +| The cleos tool is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install the cleos tool. -* Acquire functional understanding of [EOSIO Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) +* Acquire functional understanding of [Mandel Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) ## Command Reference @@ -28,7 +28,7 @@ cleos get account eosio ``` **Where**: -* `eosio` = The name of the default system account in the EOSIO blockchain. +* `eosio` = The name of the default system account in the Mandel blockchain. **Example Output** @@ -53,4 +53,4 @@ cpu bandwidth: ``` [[info | Account Fields]] -| Depending on the EOSIO network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. +| Depending on the Mandel network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md index 7efd62427f..ca23c507f0 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md @@ -10,10 +10,10 @@ Make sure to meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. * Understand what a [block](https://developers.eos.io/welcome/latest/glossary/index/#block) is and its role in the blockchain. -* Understand the [block lifecycle](https://developers.eos.io/welcome/latest/protocol-guides/consensus_protocol/#5-block-lifecycle) in the EOSIO consensus protocol. +* Understand the [block lifecycle](https://developers.eos.io/welcome/latest/protocol-guides/consensus_protocol/#5-block-lifecycle) in the Mandel consensus protocol. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md index aaf5fd7e74..f6e33fe0d8 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to retrieve infomation of an EOSIO transaction using a transaction ID. +This how-to guide provides instructions on how to retrieve infomation of a Mandel transaction using a transaction ID. The example in this how-to retrieves transaction information associated with the creation of the account **bob**. @@ -9,8 +9,8 @@ The example in this how-to retrieves transaction information associated with the Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand how transactions work in an EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +* Understand how transactions work in a Mandel blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md index 19a8ee0d7d..6e13925fc0 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md +++ b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in a Mandel blockchain. ## Before you Begin @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet import`](../03_command-reference/wallet/import.md) command. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private key](https://developers.eos.io/welcome/latest/glossary/index/#private-key) is. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md index 7a9bb7348f..7b5703b046 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in a Mandel blockchain. The example in this how-to guide displays all public keys and public/private key pairs stored within the existing default wallet. @@ -13,7 +13,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet`](../03_command-reference/wallet/index.md) commands. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private key](https://developers.eos.io/welcome/latest/glossary/index/#private-key) is. ## Command Reference diff --git a/docs/02_cleos/03_command-reference/create/account.md b/docs/02_cleos/03_command-reference/create/account.md index 976c986f56..e35d2bf146 100755 --- a/docs/02_cleos/03_command-reference/create/account.md +++ b/docs/02_cleos/03_command-reference/create/account.md @@ -30,7 +30,7 @@ Options: ``` ## Command -A set of EOSIO keys is required to create an account. The EOSIO keys can be generated by using `cleos create key`. +A set of Mandel keys is required to create an account. The Mandel keys can be generated by using `cleos create key`. ```sh cleos create account inita tester EOS4toFS3YXEQCkuuw1aqDLrtHim86Gz9u3hBdcBw5KNPZcursVHq EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA diff --git a/docs/02_cleos/03_command-reference/net/connect.md b/docs/02_cleos/03_command-reference/net/connect.md index be0b2af0b3..278f3f47c6 100755 --- a/docs/02_cleos/03_command-reference/net/connect.md +++ b/docs/02_cleos/03_command-reference/net/connect.md @@ -26,7 +26,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/disconnect.md b/docs/02_cleos/03_command-reference/net/disconnect.md index 29c3039961..f2dfa12c82 100755 --- a/docs/02_cleos/03_command-reference/net/disconnect.md +++ b/docs/02_cleos/03_command-reference/net/disconnect.md @@ -26,7 +26,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/peers.md b/docs/02_cleos/03_command-reference/net/peers.md index 2814731c75..c625506c53 100755 --- a/docs/02_cleos/03_command-reference/net/peers.md +++ b/docs/02_cleos/03_command-reference/net/peers.md @@ -25,7 +25,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/status.md b/docs/02_cleos/03_command-reference/net/status.md index f8f45265ec..7a8fd4f535 100755 --- a/docs/02_cleos/03_command-reference/net/status.md +++ b/docs/02_cleos/03_command-reference/net/status.md @@ -26,7 +26,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/set/set-account.md b/docs/02_cleos/03_command-reference/set/set-account.md index e4ed9f6e32..1e682aa485 100755 --- a/docs/02_cleos/03_command-reference/set/set-account.md +++ b/docs/02_cleos/03_command-reference/set/set-account.md @@ -2,7 +2,7 @@ set parameters dealing with account permissions [[info | JSON input]] -| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the EOSIO software. +| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the Mandel software. ## Positionals - `account` _TEXT_ - The account to set/delete a permission authority for diff --git a/docs/02_cleos/04_troubleshooting.md b/docs/02_cleos/04_troubleshooting.md index 63250119e9..748ac82df3 100644 --- a/docs/02_cleos/04_troubleshooting.md +++ b/docs/02_cleos/04_troubleshooting.md @@ -20,4 +20,4 @@ Replace API_ENDPOINT and PORT with your remote `nodeos` API endpoint detail ## "Missing Authorizations" -That means you are not using the required authorizations. Most likely you are not using correct EOSIO account or permission level to sign the transaction +That means you are not using the required authorizations. Most likely you are not using correct Mandel account or permission level to sign the transaction diff --git a/docs/02_cleos/index.md b/docs/02_cleos/index.md index 6e0ea9423b..e2303863af 100644 --- a/docs/02_cleos/index.md +++ b/docs/02_cleos/index.md @@ -4,11 +4,11 @@ content_title: Cleos ## Introduction -`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test EOSIO smart contracts. +`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test Mandel smart contracts. ## Installation -`cleos` is distributed as part of the [EOSIO software suite](https://github.com/EOSIO/eos/blob/master/README.md). To install `cleos` just visit the [EOSIO Software Installation](../00_install/index.md) section. +`cleos` is distributed as part of the [Mandel software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [Mandel Software Installation](../00_install/index.md) section. ## Using Cleos @@ -23,7 +23,7 @@ cleos --help ``` ```console -Command Line Interface to EOSIO Client +Command Line Interface to Mandel Client Usage: cleos [OPTIONS] SUBCOMMAND Options: diff --git a/docs/03_keosd/index.md b/docs/03_keosd/index.md index 43f2301dbb..99144dd25f 100644 --- a/docs/03_keosd/index.md +++ b/docs/03_keosd/index.md @@ -8,11 +8,11 @@ content_title: Keosd ## Installation -`keosd` is distributed as part of the [EOSIO software suite](https://github.com/EOSIO/eos/blob/master/README.md). To install `keosd` just visit the [EOSIO Software Installation](../00_install/index.md) section. +`keosd` is distributed as part of the [Mandel software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [Mandel Software Installation](../00_install/index.md) section. ## Operation When a wallet is unlocked with the corresponding password, `cleos` can request `keosd` to sign a transaction with the appropriate private keys. Also, `keosd` provides support for hardware-based wallets such as Secure Encalve and YubiHSM. [[info | Audience]] -| `keosd` is intended to be used by EOSIO developers only. +| `keosd` is intended to be used by Mandel developers only. diff --git a/docs/10_utilities/index.md b/docs/10_utilities/index.md index 747c95cb72..d0a078b58e 100644 --- a/docs/10_utilities/index.md +++ b/docs/10_utilities/index.md @@ -1,9 +1,9 @@ --- -content_title: EOSIO Utilities -link_text: EOSIO Utilities +content_title: Mandel Utilities +link_text: Mandel Utilities --- -This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other EOSIO software: +This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other Mandel software: * [eosio-blocklog](eosio-blocklog.md) - Low-level utility for node operators to interact with block log files. * [trace_api_util](trace_api_util.md) - Low-level utility for performing tasks associated with the [Trace API](../01_nodeos/03_plugins/trace_api_plugin/index.md). diff --git a/docs/20_upgrade-guide/79_2.0-upgrade-guide.md b/docs/20_upgrade-guide/79_2.0-upgrade-guide.md deleted file mode 100644 index 1a8d5b57ce..0000000000 --- a/docs/20_upgrade-guide/79_2.0-upgrade-guide.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -link: /20_upgrade-guide/index.md ---- diff --git a/docs/20_upgrade-guide/81_1.8-upgrade-guide.md b/docs/20_upgrade-guide/81_1.8-upgrade-guide.md deleted file mode 100644 index 9d0bdb7445..0000000000 --- a/docs/20_upgrade-guide/81_1.8-upgrade-guide.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -content_title: EOSIO 1.8 Consensus Protocol Upgrade Process ---- - -This guide is intended to instruct node operators on the steps needed to successfully transition an EOSIO network through a consensus protocol upgrade (also known as a "hard fork") with minimal disruption to users. - -## Test networks - -Before deploying the upgrade to any non-test networks, protocol upgrades should be deployed and verified on test networks. The version of nodeos supporting the initial set of protocol upgrades is [v1.8.1](https://github.com/EOSIO/eos/releases/tag/v1.8.1). Existing EOSIO-based test networks can use this version of nodeos to carry out and test the upgrade process. - -This test upgrade process can give block producers of their respective EOSIO blockchain networks practice with carrying out the steps necessary to successfully coordinate the activation of the first consensus protocol upgrade feature (or just protocol feature for short), which will fork out any nodes that have not yet updated to the new version of nodeos by the time of activation. The process will also inform block producers of the requirements for nodes to upgrade nodeos to v1.8 from v1.7 and earlier, and it can help them decide an appropriate deadline to be given as notice to the community for when the first protocol feature will be activated. - -Testing the upgrade process on test networks will also allow block explorers and other applications interacting with the blockchain to test the transition and the behavior of their applications under the new rules after activation of the individual protocol features. Some of the protocol features (`PREACTIVATE_FEATURE` and `NO_DUPLICATE_DEFERRED_ID` as examples) make slight changes to the block and transaction data structures, and therefore force applications that are reliant on the old structure to migrate. One of the protocol features (`RESTRICT_ACTION_TO_SELF`) restricts an existing authorization bypass (which has been deprecated since the v1.5.1 release of EOSIO) and could potentially break smart contracts that continue to rely on that authorization bypass. - -## Upgrade process for all EOSIO networks (including test networks) - -Because these steps require replay from genesis, after the release of [v1.8.1](https://github.com/EOSIO/eos/releases/tag/v1.8.1) of nodeos which supports the initial set of consensus protocol upgrades, all node operators should take the following steps as soon as possible. These steps should be followed on an additional node that they can afford to be taken offline for an extended period of time: - -1. Ensure that their existing node is running the most recent stable release (1.7) of nodeos and then shut down nodeos. -2. Make a backup and delete the `blocks/reversible` directory, `state-history` directory, and `state` directory within the data directory. -3. Replace their old version of nodeos with the new release. -4. Start the new 1.8 release of nodeos and let it complete replay from genesis and catch up with syncing with the network. The node should receive blocks and LIB should advance. Nodes running v1.8 and v1.7 will continue to coexist in the same network prior to the activation of the first protocol upgrade feature. - -A replay from genesis is required when upgrading nodeos from v1.7 to v1.8. Afterward, the v1.8 node can, as usual, start and stop quickly without requiring replays. The state directory generated by a v1.7 node will not be compatible with v1.8 of nodeos. Version 1 portable snapshots (generated by v1.7) will not be compatible with v1.8 which require the version 2 portable snapshots. - -Due to the long amount of time it will take to replay from genesis (even longer if running with plugins that track history), block producers of the network are suggested to provide sufficient time to the community to upgrade their nodes prior to activating the first protocol upgrade feature. - -Nodes that wish to make the transition but are not interested in tracking the history of the chain from genesis have an option to speed things up by using a version 2 portable snapshots that can be generated by synced v1.8 nodes. Since the portable snapshots are generated in a deterministic and portable manner, users can simply compare the hash of the snapshot files they downloaded from an arbitrary source to the hashes published by a variety of trusted sources, but only if they correspond to snapshots taken at the same block ID. - -### Special notes to block producers - -Block producers will obviously need to run the replay of nodeos on a separate machine that is not producing blocks. This machine will have to be production ready so that they can switch block production over to it when it has finished replaying and syncing. Alternatively, they can take a portable snapshot on the replay machine and move it to yet another machine which is production ready, then activate the switch over from their currently producing v1.7 BP node to the v1.8 node. - -Nearly all of the protocol upgrade features introduced in v1.8 first require a special protocol feature (codename `PREACTIVATE_FEATURE`) to be activated and for an updated version of the system contract that utilizes the functionality introduced by that feature to be deployed. Block producers should be aware that as soon as the `PREACTIVATE_FEATURE` protocol feature is activated by the BPs, all nodes still on v1.7 will be unable to continue syncing normally and their last irreversible block will stop advancing. For this reason, it is important to coordinate when the activation happens and announce the expected activation date with sufficient time provided to the community to upgrade their nodes in time. - -After activation of the `PREACTIVATE_FEATURE` and deployment of the updated system contract, block producers will be able to more easily coordinate activation of further protocol features. For the remaining protocol features in the v1.8 release, they can activate the features at any time and no preparation time needs to be given to the community since anyone synced up with the blockchain at that time will necessarily be on a version of nodeos that is at least v1.8 and therefore will support the entire initial set of protocol features. Furthermore, due to the `PREACTIVATE_FEATURE` protocol feature, they can activate the other remaining protocol features with an `eosio.msig` proposed transaction using the `activate` action in the new system contract and no replay is required. - -The activation of the first protocol feature, `PREACTIVATE_FEATURE`, however cannot be done with an `eosio.msig` proposed transaction. It will require more coordination and manual action by the block producers. First, block producers should come to an agreement on the earliest time that they are willing to activate the first protocol feature. - -The BPs should then set this chosen time in the configuration JSON file for the `PREACTIVATE_FEATURE` protocol upgrade of their v1.8 node. Specifically, they should modify the value for the `earliest_allowed_activation_time` field in the `protocol_features/BUILTIN-PREACTIVATE_FEATURE.json` file located in the config directory. - -It is important that this configuration change happens prior to allowing that node to produce blocks on the network. As long as more than two-thirds of the active block producers have set the same future time in the configuration file for the `PREACTIVATE_FEATURE` on their BP nodes, the network will be safe from any attempts at premature activation by some other active BP. - -After the agreed upon time has passed, any of the active block producers can activate the `PREACTIVATE_FEATURE` protocol feature with a simple request sent to the [`producer_api_plugin`](../01_nodeos/03_plugins/producer_api_plugin/index.md) of their BP node. - -To determine the specific format of the request, the digest of the `PREACTIVATE_FEATURE` protocol feature must first be determined. This can be found by looking at nodeos startup logs, or by sending a request to the `get_supported_protocol_features` endpoint provided by the [`producer_api_plugin`](../01_nodeos/03_plugins/producer_api_plugin/index.md). - -Send a request to the endpoint locally: - -``` -curl -X POST http://127.0.0.1:8888/v1/producer/get_supported_protocol_features -d '{}' | jq -``` - -In the returned array, find an object that references the `PREACTIVATE_FEATURE` codename, for example: - -``` -... -{ - "feature_digest": "0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd", - "subjective_restrictions": { - "enabled": true, - "preactivation_required": false, - "earliest_allowed_activation_time": "1970-01-01T00:00:00.000" - }, - "description_digest": "64fe7df32e9b86be2b296b3f81dfd527f84e82b98e363bc97e40bc7a83733310", - "dependencies": [], - "protocol_feature_type": "builtin", - "specification": [ - { - "name": "builtin_feature_codename", - "value": "PREACTIVATE_FEATURE" - } - ] -}, -... -``` - -In this case, the digest of the `PREACTIVATE_FEATURE` protocol feature is `0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd` (note that the values may be different depending on the local changes made to the configuration of the protocol features that are specific to the blockchain network). - -Then, the local block producing nodeos instance can be requested to activate the `PREACTIVATE_FEATURE` protocol at its earliest opportunity (i.e. the next time that node produces a block) using the following command: - -``` -curl -X POST http://127.0.0.1:8888/v1/producer/schedule_protocol_feature_activations -d '{"protocol_features_to_activate": ["0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd"]}' | jq -``` - -The above command should only be used after the time has passed the agreed upon `earliest_allowed_activation_time` for the `PREACTIVATE_FEATURE` protocol feature. - -Any synced v1.8.x nodes can be used to check which protocol features have been activated using the following command: - -``` -curl -X POST http://127.0.0.1:8888/v1/chain/get_activated_protocol_features -d '{}' | jq -``` - -For example, if the `PREACTIVATE_FEATURE` protocol feature is activated, that command may return a result such as (specific values, especially the `activation_block_num`, may vary): - -``` -{ - "activated_protocol_features": [ - { - "feature_digest": "0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd", - "activation_ordinal": 0, - "activation_block_num": 348, - "description_digest": "64fe7df32e9b86be2b296b3f81dfd527f84e82b98e363bc97e40bc7a83733310", - "dependencies": [], - "protocol_feature_type": "builtin", - "specification": [ - { - "name": "builtin_feature_codename", - "value": "PREACTIVATE_FEATURE" - } - ] - } - ] -} -``` - -Once the `PREACTIVATE_FEATURE` protocol feature has been activated, the [new system contract](https://github.com/EOSIO/eosio.contracts/releases/tag/v1.7.0) with the `activate` action can be deployed. - -## Notes for block explorers, exchanges, and applications - -Block explorers, exchanges, and applications building on the blockchain can all follow the four-step processes described above to upgrade their nodes in time and ensure their services continue when the first protocol upgrade is activated. However, they should also be aware that certain protocol features change the behavior of existing operations on the blockchain, and in some cases also slightly change the structure of blocks and transactions. - - -**First**, v1.8 changes the structure of transaction traces, even prior to the activation of any protocol features. Clients consuming transaction and action traces made available through [`history_plugin`](../01_nodeos/03_plugins/history_plugin/index.md), `mongo_db_plugin`, or [`state_history_plugin`](../01_nodeos/03_plugins/state_history_plugin/index.md) should be aware of the changes made to the trace structure (see details at [#7044](https://github.com/EOSIO/eos/pull/7044) and [#7108](https://github.com/EOSIO/eos/pull/7108)). Clients consuming the trace output of the `push_transaction` RPC from the chain API should not need to do anything since the output of that RPC should be backwards compatible. However, they are encouraged to replace usage of `push_transaction` with the new RPC [`send_transaction`](https://developers.eos.io/eosio-nodeos/reference#send_transaction) which uses the new flat structure to store the action traces. - -The [`state_history_plugin`](../01_nodeos/03_plugins/state_history_plugin/index.md) has also changed its API and the structure of the files it stores on disk in a backwards incompatible way in v1.8. These changes reflect, among other things, the transaction trace structural changes and the data structure changes made within the chain state database to support the new protocol features. Consumers of the [`state_history_plugin`](../01_nodeos/03_plugins/state_history_plugin/index.md) will need to be updated to work with the new changes in v1.8. - -**Second**, all protocol features are activated by signaling their 256-bit digest through a block. The block producer is able to place the digest of a protocol feature in a special section of the block header (called the block header extensions) that, under the original rules of v1.7, is expected to be empty. This change may especially be relevant to block explorers which need to ensure that their tools will not break because of the extra data included in the block header and ideally will update their block explorers to reflect the new information. The first time block explorers or other consumers of the blockchain data will encounter a non-empty block header extension is during the activation of the `PREACTIVATE_FEATURE` protocol feature. - -**Third**, upon activation of the `NO_DUPLICATE_DEFERRED_ID` protocol feature, contract-generated deferred transactions will include a non-empty `transaction_extensions` field. While block explorers may be interested in exposing the contents of this field in a user-friendly way, clients are free to ignore it. However, for code dealing with the binary serialized form of these transactions directly, they must be capable of successfully deserializing the transaction with the extension data present. Note that this also applies to smart contract code that may be reading the deferred transaction that caused it to execute, whether it is because it is executing an action within the deferred transaction or executing the `eosio::onerror` notification handler of the contract that sent the (failed) deferred transaction. - -**Fourth**, activation of the `RESTRICT_ACTION_TO_SELF` protocol feature will remove the authorization bypass that is available when a contract sends an inline action to itself (this authorization bypass was deprecated in the v1.5.1 release of EOSIO). Smart contract developers should ensure their contracts do not rely on this authorization bypass prior to the time the block producers activate the `RESTRICT_ACTION_TO_SELF` protocol feature, otherwise, their contracts may stop functioning correctly. diff --git a/docs/20_upgrade-guide/index.md b/docs/20_upgrade-guide/index.md deleted file mode 100644 index f627e445c3..0000000000 --- a/docs/20_upgrade-guide/index.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -content_title: EOSIO 2.0 Upgrade Guide ---- - -This section contains important instructions for node operators and other EOSIO stakeholders to transition an EOSIO network successfully through an EOSIO version or protocol upgrade. - -## Consensus Protocol Upgrades -EOSIO v2.0.x introduces two new consensus protocol upgrade features (or just protocol features for short): - -1. `WEBAUTHN_KEY`: Adds support for WebAuthn keys and signatures ([#7421](https://github.com/EOSIO/eos/pull/7421)) -2. `WTMSIG_BLOCK_SIGNATURES`: Adds support for weighted threshold multi-signature (WTMsig) authorities for block production ([#7404](https://github.com/EOSIO/eos/pull/7404), [#8002](https://github.com/EOSIO/eos/pull/8002), [#8021](https://github.com/EOSIO/eos/pull/8021)) - -Both of these features require activation through the privileged `preactivate_feature` intrinsic. This is typically facilitated by executing the `eosio::activate` system contract action (requires system contract [v1.7.0](https://github.com/EOSIO/eosio.contracts/releases/tag/v1.7.0) or later) via the `eosio.msig` contract after getting supermajority block producer approval. However, while these protocol features can be activated through coordination of the block producers alone, **it is still critical to give sufficient time for all nodes to upgrade to v2.0.x before activating any of the above two protocol features**. Activation of any of these two protocol features will immediately fork out any nodes that do not support the protocol features (e.g. any nodes running a version of nodeos earlier than v2.0.x). - -Both of the above protocol features only add new behavior to the EOSIO blockchain. They are not expected to change existing behavior in a significant way that would cause existing contracts to break. Existing applications and block explorers are also unlikely to break upon activation of these protocol features. However, these new features enable new data structures to be utilized on-chain which applications and especially block explorers need to be prepared to handle. For example, activation of the `WEBAUTHN_KEY` protocol feature means that an `eosio::newaccount` or `eosio::updateauth` action could now include WebAuthn public keys as part of the provided `authority`. So, an application dealing with these actions (e.g. a general authenticator for EOSIO transactions) will need to be prepared to support the serialization of WebAuthn public keys appearing in a place where a `public_key` ABI type is expected. Another example is how the activation of the `WTMSIG_BLOCK_SIGNATURES` protocol feature causes the `new_producers` field of a block header to always remain empty, even when a proposed producer schedule gets promoted to pending; upon activation of the `WTMSIG_BLOCK_SIGNATURES` protocol feature, the pending schedule data is instead stored (when present) within the `header_extensions` of the block header. So, block explorers expecting to show these pending producer schedules to users will need to update their code accordingly. As usual, test networks provide a great environment to try existing contracts, applications, services, etc. with the changes of the above protocol features to determine what breaks and what needs to be updated. - -For more details on the `WEBAUTH_KEY` protocol feature, see the section titled [WebAuthn Support](#webauthn-support-7421). For more details on the `WTMSIG_BLOCK_SIGNATURES` protocol feature, see the section titled [Weighted Threshold Multi-signature (WTMsig) Block Signing Authorities](#weighted-threshold-multi-signature-block-signing-authorities-7403). - -### WebAuthn Support ([#7421](https://github.com/EOSIO/eos/pull/7421)) -WebAuthn support within EOSIO is now available for developers to begin testing WebAuthn based transaction signing in their EOSIO applications. Private EOSIO chains can [start](https://github.com/EOSIO/eosio-webauthn-example-app) using WebAuthn based signatures with this release. We also anticipate releasing additional demos which will attempt to outline how Dapp authors can leverage WebAuthn for contract actions meriting higher levels of security as a second factor authorization mechanism. - -### Weighted Threshold Multi-Signature Block Signing Authorities ([#7403](https://github.com/EOSIO/eos/issues/7403)) -Block producers must be able to provide high availability for their core service of running the blockchain (aka producing blocks). A common approach to achieve this is redundant infrastructure that efficiently maintains block production, in the event of a hardware malfunction or networking issues. Weighted Threshold Multi-Signature Block Production is the first of many features that seek to provide block producers with a complete high availability solution. - -Current consensus rules require exactly one cryptographic block signing key per block producer. This key, whether stored on disk and loaded via software or protected with a hardware wallet, represents a single-point-of-failure for the operations of a block producer. If that key is lost or access to the hardware module that contains it is temporarily unavailable, the block producer has no choice but to drop blocks, impacting the whole network’s throughput. - -To improve the security and scalability of block production, weighted threshold multi-signature (WTMsig) block signing authorities provides a permission layer that allows for multiple block signing keys in a flexible scheme that will enable redundant block signing infrastructure to exist without sharing any sensitive data. - -An updated version of the system contract is required to enable block producers to use WTMsig block signing authorities. Version [v1.9.0-rc1](https://github.com/EOSIO/eosio.contracts/releases/tag/v1.9.0-rc1) of eosio.contracts adds a new `regproducer2` action to the eosio.system contract which enables a block producer candidate to register a WTMsig block signing authority. (That version of the system contract can only be deployed on an EOSIO chain that has activated the `WTMSIG_BLOCK_SIGNATURES` protocol feature.) More details are available at: [#7404](https://github.com/EOSIO/eos/pull/7404), [#8002](https://github.com/EOSIO/eos/pull/8002), [#8021](https://github.com/EOSIO/eos/pull/8021). - -## Upgrading from previous versions of EOSIO - -EOSIO v2.0.x has made changes to the state database that prevent it from working with existing state databases in v1.8.x and earlier. So upgrading from earlier versions of EOSIO requires importing the state from a portable snapshot. - -Furthermore, the changes to the state database necessitate a version bump in the portable snapshots generated by EOSIO v2.0.x from v2 to v3. However, unlike the upgrade of portable snapshot versions in EOSIO v1.8.x from v1 to v2, EOSIO v2.0.x is able to import v2 portable snapshots. This means that it is not necessary to replay the blockchain from genesis to upgrade from EOSIO v1.8.x to v2.0.x. (One exception is if the operator of the node is using the deprecated history_plugin and wishes to preserve that history.) - -Finally, EOSIO v2.0.x has also upgraded the version of the irreversible blocks log to v3. However, older versions of the blocks log are still supported, so there is no need to do anything special to handle existing blocks log files. - -### Upgrading from v1.8.x - -If the node uses the deprecated history_plugin (and the operator of the node wishes to preserve this history), the only option to upgrade is to replay the blockchain from genesis. - -Users of the state_history_plugin (SHiP) do not need to replay from genesis because the state history logs are portable and contain versioned data structures within. However, upgrading a node that uses state history without a full replay means that the state history log will contain a mix of versions for any upgrade types. For example, the changes in v2.0.x modify the `global_property_object` in the database state and so the state history log could contain a `global_property_object_v0` type (for the part of the history before the local node upgrade) and a `global_property_object_v1` type (for the part of the history after the local node upgrade). This should not cause problems for any history fillers that have been updated to support both versions of the type. However, operators should be aware that this can lead to the log file contents being slightly different across different nodes even if they all start and stop at the same blocks and have not enabled `trace-history-debug-mode`. (Replaying a v2.0.x node with state_history_plugin enabled from genesis would guarantee that the state history logs do not contain the `global_property_object_v0` type.) - -The following instructions should be followed to upgrade nodeos from v1.8.x to v2.0.x without a full replay (after making appropriate backup copies): -1. Obtain a compatible portable snapshot of the state. A v2 or v3 portable snapshot can be downloaded from a trusted source. Alternatively, one can use an existing v1.8.x node to generate a v2 portable snapshot by launching nodeos with `--read-mode=irreversible --plugin=eosio::producer_api_plugin` command-line options and then using the `/v1/producer/create_snapshot` RPC endpoint to generate a portable snapshot (e.g. run the command `curl -X POST http:/127.0.0.1:8888/v1/producer/create_snapshot -d '{}' | jq`). -2. Shut down nodeos and delete the `blocks/reversible` and `state` sub-directories within the data directory. -3. Launch nodeos v2.0.x from the generated snapshot using the `--snapshot` command line option and give it time to import the snapshot while starting up (this could take several minutes). (Subsequent launches of nodeos should not use the `--snapshot` option.) - -### Upgrading from v2.0.0-rc1, v2.0.0-rc2, or v2.0.0-rc3 - -Node operators should consider upgrading v2.0.0-rc1, v2.0.0-rc2, and v2.0.0-rc3 nodes to v2.0.0 as soon as possible. They can follow normal upgrade procedures for the upgrade. There should be no need to do a replay or import from a snapshot. diff --git a/docs/30_release-notes/87_v2.0.12.md b/docs/30_release-notes/87_v2.0.12.md deleted file mode 100644 index a7e664163a..0000000000 --- a/docs/30_release-notes/87_v2.0.12.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -link: /30_release-notes/index.md -link_text: v2.0.12 ---- diff --git a/docs/30_release-notes/88_v2.0.11.md b/docs/30_release-notes/88_v2.0.11.md deleted file mode 100644 index 46f053cca8..0000000000 --- a/docs/30_release-notes/88_v2.0.11.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -content_title: EOSIO v2.0.11 Release Notes -link_text: v2.0.11 ---- - -This release contains security and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for v2.0.11 ([#10147](https://github.com/EOSIO/eos/pull/10147)) -- Fix issue with account query db that could result in incorrect data or hung processes - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Other changes -- ([#10063](https://github.com/EOSIO/eos/pull/10063)) [release 2.0.x] Fix docker steps on tagged builds. -- ([#10135](https://github.com/EOSIO/eos/pull/10135)) Wlb/adding nodeos param tests 2.0.x -- ([#10133](https://github.com/EOSIO/eos/pull/10133)) fix compiling with boost 1.76; add include in chainbase - 2.0 - -## Documentation -- ([#10094](https://github.com/EOSIO/eos/pull/10094)) [docs] Add EOSIO 2.0.10 release notes to dev portal - 2.0 diff --git a/docs/30_release-notes/89_v2.0.10.md b/docs/30_release-notes/89_v2.0.10.md deleted file mode 100644 index 5ddad16cc7..0000000000 --- a/docs/30_release-notes/89_v2.0.10.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -content_title: EOSIO v2.0.10 Release Notes -link_text: v2.0.10 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for v2.0.10 ([#10091](https://github.com/EOSIO/eos/pull/10091)) -- Fix issue with account query db that could result in incorrect data or hung processes -- Implement a Subjective CPU billing system that helps P2P and API nodes better respond to extreme network congestion - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -### Notes on Subjective CPU Billing - -This system consists of two primary features: a subjective (node local) view of spent CPU resources that are not yet accounted for by the blockchain that allows individual nodes to predict what resource consumption will be and, a subjective penalty system to offset work done in service of erroneous or malicious transactions. - -The subjective view of CPU resources will synchronize with the resources present in the blockchain as it discovers the true CPU billing for transactions it has already accounted for. - -The system will also accumulate CPU resources spent on failing transactions that will not be relayed in a decaying "subjective penalty" which can protect the individual nodes from abusive actors while remaining tolerant to occasional mistakes. - -Subjective billing defaults to active and can be disabled with the `disable-subjective-billing` configuration in `config.ini` or on the command line. - -## Stability bug fixes -- ([#9985](https://github.com/EOSIO/eos/pull/9985)) EPE-389 net_plugin stall during head catchup - merge release/2.0.x - -## Other changes -- ([#9894](https://github.com/EOSIO/eos/pull/9894)) EOS VM OC: Support LLVM 11 - 2.0 -- ([#9911](https://github.com/EOSIO/eos/pull/9911)) add step to the pipeline to build and push to dockerhub on release br… -- ([#9944](https://github.com/EOSIO/eos/pull/9944)) Create eosio-debug-build Pipeline -- ([#9969](https://github.com/EOSIO/eos/pull/9969)) Updating name for the new Docker hub repo EOSIO instead EOS -- ([#9971](https://github.com/EOSIO/eos/pull/9971)) Fix pinned builds error due to obsolete LLVM repo -- ([#10015](https://github.com/EOSIO/eos/pull/10015)) [release 2.0.x] Fix LRT triggers -- ([#10026](https://github.com/EOSIO/eos/pull/10026)) EPE-165: Improve logic for unlinkable blocks while sync'ing -- ([#10047](https://github.com/EOSIO/eos/pull/10047)) Reduce Docker Hub Manifest Queries -- ([#10088](https://github.com/EOSIO/eos/pull/10088)) [release 2.0.x] Specify boost version for unpinned MacOS 10.14 builds - -## Documentation -- ([#10011](https://github.com/EOSIO/eos/pull/10011)) [docs] Update various cleos how-tos and fix index - 2.0 diff --git a/docs/30_release-notes/90_v2.0.9.md b/docs/30_release-notes/90_v2.0.9.md deleted file mode 100644 index f3c2740039..0000000000 --- a/docs/30_release-notes/90_v2.0.9.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -content_title: EOSIO v2.0.9 Release Notes -link_text: v2.0.9 ---- - -This release contains security and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.9 ([#9841](https://github.com/EOSIO/eos/pull/9841)) -- Fixes to packed_transaction cache -- Transaction account fail limit refactor - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Other Changes -- ([#9803](https://github.com/EOSIO/eos/pull/9803)) Fix stdout console logging: Merge back #9582 to 2.0.x diff --git a/docs/30_release-notes/91_v2.0.8.md b/docs/30_release-notes/91_v2.0.8.md deleted file mode 100644 index ecf5bad0b0..0000000000 --- a/docs/30_release-notes/91_v2.0.8.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -content_title: EOSIO v2.0.8 Release Notes -link_text: v2.0.8 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.8 ([#9745](https://github.com/EOSIO/eos/pull/9745)) - -- Adjust eos-vm-oc string intrinsic to perform as intended. -- Adjust CPU validation logic for unapplied transactions. - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Stability bug fixes -- ([#9370](https://github.com/EOSIO/eos/pull/9370)) set medium priority for process signed block - 2.0.x -- ([#9382](https://github.com/EOSIO/eos/pull/9382)) Handle case newaccount in Account Query DB -- ([#9412](https://github.com/EOSIO/eos/pull/9412)) port the fix of flight bytes bug into release/2.0.x -- ([#9423](https://github.com/EOSIO/eos/pull/9423)) Update to fc with variant blob fix - 2.0 -- ([#9441](https://github.com/EOSIO/eos/pull/9441)) Fix app() shutdown - 2.0 -- ([#9516](https://github.com/EOSIO/eos/pull/9516)) Keep http_plugin_impl alive while connection objects are alive - 2.0 -- ([#9624](https://github.com/EOSIO/eos/pull/9624)) Fixing typos on injected params for `producer_plugin::log_failed_tran… - -## Other Changes -- ([#9304](https://github.com/EOSIO/eos/pull/9304)) relaxing the on_notify constraint to * -- ([#9311](https://github.com/EOSIO/eos/pull/9311)) Track Source Files Excluded from Code Coverage Reports -- ([#9314](https://github.com/EOSIO/eos/pull/9314)) Prevent an older version of g++ to build eosio -- ([#9334](https://github.com/EOSIO/eos/pull/9334)) Add missing comma in loggers array -- ([#9399](https://github.com/EOSIO/eos/pull/9399)) [2.0.x] Fix docker tags when building forked PRs -- ([#9638](https://github.com/EOSIO/eos/pull/9638)) Migrate CI from Docker Hub to Amazon ECR -- ([#9657](https://github.com/EOSIO/eos/pull/9657)) CI: Fix Serial Test Bug + Simplification + UX -- ([#9665](https://github.com/EOSIO/eos/pull/9665)) Add "Testing Changes" Section to Pull Request Template - -## Documentation -- ([#9323](https://github.com/EOSIO/eos/pull/9323)) [docs] Remove unneeded options for nodeos replays - 2.0 -- ([#9322](https://github.com/EOSIO/eos/pull/9322)) [docs] Remove redundant nodeos replay example - 2.0 -- ([#9373](https://github.com/EOSIO/eos/pull/9373)) [docs] Fix broken link in Wallet API plugin - 2.0 -- ([#9464](https://github.com/EOSIO/eos/pull/9464)) [docs] Create nodeos concepts folder and rearrange folders - 2.0 -- ([#9479](https://github.com/EOSIO/eos/pull/9479)) [docs] Add explainers on CFD, eosio utilities, eosio-blocklog - 2.0 -- ([#9487](https://github.com/EOSIO/eos/pull/9487)) [docs] Minor edits on CFD explainer and eosio-blocklog reference - 2.0 -- ([#9488](https://github.com/EOSIO/eos/pull/9488)) [docs] Fix how-tos for delegating cpu/net with cleos - 2.0 -- ([#9491](https://github.com/EOSIO/eos/pull/9491)) [docs] Add EOSIO upgrade guide 2.0 to dev portal -- ([#9492](https://github.com/EOSIO/eos/pull/9492)) Add explicit left nav link for eosio 2.0 upgrade guide - 2.0 -- ([#9496](https://github.com/EOSIO/eos/pull/9496)) [docs] Add eosio 2.0 release notes to dev portal - 2.0 -- ([#9498](https://github.com/EOSIO/eos/pull/9498)) [docs] Add trace_api_util reference to eosio utilities docs - 2.0 -- ([#9503](https://github.com/EOSIO/eos/pull/9503)) [docs] Add slices, trace log, clog format explainers to Trace API plugin - 2.0 -- ([#9584](https://github.com/EOSIO/eos/pull/9584)) [docs] Update cleos get table reference - 2.0 -- ([#9592](https://github.com/EOSIO/eos/pull/9592)) [docs] Various additions/fixes to cleos reference - 2.0 -- ([#9602](https://github.com/EOSIO/eos/pull/9602)) [docs] Fix broken anchor link on MacOS build from source - 2.0 -- ([#9627](https://github.com/EOSIO/eos/pull/9627)) [docs] Update get_table_* reference in Chain API - 2.0 -- ([#9753](https://github.com/EOSIO/eos/pull/9753)) [docs] Update URL in net_api_plugin description - 2.0 -- ([#9754](https://github.com/EOSIO/eos/pull/9754)) [docs] Update some chain_api_plugin descriptions - 2.0 -- ([#9756](https://github.com/EOSIO/eos/pull/9756)) [docs] Remove sudo command from install/uninstall script instructions - 2.0 - -## Thanks! -Special thanks to the community contributors that submitted patches for this release: -- @nsjames diff --git a/docs/30_release-notes/92_v2.0.7.md b/docs/30_release-notes/92_v2.0.7.md deleted file mode 100644 index b92acb66f1..0000000000 --- a/docs/30_release-notes/92_v2.0.7.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -content_title: EOSIO v2.0.7 Release Notes -link_text: v2.0.7 ---- - -This release contains stability and miscellaneous fixes. - -## Stability bug fixes -- ([#9223](https://github.com/EOSIO/eos/pull/9223)) Fix log of pending block producer - 2.0 - -## Changes - -### The following logger has been added: `transaction_failure_tracing`. ([#9252](https://github.com/EOSIO/eos/pull/9252)) - -A detailed log that emits failed verdicts from relay nodes on the P2P network. In addition, it adds a logging statement for a failed signature condition. - -### New config file option: `max-nonprivileged-inline-action-size`. ([#9262](https://github.com/EOSIO/eos/pull/9262)) - -This option is the cap for the size of an inline action above which a transaction will subjectively fail; the default value is 4KB. - -## Other Changes -- ([#9170](https://github.com/EOSIO/eos/pull/9170)) Fix onblock trace tracking - 2.0 -- ([#9201](https://github.com/EOSIO/eos/pull/9201)) [2.0.x] Anka version bump -- ([#9265](https://github.com/EOSIO/eos/pull/9265)) Remove Concurrency Groups for Scheduled Builds - -## Documentation -- ([#9124](https://github.com/EOSIO/eos/pull/9124)) Update the authority example -- ([#9275](https://github.com/EOSIO/eos/pull/9275)) [docs] New threshold for non privileged inline actions - 2.0 -- ([#9288](https://github.com/EOSIO/eos/pull/9288)) [docs] Fix character formatting in nodeos CLI option - 2.0 -- ([#9290](https://github.com/EOSIO/eos/pull/9290)) [docs] Correct Producer API title in RPC reference - 2.0 diff --git a/docs/30_release-notes/93_v2.0.6.md b/docs/30_release-notes/93_v2.0.6.md deleted file mode 100644 index 97815d56bf..0000000000 --- a/docs/30_release-notes/93_v2.0.6.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -content_title: EOSIO v2.0.6 Release Notes -link_text: v2.0.6 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -- ([#9172](https://github.com/EOSIO/eos/pull/9172)) Escape Unicode C1 control code points. - -Note: These security fixes are relevant to API nodes on EOSIO blockchain networks. - -## Stability bug fixes - -- ([#9065](https://github.com/EOSIO/eos/pull/9065)) Fix for cleos and keosd race condition - 2.0 -- ([#9089](https://github.com/EOSIO/eos/pull/9089)) make ship WA key serialization match expected serialization - 2.0 -- ([#9095](https://github.com/EOSIO/eos/pull/9095)) fix gcc10 build due to libyubihsm problem - 2.0 -- ([#9127](https://github.com/EOSIO/eos/pull/9127)) Fix onblock handling in trace_api_plugin - 2.0 -- ([#9129](https://github.com/EOSIO/eos/pull/9129)) GCC 8.3 on CentOS 7 compiler workaround - 2.0 -- ([#9128](https://github.com/EOSIO/eos/pull/9128)) Restore abi_serializer backward compatibility - 2.0 - -## Changes - -### Add more information in trace-api-plugin responses for better usage. ([#9005](https://github.com/EOSIO/eos/pull/9005)) - -Adds `transaction_mroot`, `action_mroot` and `schedule_version` in block trace. Also adds `status`, `cpu_usage_us`, `net_usage_words`, `signatures`, and `transaction_header` in transaction trace. - -### New RPC endpoint **`get_accounts_by_authorizers`** ([#8899](https://github.com/EOSIO/eos/pull/8899)) - -New optional RPC endpoint **`POST /v1/chain/get_accounts_by_authorizers`** added to `chain_api_plugin` that provides a super-set of the deprecated `history_api_plugin`'s `get_key_accounts` and `get_controlled_accounts` RPC methods. - -Flag to enable endpoint (default false): **`--enable-account-queries`** - -## Other Changes - -- ([#8975](https://github.com/EOSIO/eos/pull/8975)) failing nodeos_run_test when core symbol is not SYS - 2.0 -- ([#9002](https://github.com/EOSIO/eos/pull/9002)) Support Triggering a Build that Runs ALL Tests in One Build -- ([#9007](https://github.com/EOSIO/eos/pull/9007)) Improved reporting in nodeos_forked_chain_lr_test - 2.0.x -- ([#9013](https://github.com/EOSIO/eos/pull/9013)) Bugfix for uninitialized variable in cleos - 2.0 -- ([#9009](https://github.com/EOSIO/eos/pull/9009)) Upgrade CLI11 to 1.9.0 - 2.0 -- ([#9028](https://github.com/EOSIO/eos/pull/9028)) Fix keosd auto-launching after CLI11 upgrade - 2.0 -- ([#9035](https://github.com/EOSIO/eos/pull/9035)) For Release 2.0 - Updated the priority of the APIs in producer_api_plugin and net_api_plugin to MEDIUM_HIGH -- ([#9049](https://github.com/EOSIO/eos/pull/9049)) add rapidjson license to install - 2.0 -- ([#9052](https://github.com/EOSIO/eos/pull/9052)) Print stderr if keosd_auto_launch_test.py fails - 2.0 -- ([#9060](https://github.com/EOSIO/eos/pull/9060)) Fix uninitialized struct members used as CLI flags - 2.0 -- ([#9062](https://github.com/EOSIO/eos/pull/9062)) Fix timedelta and strftime usage - 2.0 -- ([#9078](https://github.com/EOSIO/eos/pull/9078)) Update date in LICENSE - 2.0 -- ([#9063](https://github.com/EOSIO/eos/pull/9063)) add help text to wasm-runtime - 2.0.x -- ([#9084](https://github.com/EOSIO/eos/pull/9084)) Add support for specifing a logging.json to keosd - 2.0 -- ([#9082](https://github.com/EOSIO/eos/pull/9082)) Add change type to pull request template - 2.0 -- ([#8899](https://github.com/EOSIO/eos/pull/8899)) Account Query DB : Proposal to maintain get_(key|controlled)_accounts [2.0] -- ([#9103](https://github.com/EOSIO/eos/pull/9103)) Add default contract name clarifier in how to deploy smart contract - 2.0 -- ([#9109](https://github.com/EOSIO/eos/pull/9109)) [2.0.x] Bump Anka plugin version and timeouts. -- ([#9115](https://github.com/EOSIO/eos/pull/9115)) Simplify create_snapshot POST request - 2.0 -- ([#9110](https://github.com/EOSIO/eos/pull/9110)) Update algorithm for determining number of parallel jobs - 2.0 - -## Documentation - -- ([#8980](https://github.com/EOSIO/eos/pull/8980)) Add nodeos RPC API index, improve nodeos implementation doc, fix link - 2.0 -- ([#8995](https://github.com/EOSIO/eos/pull/8995)) Update example logging.json - 2.0 -- ([#9102](https://github.com/EOSIO/eos/pull/9102)) Fix inaccurate nodeos reference in wallet_api_plugin - 2.0 -- ([#9116](https://github.com/EOSIO/eos/pull/9116)) Replace inaccurate wording in how to replay from snapshot - 2.0 -- ([#9113](https://github.com/EOSIO/eos/pull/9113)) Add trace_api logger to docs - 2.0 -- ([#9142](https://github.com/EOSIO/eos/pull/9142)) Add missing reference to RPC API index [docs] - 2.0 -- ([#9141](https://github.com/EOSIO/eos/pull/9141)) Fix Trace API reference request/response inaccuracies [docs] - 2.0 -- ([#9144](https://github.com/EOSIO/eos/pull/9144)) Fix title case issue in keosd how-to [docs] - 2.0 -- ([#9145](https://github.com/EOSIO/eos/pull/9145)) Add conditional step in state history plugin how-to [docs] - 2.0 - -## Thanks! - -Special thanks to the community contributors that submitted patches for this release: -- @cc32d9 -- @oldcold diff --git a/docs/30_release-notes/94_v2.0.5.md b/docs/30_release-notes/94_v2.0.5.md deleted file mode 100644 index 2a912715ad..0000000000 --- a/docs/30_release-notes/94_v2.0.5.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -content_title: EOSIO v2.0.5 Release Notes -link_text: v2.0.5 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.5 ([#8983](https://github.com/EOSIO/eos/pull/8983)) - -- EOS-VM security fixes - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Stability bug fixes - -- ([#8826](https://github.com/EOSIO/eos/pull/8826)) trace_api_plugin yield timeout - 2.0 -- ([#8836](https://github.com/EOSIO/eos/pull/8836)) fix potential leak in OC's wrapped_fd move assignment op - 2.0 - -## Changes - -### Trace API Compressed Data Log Support ([#8826](https://github.com/EOSIO/eos/pull/8826), [#8837](https://github.com/EOSIO/eos/pull/8837), [#8881](https://github.com/EOSIO/eos/pull/8881)) - -Compressed file support was added to `trace_api_plugin`. See ([#8837](https://github.com/EOSIO/eos/pull/8837)) for more details. - -The RPC call `v1/trace_api/get_block` now has "async" http support. Therefore, executing `get_block` no longer runs on the main application thread but on the configurable `http-threads` thread pool. - -Additionally, `trace_api_plugin` now respects `http-max-response-time-ms` for limiting response time of RPC call `v1/trace_api/get_block`. It is very likely that the default value of `http-max-response-time-ms` will not be appropriate for large blocks and will need to be increased. - -## Other Changes - -- ([#8822](https://github.com/EOSIO/eos/pull/8822)) Merge minimize logging changes to 2.0.x -- ([#8823](https://github.com/EOSIO/eos/pull/8823)) yield_function for abi_serializer - 2.0 -- ([#8855](https://github.com/EOSIO/eos/pull/8855)) Improve too many bytes in flight error info - 2.0 -- ([#8861](https://github.com/EOSIO/eos/pull/8861)) HTTP Plugin async APIs [2.0] -- ([#8873](https://github.com/EOSIO/eos/pull/8873)) Fix spurious HTTP related test failure [2.0] (round 3) -- ([#8883](https://github.com/EOSIO/eos/pull/8883)) wabt: don't search for python because we don't run tests - 2.0 -- ([#8884](https://github.com/EOSIO/eos/pull/8884)) Correctly Sanitize git Branch and Tag Names -- ([#8894](https://github.com/EOSIO/eos/pull/8894)) Increase get info priority to medium high -- ([#8889](https://github.com/EOSIO/eos/pull/8889)) Sync from snapshot - 2.0 -- ([#8906](https://github.com/EOSIO/eos/pull/8906)) Remove assert check for error code 400 - release 2.0.x -- ([#8944](https://github.com/EOSIO/eos/pull/8944)) noop change to macos-10.14-unpinned.sh to regen CI image, 2.0 -- ([#8941](https://github.com/EOSIO/eos/pull/8941)) replace boost::bind with std::bind, fixing boost 1.73beta builds - 2.0 -- ([#8954](https://github.com/EOSIO/eos/pull/8954)) llvm 10 support for EOS VM OC - 2.0 -- ([#8949](https://github.com/EOSIO/eos/pull/8949)) Replace bc with shell arithmetic - 2.0 -- ([#8962](https://github.com/EOSIO/eos/pull/8962)) tests/get_table_tests.cpp: incorrect use of CORE_SYM_STR - 2.0 -- ([#8963](https://github.com/EOSIO/eos/pull/8963)) Make /bin/df ignore $BLOCKSIZE - 2.0 -- ([#8952](https://github.com/EOSIO/eos/pull/8952)) Fix SHIP block delay - 2.0 -- ([#8972](https://github.com/EOSIO/eos/pull/8972)) Add possibility to run .cicd scripts from different environments (2.0.x Backport) -- ([#8968](https://github.com/EOSIO/eos/pull/8968)) Support Running ALL Tests in One Build - -## Documentation changes - -- ([#8825](https://github.com/EOSIO/eos/pull/8825)) remove leading $ chars from shell codeblocks in README.md - 2.0 -- ([#8835](https://github.com/EOSIO/eos/pull/8835)) Trace API documentation update - 2.0 -- ([#8843](https://github.com/EOSIO/eos/pull/8843)) Fix double titles for release 2.0.x -- ([#8845](https://github.com/EOSIO/eos/pull/8845)) [docs] trace api reference api correction - 2.0 -- ([#8918](https://github.com/EOSIO/eos/pull/8918)) Updates to manual build instructions - 2.0 - -## Thanks! - -Special thanks to the community contributors that submitted patches for this release: -- @cc32d9 -- @maoueh diff --git a/docs/30_release-notes/95_v2.0.4.md b/docs/30_release-notes/95_v2.0.4.md deleted file mode 100644 index 6906b87069..0000000000 --- a/docs/30_release-notes/95_v2.0.4.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -content_title: EOSIO v2.0.4 Release Notes -link_text: v2.0.4 ---- - -This release contains stability and miscellaneous fixes. - -## Deprecation Notices - -The `read-only` option for the `read-mode` parameter in `nodeos` has been deprecated. It is possible to achieve the same behavior with `read-mode = head`, `p2p-accept-transactions = false`, and `api-accept-transactions = false`. See the sub-section "Accept transactions options" below for more details. - -Please refer to the [Consolidated EOSIO Deprecations List](https://github.com/EOSIO/eos/issues/7597) for the currently active set of deprecation notices. - -## Stability bug fixes - -- ([#8684](https://github.com/EOSIO/eos/pull/8684)) Net plugin sync priority - 2.0 -- ([#8729](https://github.com/EOSIO/eos/pull/8729)) Get info priority - 2.0 - -## Changes - -### Trace API Plugin ([#8800](https://github.com/EOSIO/eos/pull/8800)) - -This release contains the first official release of the Trace API Plugin. This plugin is an optional addition to `nodeos` that stores a tailored view of the transactions and actions that execute on the chain retrievable at a block level. The Trace API focuses on operational maintainability storing data on the filesystem instead of in RAM like the deprecated `history-plugin` and organizing that data such that operators can easily prune old data without disrupting operations. - -For more information, see the PR notes and the official documentation. - -### Exit transaction early when there is insufficient account CPU ([#8638](https://github.com/EOSIO/eos/pull/8638)) - -`nodeos` no longer considers a transaction for inclusion in a block in the process of being produced if the billed account(s) do not have sufficient CPU available to cover the previously estimated CPU usage of the transaction (only if a previous estimate for CPU usage is available). - -### Produce block immediately if resource limits are exhausted ([#8651](https://github.com/EOSIO/eos/pull/8651), [#8673](https://github.com/EOSIO/eos/pull/8673)) - -`nodeos` now immediately produces a block if either the CPU or NET usage thresholds are exceeded. This change includes a fix for dropping late blocks starting 50ms earlier than the block production window. - -New options: -* `max-block-cpu-usage-threshold-us`: -Threshold (in microseconds) of CPU block production to consider block full; when accumulated CPU usage within a block is less than `max-block-cpu-usage-threshold-us` away from `max-block-cpu-usage`, the block can be produced immediately. Default value is 5000. -* `max-block-net-usage-threshold-bytes`: -Threshold (in bytes) of NET block production to consider block full; when accumulated NET usage within a block is less than `max-block-net-usage-threshold-us` away from `max-block-net-usage`, the block can be produced immediately. Default value is 1024. - -### Accept transactions options ([#8702](https://github.com/EOSIO/eos/pull/8702)) - -New options: -* `p2p-accept-transactions`: Allow transactions received over p2p -network to be evaluated and relayed if valid. Default is true. -* `api-accept-transactions`: Allow API transactions to be evaluated -and relayed if valid. Default is true. - -Provides ability to have a `read-mode = head` with `p2p-accept-transactions = false` and `api-accept-transactions = true`. This combination creates an efficient API node that is not burdened with processing P2P transactions. - -The same behavior of the now deprecated `read-mode = read-only` can be achieved with `read-mode = head` by setting `p2p-accept-transactions = false` and `api-accept-transactions = false`. - -**WARNING:** Use of `read-mode = irreversible` now requires setting `p2p-accept-transactions = false` and `api-accept-transactions = false` to avoid assertion at startup. - -### Relay block early ([#8701](https://github.com/EOSIO/eos/pull/8701)) - -Improve block relaying performance when a block is from a trusted producer or if `nodeos` is running in light validation mode. This is achieved by relaying the block as soon as block header validation is complete (but before full block application/validation). - -## Other Changes - -- ([#8654](https://github.com/EOSIO/eos/pull/8654)) Fix format message. - 2.0 -- ([#8668](https://github.com/EOSIO/eos/pull/8668)) Add troubleshooting item for PREACTIVATE_FEATURE protocol -- ([#8689](https://github.com/EOSIO/eos/pull/8689)) incoming-defer-ratio description - 2.0 -- ([#8695](https://github.com/EOSIO/eos/pull/8695)) [2.0.x] Community PR tweaks. -- ([#8700](https://github.com/EOSIO/eos/pull/8700)) [2.0.x] Base images pipeline. -- ([#8714](https://github.com/EOSIO/eos/pull/8714)) [2.0.x] Actions rerun fixes. -- ([#8710](https://github.com/EOSIO/eos/pull/8710)) Add block producing explainer doc - 2.0 -- ([#8721](https://github.com/EOSIO/eos/pull/8721)) Fix multiple version protocol test intermittent failure - 2.0 -- ([#8727](https://github.com/EOSIO/eos/pull/8727)) Update the getting started link [merge 2] -- ([#8752](https://github.com/EOSIO/eos/pull/8752)) chain_api_plugin swagger file - 2.0 -- ([#8756](https://github.com/EOSIO/eos/pull/8756)) Fixes #8600 clean up nodeos options section -- ([#8757](https://github.com/EOSIO/eos/pull/8757)) link cleos net status reference doc with the peer network protocol doc -- ([#8590](https://github.com/EOSIO/eos/pull/8590)) db_size_api_plugin swagger file - 2.0 -- ([#8591](https://github.com/EOSIO/eos/pull/8591)) net_api_plugin swagger file - 2.0 -- ([#8592](https://github.com/EOSIO/eos/pull/8592)) producer_api_plugin swagger file - 2.0 -- ([#8593](https://github.com/EOSIO/eos/pull/8593)) test_control_api_plugin swagger file - 2.0 -- ([#8754](https://github.com/EOSIO/eos/pull/8754)) swagger configuration for docs - 2.0 -- ([#8762](https://github.com/EOSIO/eos/pull/8762)) Fix broken link in producer plugin docs - 2.0 -- ([#8763](https://github.com/EOSIO/eos/pull/8763)) Fix wasm-runtime option parameters - 2.0 -- ([#8765](https://github.com/EOSIO/eos/pull/8765)) Add Incoming-defer-ratio description - 2.0 -- ([#8767](https://github.com/EOSIO/eos/pull/8767)) Fix other blocks.log callout - 2.0 -- ([#8768](https://github.com/EOSIO/eos/pull/8768)) Improve create account description - 2.0 -- ([#8782](https://github.com/EOSIO/eos/pull/8782)) link to librt when using posix timers - 2.0 -- ([#8781](https://github.com/EOSIO/eos/pull/8781)) free unknown EOS VM OC codegen versions from the code cache - 2.0 -- ([#8794](https://github.com/EOSIO/eos/pull/8794)) disable EOS VM on non-x86 platforms - 2.0 -- ([#8803](https://github.com/EOSIO/eos/pull/8803)) Expire blacklisted scheduled transactions by LIB time - 2.0 -- ([#8811](https://github.com/EOSIO/eos/pull/8811)) Add initial Trace API plugin docs to nodeos - 2.0 -- ([#8814](https://github.com/EOSIO/eos/pull/8814)) Add RPC Trace API plugin reference to nodeos - 2.0 diff --git a/docs/30_release-notes/96_v2.0.3.md b/docs/30_release-notes/96_v2.0.3.md deleted file mode 100644 index 1ba0a6ffb2..0000000000 --- a/docs/30_release-notes/96_v2.0.3.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -content_title: EOSIO v2.0.3 Release Notes -link_text: v2.0.3 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.3 ([#8643](https://github.com/EOSIO/eos/pull/8643)) - -- Add deadline to base58 encoding. - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Stability bug fixes - -- ([#8617](https://github.com/EOSIO/eos/pull/8617)) Init net_plugin member variables - 2.0 - -## Other Changes - -- ([#8606](https://github.com/EOSIO/eos/pull/8606)) Skip sync from genesis and resume from state test on tagged builds -- ([#8612](https://github.com/EOSIO/eos/pull/8612)) [2.0.x] Actions for community PRs. -- ([#8633](https://github.com/EOSIO/eos/pull/8633)) remove brew's python@2 install - 2.0 -- ([#8636](https://github.com/EOSIO/eos/pull/8636)) bump script's macos version check to 10.14 - 2.0 - -## Deprecation notice reminder - -Please refer to the [Consolidated EOSIO Deprecations List](https://github.com/EOSIO/eos/issues/7597) for the currently active set of deprecation notices. diff --git a/docs/30_release-notes/97_v2.0.2.md b/docs/30_release-notes/97_v2.0.2.md deleted file mode 100644 index c9707f171c..0000000000 --- a/docs/30_release-notes/97_v2.0.2.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -content_title: EOSIO v2.0.2 Release Notes -link_text: v2.0.2 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.2 ([#8595](https://github.com/EOSIO/eos/pull/8595)) - -- Restrict allowed block signature types. - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Stability bug fixes - -- ([#8526](https://github.com/EOSIO/eos/pull/8526)) Handle socket close before async callback - 2.0 -- ([#8546](https://github.com/EOSIO/eos/pull/8546)) Net plugin dispatch - 2.0 -- ([#8552](https://github.com/EOSIO/eos/pull/8552)) Net plugin unlinkable blocks - 2.0 -- ([#8560](https://github.com/EOSIO/eos/pull/8560)) Backport of 8056 to 2.0 -- ([#8561](https://github.com/EOSIO/eos/pull/8561)) Net plugin post - 2.0 -- ([#8564](https://github.com/EOSIO/eos/pull/8564)) Delayed production time - 2.0 - -## Changes - -### Limit block production window ([#8571](https://github.com/EOSIO/eos/pull/8571), [#8578](https://github.com/EOSIO/eos/pull/8578)) - -The new options `cpu-effort-percent` and `last-block-cpu-effort-percent` now provide a mechanism to restrict the amount of time a producer is processing transactions for inclusion into a block. It also controls the time a producer will finalize/produce and transmit a block. Block construction now always begins at whole or half seconds for the next block. - -### Stricter signature parsing - -Versions of EOSIO prior to v2.0.x accept keys and signatures containing extra data at the end. In EOSIO v2.0.x, the Base58 string parser performs additional sanity checks on keys and signatures to make sure they do not contain more data than necessary. These stricter checks cause nodes to reject signatures generated by some transaction signing libraries; eosjs v20 is known to generate proper signatures. For more information see issue [#8534](https://github.com/EOSIO/eos/issues/8534). - -## Other Changes - -- ([#8555](https://github.com/EOSIO/eos/pull/8555)) Drop late check - 2.0 -- ([#8557](https://github.com/EOSIO/eos/pull/8557)) Read-only with drop-late-block - 2.0 -- ([#8568](https://github.com/EOSIO/eos/pull/8568)) Timestamp watermark slot - 2.0.x -- ([#8577](https://github.com/EOSIO/eos/pull/8577)) [release 2.0.x] Documentation patch 1 update -- ([#8583](https://github.com/EOSIO/eos/pull/8583)) P2p read only - 2.0 -- ([#8589](https://github.com/EOSIO/eos/pull/8589)) Producer plugin log - 2.0 - -## Deprecation notice reminder - -Please refer to the [Consolidated EOSIO Deprecations List](https://github.com/EOSIO/eos/issues/7597) for the currently active set of deprecation notices. diff --git a/docs/30_release-notes/98_v2.0.1.md b/docs/30_release-notes/98_v2.0.1.md deleted file mode 100644 index 755ef919c3..0000000000 --- a/docs/30_release-notes/98_v2.0.1.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -content_title: EOSIO v2.0.1 Release Notes -link_text: v2.0.1 ---- - -This release contains security, stability, and miscellaneous fixes. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.1 ([#8514](https://github.com/EOSIO/eos/pull/8514)) - -- Earlier block validation for greater security. -- Improved handling of deferred transactions during block production. -- Reduce net plugin logging and handshake size limits. - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -## Stability bug fixes - -- ([#8471](https://github.com/EOSIO/eos/pull/8471)) Remove new block id notify feature - 2.0 -- ([#8472](https://github.com/EOSIO/eos/pull/8472)) Report block header diff when digests do not match - 2.0 -- ([#8496](https://github.com/EOSIO/eos/pull/8496)) Drop late blocks - 2.0 -- ([#8510](https://github.com/EOSIO/eos/pull/8510)) http_plugin shutdown - 2.0 - -## Other Changes - -- ([#8430](https://github.com/EOSIO/eos/pull/8430)) Update fc to fix crash in logging -- ([#8435](https://github.com/EOSIO/eos/pull/8435)) [release/2.0.x] Update README.md and hotfix documentation links -- ([#8452](https://github.com/EOSIO/eos/pull/8452)) [2.0.x] [CI/CD] Boost will not install without SDKROOT -- ([#8457](https://github.com/EOSIO/eos/pull/8457)) [2.0.x] reverting fc -- ([#8458](https://github.com/EOSIO/eos/pull/8458)) [2.0.x] Pipeline file for testing the build script -- ([#8467](https://github.com/EOSIO/eos/pull/8467)) [2.0.x] Switching to using the EOSIO fork of anka-buildkite-plugin for security reasons -- ([#8515](https://github.com/EOSIO/eos/pull/8515)) [2.0.x] Don't trigger LRT a second time - -## Deprecation notice reminder - -Please refer to the [Consolidated EOSIO Deprecations List](https://github.com/EOSIO/eos/issues/7597) for the currently active set of deprecation notices. diff --git a/docs/30_release-notes/99_v2.0.0.md b/docs/30_release-notes/99_v2.0.0.md deleted file mode 100644 index 6462f86fad..0000000000 --- a/docs/30_release-notes/99_v2.0.0.md +++ /dev/null @@ -1,377 +0,0 @@ ---- -content_title: EOSIO v2.0.0 Release Notes -link_text: v2.0.0 ---- - -This release contains security, stability, and miscellaneous fixes. - -This release also includes an EOSIO consensus upgrade. Please see the "Consensus Protocol Upgrades" section below for details. These protocol upgrades necessitate a change to the state database structure which requires a nodeos upgrade process that involves more steps than in the case of most minor release upgrades. For details on the upgrade process, see the "Upgrading from previous versions of EOSIO" section below. - -## Security bug fixes - -### Consolidated Security Fixes for 2.0.0 ([#8420](https://github.com/EOSIO/eos/pull/8420)) - -- Limit size of response to API requests -- EOS VM fixes - -Note: These security fixes are relevant to all nodes on EOSIO blockchain networks. - -The above is in addition to the other security fixes that were introduced in prior release candidates for 2.0.0: - -- ([#8195](https://github.com/EOSIO/eos/pull/8195)) Consolidated Security Fixes for 2.0.0-rc2 -- ([#8344](https://github.com/EOSIO/eos/pull/8344)) Consolidated Security Fixes for 2.0.0-rc3 - -## Stability bug fixes - -- ([#8399](https://github.com/EOSIO/eos/pull/8399)) Net plugin sync check - 2.0 - -This above is in addition to the other stability fixes that were introduced in prior release candidates for 2.0.0: - -- ([#8084](https://github.com/EOSIO/eos/pull/8084)) Net plugin remove read delays - 2.0 -- ([#8099](https://github.com/EOSIO/eos/pull/8099)) net_plugin remove sync w/peer check - 2.0 -- ([#8120](https://github.com/EOSIO/eos/pull/8120)) Net plugin sync fix - 2.0 -- ([#8229](https://github.com/EOSIO/eos/pull/8229)) Net plugin sync -- ([#8285](https://github.com/EOSIO/eos/pull/8285)) Net plugin handshake -- ([#8298](https://github.com/EOSIO/eos/pull/8298)) net_plugin lib sync -- ([#8303](https://github.com/EOSIO/eos/pull/8303)) net_plugin boost asio error handling -- ([#8305](https://github.com/EOSIO/eos/pull/8305)) net_plugin thread protection peer logging variables -- ([#8311](https://github.com/EOSIO/eos/pull/8311)) Fix race in fc::message_buffer and move message_buffer_tests to fc. -- ([#8307](https://github.com/EOSIO/eos/pull/8307)) reset the new handler - -## Changes - -### EOS VM: New High Performance WASM Runtimes ([#7974](https://github.com/EOSIO/eos/pull/7974), [#7975](https://github.com/EOSIO/eos/pull/7975)) -Three new WASM runtimes are available in this release: EOS VM Interpreter, EOS VM Just In Time Compiler (JIT), and EOS VM Optimized Compiler. - -EOS VM Interpreter is a low latency interpreter and is included to enable future support for smart contract debuggers. EOS VM JIT is a low latency single pass compiler for x86_64 platforms. To use EOS VM Interpreter or EOS VM JIT, set the `wasm-runtime` to either `eos-vm` or `eos-vm-jit` respectively - -EOS VM Optimized Compiler is a high performance WASM _tier-up_ runtime available on the x86_64 Linux platform that works in conjunction with the configured baseline runtime (such as EOS VM JIT). When enabled via `eos-vm-oc-enable`, actions on a contract are initially dispatched to the baseline runtime while EOS VM Optimized Compiler does an optimized compilation in the background. Up to the configured `eos-vm-oc-compile-threads` compilations can be ongoing simultaneously. Once the background compilation is complete, actions on that contract will then be run with the optimized compiled code from then on. This optimized compile can take a handful of seconds but since it is performed in the background it does not cause delays. Optimized compilations are also saved to a new data file (`code_cache.bin` in the data directory) so when restarting nodeos there is no need to recompile previously compiled contracts. - -None of the EOS VM runtimes require a replay nor activation of any consensus protocol upgrades. They can be switched between (including enabling and disabling EOS VM Optimized Compiler) at will. - -At this time, **block producers should consider all running EOS VM JIT as the WASM runtime on their block producing nodes**. Other non-producing nodes should feel free to use the faster EOS VM Optimized Compiler runtime instead. - -### Consensus Protocol Upgrades - -Refer to this section on the [Upgrade Guide: Consensus Protocol Upgrades](../20_upgrade-guide/index.md#consensus-protocol-upgrades). - -### Multi-threaded net_plugin -We have added multi-threading support to net_plugin. Almost all processing in the net_plugin (block propagation, transaction processing, block/transaction packing/unpacking etc.) are now handled by separate threads distinct from the main application thread. This significantly improves transaction processing and block processing performance on multi-producer EOSIO networks. The `net-threads` arg (defaults to 2) controls the number of worker threads in net_plugin thread pool.([#6845](https://github.com/EOSIO/eos/pull/6845), [#7598](https://github.com/EOSIO/eos/pull/7598), [#7392](https://github.com/EOSIO/eos/pull/7392), [#7786](https://github.com/EOSIO/eos/pull/7786) and related optimizations are available in: [#7686](https://github.com/EOSIO/eos/pull/7686), [#7785](https://github.com/EOSIO/eos/pull/7785), [#7721](https://github.com/EOSIO/eos/pull/7721), [#7825](https://github.com/EOSIO/eos/pull/7825), and [#7756](https://github.com/EOSIO/eos/pull/7756)). - -### Chain API Enhancements ([#7530](https://github.com/EOSIO/eos/pull/7530)) -The `uint128` and `int128` ABI types are now represented as decimal numbers rather than the old little-endian hexadecimal representation. This means that the JSON representation of table rows returned by the `get_table_rows` RPC will represent fields using this type differently than in prior versions. It also means that the `lower_bound` and `upper_bound` fields for `get_table_rows` RPC requests that search using a `uint128` secondary index will need to use the new decimal representation. This change makes the ABI serialization for `uint128` and `int128` ABI types consistent with [eosjs](https://github.com/EOSIO/eosjs) and [abieos](http://github.com/EOSIO/abieos). - -The `get_table_rows` RPC when used with secondary index types like `sha256`, `i256`, and `ripemd160` had bugs that scrambled the bytes in the `lower_bound` and `upper_bound` input field. This release now fixes these issues allowing clients to properly search for tables rows using these index types. - -A new field `next_key` has been added to the response of the `get_table_rows` RPC which represents the key of the next row (in the same format as `lower_bound` and `upper_bound`) that was not able to be returned in the response due to timeout limitations or the user-specified limit. The value of the `next_key` can be used as the `lower_bound` input for subsequent requests in order to retrieve a range of a large number of rows that could not be retrieved within just a single request. - -## Upgrading from previous versions of EOSIO - -Refer to this section on the [Upgrade Guide: Upgrading from previous versions of EOSIO](../20_upgrade-guide/index.md#upgrading-from-previous-versions-of-eosio). - -## Deprecation and Removal Notices - -### WAVM removed ([#8407](https://github.com/EOSIO/eos/pull/8407)) - -The WAVM WebAssembly runtime was deprecated several months ago with the release of [EOSIO v2.0.0-rc1](https://github.com/EOSIO/eos/releases/tag/v2.0.0-rc1) which introduced EOS VM. Now with the release of a stable version 2.0.0, EOS VM (JIT or Optimized Compiler variants) can be used instead of WAVM. So WAVM has now been removed as a WASM runtime option from nodeos. - -### Deprecation notice reminder - -Please refer to the [Consolidated EOSIO Deprecations List](https://github.com/EOSIO/eos/issues/7597) for the currently active set of deprecation notices. - -## Other Changes - -- ([#7247](https://github.com/EOSIO/eos/pull/7247)) Change default log level from debug to info. - develop -- ([#7238](https://github.com/EOSIO/eos/pull/7238)) Remove unused cpack bits; these are not being used -- ([#7248](https://github.com/EOSIO/eos/pull/7248)) Pass env to build script installs -- ([#6913](https://github.com/EOSIO/eos/pull/6913)) Block log util#6884 -- ([#7249](https://github.com/EOSIO/eos/pull/7249)) Http configurable logging -- ([#7255](https://github.com/EOSIO/eos/pull/7255)) Move Test Metrics Code to Agent -- ([#7217](https://github.com/EOSIO/eos/pull/7217)) Created Universal Pipeline Configuration File -- ([#7264](https://github.com/EOSIO/eos/pull/7264)) use protocol-features-sync-nodes branch for LRT pipeline - develop -- ([#7207](https://github.com/EOSIO/eos/pull/7207)) Optimize mongodb plugin -- ([#7276](https://github.com/EOSIO/eos/pull/7276)) correct net_plugin's win32 check -- ([#7279](https://github.com/EOSIO/eos/pull/7279)) build unittests in c++17, not c++14 -- ([#7282](https://github.com/EOSIO/eos/pull/7282)) Fix cleos REX help - develop -- ([#7284](https://github.com/EOSIO/eos/pull/7284)) remove boost asio string_view workaround -- ([#7286](https://github.com/EOSIO/eos/pull/7286)) chainbase uniqueness violation fixes -- ([#7287](https://github.com/EOSIO/eos/pull/7287)) restrict range of error codes that contracts are allowed to emit -- ([#7278](https://github.com/EOSIO/eos/pull/7278)) simplify openssl setup in cmakelists -- ([#7288](https://github.com/EOSIO/eos/pull/7288)) Changes for Boost 1_70_0 -- ([#7285](https://github.com/EOSIO/eos/pull/7285)) Use of Mac Anka Fleet instead of iMac fleet -- ([#7293](https://github.com/EOSIO/eos/pull/7293)) Update EosioTester.cmake.in (develop) -- ([#7290](https://github.com/EOSIO/eos/pull/7290)) Block log util test -- ([#6845](https://github.com/EOSIO/eos/pull/6845)) Net plugin multithread -- ([#7295](https://github.com/EOSIO/eos/pull/7295)) Modify the pipeline control file for triggered builds -- ([#7305](https://github.com/EOSIO/eos/pull/7305)) Eliminating trigger to allow for community PR jobs to run again -- ([#7306](https://github.com/EOSIO/eos/pull/7306)) when unable to find mongo driver stop cmake -- ([#7309](https://github.com/EOSIO/eos/pull/7309)) add debug_mode to state history plugin - develop -- ([#7310](https://github.com/EOSIO/eos/pull/7310)) Switched to git checkout of commit + supporting forked repo -- ([#7291](https://github.com/EOSIO/eos/pull/7291)) add DB guard check for nodeos_under_min_avail_ram.py -- ([#7240](https://github.com/EOSIO/eos/pull/7240)) add signal tests -- ([#7315](https://github.com/EOSIO/eos/pull/7315)) Add REX balance info to cleos get account command -- ([#7304](https://github.com/EOSIO/eos/pull/7304)) transaction_metadata thread safety -- ([#7321](https://github.com/EOSIO/eos/pull/7321)) Only call init if system contract is loaded -- ([#7275](https://github.com/EOSIO/eos/pull/7275)) remove win32 from CMakeLists.txt -- ([#7322](https://github.com/EOSIO/eos/pull/7322)) Fix under min avail ram test -- ([#7327](https://github.com/EOSIO/eos/pull/7327)) fix block serialization order in fork_database::close - develop -- ([#7331](https://github.com/EOSIO/eos/pull/7331)) Use debug level logging for --verbose -- ([#7325](https://github.com/EOSIO/eos/pull/7325)) Look in both lib and lib64 for CMake modules when building EOSIO Tester -- ([#7337](https://github.com/EOSIO/eos/pull/7337)) correct signed mismatch warning in http_plugin -- ([#7348](https://github.com/EOSIO/eos/pull/7348)) Anka develop fix -- ([#7320](https://github.com/EOSIO/eos/pull/7320)) Add test for various chainbase objects which contain fields that require dynamic allocation -- ([#7350](https://github.com/EOSIO/eos/pull/7350)) correct signed mismatch warning in chain controller -- ([#7356](https://github.com/EOSIO/eos/pull/7356)) Fixes for Boost 1.70 to compile with our current CMake -- ([#7359](https://github.com/EOSIO/eos/pull/7359)) update to use boost 1.70 -- ([#7341](https://github.com/EOSIO/eos/pull/7341)) Add Version Check for Package Builder -- ([#7367](https://github.com/EOSIO/eos/pull/7367)) Fix exception # -- ([#7342](https://github.com/EOSIO/eos/pull/7342)) Update to appbase max priority on main thread -- ([#7336](https://github.com/EOSIO/eos/pull/7336)) (softfloat sync) clean up strict-aliasing rules warnings -- ([#7371](https://github.com/EOSIO/eos/pull/7371)) Adds configuration for replay test pipeline -- ([#7370](https://github.com/EOSIO/eos/pull/7370)) Fix `-b` flag for `cleos get table` subcommand -- ([#7369](https://github.com/EOSIO/eos/pull/7369)) Add `boost/asio/io_context.hpp` header to `transaction_metadata.hpp` for branch `develop` -- ([#7385](https://github.com/EOSIO/eos/pull/7385)) Ship: port #7383 and #7384 to develop -- ([#7377](https://github.com/EOSIO/eos/pull/7377)) Allow aliases of variants in ABI -- ([#7316](https://github.com/EOSIO/eos/pull/7316)) Explicit name -- ([#7389](https://github.com/EOSIO/eos/pull/7389)) Fix develop merge -- ([#7379](https://github.com/EOSIO/eos/pull/7379)) transaction deadline cleanup -- ([#7380](https://github.com/EOSIO/eos/pull/7380)) Producer incoming-transaction-queue-size-mb -- ([#7391](https://github.com/EOSIO/eos/pull/7391)) Allow for EOS clone to be a submodule -- ([#7390](https://github.com/EOSIO/eos/pull/7390)) port db_modes_test to python -- ([#7399](https://github.com/EOSIO/eos/pull/7399)) throw error if trying to create non R1 key on SE or YubiHSM wallet -- ([#7394](https://github.com/EOSIO/eos/pull/7394)) (fc sync) static_variant improvements & fix certificate trust when trust settings is empty -- ([#7405](https://github.com/EOSIO/eos/pull/7405)) Centralize EOSIO Pipeline -- ([#7401](https://github.com/EOSIO/eos/pull/7401)) state database versioning -- ([#7392](https://github.com/EOSIO/eos/pull/7392)) Trx blk connections -- ([#7433](https://github.com/EOSIO/eos/pull/7433)) use imported targets for boost & cleanup fc/appbase/chainbase standalone usage -- ([#7434](https://github.com/EOSIO/eos/pull/7434)) (chainbase) don’t keep file mapping active when in heap/locked mode -- ([#7432](https://github.com/EOSIO/eos/pull/7432)) No need to start keosd for cleos command which doesn't need keosd -- ([#7430](https://github.com/EOSIO/eos/pull/7430)) Add option for cleos sign subcommand to ask keosd for signing -- ([#7425](https://github.com/EOSIO/eos/pull/7425)) txn json to file -- ([#7440](https://github.com/EOSIO/eos/pull/7440)) Fix #7436 SIGSEGV - develop -- ([#7461](https://github.com/EOSIO/eos/pull/7461)) Name txn_test_gen threads -- ([#7442](https://github.com/EOSIO/eos/pull/7442)) Enhance cleos error message when parsing JSON argument -- ([#7451](https://github.com/EOSIO/eos/pull/7451)) set initial costs for expensive parallel unit tests -- ([#7366](https://github.com/EOSIO/eos/pull/7366)) BATS bash tests for build scripts + various other improvements and fixes -- ([#7467](https://github.com/EOSIO/eos/pull/7467)) Pipeline Configuration File Update -- ([#7476](https://github.com/EOSIO/eos/pull/7476)) Various improvements from pull/7458 -- ([#7488](https://github.com/EOSIO/eos/pull/7488)) Various BATS fixes to fix CI/CD -- ([#7489](https://github.com/EOSIO/eos/pull/7489)) Fix Incorrectly Resolved and Untested Merge Conflicts in Pipeline Configuration File -- ([#7474](https://github.com/EOSIO/eos/pull/7474)) fix copy_bin() for win32 builds -- ([#7478](https://github.com/EOSIO/eos/pull/7478)) remove stray SIGUSR1 -- ([#7475](https://github.com/EOSIO/eos/pull/7475)) guard unix socket support in http_plugin depending on platform support -- ([#7492](https://github.com/EOSIO/eos/pull/7492)) Enabled helpers for unpinned builds. -- ([#7482](https://github.com/EOSIO/eos/pull/7482)) Let delete-all-blocks option to only remove the contents instead of the directory itself -- ([#7502](https://github.com/EOSIO/eos/pull/7502)) [develop] Versioned images (prep for hashing) -- ([#7507](https://github.com/EOSIO/eos/pull/7507)) use create_directories in initialize_protocol_features - develop -- ([#7484](https://github.com/EOSIO/eos/pull/7484)) return zero exit status for nodeos version, help, fixed reversible, and extracted genesis -- ([#7468](https://github.com/EOSIO/eos/pull/7468)) Versioning library -- ([#7486](https://github.com/EOSIO/eos/pull/7486)) [develop] Ensure we're in repo root -- ([#7515](https://github.com/EOSIO/eos/pull/7515)) Custom path support for eosio installation. -- ([#7516](https://github.com/EOSIO/eos/pull/7516)) on supported platforms build with system clang by default -- ([#7519](https://github.com/EOSIO/eos/pull/7519)) [develop] Removed lrt from pipeline.jsonc -- ([#7525](https://github.com/EOSIO/eos/pull/7525)) [develop] Readlink quick fix and BATS test fixes -- ([#7532](https://github.com/EOSIO/eos/pull/7532)) [develop] BASE IMAGE Fixes -- ([#7535](https://github.com/EOSIO/eos/pull/7535)) Add -j option to print JSON format for cleos get currency balance. -- ([#7537](https://github.com/EOSIO/eos/pull/7537)) connection via listen needs to start in connecting mode -- ([#7497](https://github.com/EOSIO/eos/pull/7497)) properly add single quotes for parameter with spaces in logs output -- ([#7544](https://github.com/EOSIO/eos/pull/7544)) restore usage of devtoolset-8 on centos7 -- ([#7547](https://github.com/EOSIO/eos/pull/7547)) Sighup logging -- ([#7421](https://github.com/EOSIO/eos/pull/7421)) WebAuthn key and signature support -- ([#7572](https://github.com/EOSIO/eos/pull/7572)) [develop] Don't create mongo folders unless ENABLE_MONGO is true -- ([#7576](https://github.com/EOSIO/eos/pull/7576)) [develop] Better found/not found messages for clarity -- ([#7545](https://github.com/EOSIO/eos/pull/7545)) add nodiscard attribute to tester's push_action -- ([#7581](https://github.com/EOSIO/eos/pull/7581)) Update to fc with logger fix -- ([#7558](https://github.com/EOSIO/eos/pull/7558)) [develop] Ability to set *_DIR on CLI -- ([#7553](https://github.com/EOSIO/eos/pull/7553)) [develop] CMAKE version check before dependencies are installed -- ([#7584](https://github.com/EOSIO/eos/pull/7584)) fix hash<>::result_type deprecation spam -- ([#7588](https://github.com/EOSIO/eos/pull/7588)) [develop] Various BATS test fixes -- ([#7578](https://github.com/EOSIO/eos/pull/7578)) [develop] -i support for relative paths -- ([#7449](https://github.com/EOSIO/eos/pull/7449)) add accurate checktime timer for macOS -- ([#7591](https://github.com/EOSIO/eos/pull/7591)) [develop] SUDO_COMMAND -> NEW_SUDO_COMMAND (base fixed) -- ([#7594](https://github.com/EOSIO/eos/pull/7594)) [develop] Install location fix -- ([#7586](https://github.com/EOSIO/eos/pull/7586)) Modify transaction_ack to process bcast_transaction and rejected_transaction correctly -- ([#7585](https://github.com/EOSIO/eos/pull/7585)) Enhance cleos to enable new RPC send_transaction -- ([#7599](https://github.com/EOSIO/eos/pull/7599)) Use updated sync nodes for sync tests -- ([#7608](https://github.com/EOSIO/eos/pull/7608)) indicate in brew bottle mojave is required -- ([#7615](https://github.com/EOSIO/eos/pull/7615)) Change hardcoded currency symbol in testnet.template into a variable -- ([#7610](https://github.com/EOSIO/eos/pull/7610)) use explicit billing for unapplied and deferred transactions in tester - develop -- ([#7621](https://github.com/EOSIO/eos/pull/7621)) Call resolve on connection strand -- ([#7623](https://github.com/EOSIO/eos/pull/7623)) additional wasm unittests around max depth -- ([#7607](https://github.com/EOSIO/eos/pull/7607)) Improve nodeos make-index speeds -- ([#7598](https://github.com/EOSIO/eos/pull/7598)) Net plugin block id notification -- ([#7624](https://github.com/EOSIO/eos/pull/7624)) bios-boot-tutorial.py: bugfix, SYS hardcoded instead of using command… -- ([#7632](https://github.com/EOSIO/eos/pull/7632)) [develop] issues/7627: Install script missing ! -- ([#7634](https://github.com/EOSIO/eos/pull/7634)) fix fc::temp_directory usage in tester -- ([#7642](https://github.com/EOSIO/eos/pull/7642)) remove stale warning about dirty metadata -- ([#7640](https://github.com/EOSIO/eos/pull/7640)) fix win32 build of eosio-blocklog -- ([#7643](https://github.com/EOSIO/eos/pull/7643)) remove unused dlfcn.h include; troublesome for win32 -- ([#7645](https://github.com/EOSIO/eos/pull/7645)) add eosio-blocklog to base install component -- ([#7651](https://github.com/EOSIO/eos/pull/7651)) Port #7619 to develop -- ([#7652](https://github.com/EOSIO/eos/pull/7652)) remove raise() in keosd in favor of simple appbase quit (de-posix it) -- ([#7453](https://github.com/EOSIO/eos/pull/7453)) Refactor unapplied transaction queue -- ([#7657](https://github.com/EOSIO/eos/pull/7657)) (chainbase sync) print name of DB causing failure condition & win32 fixes -- ([#7663](https://github.com/EOSIO/eos/pull/7663)) Fix path error in cleos set code/abi -- ([#7633](https://github.com/EOSIO/eos/pull/7633)) Small optimization to move more trx processing off application thread -- ([#7662](https://github.com/EOSIO/eos/pull/7662)) fix fork resolve in special case -- ([#7667](https://github.com/EOSIO/eos/pull/7667)) fix 7600 double confirm after changing sign key -- ([#7625](https://github.com/EOSIO/eos/pull/7625)) Fix flaky tests - mainly net_plugin fixes -- ([#7672](https://github.com/EOSIO/eos/pull/7672)) Fix memory leak -- ([#7676](https://github.com/EOSIO/eos/pull/7676)) Remove unused code -- ([#7677](https://github.com/EOSIO/eos/pull/7677)) Commas go outside the quotes... -- ([#7675](https://github.com/EOSIO/eos/pull/7675)) wasm unit test with an imported function as start function -- ([#7678](https://github.com/EOSIO/eos/pull/7678)) Issue 3516 fix -- ([#7404](https://github.com/EOSIO/eos/pull/7404)) wtmsig block production -- ([#7686](https://github.com/EOSIO/eos/pull/7686)) Unapplied transaction queue performance -- ([#7685](https://github.com/EOSIO/eos/pull/7685)) Integration Test descriptions and timeout fix -- ([#7691](https://github.com/EOSIO/eos/pull/7691)) Fix nodeos 1.8.x to > 1.7.x peering issue (allowed-connection not equal to "any") -- ([#7250](https://github.com/EOSIO/eos/pull/7250)) wabt: reduce redundant memset -- ([#7702](https://github.com/EOSIO/eos/pull/7702)) fix producer_plugin watermark tracking - develop -- ([#7477](https://github.com/EOSIO/eos/pull/7477)) Fix abi_serializer to encode optional non-built_in types -- ([#7703](https://github.com/EOSIO/eos/pull/7703)) return flat_multimap from transaction::validate_and_extract_extensions -- ([#7720](https://github.com/EOSIO/eos/pull/7720)) Fix bug to make sed -i work properly on Mac -- ([#7716](https://github.com/EOSIO/eos/pull/7716)) [TRAVIS POC] develop Support passing in JOBS for docker/kube multi-tenancy -- ([#7707](https://github.com/EOSIO/eos/pull/7707)) add softfloat only injection mode -- ([#7725](https://github.com/EOSIO/eos/pull/7725)) Fix increment in test -- ([#7729](https://github.com/EOSIO/eos/pull/7729)) Fix db_modes_test -- ([#7734](https://github.com/EOSIO/eos/pull/7734)) Fix db exhaustion -- ([#7487](https://github.com/EOSIO/eos/pull/7487)) Enable extended_asset to be encoded from array -- ([#7736](https://github.com/EOSIO/eos/pull/7736)) unit test ensuring that OOB table init allowed on set code; fails on action -- ([#7744](https://github.com/EOSIO/eos/pull/7744)) (appbase) update to get non-option fix & unique_ptr tweak -- ([#7746](https://github.com/EOSIO/eos/pull/7746)) (chainbase sync) fix build with boost 1.71 -- ([#7721](https://github.com/EOSIO/eos/pull/7721)) Improve signature recovery -- ([#7757](https://github.com/EOSIO/eos/pull/7757)) remove stale license headers -- ([#7756](https://github.com/EOSIO/eos/pull/7756)) block_log performance improvement, and misc. -- ([#7654](https://github.com/EOSIO/eos/pull/7654)) exclusively use timer for checktime -- ([#7763](https://github.com/EOSIO/eos/pull/7763)) Use fc::cfile instead of std::fstream for state_history -- ([#7770](https://github.com/EOSIO/eos/pull/7770)) Net plugin sync fix -- ([#7717](https://github.com/EOSIO/eos/pull/7717)) Support for v2 snapshots with pending producer schedules -- ([#7795](https://github.com/EOSIO/eos/pull/7795)) Hardcode initial eosio ABI: #7794 -- ([#7792](https://github.com/EOSIO/eos/pull/7792)) Restore default logging if logging.json is removed when SIGHUP. -- ([#7791](https://github.com/EOSIO/eos/pull/7791)) Producer plugin -- ([#7786](https://github.com/EOSIO/eos/pull/7786)) Remove redundant work from net plugin -- ([#7785](https://github.com/EOSIO/eos/pull/7785)) Optimize block log usage -- ([#7812](https://github.com/EOSIO/eos/pull/7812)) Add IMPORTANT file and update README - develop -- ([#7820](https://github.com/EOSIO/eos/pull/7820)) rename IMPORTANT to IMPORTANT.md - develop -- ([#7809](https://github.com/EOSIO/eos/pull/7809)) Correct cpu_usage calculation when more than one signature -- ([#7803](https://github.com/EOSIO/eos/pull/7803)) callback support for checktime timer expiry -- ([#7838](https://github.com/EOSIO/eos/pull/7838)) Bandwidth - develop -- ([#7845](https://github.com/EOSIO/eos/pull/7845)) Deprecate network version match - develop -- ([#7700](https://github.com/EOSIO/eos/pull/7700)) [develop] Travis CI + Buildkite 3.0 -- ([#7825](https://github.com/EOSIO/eos/pull/7825)) apply_block optimization -- ([#7849](https://github.com/EOSIO/eos/pull/7849)) Increase Contracts Builder Timeout + Fix $SKIP_MAC -- ([#7854](https://github.com/EOSIO/eos/pull/7854)) Net plugin sync -- ([#7860](https://github.com/EOSIO/eos/pull/7860)) [develop] Ensure release flag is added to all builds. -- ([#7873](https://github.com/EOSIO/eos/pull/7873)) [develop] Mac Builder Boost Fix -- ([#7868](https://github.com/EOSIO/eos/pull/7868)) cleos get actions -- ([#7774](https://github.com/EOSIO/eos/pull/7774)) update WAVM to be compatible with LLVM 7 through 9 -- ([#7864](https://github.com/EOSIO/eos/pull/7864)) Add output of build info on nodeos startup -- ([#7881](https://github.com/EOSIO/eos/pull/7881)) [develop] Ensure Artfacts Upload on Failed Tests -- ([#7886](https://github.com/EOSIO/eos/pull/7886)) promote read-only disablement log from net_plugin to warn level -- ([#7887](https://github.com/EOSIO/eos/pull/7887)) print unix socket path when there is an error starting unix socket server -- ([#7889](https://github.com/EOSIO/eos/pull/7889)) Update docker builder tag -- ([#7891](https://github.com/EOSIO/eos/pull/7891)) Fix exit crash - develop -- ([#7877](https://github.com/EOSIO/eos/pull/7877)) Create Release Build Test -- ([#7883](https://github.com/EOSIO/eos/pull/7883)) Add Support for eosio-test-stability Pipeline -- ([#7903](https://github.com/EOSIO/eos/pull/7903)) adds support for builder priority queues -- ([#7853](https://github.com/EOSIO/eos/pull/7853)) change behavior of recover_key to better support variable length keys -- ([#7901](https://github.com/EOSIO/eos/pull/7901)) [develop] Add Trigger for LRTs and Multiversion Tests Post PR -- ([#7914](https://github.com/EOSIO/eos/pull/7914)) [Develop] Forked PR fix -- ([#7923](https://github.com/EOSIO/eos/pull/7923)) return error when attempting to remove key from YubiHSM wallet -- ([#7910](https://github.com/EOSIO/eos/pull/7910)) [Develop] Updated anka plugin, added failover for registries, and added sleep fix for git clone/networking bug -- ([#7926](https://github.com/EOSIO/eos/pull/7926)) Better error check in test -- ([#7919](https://github.com/EOSIO/eos/pull/7919)) decouple wavm runtime from being required & initial support for platform specific wasm runtimes -- ([#7927](https://github.com/EOSIO/eos/pull/7927)) Fix Release Build Type for macOS on Travis CI -- ([#7931](https://github.com/EOSIO/eos/pull/7931)) Fix intermittent crash on exit when port already in use - develop -- ([#7930](https://github.com/EOSIO/eos/pull/7930)) use -fdiagnostics-color=always even for clang -- ([#7933](https://github.com/EOSIO/eos/pull/7933)) [Develop] Support all BK/Travis cases in Submodule Regression Script -- ([#7943](https://github.com/EOSIO/eos/pull/7943)) Change eosio-launcher enable-gelf-logging argument default to false. -- ([#7946](https://github.com/EOSIO/eos/pull/7946)) Forked chain test error statement - develop -- ([#7948](https://github.com/EOSIO/eos/pull/7948)) net_plugin correctly handle unknown_block_exception - develop -- ([#7954](https://github.com/EOSIO/eos/pull/7954)) remove bad semicolon (in unused but compiled code) -- ([#7952](https://github.com/EOSIO/eos/pull/7952)) Unable to Create Block Log Index #7865 -- ([#7953](https://github.com/EOSIO/eos/pull/7953)) Refactor producer plugin start_block - develop -- ([#7841](https://github.com/EOSIO/eos/pull/7841)) 7646 chain id in blog -- ([#7958](https://github.com/EOSIO/eos/pull/7958)) [develop] Fix Mac builds on Travis -- ([#7962](https://github.com/EOSIO/eos/pull/7962)) set immutable chain_id during construction of controller -- ([#7957](https://github.com/EOSIO/eos/pull/7957)) Upgrade to Boost 1.71.0 -- ([#7971](https://github.com/EOSIO/eos/pull/7971)) Net plugin unexpected block - develop -- ([#7967](https://github.com/EOSIO/eos/pull/7967)) support unix socket HTTP server for nodeos -- ([#7947](https://github.com/EOSIO/eos/pull/7947)) Function body code size test -- ([#7955](https://github.com/EOSIO/eos/pull/7955)) EOSIO WASM Spec tests -- ([#7978](https://github.com/EOSIO/eos/pull/7978)) use the LLVM 7 library provided by SCL on CentOS7 -- ([#7983](https://github.com/EOSIO/eos/pull/7983)) port consolidated security fixes for 1.8.4 to develop; add unit tests associated with consolidated security fixes for 1.8.1 -- ([#7986](https://github.com/EOSIO/eos/pull/7986)) Remove unnecessary comment -- ([#7985](https://github.com/EOSIO/eos/pull/7985)) more bug fixes with chain_id in state changes -- ([#7974](https://github.com/EOSIO/eos/pull/7974)) Experimental/wb2 jit -- ([#7989](https://github.com/EOSIO/eos/pull/7989)) Correct designator order for field of get_table_rows_params -- ([#7992](https://github.com/EOSIO/eos/pull/7992)) move wasm_allocator from wasm_interface to controller -- ([#7995](https://github.com/EOSIO/eos/pull/7995)) new timeout to handle when two jobs on the same host are maxing their… -- ([#7993](https://github.com/EOSIO/eos/pull/7993)) update eos-vm to latest develop, fix issues with instantiation limit … -- ([#7991](https://github.com/EOSIO/eos/pull/7991)) missing block log chain id unit tests -- ([#8001](https://github.com/EOSIO/eos/pull/8001)) Net plugin trx progress - develop -- ([#8003](https://github.com/EOSIO/eos/pull/8003)) update eos-vm ref -- ([#7988](https://github.com/EOSIO/eos/pull/7988)) Net plugin version match -- ([#8004](https://github.com/EOSIO/eos/pull/8004)) bump version -- ([#7975](https://github.com/EOSIO/eos/pull/7975)) EOS-VM Optimized Compiler -- ([#8007](https://github.com/EOSIO/eos/pull/8007)) disallow WAVM with EOS-VM OC -- ([#8010](https://github.com/EOSIO/eos/pull/8010)) Change log level of index write -- ([#8009](https://github.com/EOSIO/eos/pull/8009)) pending incoming order on subjective failure -- ([#8013](https://github.com/EOSIO/eos/pull/8013)) ensure eos-vm-oc headers get installed -- ([#8008](https://github.com/EOSIO/eos/pull/8008)) Increase stability of nodeos_under_min_avail_ram.py - develop -- ([#8015](https://github.com/EOSIO/eos/pull/8015)) two fixes for eosio tester cmake modules -- ([#8019](https://github.com/EOSIO/eos/pull/8019)) [Develop] Change submodule script to see stderr for git commands -- ([#8014](https://github.com/EOSIO/eos/pull/8014)) Retain persisted trx until expired on speculative nodes -- ([#8024](https://github.com/EOSIO/eos/pull/8024)) Add optional ability to disable WASM Spec Tests -- ([#8023](https://github.com/EOSIO/eos/pull/8023)) Make subjective_cpu_leeway a config option -- ([#8025](https://github.com/EOSIO/eos/pull/8025)) Fix build script LLVM symlinking -- ([#8026](https://github.com/EOSIO/eos/pull/8026)) update EOS VM Optimized Compiler naming convention -- ([#8012](https://github.com/EOSIO/eos/pull/8012)) 7939 trim block log v3 support -- ([#8029](https://github.com/EOSIO/eos/pull/8029)) update eos-vm ref and install eos-vm license -- ([#8033](https://github.com/EOSIO/eos/pull/8033)) net_plugin better error for unknown block -- ([#8034](https://github.com/EOSIO/eos/pull/8034)) EOS VM OC license updates -- ([#8042](https://github.com/EOSIO/eos/pull/8042)) [2.0.x] dockerhub | eosio/producer -> eosio/ci -- ([#8050](https://github.com/EOSIO/eos/pull/8050)) Add greylist limit - v2.0.x -- ([#8060](https://github.com/EOSIO/eos/pull/8060)) #8054: fix commas in ship abi -- ([#8072](https://github.com/EOSIO/eos/pull/8072)) nodeos & keosd version reporting - 2.0 -- ([#8071](https://github.com/EOSIO/eos/pull/8071)) Update cleos to support new producer schedule - 2.0 -- ([#8070](https://github.com/EOSIO/eos/pull/8070)) don't rebuild llvm unnecessarily during pinned builds - 2.0 -- ([#8074](https://github.com/EOSIO/eos/pull/8074)) [2.0.x] Upgrade mac anka template to 10.14.6 -- ([#8076](https://github.com/EOSIO/eos/pull/8076)) Handle cases where version_* not specified in CMakeLists.txt - 2.0 -- ([#8088](https://github.com/EOSIO/eos/pull/8088)) [2.0.x] Linux build fleet update -- ([#8091](https://github.com/EOSIO/eos/pull/8091)) report block extensions_type contents in RPC and eosio-blocklog tool - 2.0 -- ([#8105](https://github.com/EOSIO/eos/pull/8105)) Modify --print-default-config to exit with success - 2.0 -- ([#8113](https://github.com/EOSIO/eos/pull/8113)) [2.0.x] WASM Spec Test Step in CI -- ([#8114](https://github.com/EOSIO/eos/pull/8114)) [2.0.x] Mac OSX steps need a min of 1 hour -- ([#8127](https://github.com/EOSIO/eos/pull/8127)) [2.0.x] Move the ensure step into the build step, eliminating the need for templaters -- ([#8144](https://github.com/EOSIO/eos/pull/8144)) fix pinned builds on fresh macOS install - 2.0 -- ([#8149](https://github.com/EOSIO/eos/pull/8149)) [2.0.x] CI platform directories -- ([#8155](https://github.com/EOSIO/eos/pull/8155)) Post State history callback as medium priority - 2.0 -- ([#8173](https://github.com/EOSIO/eos/pull/8173)) ensure GMP is always dynamically linked - 2.0 -- ([#8175](https://github.com/EOSIO/eos/pull/8175)) [2.0.x] Unpinned and WASM test fixes -- ([#8168](https://github.com/EOSIO/eos/pull/8168)) add harden flags to cicd & pinned builds - 2.0 -- ([#8180](https://github.com/EOSIO/eos/pull/8180)) [2.0.x] 10 second sleep to address heavy usage wait-network bug in Anka -- ([#8192](https://github.com/EOSIO/eos/pull/8192)) Reduce logging - 2.0 -- ([#8367](https://github.com/EOSIO/eos/pull/8367)) Add Sync from Genesis Test -- ([#8363](https://github.com/EOSIO/eos/pull/8363)) Fix linking OpenSSL (branch `release/2.0.x`) -- ([#8383](https://github.com/EOSIO/eos/pull/8383)) Escape BUILDKITE_COMMIT to generate tag properly -- ([#8385](https://github.com/EOSIO/eos/pull/8385)) Propagate exceptions out push_block - 2.0 -- ([#8391](https://github.com/EOSIO/eos/pull/8391)) Add eosio-resume-from-state Test -- ([#8393](https://github.com/EOSIO/eos/pull/8393)) Make multiversion protocol test conditional. -- ([#8402](https://github.com/EOSIO/eos/pull/8402)) fix EOS VM OC monitor thread name - 2.0 -- ([#8406](https://github.com/EOSIO/eos/pull/8406)) [2.0.x] Modified Amazon and Centos to use yum install ccache -- ([#8414](https://github.com/EOSIO/eos/pull/8414)) Add better logging of exceptions in emit - 2.0 -- ([#8328](https://github.com/EOSIO/eos/pull/8328)) Fix bios boot python script due to 2.0.x changes -- ([#8293](https://github.com/EOSIO/eos/pull/8293)) Add nodeos/cleos/keosd docs from develop, update README -- ([#8425](https://github.com/EOSIO/eos/pull/8425)) fix discovery of openssl in tester cmake when OPENSSL_ROOT_DIR not set - 2.0 - -## Thanks! - -Special thanks to the community contributors that submitted patches for this release: -- @UMU618 -- @conr2d -- @YordanPavlov -- @baegjae -- @olexiybuyanskyy -- @spartucus -- @rdewilder diff --git a/docs/30_release-notes/index.md b/docs/30_release-notes/index.md deleted file mode 100644 index 94b9a53f52..0000000000 --- a/docs/30_release-notes/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -content_title: EOSIO v2.0.12 Release Notes ---- - -This release contains security updates and miscellaneous fixes. - -## Security updates - -### Consolidated Security Updates for v2.0.12 ([#10264](https://github.com/EOSIO/eos/pull/10264)) -- Apply three-strikes rule to all transaction failures -- Apply unconditional subjective CPU check along with some additional logging -- Provide options to enable subjective CPU billing for P2P and API transactions ,and provide an option to disable it for individual accounts - -This release expands upon the subjective CPU billing introduced in ([v2.0.10](https://github.com/EOSIO/eos/tree/v2.0.10)). Subjective billing (disabled by default) can now be applied to transactions that come in from either P2P connections, API requests, or both. By setting `disable-subjective-billing` to `false` both P2P and API transactions will have subjective CPU billing applied. Using `disable-subjective-p2p-billing` and/or `disable-subjective-api-billing` will allow subjective CPU billing to be enabled/disabled for P2P transactions or API transactions respectively. Another option , `disable-subjective-account-billing = `, is used to selectively disable subjective CPU billing for certain accounts while applying subjective CPU billing to all other accounts. - -`cleos get account` is enhanced to report `subjective cpu bandwidth`, which contains used subjective CPU billing in microseconds for a particular account on a given node. - -Note: These security updates are relevant to all nodes on EOSIO blockchain networks. - - -## Other changes -- ([#10155](https://github.com/EOSIO/eos/pull/10155)) [2.0.x] Improve timeouts occurring on Anka builds. -- ([#10171](https://github.com/EOSIO/eos/pull/10171)) Wlb/ctest generalization for parameter tests 2.0.x -- ([#10233](https://github.com/EOSIO/eos/pull/10233)) Support Running Version Tests on Fresh OS Installs -- ([#10244](https://github.com/EOSIO/eos/pull/10244)) migrate boost downloads from BinTray to JFrog Artifactory - 2.0 -- ([#10250](https://github.com/EOSIO/eos/pull/10250)) Rel 2.0.x: Subjective CPU billing cleos enhancement and adding subjective_cpu_bill to /v1/chain/get_account result -## Documentation -- ([#10186](https://github.com/EOSIO/eos/pull/10186)) Add EOSIO 2.0.11 release notes to dev portal - 2.0 diff --git a/docs/index.md b/docs/index.md index 9cfcdb8292..8acf1ecb74 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,21 +1,21 @@ --- -content_title: EOSIO Overview +content_title: Mandel Overview --- -EOSIO is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. EOSIO comes with a number of programs. The primary ones included in EOSIO are the following: +Mandel is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. Mandel comes with a number of programs. The primary ones included in Mandel are the following: -* [Nodeos](01_nodeos/index.md) (node + eos = nodeos) - Core service daemon that runs a node for block production, API endpoints, or local development. -* [Cleos](02_cleos/index.md) (cli + eos = cleos) - Command line interface to interact with the blockchain (via `nodeos`) and manage wallets (via `keosd`). -* [Keosd](03_keosd/index.md) (key + eos = keosd) - Component that manages EOSIO keys in wallets and provides a secure enclave for digital signing. +* [Nodeos](01_nodeos/index.md) - Core service daemon that runs a node for block production, API endpoints, or local development. +* [Cleos](02_cleos/index.md) - Command line interface to interact with the blockchain (via `nodeos`) and manage wallets (via `keosd`). +* [Keosd](03_keosd/index.md) - Component that manages Mandel keys in wallets and provides a secure enclave for digital signing. The basic relationship between these components is illustrated in the diagram below. -![EOSIO components](eosio_components.png) +![Mandel components](mandel_components.png) -Additional EOSIO Resources: -* [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. -* [Upgrade Guide](20_upgrade-guide/index.md) - EOSIO version/protocol upgrade guide. -* [Release Notes](30_release-notes/index.md) - All release notes for this EOSIO version. +Additional Mandel Resources: +* [Mandel Utilities](10_utilities/index.md) - Utilities that complement the Mandel software. +* [Upgrade Guide](20_upgrade-guide/index.md) - Mandel version/protocol upgrade guide. +* [Release Notes](30_release-notes/index.md) - All release notes for this Mandel version. [[info | What's Next?]] -| [Install the EOSIO Software](00_install/index.md) before exploring the sections above. +| [Install the Mandel Software](00_install/index.md) before exploring the sections above. diff --git a/docs/eosio_components.png b/docs/mandel_components.png similarity index 100% rename from docs/eosio_components.png rename to docs/mandel_components.png From 4c8f1fd39f213791d67a498923339bdccd617169 Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Thu, 7 Jul 2022 08:16:58 -0400 Subject: [PATCH 095/111] Fixes added link to DUNE --- docs/00_install/01_build-from-source/index.md | 122 +++++++++++++----- docs/00_install/index.md | 8 +- .../02_usage/01_nodeos-configuration.md | 5 +- .../03_development-environment/index.md | 4 +- 4 files changed, 103 insertions(+), 36 deletions(-) diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 7e9bdfbc44..31a3888b4b 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -4,53 +4,117 @@ content_title: Build Mandel from Source The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests. -## Building Mandel +### Building From Source +Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured. Notable requirements to build are: +* C++17 compiler and standard library +* boost 1.67+ +* CMake 3.8+ +* (for Linux only) LLVM 7 - 11 (newer versions do not work) + +A few other common libraries are tools also required such as openssl 1.1+, libcurl, curl, libusb, GMP, Python 3, and zlib. + +**A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes. + +Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different mandel versions (mandel requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot). + +#### Building Pinned Build Binary Packages +In the directory `/scripts` you will find the two scripts `install_deps.sh` and `pinned_build.sh`. If you haven't installed build dependencies then run `install_deps.sh`. Then run `pinned_build.sh `. + +The dependencies directory is where the script will pull the C++ dependencies that need to be built with the pinned compiler for building the pinned binaries for binary packaging. + +The binary package will be produced in the mandel build directory that was supplied. + +#### Manual (non "pinned") Build Instructions + +
+ Ubuntu 20.04 & 22.04 Build Instructions + +Install required dependencies: +``` +apt-get update && apt-get install \ + build-essential \ + cmake \ + curl \ + git \ + libboost-all-dev \ + libcurl4-openssl-dev \ + libgmp-dev \ + libssl-dev \ + libusb-1.0-0-dev \ + llvm-11-dev \ + pkg-config +``` +and perform the build: ``` git submodule update --init --recursive mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release .. -make -j $(nproc) +make -j $(nproc) package ``` +
-We support the following CMake options: +
+ Ubuntu 18.04 Build Instructions + +Install required dependencies. You will need to build Boost from source on this distribution. ``` --DCMAKE_CXX_COMPILER_LAUNCHER=ccache Speed up builds --DCMAKE_C_COMPILER_LAUNCHER=ccache Speed up builds --DCMAKE_BUILD_TYPE=DEBUG Debug builds --DDISABLE_WASM_SPEC_TESTS=yes Speed up builds and skip many tests --DCMAKE_INSTALL_PREFIX=/foo/bar Where to install to --DENABLE_OC=no Disable OC support; useful when this repo is used - as a library --GNinja Use ninja instead of make - (faster on high-core-count machines) +apt-get update && apt-get install \ + build-essential \ + cmake \ + curl \ + g++-8 \ + git \ + libcurl4-openssl-dev \ + libgmp-dev \ + libssl-dev \ + libusb-1.0-0-dev \ + llvm-7-dev \ + pkg-config \ + python3 \ + zlib1g-dev + +curl -L https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 | tar jx && \ + cd boost_1_79_0 && \ + ./bootstrap.sh --prefix=$HOME/boost1.79 && \ + ./b2 --with-iostreams --with-date_time --with-filesystem --with-system \ + --with-program_options --with-chrono --with-test -j$(nproc) install && \ + cd .. ``` - -I highly recommend the ccache options. They don't speed up the first clean build, but they speed up future clean builds after the first build. - -### Running tests - +and perform the build: ``` +git submodule update --init --recursive +mkdir build cd build +cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 \ + -DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release .. \ +make -j $(nproc) package +``` +After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software. +
-# Runs parallelizable tests in parallel. This runs much faster when -# -DDISABLE_WASM_SPEC_TESTS=yes is used. -ctest -j $(nproc) -LE "nonparallelizable_tests|long_running_tests" -E "full-version-label-test|release-build-test|print-build-info-test" +### Running Tests -# These tests can't run in parallel. -ctest -L "nonparallelizable_tests" +When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel. -# These tests can't run in parallel. They also take a long time to run. -ctest -L "long_running_tests" ``` +cd build -## Other Compilers +# "parallelizable tests": the minimum test set that should be run +ctest -j $(nproc) -LE _tests -To override `clang`'s default compiler toolchain, add these flags to the `cmake` command within the above instructions: +# Also consider running the WASM spec tests for more coverage +ctest -j $(nproc) -L wasm_spec_tests +``` -`-DCMAKE_CXX_COMPILER=/path/to/c++ -DCMAKE_C_COMPILER=/path/to/cc` +Some other tests are available and recommended but be aware they can be sensitive to other software running on the same host and they may **SIGKILL** other nodeos instances running on the host. +``` +cd build -## Debug Builds +# These tests can't run in parallel but are recommended. +ctest -L "nonparallelizable_tests" -For a debug build, add `-DCMAKE_BUILD_TYPE=Debug`. Other common build types include `Release` and `RelWithDebInfo`. +# These tests can't run in parallel. They also take a long time to run. +ctest -L "long_running_tests" +``` \ No newline at end of file diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 7ed71bdcdb..4d39062839 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -15,4 +15,10 @@ Mandel currently supports the following operating systems: 3. Ubuntu 22.04 [[info | Note]] -| It may be possible to install Mandel on other Unix-based operating systems. This is not officially supported, though. +| It may be possible to build and install Mandel on other Unix-based operating systems. This is not officially supported, though. + +## Docker Utilities for Node Execution (D.U.N.E.) + +If you are using different operating system or prefer not to build Mandel from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring Mandel and doing contract development pretty much instantly + +* [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/eosnetworkfoundation/DUNE) diff --git a/docs/01_nodeos/02_usage/01_nodeos-configuration.md b/docs/01_nodeos/02_usage/01_nodeos-configuration.md index 7ed18bc8f6..1ab5db8933 100644 --- a/docs/01_nodeos/02_usage/01_nodeos-configuration.md +++ b/docs/01_nodeos/02_usage/01_nodeos-configuration.md @@ -10,9 +10,8 @@ For example, the CLI option `--plugin eosio::chain_api_plugin` can also be set b ## `config.ini` location -The default `config.ini` can be found in the following folders: -- Mac OS: `~/Library/Application Support/eosio/nodeos/config` -- Linux: `~/.local/share/eosio/nodeos/config` +The default `config.ini` can be found in the following folder on Linux: +`~/.local/share/eosio/nodeos/config` A custom `config.ini` file can be set by passing the `nodeos` option `--config path/to/config.ini`. diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index c09829aba9..6ced9ef847 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -19,9 +19,7 @@ While this option can technically be used for smart contract development, it may ## Official Testnet -The official testnet is available for testing Mandel dApps and smart contracts: - -* [testnet.eos.io](https://testnet.eos.io/) +The official testnet for testing Mandel dApps and smart contracts will be available soon ## Third-Party Testnets From 0da59704a62c9969779112aa29f0de46c1b57264 Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Thu, 7 Jul 2022 12:57:03 -0400 Subject: [PATCH 096/111] Mandel -> EOSIO --- docs/00_install/01_build-from-source/index.md | 2 +- docs/00_install/index.md | 12 ++++++------ .../02_node-setups/00_producing-node.md | 8 ++++---- .../02_node-setups/01_non-producing-node.md | 8 ++++---- .../00_local-single-node-testnet.md | 4 ++-- .../01_local-multi-node-testnet.md | 8 ++++---- .../03_development-environment/index.md | 4 ++-- .../01_nodeos/03_plugins/chain_plugin/index.md | 2 +- .../01_nodeos/03_plugins/login_plugin/index.md | 2 +- .../03_plugins/producer_plugin/index.md | 4 ++-- ...10_how-to-fast-start-without-old-history.md | 2 +- ...ow-to-replay-or-resync-with-full-history.md | 2 +- ...how-to-create-snapshot-with-full-history.md | 2 +- ...ow-to-restore-snapshot-with-full-history.md | 2 +- .../03_plugins/trace_api_plugin/index.md | 8 ++++---- .../03_plugins/txn_test_gen_plugin/index.md | 2 +- docs/01_nodeos/06_logging/index.md | 4 ++-- .../07_concepts/05_storage-and-read-modes.md | 6 +++--- .../07_concepts/10_context-free-data/index.md | 2 +- docs/01_nodeos/08_troubleshooting/index.md | 4 ++-- docs/01_nodeos/index.md | 6 +++--- .../02_how-to-guides/how-to-create-a-wallet.md | 2 +- .../how-to-create-an-account.md | 10 +++++----- .../how-to-create-key-pairs.md | 6 +++--- .../how-to-delegate-CPU-resource.md | 6 +++--- .../how-to-delegate-net-resource.md | 6 +++--- .../how-to-deploy-a-smart-contract.md | 2 +- .../how-to-get-account-information.md | 10 +++++----- .../how-to-get-block-information.md | 4 ++-- .../how-to-get-transaction-information.md | 6 +++--- .../02_how-to-guides/how-to-import-a-key.md | 4 ++-- .../how-to-list-all-key-pairs.md | 4 ++-- .../03_command-reference/create/account.md | 2 +- .../03_command-reference/net/connect.md | 2 +- .../03_command-reference/net/disconnect.md | 2 +- .../02_cleos/03_command-reference/net/peers.md | 2 +- .../03_command-reference/net/status.md | 2 +- .../03_command-reference/set/set-account.md | 2 +- docs/02_cleos/04_troubleshooting.md | 2 +- docs/02_cleos/index.md | 6 +++--- docs/03_keosd/index.md | 4 ++-- docs/10_utilities/index.md | 6 +++--- docs/index.md | 18 +++++++++--------- 43 files changed, 101 insertions(+), 101 deletions(-) diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 31a3888b4b..343ad80ccc 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -1,5 +1,5 @@ --- -content_title: Build Mandel from Source +content_title: Build EOSIO from Source --- The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests. diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 4d39062839..0bfa20716f 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -1,24 +1,24 @@ --- -content_title: Mandel Software Installation +content_title: EOSIO Software Installation --- -The best way to install and use the Mandel software is to build it from source: +The best way to install and use the EOSIO software is to build it from source: -* [Build Mandel from Source](01_build-from-source/index.md) +* [Build EOSIO from Source](01_build-from-source/index.md) ## Supported Operating Systems -Mandel currently supports the following operating systems: +EOSIO currently supports the following operating systems: 1. Ubuntu 18.04 2. Ubuntu 20.04 3. Ubuntu 22.04 [[info | Note]] -| It may be possible to build and install Mandel on other Unix-based operating systems. This is not officially supported, though. +| It may be possible to build and install EOSIO on other Unix-based operating systems. This is not officially supported, though. ## Docker Utilities for Node Execution (D.U.N.E.) -If you are using different operating system or prefer not to build Mandel from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring Mandel and doing contract development pretty much instantly +If you are using different operating system or prefer not to build EOSIO from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring EOSIO and doing contract development pretty much instantly * [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/eosnetworkfoundation/DUNE) diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index d6950fc4c7..f9555ba262 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -7,12 +7,12 @@ content_title: Producing Node Setup ## Goal -This section describes how to set up a producing node within the Mandel network. A producing node, as its name implies, is a node that is configured to produce blocks in an `Mandel` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). +This section describes how to set up a producing node within the EOSIO network. A producing node, as its name implies, is a node that is configured to produce blocks in an `EOSIO` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). ## Before you begin -* [Install the Mandel software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built Mandel using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps @@ -49,7 +49,7 @@ producer-name = youraccount You will need to set the private key for your producer. The public key should have an authority for the producer account defined above. `signature-provider` is defined with a 3-field tuple: -* `public-key` - A valid Mandel public key in form of a string. +* `public-key` - A valid EOSIO public key in form of a string. * `provider-spec` - It's a string formatted like : * `provider-type` - KEY or KEOSD diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index 6ad52526e1..77365ef18f 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -4,12 +4,12 @@ content_title: Non-producing Node Setup ## Goal -This section describes how to set up a non-producing node within the Mandel network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `Mandel` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. +This section describes how to set up a non-producing node within the EOSIO network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `EOSIO` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. ## Before you begin -* [Install the Mandel software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built Mandel using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps @@ -37,4 +37,4 @@ nodeos ... --p2p-peer-address=106.10.42.238:9876 ### 2. Enable one or more available plugins -Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the Mandel RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. +Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the EOSIO RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index f1e7f8be2a..53ca22048c 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -12,8 +12,8 @@ This section describes how to set up a single-node blockchain configuration runn ## Before you begin -* [Install the Mandel software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built Mandel using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 2794ad9c79..9bccdf0fed 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -10,7 +10,7 @@ This section describes how to set up a multi-node blockchain configuration runni ## Before you begin -* [Install the Mandel software](../../../00_install/index.md) before starting this section. +* [Install the EOSIO software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -23,7 +23,7 @@ Open four "terminal" windows and perform the following steps: - [Steps](#steps) - [1. Start the Wallet Manager](#1-start-the-wallet-manager) - [2. Create a Default Wallet](#2-create-a-default-wallet) - - [3. Loading the Mandel Key](#3-loading-the-mandel-key) + - [3. Loading the EOSIO Key](#3-loading-the-mandel-key) - [4. Start the First Producer Node](#4-start-the-first-producer-node) - [5. Start the Second Producer Node](#5-start-the-second-producer-node) - [6. Get Nodes Info](#6-get-nodes-info) @@ -69,7 +69,7 @@ Without password imported keys will not be retrievable. `keosd` will generate some status output in its window. We will continue to use this second window for subsequent `cleos` commands. -### 3. Loading the Mandel Key +### 3. Loading the EOSIO Key The private blockchain launched in the steps above is created with a default initial key which must be loaded into the wallet. @@ -93,7 +93,7 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node -The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the Mandel binaries. +The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the EOSIO binaries. To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index 6ced9ef847..fcb7f7b463 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -19,11 +19,11 @@ While this option can technically be used for smart contract development, it may ## Official Testnet -The official testnet for testing Mandel dApps and smart contracts will be available soon +The official testnet for testing EOSIO dApps and smart contracts will be available soon ## Third-Party Testnets -The following third-party testnets are available for testing Mandel dApps and smart contracts: +The following third-party testnets are available for testing EOSIO dApps and smart contracts: * Jungle Testnet [monitor](https://monitor.jungletestnet.io/), [website](https://jungletestnet.io/) * [CryptoKylin Testnet](https://www.cryptokylin.io/) diff --git a/docs/01_nodeos/03_plugins/chain_plugin/index.md b/docs/01_nodeos/03_plugins/chain_plugin/index.md index 3815ef6346..b60b394dd3 100644 --- a/docs/01_nodeos/03_plugins/chain_plugin/index.md +++ b/docs/01_nodeos/03_plugins/chain_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `chain_plugin` is a core plugin required to process and aggregate chain data on a Mandel node. +The `chain_plugin` is a core plugin required to process and aggregate chain data on a EOSIO node. ## Usage diff --git a/docs/01_nodeos/03_plugins/login_plugin/index.md b/docs/01_nodeos/03_plugins/login_plugin/index.md index 74d0b2a205..68df9d4c1e 100644 --- a/docs/01_nodeos/03_plugins/login_plugin/index.md +++ b/docs/01_nodeos/03_plugins/login_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `login_plugin` supports the concept of applications authenticating with the Mandel blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. +The `login_plugin` supports the concept of applications authenticating with the EOSIO blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. ## Usage diff --git a/docs/01_nodeos/03_plugins/producer_plugin/index.md b/docs/01_nodeos/03_plugins/producer_plugin/index.md index ac6475e761..14b5be24ba 100644 --- a/docs/01_nodeos/03_plugins/producer_plugin/index.md +++ b/docs/01_nodeos/03_plugins/producer_plugin/index.md @@ -49,7 +49,7 @@ Config Options for eosio::producer_plugin: = Where: is a string form of - a vaild Mandel public + a vaild EOSIO public key is a string in the @@ -59,7 +59,7 @@ Config Options for eosio::producer_plugin: is KEY, or KEOSD KEY: is a string form of - a valid Mandel + a valid EOSIO private key which maps to the provided public key diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md index facd99cbac..4e1f534483 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md @@ -8,7 +8,7 @@ This procedure records the current chain state and future history, without previ ## Before you begin -* Make sure [Mandel is installed](../../../00_install/index.md). +* Make sure [EOSIO is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md index b1ada13126..9f0a7308f0 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md @@ -8,7 +8,7 @@ This procedure records the entire chain history. ## Before you begin -* Make sure [Mandel is installed](../../../00_install/index.md). +* Make sure [EOSIO is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md index 712b48c7a5..19d69e9c28 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure creates a database containing the chain state, with full history ## Before you begin -* Make sure [Mandel is installed](../../../00_install/index.md). +* Make sure [EOSIO is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md index 582ea6b6c2..6eb2e76db4 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure restores an existing snapshot with full history, so the node can ## Before you begin -* Make sure [Mandel is installed](../../../00_install/index.md). +* Make sure [EOSIO is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md index 696a397709..160e2aa2e5 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md @@ -5,11 +5,11 @@ The `trace_api_plugin` provides a consumer-focused long-term API for retrieving ## Purpose -While integrating applications such as block explorers and exchanges with a Mandel blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: +While integrating applications such as block explorers and exchanges with a EOSIO blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: * A transcript of retired actions and related metadata * A consumer-focused long-term API to retrieve blocks -* Maintainable resource commitments at the Mandel nodes +* Maintainable resource commitments at the EOSIO nodes Therefore, one crucial goal of the `trace_api_plugin` is to improve the maintenance of node resources (file system, disk space, memory used, etc.). This goal is different from the existing `history_plugin` which provides far more configurable filtering and querying capabilities, or the existing `state_history_plugin` which provides a binary streaming interface to access structural chain data, action data, as well as state deltas. @@ -101,7 +101,7 @@ nodeos ... --plugin eosio::chain_plugin [options] \ ## Configuration Example -Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some Mandel reference contracts: +Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some EOSIO reference contracts: ```sh nodeos --data-dir data_dir --config-dir config_dir --trace-dir traces_dir @@ -191,7 +191,7 @@ If resource usage cannot be effectively managed via the `trace-minimum-irreversi ## Manual Maintenance -The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed Mandel system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). +The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed EOSIO system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). [[info | For node operators]] | Node operators can take full control over the lifetime of the historical data available in their nodes via the `trace-api-plugin` and the `trace-minimum-irreversible-history-blocks` and `trace-minimum-uncompressed-irreversible-history-blocks` options in conjunction with any external filesystem resource manager. diff --git a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md index 9150e4fd1b..efbb5a0204 100644 --- a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md +++ b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md @@ -4,7 +4,7 @@ The `txn_test_gen_plugin` is used for transaction test purposes. [[info | For More Information]] -For more information, check the [txn_test_gen_plugin/README.md](https://github.com/eosnetworkfoundation/mandel/tree/main/plugins/txn_test_gen_plugin) on the Mandel/eos repository. +For more information, check the [txn_test_gen_plugin/README.md](https://github.com/eosnetworkfoundation/mandel/tree/main/plugins/txn_test_gen_plugin) on the EOSIO/eos repository. ## Usage diff --git a/docs/01_nodeos/06_logging/index.md b/docs/01_nodeos/06_logging/index.md index 0b1fdb8c7d..8a7670e7fb 100644 --- a/docs/01_nodeos/06_logging/index.md +++ b/docs/01_nodeos/06_logging/index.md @@ -6,7 +6,7 @@ Logging for `nodeos` is controlled by the `logging.json` file. CLI options can b ## Appenders -The logging library built into Mandel supports two appender types: +The logging library built into EOSIO supports two appender types: - [Console](#console) - [GELF](#gelf) (Graylog Extended Log Format) @@ -74,7 +74,7 @@ Example: ## Loggers -The logging library built into Mandel currently supports the following loggers: +The logging library built into EOSIO currently supports the following loggers: - `default` - the default logger, always enabled. - `net_plugin_impl` - detailed logging for the net plugin. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index b682285906..df2a872729 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -2,7 +2,7 @@ content_title: Storage and Read Modes --- -The Mandel platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) +The EOSIO platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) ## Blockchain State and Storage @@ -15,9 +15,9 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain * The `pending block` is an in memory block containing transactions as they are processed and pushed into the block; this will/may eventually become the head block. If the `nodeos` instance is the producing node, the pending block is distributed to other `nodeos` instances. * Outside the chain state, block data is cached in RAM until it becomes final/irreversible; especifically the signed block itself. After the last irreversible block (LIB) catches up to the block, that block is then retrieved from the irreversible blocks log. -## Mandel Interfaces +## EOSIO Interfaces -Mandel provides a set of [services](../../) and [interfaces](https://developers.eos.io/manuals/eosio.cdt/latest/files) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +EOSIO provides a set of [services](../../) and [interfaces](https://developers.eos.io/manuals/eosio.cdt/latest/files) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API diff --git a/docs/01_nodeos/07_concepts/10_context-free-data/index.md b/docs/01_nodeos/07_concepts/10_context-free-data/index.md index cb894d55ee..0a31072bcb 100644 --- a/docs/01_nodeos/07_concepts/10_context-free-data/index.md +++ b/docs/01_nodeos/07_concepts/10_context-free-data/index.md @@ -4,7 +4,7 @@ link_text: Context-Free Data --- ## Overview -The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, Mandel blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. +The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, EOSIO blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. ## Concept The goal of context-free data is to allow blockchain applications the option to store non-essential information within a transaction. Some examples of context-free data include: diff --git a/docs/01_nodeos/08_troubleshooting/index.md b/docs/01_nodeos/08_troubleshooting/index.md index be225e3070..92db833328 100644 --- a/docs/01_nodeos/08_troubleshooting/index.md +++ b/docs/01_nodeos/08_troubleshooting/index.md @@ -28,7 +28,7 @@ Command Line Options for eosio::chain_plugin: Start `nodeos` with `--shared-memory-size-mb 1024`. A 1 GB shared memory file allows approximately half a million transactions. -### What version of Mandel am I running/connecting to? +### What version of EOSIO am I running/connecting to? If defaults can be used, then `cleos get info` will output a block that contains a field called `server_version`. If your `nodeos` is not using the defaults, then you need to know the URL of the `nodeos`. In that case, use the following with your `nodeos` URL: @@ -44,4 +44,4 @@ cleos --url http://localhost:8888 get info | grep server_version ### Error 3070000: WASM Exception Error -If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot a Mandel-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). +If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot a EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). diff --git a/docs/01_nodeos/index.md b/docs/01_nodeos/index.md index 21b8e045a1..9877dc16a9 100644 --- a/docs/01_nodeos/index.md +++ b/docs/01_nodeos/index.md @@ -4,11 +4,11 @@ content_title: Nodeos ## Introduction -`nodeos` is the core service daemon that runs on every Mandel node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. +`nodeos` is the core service daemon that runs on every EOSIO node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. ## Installation -`nodeos` is distributed as part of the [Mandel software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [Mandel Software Installation](../00_install/index.md) section. +`nodeos` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [EOSIO Software Installation](../00_install/index.md) section. ## Explore @@ -23,4 +23,4 @@ Navigate the sections below to configure and use `nodeos`. * [Troubleshooting](08_troubleshooting/index.md) - Common `nodeos` troubleshooting questions. [[info | Access Node]] -| A local or remote Mandel access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. +| A local or remote EOSIO access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md index f5a6528f0b..4973217f16 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. * Understand [Accounts and Permissions](https://developers.eos.io/welcome/latest/protocol-guides/accounts_and_permissions) in the protocol documents. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md index 528c500a37..20fc565847 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to create a new Mandel blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. +This how-to guide provides instructions on how to create a new EOSIO blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. The example in this how-to guide creates a new account named **bob**, authorized by the default system account **eosio**, using the `cleos` CLI tool. @@ -10,8 +10,8 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| The cleos tool is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install the cleos tool. -* Learn about [Mandel Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) +| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +* Learn about [EOSIO Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) * Learn about Asymmetric Cryptography - [public key](https://developers.eos.io/welcome/v2.1/glossary/index#public-key) and [private key](https://developers.eos.io/welcome/v2.1/glossary/index#private-key) pairs. * Create public/private keypairs for the `owner` and `active` permissions of an account. @@ -34,7 +34,7 @@ cleos create account eosio bob EOS87TQktA5RVse2EguhztfQVEh6XXxBmgkU8b4Y5YnGvtYAo * `bob` = the name of the new account conforming to [account naming conventions](https://developers.eos.io/welcome/v2.1/protocol-guides/accounts_and_permissions#2-accounts) * `EOS87TQ...AoLGNN` = the owner public key or permission level for the new account (**required**) [[info | Note]] -| To create a new account in the Mandel blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created Mandel blockchain, the default system account used to create a new account is **eosio**. +| To create a new account in the EOSIO blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created EOSIO blockchain, the default system account used to create a new account is **eosio**. **Example Output** @@ -46,4 +46,4 @@ warning: transaction executed locally, but may not be confirmed by the network y ### Summary -By following these instructions, you are able to create a new Mandel account in your blockchain environment. +By following these instructions, you are able to create a new EOSIO account in your blockchain environment. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md index 385fc6b017..069d14e0d1 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md @@ -1,14 +1,14 @@ ## Overview -This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in a Mandel blockchain. +This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in a EOSIO blockchain. ## Before you begin Make sure you meet the following requirements: * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install the cleos tool. -* Learn about asymmetric cryptography (public and private keypair) in the context of a Mandel blockchain. +| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +* Learn about asymmetric cryptography (public and private keypair) in the context of a EOSIO blockchain. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 606209e3d6..6291e9b284 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a Mandel blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a Mandel blockchain. +* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a EOSIO blockchain. +* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a EOSIO blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index 51ec81b0b9..5c74b7a9a7 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a Mandel blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a Mandel blockchain. +* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a EOSIO blockchain. +* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a EOSIO blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md index ccb970fbf2..b38656bbd7 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md +++ b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md @@ -1,6 +1,6 @@ ## Goal -Deploy a Mandel contract +Deploy a EOSIO contract ## Before you begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md index fabf5045fe..91c399a951 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md @@ -1,15 +1,15 @@ ## Overview -This how-to guide provides instructions on how to query infomation of a Mandel account. The example in this how-to guide retrieves information of the `eosio` account. +This how-to guide provides instructions on how to query infomation of a EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. ## Before you begin * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install the cleos tool. +| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Acquire functional understanding of [Mandel Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) +* Acquire functional understanding of [EOSIO Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) ## Command Reference @@ -28,7 +28,7 @@ cleos get account eosio ``` **Where**: -* `eosio` = The name of the default system account in the Mandel blockchain. +* `eosio` = The name of the default system account in the EOSIO blockchain. **Example Output** @@ -53,4 +53,4 @@ cpu bandwidth: ``` [[info | Account Fields]] -| Depending on the Mandel network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. +| Depending on the EOSIO network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md index ca23c507f0..7efd62427f 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md @@ -10,10 +10,10 @@ Make sure to meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Understand what a [block](https://developers.eos.io/welcome/latest/glossary/index/#block) is and its role in the blockchain. -* Understand the [block lifecycle](https://developers.eos.io/welcome/latest/protocol-guides/consensus_protocol/#5-block-lifecycle) in the Mandel consensus protocol. +* Understand the [block lifecycle](https://developers.eos.io/welcome/latest/protocol-guides/consensus_protocol/#5-block-lifecycle) in the EOSIO consensus protocol. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md index f6e33fe0d8..27b9422701 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to retrieve infomation of a Mandel transaction using a transaction ID. +This how-to guide provides instructions on how to retrieve infomation of a EOSIO transaction using a transaction ID. The example in this how-to retrieves transaction information associated with the creation of the account **bob**. @@ -9,8 +9,8 @@ The example in this how-to retrieves transaction information associated with the Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. -* Understand how transactions work in a Mandel blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +* Understand how transactions work in a EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md index 6e13925fc0..614be5cb59 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md +++ b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in a Mandel blockchain. +This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in a EOSIO blockchain. ## Before you Begin @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet import`](../03_command-reference/wallet/import.md) command. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private key](https://developers.eos.io/welcome/latest/glossary/index/#private-key) is. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md index 7b5703b046..d76430fd5c 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in a Mandel blockchain. +This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in a EOSIO blockchain. The example in this how-to guide displays all public keys and public/private key pairs stored within the existing default wallet. @@ -13,7 +13,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet`](../03_command-reference/wallet/index.md) commands. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private key](https://developers.eos.io/welcome/latest/glossary/index/#private-key) is. ## Command Reference diff --git a/docs/02_cleos/03_command-reference/create/account.md b/docs/02_cleos/03_command-reference/create/account.md index e35d2bf146..976c986f56 100755 --- a/docs/02_cleos/03_command-reference/create/account.md +++ b/docs/02_cleos/03_command-reference/create/account.md @@ -30,7 +30,7 @@ Options: ``` ## Command -A set of Mandel keys is required to create an account. The Mandel keys can be generated by using `cleos create key`. +A set of EOSIO keys is required to create an account. The EOSIO keys can be generated by using `cleos create key`. ```sh cleos create account inita tester EOS4toFS3YXEQCkuuw1aqDLrtHim86Gz9u3hBdcBw5KNPZcursVHq EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA diff --git a/docs/02_cleos/03_command-reference/net/connect.md b/docs/02_cleos/03_command-reference/net/connect.md index 278f3f47c6..be0b2af0b3 100755 --- a/docs/02_cleos/03_command-reference/net/connect.md +++ b/docs/02_cleos/03_command-reference/net/connect.md @@ -26,7 +26,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/disconnect.md b/docs/02_cleos/03_command-reference/net/disconnect.md index f2dfa12c82..29c3039961 100755 --- a/docs/02_cleos/03_command-reference/net/disconnect.md +++ b/docs/02_cleos/03_command-reference/net/disconnect.md @@ -26,7 +26,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/peers.md b/docs/02_cleos/03_command-reference/net/peers.md index c625506c53..2814731c75 100755 --- a/docs/02_cleos/03_command-reference/net/peers.md +++ b/docs/02_cleos/03_command-reference/net/peers.md @@ -25,7 +25,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/status.md b/docs/02_cleos/03_command-reference/net/status.md index 7a8fd4f535..f8f45265ec 100755 --- a/docs/02_cleos/03_command-reference/net/status.md +++ b/docs/02_cleos/03_command-reference/net/status.md @@ -26,7 +26,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the Mandel software. [Installing Mandel](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/set/set-account.md b/docs/02_cleos/03_command-reference/set/set-account.md index 1e682aa485..e4ed9f6e32 100755 --- a/docs/02_cleos/03_command-reference/set/set-account.md +++ b/docs/02_cleos/03_command-reference/set/set-account.md @@ -2,7 +2,7 @@ set parameters dealing with account permissions [[info | JSON input]] -| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the Mandel software. +| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the EOSIO software. ## Positionals - `account` _TEXT_ - The account to set/delete a permission authority for diff --git a/docs/02_cleos/04_troubleshooting.md b/docs/02_cleos/04_troubleshooting.md index 748ac82df3..63250119e9 100644 --- a/docs/02_cleos/04_troubleshooting.md +++ b/docs/02_cleos/04_troubleshooting.md @@ -20,4 +20,4 @@ Replace API_ENDPOINT and PORT with your remote `nodeos` API endpoint detail ## "Missing Authorizations" -That means you are not using the required authorizations. Most likely you are not using correct Mandel account or permission level to sign the transaction +That means you are not using the required authorizations. Most likely you are not using correct EOSIO account or permission level to sign the transaction diff --git a/docs/02_cleos/index.md b/docs/02_cleos/index.md index e2303863af..fbe3ca8d30 100644 --- a/docs/02_cleos/index.md +++ b/docs/02_cleos/index.md @@ -4,11 +4,11 @@ content_title: Cleos ## Introduction -`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test Mandel smart contracts. +`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test EOSIO smart contracts. ## Installation -`cleos` is distributed as part of the [Mandel software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [Mandel Software Installation](../00_install/index.md) section. +`cleos` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [EOSIO Software Installation](../00_install/index.md) section. ## Using Cleos @@ -23,7 +23,7 @@ cleos --help ``` ```console -Command Line Interface to Mandel Client +Command Line Interface to EOSIO Client Usage: cleos [OPTIONS] SUBCOMMAND Options: diff --git a/docs/03_keosd/index.md b/docs/03_keosd/index.md index 99144dd25f..cfd45cb9de 100644 --- a/docs/03_keosd/index.md +++ b/docs/03_keosd/index.md @@ -8,11 +8,11 @@ content_title: Keosd ## Installation -`keosd` is distributed as part of the [Mandel software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [Mandel Software Installation](../00_install/index.md) section. +`keosd` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [EOSIO Software Installation](../00_install/index.md) section. ## Operation When a wallet is unlocked with the corresponding password, `cleos` can request `keosd` to sign a transaction with the appropriate private keys. Also, `keosd` provides support for hardware-based wallets such as Secure Encalve and YubiHSM. [[info | Audience]] -| `keosd` is intended to be used by Mandel developers only. +| `keosd` is intended to be used by EOSIO developers only. diff --git a/docs/10_utilities/index.md b/docs/10_utilities/index.md index d0a078b58e..747c95cb72 100644 --- a/docs/10_utilities/index.md +++ b/docs/10_utilities/index.md @@ -1,9 +1,9 @@ --- -content_title: Mandel Utilities -link_text: Mandel Utilities +content_title: EOSIO Utilities +link_text: EOSIO Utilities --- -This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other Mandel software: +This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other EOSIO software: * [eosio-blocklog](eosio-blocklog.md) - Low-level utility for node operators to interact with block log files. * [trace_api_util](trace_api_util.md) - Low-level utility for performing tasks associated with the [Trace API](../01_nodeos/03_plugins/trace_api_plugin/index.md). diff --git a/docs/index.md b/docs/index.md index 8acf1ecb74..5ccf7dd462 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,21 +1,21 @@ --- -content_title: Mandel Overview +content_title: EOSIO Overview --- -Mandel is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. Mandel comes with a number of programs. The primary ones included in Mandel are the following: +EOSIO is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. EOSIO comes with a number of programs. The primary ones included in EOSIO are the following: * [Nodeos](01_nodeos/index.md) - Core service daemon that runs a node for block production, API endpoints, or local development. * [Cleos](02_cleos/index.md) - Command line interface to interact with the blockchain (via `nodeos`) and manage wallets (via `keosd`). -* [Keosd](03_keosd/index.md) - Component that manages Mandel keys in wallets and provides a secure enclave for digital signing. +* [Keosd](03_keosd/index.md) - Component that manages EOSIO keys in wallets and provides a secure enclave for digital signing. The basic relationship between these components is illustrated in the diagram below. -![Mandel components](mandel_components.png) +![EOSIO components](mandel_components.png) -Additional Mandel Resources: -* [Mandel Utilities](10_utilities/index.md) - Utilities that complement the Mandel software. -* [Upgrade Guide](20_upgrade-guide/index.md) - Mandel version/protocol upgrade guide. -* [Release Notes](30_release-notes/index.md) - All release notes for this Mandel version. +Additional EOSIO Resources: +* [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. +* [Upgrade Guide](20_upgrade-guide/index.md) - EOSIO version/protocol upgrade guide. +* [Release Notes](30_release-notes/index.md) - All release notes for this EOSIO version. [[info | What's Next?]] -| [Install the Mandel Software](00_install/index.md) before exploring the sections above. +| [Install the EOSIO Software](00_install/index.md) before exploring the sections above. From 27cb589ad90e88059ccbea6dadc4e9b55ea5980e Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Thu, 7 Jul 2022 12:59:53 -0400 Subject: [PATCH 097/111] Update "an EOSIO" --- docs/01_nodeos/03_plugins/chain_plugin/index.md | 2 +- docs/01_nodeos/03_plugins/trace_api_plugin/index.md | 2 +- docs/01_nodeos/08_troubleshooting/index.md | 2 +- docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md | 4 ++-- .../02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md | 4 ++-- .../02_cleos/02_how-to-guides/how-to-delegate-net-resource.md | 4 ++-- .../02_how-to-guides/how-to-deploy-a-smart-contract.md | 2 +- .../02_how-to-guides/how-to-get-account-information.md | 2 +- .../02_how-to-guides/how-to-get-transaction-information.md | 4 ++-- docs/02_cleos/02_how-to-guides/how-to-import-a-key.md | 2 +- docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/01_nodeos/03_plugins/chain_plugin/index.md b/docs/01_nodeos/03_plugins/chain_plugin/index.md index b60b394dd3..9da5921080 100644 --- a/docs/01_nodeos/03_plugins/chain_plugin/index.md +++ b/docs/01_nodeos/03_plugins/chain_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `chain_plugin` is a core plugin required to process and aggregate chain data on a EOSIO node. +The `chain_plugin` is a core plugin required to process and aggregate chain data on an EOSIO node. ## Usage diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md index 160e2aa2e5..74d1215ec0 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md @@ -5,7 +5,7 @@ The `trace_api_plugin` provides a consumer-focused long-term API for retrieving ## Purpose -While integrating applications such as block explorers and exchanges with a EOSIO blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: +While integrating applications such as block explorers and exchanges with an EOSIO blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: * A transcript of retired actions and related metadata * A consumer-focused long-term API to retrieve blocks diff --git a/docs/01_nodeos/08_troubleshooting/index.md b/docs/01_nodeos/08_troubleshooting/index.md index 92db833328..409ca6c371 100644 --- a/docs/01_nodeos/08_troubleshooting/index.md +++ b/docs/01_nodeos/08_troubleshooting/index.md @@ -44,4 +44,4 @@ cleos --url http://localhost:8888 get info | grep server_version ### Error 3070000: WASM Exception Error -If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot a EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). +If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md index 069d14e0d1..e3e298aefe 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in a EOSIO blockchain. +This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in an EOSIO blockchain. ## Before you begin @@ -8,7 +8,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos` [[info | Note]] | The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about asymmetric cryptography (public and private keypair) in the context of a EOSIO blockchain. +* Learn about asymmetric cryptography (public and private keypair) in the context of an EOSIO blockchain. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 6291e9b284..155c738bf6 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -14,8 +14,8 @@ Make sure you meet the following requirements: * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a EOSIO blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a EOSIO blockchain. +* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in an EOSIO blockchain. +* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in an EOSIO blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index 5c74b7a9a7..ac26f6e52a 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -14,8 +14,8 @@ Make sure you meet the following requirements: * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in a EOSIO blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in a EOSIO blockchain. +* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in an EOSIO blockchain. +* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in an EOSIO blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md index b38656bbd7..32fcce2c00 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md +++ b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md @@ -1,6 +1,6 @@ ## Goal -Deploy a EOSIO contract +Deploy an EOSIO contract ## Before you begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md index 91c399a951..7dc5f686d0 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to query infomation of a EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. +This how-to guide provides instructions on how to query infomation of an EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. ## Before you begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md index 27b9422701..aaf5fd7e74 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to retrieve infomation of a EOSIO transaction using a transaction ID. +This how-to guide provides instructions on how to retrieve infomation of an EOSIO transaction using a transaction ID. The example in this how-to retrieves transaction information associated with the creation of the account **bob**. @@ -10,7 +10,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand how transactions work in a EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. +* Understand how transactions work in an EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md index 614be5cb59..19a8ee0d7d 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md +++ b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in a EOSIO blockchain. +This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an EOSIO blockchain. ## Before you Begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md index d76430fd5c..7a9bb7348f 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in a EOSIO blockchain. +This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an EOSIO blockchain. The example in this how-to guide displays all public keys and public/private key pairs stored within the existing default wallet. From 287a6e799a0d5a1bdbb58edc6de2791e3901a0a3 Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Thu, 7 Jul 2022 13:08:58 -0400 Subject: [PATCH 098/111] Fixed butchered by md plugin index --- .../01_local-multi-node-testnet.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 9bccdf0fed..698f0414de 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -18,15 +18,12 @@ This section describes how to set up a multi-node blockchain configuration runni Open four "terminal" windows and perform the following steps: -- [Goal](#goal) -- [Before you begin](#before-you-begin) -- [Steps](#steps) - - [1. Start the Wallet Manager](#1-start-the-wallet-manager) - - [2. Create a Default Wallet](#2-create-a-default-wallet) - - [3. Loading the EOSIO Key](#3-loading-the-mandel-key) - - [4. Start the First Producer Node](#4-start-the-first-producer-node) - - [5. Start the Second Producer Node](#5-start-the-second-producer-node) - - [6. Get Nodes Info](#6-get-nodes-info) +1. [Start the Wallet Manager](#1-start-the-wallet-manager) +2. [Create a Default Wallet](#2-create-a-default-wallet) +3. [Loading the EOSIO Key](#3-loading-the-eosio-key) +4. [Start the First Producer Node](#4-start-the-first-producer-node) +5. [Start the Second Producer Node](#5-start-the-second-producer-node) +6. [Get Nodes Info](#6-get-nodes-info) ### 1. Start the Wallet Manager From 847d114e62a54196efb63c2c55eb1973fdb2dcf3 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Mon, 18 Jul 2022 14:56:18 -0700 Subject: [PATCH 099/111] general doc cleanup fixed broken links and unclosed '<' --- .../02_node-setups/00_producing-node.md | 14 +- .../02_node-setups/01_non-producing-node.md | 8 +- .../00_local-single-node-testnet.md | 10 +- .../03_plugins/producer_plugin/index.md | 124 +++++++++--------- .../how-to-replay-from-a-snapshot.md | 2 +- docs/01_nodeos/04_replays/index.md | 6 +- .../03_command-reference/convert/index.md | 8 +- .../03_command-reference/create/index.md | 4 +- .../get/transaction-status.md | 4 +- docs/02_cleos/03_command-reference/index.md | 7 +- .../03_command-reference/net/connect.md | 6 +- .../03_command-reference/net/disconnect.md | 6 +- .../03_command-reference/net/index.md | 14 +- .../03_command-reference/net/peers.md | 4 +- .../03_command-reference/net/status.md | 6 +- .../03_command-reference/set/index.md | 12 +- .../03_command-reference/system/system-rex.md | 38 +++--- .../system/system-voteproducer.md | 8 +- .../03_command-reference/version/index.md | 2 +- .../15_plugins/wallet_plugin/index.md | 5 +- docs/index.md | 8 +- 21 files changed, 163 insertions(+), 133 deletions(-) diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index f9555ba262..7bb7d2a2ba 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -12,7 +12,11 @@ This section describes how to set up a producing node within the EOSIO network. ## Before you begin * [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. + +[//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) +[//]: # ( If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) + * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps @@ -46,11 +50,11 @@ producer-name = youraccount ### 3. Set the Producer's signature-provider -You will need to set the private key for your producer. The public key should have an authority for the producer account defined above. +You will need to set the private key for your producer. The public key should have an authority for the producer account defined above. `signature-provider` is defined with a 3-field tuple: * `public-key` - A valid EOSIO public key in form of a string. -* `provider-spec` - It's a string formatted like : +* `provider-spec` - It's a string formatted like `:` * `provider-type` - KEY or KEOSD #### Using a Key: @@ -65,7 +69,7 @@ signature-provider = PUBLIC_SIGNING_KEY=KEY:PRIVATE_SIGNING_KEY ``` #### Using Keosd: -You can also use `keosd` instead of hard-defining keys. +You can also use `keosd` instead of hard-defining keys. ```console # config.ini: @@ -87,7 +91,7 @@ p2p-peer-address = 123.255.78.9:9876 ### 5. Load the Required Plugins -In your [config.ini](../index.md), confirm the following plugins are loading or append them if necessary. +In your [config.ini](../index.md), confirm the following plugins are loading or append them if necessary. ```console # config.ini: diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index 77365ef18f..b85a014c34 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -9,12 +9,16 @@ This section describes how to set up a non-producing node within the EOSIO netwo ## Before you begin * [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. + +[//]: # ( THIS IS A COMMENT NEXT LINK CONTAINS A BROKEN LINK ) +[//]: # ( If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) + * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps -To setup a non-producing node is simple. +To setup a non-producing node is simple. 1. [Set Peers](#1-set-peers) 2. [Enable one or more available plugins](#2-enable-one-or-more-available-plugins) diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index 53ca22048c..4b0f8d1b56 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -13,7 +13,11 @@ This section describes how to set up a single-node blockchain configuration runn ## Before you begin * [Install the EOSIO software](../../../00_install/index.md) before starting this section. -* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. If you built EOSIO using shell scripts, make sure to run the [Install Script](../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md). +* It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. + +[//]: # (THIS IS A COMMENT, NEXT LINK HAS BROKEN LINK) +[//]: # (If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) + * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. ## Steps @@ -87,7 +91,7 @@ The more advanced user will likely have need to modify the configuration. `node * Linux: `~/.local/share/eosio/nodeos/config` The build seeds this folder with a default `genesis.json` file. A configuration folder can be specified using the `--config-dir` command line argument to `nodeos`. If you use this option, you will need to manually copy a `genesis.json` file to your config folder. - + `nodeos` will need a properly configured `config.ini` file in order to do meaningful work. On startup, `nodeos` looks in the config folder for `config.ini`. If one is not found, a default `config.ini` file is created. If you do not already have a `config.ini` file ready to use, run `nodeos` and then close it immediately with Ctrl-C. A default configuration (`config.ini`) will have been created in the config folder. Edit the `config.ini` file, adding/updating the following settings to the defaults already in place: ```console @@ -115,7 +119,7 @@ nodeos * Mac OS: `~/Library/Application\ Support/eosio/nodeos/data` * Linux: `~/.local/share/eosio/nodeos/data` - + A data folder can be specified using the `--data-dir` command line argument to `nodeos`. [[info | What's next?]] diff --git a/docs/01_nodeos/03_plugins/producer_plugin/index.md b/docs/01_nodeos/03_plugins/producer_plugin/index.md index 14b5be24ba..66e1b0077f 100644 --- a/docs/01_nodeos/03_plugins/producer_plugin/index.md +++ b/docs/01_nodeos/03_plugins/producer_plugin/index.md @@ -24,100 +24,100 @@ These can be specified from both the `nodeos` command-line or the `config.ini` f ```console Config Options for eosio::producer_plugin: - -e [ --enable-stale-production ] Enable block production, even if the + -e [ --enable-stale-production ] Enable block production, even if the chain is stale. - -x [ --pause-on-startup ] Start this node in a state where + -x [ --pause-on-startup ] Start this node in a state where production is paused - --max-transaction-time arg (=30) Limits the maximum time (in - milliseconds) that is allowed a pushed - transaction's code to execute before + --max-transaction-time arg (=30) Limits the maximum time (in + milliseconds) that is allowed a pushed + transaction's code to execute before being considered invalid --max-irreversible-block-age arg (=-1) - Limits the maximum age (in seconds) of + Limits the maximum age (in seconds) of the DPOS Irreversible Block for a chain - this node will produce blocks on (use + this node will produce blocks on (use negative value to indicate unlimited) - -p [ --producer-name ] arg ID of producer controlled by this node - (e.g. inita; may specify multiple + -p [ --producer-name ] arg ID of producer controlled by this node + (e.g. inita; may specify multiple times) - --private-key arg (DEPRECATED - Use signature-provider - instead) Tuple of [public key, WIF - private key] (may specify multiple + --private-key arg (DEPRECATED - Use signature-provider + instead) Tuple of [public key, WIF + private key] (may specify multiple times) --signature-provider arg (=EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3) - Key=Value pairs in the form + Key=Value pairs in the form = Where: - is a string form of + is a string form of a vaild EOSIO public key - - is a string in the + + is a string in the form : - + is KEY, or KEOSD - - KEY: is a string form of - a valid EOSIO - private key which + + KEY: is a string form of + a valid EOSIO + private key which maps to the provided public key - - KEOSD: is the URL where - keosd is available - and the approptiate - wallet(s) are + + KEOSD: is the URL where + keosd is available + and the approptiate + wallet(s) are unlocked - --keosd-provider-timeout arg (=5) Limits the maximum time (in - milliseconds) that is allowed for - sending blocks to a keosd provider for + --keosd-provider-timeout arg (=5) Limits the maximum time (in + milliseconds) that is allowed for + sending blocks to a keosd provider for signing --greylist-account arg account that can not access to extended CPU/NET virtual resources - --greylist-limit arg (=1000) Limit (between 1 and 1000) on the + --greylist-limit arg (=1000) Limit (between 1 and 1000) on the multiple that CPU/NET virtual resources - can extend during low usage (only - enforced subjectively; use 1000 to not + can extend during low usage (only + enforced subjectively; use 1000 to not enforce any limit) --produce-time-offset-us arg (=0) Offset of non last block producing time - in microseconds. Valid range 0 .. + in microseconds. Valid range 0 .. -block_time_interval. --last-block-time-offset-us arg (=-200000) - Offset of last block producing time in - microseconds. Valid range 0 .. + Offset of last block producing time in + microseconds. Valid range 0 .. -block_time_interval. --cpu-effort-percent arg (=80) Percentage of cpu block production time - used to produce block. Whole number + used to produce block. Whole number percentages, e.g. 80 for 80% --last-block-cpu-effort-percent arg (=80) Percentage of cpu block production time - used to produce last block. Whole + used to produce last block. Whole number percentages, e.g. 80 for 80% --max-block-cpu-usage-threshold-us arg (=5000) - Threshold of CPU block production to - consider block full; when within - threshold of max-block-cpu-usage block + Threshold of CPU block production to + consider block full; when within + threshold of max-block-cpu-usage block can be produced immediately --max-block-net-usage-threshold-bytes arg (=1024) - Threshold of NET block production to - consider block full; when within - threshold of max-block-net-usage block + Threshold of NET block production to + consider block full; when within + threshold of max-block-net-usage block can be produced immediately --max-scheduled-transaction-time-per-block-ms arg (=100) - Maximum wall-clock time, in - milliseconds, spent retiring scheduled - transactions in any block before - returning to normal transaction + Maximum wall-clock time, in + milliseconds, spent retiring scheduled + transactions in any block before + returning to normal transaction processing. --subjective-cpu-leeway-us arg (=31000) - Time in microseconds allowed for a - transaction that starts with - insufficient CPU quota to complete and + Time in microseconds allowed for a + transaction that starts with + insufficient CPU quota to complete and cover its CPU usage. --subjective-account-max-failures arg (=3) - Sets the maximum amount of failures - that are allowed for a given account + Sets the maximum amount of failures + that are allowed for a given account per block. Disregarded for accounts that have been whitelisted by disabling subjective @@ -128,33 +128,33 @@ Config Options for eosio::producer_plugin: Sets the time to return full subjective cpu for accounts --incoming-defer-ratio arg (=1) ratio between incoming transactions and - deferred transactions when both are + deferred transactions when both are queued for execution --incoming-transaction-queue-size-mb arg (=1024) - Maximum size (in MiB) of the incoming + Maximum size (in MiB) of the incoming transaction queue. Exceeding this value will subjectively drop transaction with resource exhaustion. - --disable-api-persisted-trx Disable the re-apply of API + --disable-api-persisted-trx Disable the re-apply of API transactions. - --disable-subjective-billing arg (=1) Disable subjective CPU billing for + --disable-subjective-billing arg (=1) Disable subjective CPU billing for API/P2P transactions --disable-subjective-account-billing arg - Account which is excluded from + Account which is excluded from subjective CPU billing Account is considered whitelisted and will not be subject to enforcement of subjective-account-max-failures. --disable-subjective-p2p-billing arg (=1) - Disable subjective CPU billing for P2P + Disable subjective CPU billing for P2P transactions --disable-subjective-api-billing arg (=1) - Disable subjective CPU billing for API + Disable subjective CPU billing for API transactions - --producer-threads arg (=2) Number of worker threads in producer + --producer-threads arg (=2) Number of worker threads in producer thread pool --snapshots-dir arg (="snapshots") the location of the snapshots directory - (absolute path or relative to + (absolute path or relative to application data dir) ``` @@ -172,7 +172,7 @@ The option below sets the ratio between the incoming transaction and the deferre --incoming-defer-ratio arg (=1) ``` -By default value of `1`, the `producer` plugin processes one incoming transaction per deferred transaction. When `arg` sets to `10`, the `producer` plugin processes 10 incoming transactions per deferred transaction. +By default value of `1`, the `producer` plugin processes one incoming transaction per deferred transaction. When `arg` sets to `10`, the `producer` plugin processes 10 incoming transactions per deferred transaction. If the `arg` is set to a sufficiently large number, the plugin always processes the incoming transaction first until the queue of the incoming transactions is empty. Respectively, if the `arg` is 0, the `producer` plugin processes the deferred transactions queue first. diff --git a/docs/01_nodeos/04_replays/how-to-replay-from-a-snapshot.md b/docs/01_nodeos/04_replays/how-to-replay-from-a-snapshot.md index cb7bd5028d..3c79cc72a5 100644 --- a/docs/01_nodeos/04_replays/how-to-replay-from-a-snapshot.md +++ b/docs/01_nodeos/04_replays/how-to-replay-from-a-snapshot.md @@ -6,7 +6,7 @@ Once you have obtained a copy of a valid snapshot file from which you wish to cr location | name | action ----------------- | -------------------------- | ------------ -data/snapshots | .bin | place the snapshot file you want to replay here +data/snapshots | `.bin` | place the snapshot file you want to replay here data/ | * | remove You can use `snapshots-dir = "snapshots" ` in the configuration file or using the `--snapshots-dir` command line option, to specify the where to find the the snapshot to replay, use `--snapshot` to specify the name of the snapshot to replay. diff --git a/docs/01_nodeos/04_replays/index.md b/docs/01_nodeos/04_replays/index.md index 0ec937f15a..e618fef78a 100644 --- a/docs/01_nodeos/04_replays/index.md +++ b/docs/01_nodeos/04_replays/index.md @@ -17,7 +17,7 @@ Snapshot files can be created from a running `nodeos` instance. The snapshot con * [How To Generate a Blocks Log](how-to-generate-a-blocks.log.md) * [How To Generate a Snapshot](how-to-generate-a-snapshot.md) * [How To Replay from a Blocks Log](how-to-replay-from-a-blocks.log.md) -* [How to Replay from a Snapshot](how-to-replay-from-a-snapshot.md) +* [How to Replay from a Snapshot](../04_replays/how-to-replay-from-a-snapshot.md) ## Replay Snapshot-specific Options @@ -41,9 +41,9 @@ This tells `nodeos` to clear the local chain state and local the `blocks.log` fi - **--truncate-at-block** Default argument (=0), only used if the given value is non-zero. Using this option when replaying the blockchain will force the replay to stop at the specified block number. This option will only work if replaying with the `--hard-replay-blockchain` option. The local `nodeos` process will contain the chain state for that block. This option may be useful for checking blockchain state at specific points in time. It is intended for testing/validation and is not intended to be used when creating a local `nodeos` instance which is synchronized with the network. - + - **--snapshot** -Use this option to specify which snapshot file to use to recreate the chain state from a snapshot file. This option will not replay the `blocks.log` file. The `nodeos` instance will not know the full transaction history of the blockchain. +Use this option to specify which snapshot file to use to recreate the chain state from a snapshot file. This option will not replay the `blocks.log` file. The `nodeos` instance will not know the full transaction history of the blockchain. - **--snapshots-dir** You can use this to specify the location of the snapshot file directory (absolute path or relative to application data dir.) diff --git a/docs/02_cleos/03_command-reference/convert/index.md b/docs/02_cleos/03_command-reference/convert/index.md index d4ae096130..404478ffed 100755 --- a/docs/02_cleos/03_command-reference/convert/index.md +++ b/docs/02_cleos/03_command-reference/convert/index.md @@ -2,7 +2,7 @@ Pack and unpack transactions ## subcommands -- [pack_transaction](pack_transaction) - From plain signed json to packed form -- [unpack_transaction](unpack_transaction) - From packed to plain signed json form -- [pack_action_data](pack_action_data) - From json action data to packed form -- [unpack_action_data](unpack_action_data) - From packed to json action data form \ No newline at end of file +- [pack_transaction](pack_transaction.md) - From plain signed json to packed form +- [unpack_transaction](unpack_transaction.md) - From packed to plain signed json form +- [pack_action_data](pack_action_data.md) - From json action data to packed form +- [unpack_action_data](unpack_action_data.md) - From packed to json action data form diff --git a/docs/02_cleos/03_command-reference/create/index.md b/docs/02_cleos/03_command-reference/create/index.md index 6e559a6b6e..a4783da2de 100755 --- a/docs/02_cleos/03_command-reference/create/index.md +++ b/docs/02_cleos/03_command-reference/create/index.md @@ -2,8 +2,8 @@ Create various items, on and off the blockchain ## Subcommands -- [key](key) - Create a new keypair and print the public and private keys -- [account](account) - Create a new account on the blockchain +- [key](key.md) - Create a new keypair and print the public and private keys +- [account](account.md) - Create a new account on the blockchain ```console Create various items, on and off the blockchain diff --git a/docs/02_cleos/03_command-reference/get/transaction-status.md b/docs/02_cleos/03_command-reference/get/transaction-status.md index 4873a8fea9..852d8a0d8a 100644 --- a/docs/02_cleos/03_command-reference/get/transaction-status.md +++ b/docs/02_cleos/03_command-reference/get/transaction-status.md @@ -3,7 +3,7 @@ Gets current blockchain state and, if available, transaction information given the transaction id. For query to work, the transaction finality status feature must be enabled by configuring -the chain plugin with the config option "--transaction-finality-status-max-storage-size-gb " +the chain plugin with the config option "--transaction-finality-status-max-storage-size-gb \" in nodeos. ## Position Parameters @@ -19,7 +19,7 @@ in nodeos. cleos get transaction-status 6438df82216dfaf46978f703fb818b49110dbfc5d9b521b5d08c342277438b29 ``` -This command simply returns the current chain status and transaction status information (if available). +This command simply returns the current chain status and transaction status information (if available). ```json { diff --git a/docs/02_cleos/03_command-reference/index.md b/docs/02_cleos/03_command-reference/index.md index fe9d4c01af..14336c52f3 100644 --- a/docs/02_cleos/03_command-reference/index.md +++ b/docs/02_cleos/03_command-reference/index.md @@ -12,7 +12,8 @@ Documentation for all `cleos` main commands - [sign](sign.md) - Sign a transaction - [push](push) - Push arbitrary transactions to the blockchain - [multisig](multisig) - Multisig contract commands - + +[//]: # ( THIS IS A COMMENT FOLLOWING LINE HAD JS COMMENTS JS COMMENTS BREAK MDX ) +[//]: # ( wrap wrap - Wrap contract commands ) + - [system](system) - Send eosio.system contract action to the blockchain. diff --git a/docs/02_cleos/03_command-reference/net/connect.md b/docs/02_cleos/03_command-reference/net/connect.md index be0b2af0b3..646762cf1d 100755 --- a/docs/02_cleos/03_command-reference/net/connect.md +++ b/docs/02_cleos/03_command-reference/net/connect.md @@ -4,7 +4,11 @@ cleos net connect [OPTIONS] host ``` **Where:** -* [OPTIONS] = See **Options** in the [**Command Usage**](command-usage) section below. +* [OPTIONS] = See **Options** section TBD + +[//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) +[//]: # (in the **Command Usage** command-usage section below.) + * host = The hostname:port to connect to **Note:** The arguments and options enclosed in square brackets are optional. diff --git a/docs/02_cleos/03_command-reference/net/disconnect.md b/docs/02_cleos/03_command-reference/net/disconnect.md index 29c3039961..d375c4b239 100755 --- a/docs/02_cleos/03_command-reference/net/disconnect.md +++ b/docs/02_cleos/03_command-reference/net/disconnect.md @@ -4,8 +4,10 @@ cleos net disconnect [OPTIONS] host ``` **Where:** -* [OPTIONS] = See **Options** in the [**Command Usage**](command-usage) section below. -* host = The hostname:port to disconnect from +* [OPTIONS] = See **Options**section TBD + +[//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) +[//]: # (in the **Command Usage** command-usage section below.) **Note:** The arguments and options enclosed in square brackets are optional. diff --git a/docs/02_cleos/03_command-reference/net/index.md b/docs/02_cleos/03_command-reference/net/index.md index 5b09ff42f9..e6067dcb4c 100755 --- a/docs/02_cleos/03_command-reference/net/index.md +++ b/docs/02_cleos/03_command-reference/net/index.md @@ -8,11 +8,11 @@ Usage: cleos net SUBCOMMAND ``` ## Subcommands - - - [cleos net connect](connect) start a new connection to a peer - - [cleos net disconnect](disconnect) close an existing connection - - - [cleos net status](status) status of existing connection - - - [cleos net peers](peers) status of all existing peers + - [cleos net connect](connect.md) start a new connection to a peer + + - [cleos net disconnect](disconnect.md) close an existing connection + + - [cleos net status](status.md) status of existing connection + + - [cleos net peers](peers.md) status of all existing peers diff --git a/docs/02_cleos/03_command-reference/net/peers.md b/docs/02_cleos/03_command-reference/net/peers.md index 2814731c75..81b5adc612 100755 --- a/docs/02_cleos/03_command-reference/net/peers.md +++ b/docs/02_cleos/03_command-reference/net/peers.md @@ -4,7 +4,9 @@ cleos net peers [OPTIONS] ``` **Where:** -* [OPTIONS] = See **Options** in the [**Command Usage**](command-usage) section below. +* [OPTIONS] = See **Options** section TBD + +[//]: # (in the **Command Usage** command-usage section below.) **Note:** The arguments and options enclosed in square brackets are optional. diff --git a/docs/02_cleos/03_command-reference/net/status.md b/docs/02_cleos/03_command-reference/net/status.md index f8f45265ec..55b9052a4b 100755 --- a/docs/02_cleos/03_command-reference/net/status.md +++ b/docs/02_cleos/03_command-reference/net/status.md @@ -4,7 +4,11 @@ cleos net status [OPTIONS] host ``` **Where:** -* [OPTIONS] = See **Options** in the [**Command Usage**](command-usage) section below. +* [OPTIONS] = See **Options** section TBD + +[//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) +[//]: # (in the **Command Usage** command-usage section below.) + * host = The hostname:port to query status of connection **Note:** The arguments and options enclosed in square brackets are optional. diff --git a/docs/02_cleos/03_command-reference/set/index.md b/docs/02_cleos/03_command-reference/set/index.md index 1bb8a95799..ff2e281f4c 100755 --- a/docs/02_cleos/03_command-reference/set/index.md +++ b/docs/02_cleos/03_command-reference/set/index.md @@ -12,9 +12,9 @@ Options: ``` ## Subcommands - -- [code](set-code) - create or update the code on an account -- [abi](set-abi) - create or update the abi on an account -- [contract](set-contract) - create or update the contract on an account -- [account](set-account) - set or update blockchain account state -- [action](set-action) - set or update blockchain action state + +- [code](set-code.md) - create or update the code on an account +- [abi](set-abi.md) - create or update the abi on an account +- [contract](set-contract.md) - create or update the contract on an account +- [account](set-account.md) - set or update blockchain account state +- [action](set-action.md) - set or update blockchain action state diff --git a/docs/02_cleos/03_command-reference/system/system-rex.md b/docs/02_cleos/03_command-reference/system/system-rex.md index 8d872d1727..81f0666b34 100755 --- a/docs/02_cleos/03_command-reference/system/system-rex.md +++ b/docs/02_cleos/03_command-reference/system/system-rex.md @@ -4,22 +4,22 @@ Actions related to REX (the resource exchange). ## Subcommands -- [deposit](system-rex-deposit) - Deposit into owner's REX fund by transfering from owner's liquid token balance -- [withdraw](system-rex-withdraw) - Withdraw from owner's REX fund by transfering to owner's liquid token balance -- [buyrex](system-rex-buyrex) - Buy REX using tokens in owner's REX fund -- [lendrex](system-rex-lendrex) - Deposit tokens to REX fund and use the tokens to buy REX -- [unstaketorex](system-rex-unstaketorex) - Buy REX using staked tokens -- [sellrex](system-rex-sellrex) - Sell REX tokens -- [cancelrexorder](system-rex-cancelrexorder) - Cancel queued REX sell order if one exists -- [mvtosavings](system-rex-mvtosavings) - Move REX tokens to savings bucket -- [mvfromsavings](system-rex-mvfromsavings) - Move REX tokens out of savings bucket -- [rentcpu](system-rex-rentcpu) - Rent CPU bandwidth for 30 days -- [rentnet](system-rex-rentnet) - Rent Network bandwidth for 30 days -- [fundcpuloan](system-rex-fundcpuloan) - Deposit into a CPU loan fund -- [fundnetloan](system-rex-fundnetloan) - Deposit into a Network loan fund -- [defundcpuloan](system-rex-defundcpuloan) - Withdraw from a CPU loan fund -- [defundnetloan](system-rex-defundnetloan) - Withdraw from a Network loan fund -- [consolidate](system-rex-consolidate) - Consolidate REX maturity buckets into one that matures in 4 days -- [updaterex](system-rex-updaterex) - Update REX owner vote stake and vote weight -- [rexexec](system-rex-rexexec) - Perform REX maintenance by processing expired loans and unfilled sell orders -- [closerex](system-rex-closerex) - Delete unused REX-related user table entries +- [deposit](system-rex-deposit.md) - Deposit into owner's REX fund by transfering from owner's liquid token balance +- [withdraw](system-rex-withdraw.md) - Withdraw from owner's REX fund by transfering to owner's liquid token balance +- [buyrex](system-rex-buyrex.md) - Buy REX using tokens in owner's REX fund +- [lendrex](system-rex-lendrex.md) - Deposit tokens to REX fund and use the tokens to buy REX +- [unstaketorex](system-rex-unstaketorex.md) - Buy REX using staked tokens +- [sellrex](system-rex-sellrex.md) - Sell REX tokens +- [cancelrexorder](system-rex-cancelrexorder.md) - Cancel queued REX sell order if one exists +- [mvtosavings](system-rex-mvtosavings.md) - Move REX tokens to savings bucket +- [mvfromsavings](system-rex-mvfromsavings.md) - Move REX tokens out of savings bucket +- [rentcpu](system-rex-rentcpu.md) - Rent CPU bandwidth for 30 days +- [rentnet](system-rex-rentnet.md) - Rent Network bandwidth for 30 days +- [fundcpuloan](system-rex-fundcpuloan.md) - Deposit into a CPU loan fund +- [fundnetloan](system-rex-fundnetloan.md) - Deposit into a Network loan fund +- [defundcpuloan](system-rex-defundcpuloan.md) - Withdraw from a CPU loan fund +- [defundnetloan](system-rex-defundnetloan.md) - Withdraw from a Network loan fund +- [consolidate](system-rex-consolidate.md) - Consolidate REX maturity buckets into one that matures in 4 days +- [updaterex](system-rex-updaterex.md) - Update REX owner vote stake and vote weight +- [rexexec](system-rex-rexexec.md) - Perform REX maintenance by processing expired loans and unfilled sell orders +- [closerex](system-rex-closerex.md) - Delete unused REX-related user table entries diff --git a/docs/02_cleos/03_command-reference/system/system-voteproducer.md b/docs/02_cleos/03_command-reference/system/system-voteproducer.md index 4a4af137b2..c63e6c3b7e 100755 --- a/docs/02_cleos/03_command-reference/system/system-voteproducer.md +++ b/docs/02_cleos/03_command-reference/system/system-voteproducer.md @@ -1,5 +1,5 @@ ## Subcommands -- [voteproducer proxy](system-voteproducer-proxy) - Vote your stake through a proxy -- [voteproducer prods](system-voteproducer-prods) - Vote for one or more producers -- [voteproducer approve](system-voteproducer-approve) -Add one producer to list of voted producers -- [voteproducer unapprove](system-voteproducer-unapprove) - Remove one producer from list of voted producers \ No newline at end of file +- [voteproducer proxy](system-voteproducer-proxy.md) - Vote your stake through a proxy +- [voteproducer prods](system-voteproducer-prods.md) - Vote for one or more producers +- [voteproducer approve](system-voteproducer-approve.md) -Add one producer to list of voted producers +- [voteproducer unapprove](system-voteproducer-unapprove.md) - Remove one producer from list of voted producers diff --git a/docs/02_cleos/03_command-reference/version/index.md b/docs/02_cleos/03_command-reference/version/index.md index 14a8b1be4d..dde0850939 100755 --- a/docs/02_cleos/03_command-reference/version/index.md +++ b/docs/02_cleos/03_command-reference/version/index.md @@ -9,7 +9,7 @@ cleos version ``` ## Subcommands -[client](client) - Retrieve version information of the client +[client](client.md) - Retrieve version information of the client ```sh cleos version client diff --git a/docs/03_keosd/15_plugins/wallet_plugin/index.md b/docs/03_keosd/15_plugins/wallet_plugin/index.md index 418189ce1e..03b71af74a 100644 --- a/docs/03_keosd/15_plugins/wallet_plugin/index.md +++ b/docs/03_keosd/15_plugins/wallet_plugin/index.md @@ -21,7 +21,10 @@ None ## Dependencies -* [`http_plugin`](../http_plugin/index.md) +* `http_plugin` + +[//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) +[//]: # ( `http_plugin` ../http_plugin.md ) ### Load Dependency Examples diff --git a/docs/index.md b/docs/index.md index 5ccf7dd462..76a5441fcd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,9 +13,11 @@ The basic relationship between these components is illustrated in the diagram be ![EOSIO components](mandel_components.png) Additional EOSIO Resources: -* [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. -* [Upgrade Guide](20_upgrade-guide/index.md) - EOSIO version/protocol upgrade guide. -* [Release Notes](30_release-notes/index.md) - All release notes for this EOSIO version. +* [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. + +[//]: # (THIS IS A COMMENT REMOVING BROKEN LINKS) +[//]: #Upgrade-Guide-20_upgrade-guide/index.md-EOSIO-version/protocol-upgrade-guide. +[//]: # (Release Notes 30_release-notes/index.md - All release notes for this EOSIO version.) [[info | What's Next?]] | [Install the EOSIO Software](00_install/index.md) before exploring the sections above. From 6cccdfa98c3616464b019eba1ef6e49b39378a6f Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Sun, 17 Jul 2022 23:02:54 -0400 Subject: [PATCH 100/111] Added FreeBSD build instructions --- docs/00_install/01_build-from-source/index.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 343ad80ccc..101f5a5b32 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -94,6 +94,31 @@ make -j $(nproc) package After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software.
+
+ FreeBSD 13.1 Build Instructions + +Install required dependencies: +``` +pkg update && pkg install \ + git \ + cmake \ + curl \ + boost-all \ + python3 \ + openssl \ + llvm11 \ + pkgconf +``` +and perform the build (please note that FreeBSD 13.1 comes with llvm13 by default so you should provide clang11 options to cmake): +``` +git submodule update --init --recursive +mkdir build +cd build +cmake -DCMAKE_CXX_COMPILER=clang++11 -DCMAKE_C_COMPILER=clang11 -DCMAKE_BUILD_TYPE=Release .. +make -j $(nproc) package +``` +
+ ### Running Tests When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel. From 61176512ef1842b2b82a441f399ea41800e049d6 Mon Sep 17 00:00:00 2001 From: 766C6164 Date: Tue, 19 Jul 2022 02:26:01 -0400 Subject: [PATCH 101/111] Moved unsupported stuff in a separate file --- .../00_build-unsupported-os.md | 59 +++++++++++++++++++ docs/00_install/01_build-from-source/index.md | 25 -------- docs/00_install/index.md | 4 +- 3 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 docs/00_install/01_build-from-source/00_build-unsupported-os.md diff --git a/docs/00_install/01_build-from-source/00_build-unsupported-os.md b/docs/00_install/01_build-from-source/00_build-unsupported-os.md new file mode 100644 index 0000000000..ee59d0f0f3 --- /dev/null +++ b/docs/00_install/01_build-from-source/00_build-unsupported-os.md @@ -0,0 +1,59 @@ +--- +content_title: Build EOSIO from Source on Other Unix-based OS +--- + +**Please keep in mind that instructions for building from source on other unsupported operating systems provided here should be considered experimental and provided AS-IS on a best-effort basis and may not be fully featured.** + +**A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes. + +Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different mandel versions (mandel requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot). + +
+ FreeBSD 13.1 Build Instructions + +Install required dependencies: +``` +pkg update && pkg install \ + git \ + cmake \ + curl \ + boost-all \ + python3 \ + openssl \ + llvm11 \ + pkgconf +``` +and perform the build (please note that FreeBSD 13.1 comes with llvm13 by default so you should provide clang11 options to cmake): +``` +git submodule update --init --recursive +mkdir build +cd build +cmake -DCMAKE_CXX_COMPILER=clang++11 -DCMAKE_C_COMPILER=clang11 -DCMAKE_BUILD_TYPE=Release .. +make -j $(nproc) package +``` +
+ +### Running Tests + +When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel. + +``` +cd build + +# "parallelizable tests": the minimum test set that should be run +ctest -j $(nproc) -LE _tests + +# Also consider running the WASM spec tests for more coverage +ctest -j $(nproc) -L wasm_spec_tests +``` + +Some other tests are available and recommended but be aware they can be sensitive to other software running on the same host and they may **SIGKILL** other nodeos instances running on the host. +``` +cd build + +# These tests can't run in parallel but are recommended. +ctest -L "nonparallelizable_tests" + +# These tests can't run in parallel. They also take a long time to run. +ctest -L "long_running_tests" +``` \ No newline at end of file diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 101f5a5b32..343ad80ccc 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -94,31 +94,6 @@ make -j $(nproc) package After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software. -
- FreeBSD 13.1 Build Instructions - -Install required dependencies: -``` -pkg update && pkg install \ - git \ - cmake \ - curl \ - boost-all \ - python3 \ - openssl \ - llvm11 \ - pkgconf -``` -and perform the build (please note that FreeBSD 13.1 comes with llvm13 by default so you should provide clang11 options to cmake): -``` -git submodule update --init --recursive -mkdir build -cd build -cmake -DCMAKE_CXX_COMPILER=clang++11 -DCMAKE_C_COMPILER=clang11 -DCMAKE_BUILD_TYPE=Release .. -make -j $(nproc) package -``` -
- ### Running Tests When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel. diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 0bfa20716f..23a61b3271 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -15,7 +15,9 @@ EOSIO currently supports the following operating systems: 3. Ubuntu 22.04 [[info | Note]] -| It may be possible to build and install EOSIO on other Unix-based operating systems. This is not officially supported, though. +| It may be possible to build and install EOSIO on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported. + +* [Build EOSIO on Other Unix-based Systems](01_build-from-source/00_build-unsupported-os.md) ## Docker Utilities for Node Execution (D.U.N.E.) From 2bbcdae2f63e9345ecd1f8f9f6ff5bc50ccf7258 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Thu, 4 Aug 2022 17:52:00 -0700 Subject: [PATCH 102/111] documentation fixes to power developer doc portal * Support MDX parsing * Replace github references to EOS Network Foundation * Replace references to old documentation portal * Fix broken links Markdown files under `docs` and under `tutorial` The developer documentation portal is powered by markdown files. These files are parsed to create a nice looking web site. We use MDX as the parsing engine. MDX requires all html tags are closed. We went through all the files removing unneeded '
' tags, enclosing angle brackets in quotes, and closing img tags. Many times we found documentation pointing to old repositories that had not been updated in years. We updated the links and pointed to repositories that are better maintained. We made sure links to the documentation portal did not leak back to older, previous versions. We found relative links that no longer existed. We made sure to point the links to best location. Sometimes the links broke because were missing a key file extension. We made sure to add back the file extenstion. **Note:** This is essentially a no-op; however summarizing here for anyone following the commit history. Glossary and Protocol Guides were added and removed during the course of development. We had added a Glossary and Protocol Guides , and we decided to utilize the welcome repository as the source for both. commit ba20420c42f2f8bbf3396102d3ac22261028af30 Author: Eric Passmore Date: Thu Aug 4 12:46:52 2022 -0700 Testsnets anchor link was not working rm it commit d5de39dbbe250d2a9878c82de990c086c3b7b122 Author: Eric Passmore Date: Thu Aug 4 10:27:42 2022 -0700 adding missing .md ext commit 9dbb885d2eb308e60a2db909c9aed7b5dcb4289a Author: Eric Passmore Date: Thu Aug 4 10:24:49 2022 -0700 found another eos.io reference to replace commit 6a10c44b5863552c85c283db5b6d24e84b84f2cf Author: Eric Passmore Date: Thu Aug 4 08:47:02 2022 -0700 moved away from eos testnet commit 023c8e50724b766b0b9c8ce859d106101bc90fc8 Merge: 9d486ab51 6514a7d63 Author: Eric Passmore Date: Thu Aug 4 08:33:00 2022 -0700 Merge remote-tracking branch 'origin/main' into documentation-fixes Fixing docs by removing eosio references, need resync with main to catch merge issues early commit 9d486ab51aa399a4e5c7a038c19531071a88e900 Author: Eric Passmore Date: Tue Aug 2 08:19:36 2022 -0700 updated protocol-guides links to include number commit 907d9e2af8796087ba830f10f53df0063d0a621d Author: Eric Passmore Date: Fri Jul 29 16:23:41 2022 -0700 removed general_info replaced by welcome repository markdown commit 07efa3fb831ef2d57f68be0ef3aa21e28c346a80 Merge: 056239ccc d36ca7a52 Author: Eric Passmore Date: Fri Jul 29 07:10:24 2022 -0700 merging with upstream/main keeping up to date commit 056239cccb5e3337b5598364190cd4dc9d16a281 Merge: b921bdf98 b378866ef Author: Eric Passmore Date: Tue Jul 26 17:08:43 2022 -0700 Merge remote-tracking branch 'refs/remotes/origin/documentation-fixes' into documentation-fixes Note pulled in "changes to lower bound description" 766C6164 Resolved Conflicts No Changes: docs/general_info/glossary.md docs/general_info/protocol-guides/consensus_protocol.md docs/general_info/protocol-guides/network_peer_protocol.md docs/general_info/protocol-guides/transactions_protocol.md Changes to be committed: modified: docs/general_info/protocol-guides/accounts_and_permissions.md modified: libraries/chain/include/eosio/chain/webassembly/interface.hpp commit b921bdf987c0206b6704968eaca3bc05c505d469 Author: Eric Passmore Date: Tue Jul 26 16:44:25 2022 -0700 removed eos.io from markdown - Added docs/general_info/glossary.md - Added docs/general_info/protocol-guides - overview only for accounts_and_permissions.md - overview only for transactions_protocol.md - overview only for network_peer_protocol.md - overview only for consensus_protocol.md - Updated glossary.md to relative path (no more eos.io) - Fixed links adding missing .md extenstion - Updated protocol-guides to relative path (no more eos.io) - Included BiosBoot tutorial on main document portal - Fixed or removed broken links inside newly added glossary, guides, and tutorials Note: squashed commits on branch down to single commit, less noise, easier to cherry-pick commit b378866eff4be5cd3986c88a6d6ff39a802fee57 Author: Eric Passmore Date: Tue Jul 26 15:36:42 2022 -0700 adding back more missing .md extenstions, and simplying bios-boot-tutorial commit 2f7c0e65cbf360ba13102c8a5341714c4ce1159d Author: Eric Passmore Date: Tue Jul 26 15:14:16 2022 -0700 fixing more missing .md ext commit 07b1f16962921acdd35d24c87e6a87378c7a10fc Author: Eric Passmore Date: Tue Jul 26 15:03:06 2022 -0700 updated with .md ext commit 002b01ddc81e67d09dba40fae9cc2303b4efed7b Author: Eric Passmore Date: Tue Jul 26 14:29:33 2022 -0700 updated formate for glossary links to include .md commit bf344ae16c76ca1109672b8e9cccc5a69527e3d3 Merge: 3bbb956b5 0cb196b7f Author: Eric Passmore Date: Tue Jul 26 08:48:05 2022 -0700 merging main into documentation-fixes, after removing eso.io references adding glossary and guides commit 3bbb956b524267c788dd9614011abeda1be96b93 Author: Eric Passmore Date: Tue Jul 26 08:47:12 2022 -0700 remove eos.io references, added glossary, guides --- .../00_build-unsupported-os.md | 8 +- docs/00_install/01_build-from-source/index.md | 12 ++- .../03_development-environment/index.md | 8 +- .../03_plugins/history_api_plugin/index.md | 3 - .../03_plugins/net_api_plugin/index.md | 2 +- docs/01_nodeos/03_plugins/net_plugin/index.md | 76 +++++++++---------- ...0_how-to-fast-start-without-old-history.md | 2 +- ...w-to-restore-snapshot-with-full-history.md | 2 +- .../07_concepts/05_storage-and-read-modes.md | 6 +- docs/01_nodeos/08_troubleshooting/index.md | 16 ++-- .../how-to-create-a-wallet.md | 6 +- .../how-to-create-an-account.md | 10 +-- .../how-to-delegate-CPU-resource.md | 6 +- .../how-to-delegate-net-resource.md | 6 +- .../how-to-get-account-information.md | 6 +- .../how-to-get-block-information.md | 10 ++- .../how-to-get-transaction-information.md | 10 +-- .../02_how-to-guides/how-to-import-a-key.md | 10 +-- .../how-to-list-all-key-pairs.md | 10 +-- .../03_command-reference/get/account.md | 6 +- .../03_command-reference/net/peers.md | 2 +- .../03_command-reference/net/status.md | 2 +- .../03_command-reference/set/set-account.md | 2 +- .../03_command-reference/set/set-action.md | 6 +- docs/index.md | 2 +- tutorials/bios-boot-tutorial/README.md | 2 - 26 files changed, 118 insertions(+), 113 deletions(-) mode change 100755 => 100644 docs/02_cleos/03_command-reference/get/account.md mode change 100755 => 100644 docs/02_cleos/03_command-reference/net/peers.md mode change 100755 => 100644 docs/02_cleos/03_command-reference/net/status.md mode change 100755 => 100644 docs/02_cleos/03_command-reference/set/set-account.md mode change 100755 => 100644 docs/02_cleos/03_command-reference/set/set-action.md diff --git a/docs/00_install/01_build-from-source/00_build-unsupported-os.md b/docs/00_install/01_build-from-source/00_build-unsupported-os.md index ee59d0f0f3..a9988c0215 100644 --- a/docs/00_install/01_build-from-source/00_build-unsupported-os.md +++ b/docs/00_install/01_build-from-source/00_build-unsupported-os.md @@ -4,6 +4,10 @@ content_title: Build EOSIO from Source on Other Unix-based OS **Please keep in mind that instructions for building from source on other unsupported operating systems provided here should be considered experimental and provided AS-IS on a best-effort basis and may not be fully featured.** +### Using DUNE + +For the official multi-platform support try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) which runs in an ubuntu image via a docker container. + **A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes. Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different mandel versions (mandel requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot). @@ -11,7 +15,7 @@ Generally we recommend performing what we refer to as a "pinned build" which ens
FreeBSD 13.1 Build Instructions -Install required dependencies: +Install required dependencies: ``` pkg update && pkg install \ git \ @@ -56,4 +60,4 @@ ctest -L "nonparallelizable_tests" # These tests can't run in parallel. They also take a long time to run. ctest -L "long_running_tests" -``` \ No newline at end of file +``` diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 343ad80ccc..d2a817d01b 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -4,6 +4,10 @@ content_title: Build EOSIO from Source The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests. +### Using DUNE + +As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) for the easiest way to get started, and for multi-platform support. + ### Building From Source Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured. Notable requirements to build are: @@ -30,7 +34,7 @@ The binary package will be produced in the mandel build directory that was suppl
Ubuntu 20.04 & 22.04 Build Instructions -Install required dependencies: +Install required dependencies: ``` apt-get update && apt-get install \ build-essential \ @@ -58,7 +62,7 @@ make -j $(nproc) package
Ubuntu 18.04 Build Instructions -Install required dependencies. You will need to build Boost from source on this distribution. +Install required dependencies. You will need to build Boost from source on this distribution. ``` apt-get update && apt-get install \ build-essential \ @@ -74,7 +78,7 @@ apt-get update && apt-get install \ pkg-config \ python3 \ zlib1g-dev - + curl -L https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 | tar jx && \ cd boost_1_79_0 && \ ./bootstrap.sh --prefix=$HOME/boost1.79 && \ @@ -117,4 +121,4 @@ ctest -L "nonparallelizable_tests" # These tests can't run in parallel. They also take a long time to run. ctest -L "long_running_tests" -``` \ No newline at end of file +``` diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index fcb7f7b463..9305397d45 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -8,18 +8,18 @@ There are several ways to configure a `nodeos` environment for development and t This is the go-to option for smart contract developers, aspiring Block Producers or Non-Producing Node operators. It has the most simple configuration with the least number of requirements. -* [Configure Nodeos as a Local Single-node Testnet](00_local-single-node-testnet.md) +* [Configure Nodeos as a Local Single-node Testnet](00_local-single-node-testnet.md) ## Local Multi-Node Testnet While this option can technically be used for smart contract development, it may be overkill. This is most beneficial for those who are working on aspects of core development, such as benchmarking, optimization and experimentation. It's also a good option for hands-on learning and concept proofing. * [Configure Nodeos as a Local Two-Node Testnet](01_local-multi-node-testnet.md) -* [Configure Nodeos as a Local 21-Node Testnet](https://github.com/eosnetworkfoundation/mandel/tree/main/tutorials/bios-boot-tutorial) +* [Configure Nodeos as a Local 21-Node Testnet](/tutorials/bios-boot-tutorial.md) -## Official Testnet +## Official Testing Node -The official testnet for testing EOSIO dApps and smart contracts will be available soon +Try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) for the easiest way to get started, and for multi-platform support. ## Third-Party Testnets diff --git a/docs/01_nodeos/03_plugins/history_api_plugin/index.md b/docs/01_nodeos/03_plugins/history_api_plugin/index.md index df8e448aca..a506e94b75 100644 --- a/docs/01_nodeos/03_plugins/history_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/history_api_plugin/index.md @@ -12,9 +12,6 @@ It provides four RPC API endpoints: * get_key_accounts * get_controlled_accounts -[[info | More Info]] -| See HISTORY section of [RPC API](https://developers.eos.io/eosio-nodeos/reference). - The four actions listed above are used by the following `cleos` commands (matching order): * get actions diff --git a/docs/01_nodeos/03_plugins/net_api_plugin/index.md b/docs/01_nodeos/03_plugins/net_api_plugin/index.md index ac7ca7273f..bf6bdfbf0d 100644 --- a/docs/01_nodeos/03_plugins/net_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/net_api_plugin/index.md @@ -8,7 +8,7 @@ The `net_api_plugin` provides four RPC API endpoints: * connections * status -See [Net API Reference Documentation](https://developers.eos.io/manuals/eos/latest/nodeos/plugins/net_api_plugin/api-reference/index). +See [Net API Reference Documentation](http://docs.eosnetwork.com/reference/mandel-plugins/net_api.html). [[caution | Caution]] | This plugin exposes endpoints that allow management of p2p connections. Running this plugin on a publicly accessible node is not recommended as it can be exploited. diff --git a/docs/01_nodeos/03_plugins/net_plugin/index.md b/docs/01_nodeos/03_plugins/net_plugin/index.md index e7da4beb85..a7762c922c 100644 --- a/docs/01_nodeos/03_plugins/net_plugin/index.md +++ b/docs/01_nodeos/03_plugins/net_plugin/index.md @@ -23,77 +23,77 @@ Config Options for eosio::net_plugin: --p2p-listen-endpoint arg (=0.0.0.0:9876) The actual host:port used to listen for incoming p2p connections. - --p2p-server-address arg An externally accessible host:port for - identifying this node. Defaults to + --p2p-server-address arg An externally accessible host:port for + identifying this node. Defaults to p2p-listen-endpoint. - --p2p-peer-address arg The public endpoint of a peer node to - connect to. Use multiple - p2p-peer-address options as needed to + --p2p-peer-address arg The public endpoint of a peer node to + connect to. Use multiple + p2p-peer-address options as needed to compose a network. Syntax: host:port[:|] - The optional 'trx' and 'blk' - indicates to node that only - transactions 'trx' or blocks 'blk' + The optional 'trx' and 'blk' + indicates to node that only + transactions 'trx' or blocks 'blk' should be sent. Examples: - p2p.eos.io:9876 - p2p.trx.eos.io:9876:trx - p2p.blk.eos.io:9876:blk - + p2p.domain.io:9876 + p2p.trx.domaine.io:9876:trx + p2p.blk.domain.io:9876:blk + --p2p-max-nodes-per-host arg (=1) Maximum number of client nodes from any single IP address - --p2p-accept-transactions arg (=1) Allow transactions received over p2p - network to be evaluated and relayed if + --p2p-accept-transactions arg (=1) Allow transactions received over p2p + network to be evaluated and relayed if valid. --agent-name arg (="EOS Test Agent") The name supplied to identify this node amongst the peers. - --allowed-connection arg (=any) Can be 'any' or 'producers' or - 'specified' or 'none'. If 'specified', - peer-key must be specified at least - once. If only 'producers', peer-key is - not required. 'producers' and + --allowed-connection arg (=any) Can be 'any' or 'producers' or + 'specified' or 'none'. If 'specified', + peer-key must be specified at least + once. If only 'producers', peer-key is + not required. 'producers' and 'specified' may be combined. - --peer-key arg Optional public key of peer allowed to + --peer-key arg Optional public key of peer allowed to connect. May be used multiple times. - --peer-private-key arg Tuple of [PublicKey, WIF private key] + --peer-private-key arg Tuple of [PublicKey, WIF private key] (may specify multiple times) - --max-clients arg (=25) Maximum number of clients from which - connections are accepted, use 0 for no + --max-clients arg (=25) Maximum number of clients from which + connections are accepted, use 0 for no limit - --connection-cleanup-period arg (=30) number of seconds to wait before + --connection-cleanup-period arg (=30) number of seconds to wait before cleaning up dead connections --max-cleanup-time-msec arg (=10) max connection cleanup time per cleanup call in milliseconds --p2p-dedup-cache-expire-time-sec arg (=10) - Maximum time to track transaction for + Maximum time to track transaction for duplicate optimization - --net-threads arg (=2) Number of worker threads in net_plugin + --net-threads arg (=2) Number of worker threads in net_plugin thread pool --sync-fetch-span arg (=100) number of blocks to retrieve in a chunk - from any individual peer during + from any individual peer during synchronization - --use-socket-read-watermark arg (=0) Enable experimental socket read + --use-socket-read-watermark arg (=0) Enable experimental socket read watermark optimization --peer-log-format arg (=["${_name}" ${_ip}:${_port}]) - The string used to format peers when + The string used to format peers when logging messages about them. Variables are escaped with ${}. Available Variables: _name self-reported name - - _id self-reported ID (64 hex + + _id self-reported ID (64 hex characters) - - _sid first 8 characters of + + _sid first 8 characters of _peer.id - + _ip remote IP address of peer - + _port remote port number of peer - + _lip local IP address connected to peer - - _lport local port number connected + + _lport local port number connected to peer ``` diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md index 4e1f534483..962b9e711c 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md @@ -20,7 +20,7 @@ This procedure records the current chain state and future history, without previ 2. Make sure `data/state` does not exist -3. Start `nodeos` with the `--snapshot` option, and the options listed in the [`state_history_plugin`](#index.md). +3. Start `nodeos` with the `--snapshot` option, and the options listed in the [`state_history_plugin`](index.md). 4. Look for `Placing initial state in block n` in the log, where n is the start block number. diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md index 6eb2e76db4..52e3b27e5e 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md @@ -21,7 +21,7 @@ This procedure restores an existing snapshot with full history, so the node can 2. Make sure `data/state` does not exist -3. Start `nodeos` with the `--snapshot` option, and the options listed in the [`state_history_plugin`](#index.md). +3. Start `nodeos` with the `--snapshot` option, and the options listed in the [`state_history_plugin`](index.md). 4. Do not stop `nodeos` until it has received at least 1 block from the network, or it won't be able to restart. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index df2a872729..08f1f7ba81 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -17,7 +17,7 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain ## EOSIO Interfaces -EOSIO provides a set of [services](../../) and [interfaces](https://developers.eos.io/manuals/eosio.cdt/latest/files) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +EOSIO provides a set of [services](../../) and [interfaces](http://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API @@ -40,7 +40,7 @@ Clients such as `cleos` and the RPC API, will see database state as of the curre Speculative mode is low latency but fragile, there is no guarantee that the transactions reflected in the state will be included in the chain OR that they will reflected in the same order the state implies. -This mode features the lowest latency, but is the least consistent. +This mode features the lowest latency, but is the least consistent. In speculative mode `nodeos` is able to execute transactions which have TaPoS (Transaction as Proof of Stake) pointing to any valid block in a fork considered to be the best fork by this node. @@ -61,7 +61,7 @@ Clients such as `cleos` and the RPC API will see database state as of the curren ### Irreversible Mode -When `nodeos` is configured to be in irreversible read mode, it will still track the most up-to-date blocks in the fork database, but the state will lag behind the current best head block, sometimes referred to as the fork DB head, to always reflect the state of the last irreversible block. +When `nodeos` is configured to be in irreversible read mode, it will still track the most up-to-date blocks in the fork database, but the state will lag behind the current best head block, sometimes referred to as the fork DB head, to always reflect the state of the last irreversible block. Clients such as `cleos` and the RPC API will see database state as of the current head block of the chain. It **will not** include changes made by transactions known to this node but not included in the chain, such as unconfirmed transactions. diff --git a/docs/01_nodeos/08_troubleshooting/index.md b/docs/01_nodeos/08_troubleshooting/index.md index 409ca6c371..7aa22031d8 100644 --- a/docs/01_nodeos/08_troubleshooting/index.md +++ b/docs/01_nodeos/08_troubleshooting/index.md @@ -4,7 +4,7 @@ content_title: Nodeos Troubleshooting ### "Database dirty flag set (likely due to unclean shutdown): replay required" -`nodeos` needs to be shut down cleanly. To ensure this is done, send a `SIGTERM`, `SIGQUIT` or `SIGINT` and wait for the process to shutdown. Failing to do this will result in this error. If you get this error, your only recourse is to replay by starting `nodeos` with `--replay-blockchain` +`nodeos` needs to be shut down cleanly. To ensure this is done, send a `SIGTERM`, `SIGQUIT` or `SIGINT` and wait for the process to shutdown. Failing to do this will result in this error. If you get this error, your only recourse is to replay by starting `nodeos` with `--replay-blockchain` ### "Memory does not match data" Error at Restart @@ -12,15 +12,15 @@ If you get an error such as `St9exception: content of memory does not match data ``` Command Line Options for eosio::chain_plugin: - --force-all-checks do not skip any checks that can be - skipped while replaying irreversible + --force-all-checks do not skip any checks that can be + skipped while replaying irreversible blocks - --replay-blockchain clear chain state database and replay + --replay-blockchain clear chain state database and replay all blocks - --hard-replay-blockchain clear chain state database, recover as - many blocks as possible from the block + --hard-replay-blockchain clear chain state database, recover as + many blocks as possible from the block log, and then replay those blocks - --delete-all-blocks clear chain state database and block + --delete-all-blocks clear chain state database and block log ``` @@ -44,4 +44,4 @@ cleos --url http://localhost:8888 get info | grep server_version ### Error 3070000: WASM Exception Error -If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. More details about it and how to enable it can be found in the [Bios Boot Sequence Tutorial](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence/#112-set-the-eosiosystem-contract). For more information, you may also visit the [Nodeos Upgrade Guides](https://developers.eos.io/manuals/eos/latest/nodeos/upgrade-guides/). +If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md index 4973217f16..06e3ff199b 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md @@ -13,9 +13,9 @@ Make sure you meet the following requirements: [[info | Note]] | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [Accounts and Permissions](https://developers.eos.io/welcome/latest/protocol-guides/accounts_and_permissions) in the protocol documents. -* Understand what a [public](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private](https://developers.eos.io/welcome/latest/glossary/index/#private-key) key pair is. +* Understand what an [account](/glossary.md#account) is and its role in the blockchain. +* Understand [Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) in the protocol documents. +* Understand what a [public](/glossary.md#public-key) and [private](/glossary.md#private-key) key pair is. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md index 20fc565847..1fd79840ff 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md @@ -2,7 +2,7 @@ This how-to guide provides instructions on how to create a new EOSIO blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. -The example in this how-to guide creates a new account named **bob**, authorized by the default system account **eosio**, using the `cleos` CLI tool. +The example in this how-to guide creates a new account named **bob**, authorized by the default system account **eosio**, using the `cleos` CLI tool. ## Before you Begin @@ -10,9 +10,9 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about [EOSIO Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) -* Learn about Asymmetric Cryptography - [public key](https://developers.eos.io/welcome/v2.1/glossary/index#public-key) and [private key](https://developers.eos.io/welcome/v2.1/glossary/index#private-key) pairs. +| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +* Learn about [EOSIO Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) +* Learn about Asymmetric Cryptography - [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) pairs. * Create public/private keypairs for the `owner` and `active` permissions of an account. ## Command Reference @@ -31,7 +31,7 @@ cleos create account eosio bob EOS87TQktA5RVse2EguhztfQVEh6XXxBmgkU8b4Y5YnGvtYAo ``` **Where**: * `eosio` = the system account that authorizes the creation of a new account -* `bob` = the name of the new account conforming to [account naming conventions](https://developers.eos.io/welcome/v2.1/protocol-guides/accounts_and_permissions#2-accounts) +* `bob` = the name of the new account conforming to [account naming conventions](/protocol-guides/04_accounts_and_permissions.md#2-accounts) * `EOS87TQ...AoLGNN` = the owner public key or permission level for the new account (**required**) [[info | Note]] | To create a new account in the EOSIO blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created EOSIO blockchain, the default system account used to create a new account is **eosio**. diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 155c738bf6..00d977278a 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -13,9 +13,9 @@ Make sure you meet the following requirements: | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. -* Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in an EOSIO blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in an EOSIO blockchain. +* Understand what an [account](/glossary.md#account) is and its role in the blockchain. +* Understand [CPU bandwidth](/glossary.md#cpu) in an EOSIO blockchain. +* Understand [NET bandwidth](/glossary.md#net) in an EOSIO blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index ac26f6e52a..c3bd8d8bd8 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -13,9 +13,9 @@ Make sure you meet the following requirements: | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. -* Understand what an [account](https://developers.eos.io/welcome/latest/glossary/index/#account) is and its role in the blockchain. -* Understand [NET bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#net) in an EOSIO blockchain. -* Understand [CPU bandwidth](https://developers.eos.io/welcome/latest/glossary/index/#cpu) in an EOSIO blockchain. +* Understand what an [account](/glossary.md#account) is and its role in the blockchain. +* Understand [NET bandwidth](/glossary.md#net) in an EOSIO blockchain. +* Understand [CPU bandwidth](/glossary.md#cpu) in an EOSIO blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md index 7dc5f686d0..1213c0ac51 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md @@ -1,15 +1,15 @@ ## Overview -This how-to guide provides instructions on how to query infomation of an EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. +This how-to guide provides instructions on how to query infomation of an EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. ## Before you begin * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Acquire functional understanding of [EOSIO Accounts and Permissions](https://developers.eos.io/welcome/v2.1/protocol/accounts_and_permissions) +* Acquire functional understanding of [EOSIO Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md index 7efd62427f..216413ed1e 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md @@ -12,8 +12,8 @@ Make sure to meet the following requirements: [[info | Note]] | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand what a [block](https://developers.eos.io/welcome/latest/glossary/index/#block) is and its role in the blockchain. -* Understand the [block lifecycle](https://developers.eos.io/welcome/latest/protocol-guides/consensus_protocol/#5-block-lifecycle) in the EOSIO consensus protocol. +* Understand what a [block](/glossary.md#block) is and its role in the blockchain. +* Understand the [block lifecycle](/protocol-guides/01_consensus_protocol.md#5-block-lifecycle) in the EOSIO consensus protocol. ## Steps @@ -34,8 +34,10 @@ Some examples are provided below: **Example Output** ```sh -cleos -u https://api.testnet.eos.io get block 48351112 +cleos -u https://choiceofyourprovider get block 48351112 ``` +Reference to [testnet providers](/resources/index.md) + ```json { "timestamp": "2021-01-28T17:58:59.500", @@ -59,7 +61,7 @@ cleos -u https://api.testnet.eos.io get block 48351112 **Example Output** ```sh -cleos -u https://api.testnet.eos.io get block 02e1c7888a92206573ae38d00e09366c7ba7bc54cd8b7996506f7d2a619c43ba +cleos -u https://choiceofyourprovider get block 02e1c7888a92206573ae38d00e09366c7ba7bc54cd8b7996506f7d2a619c43ba ``` ```json { diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md index aaf5fd7e74..717d6b225a 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md @@ -2,7 +2,7 @@ This how-to guide provides instructions on how to retrieve infomation of an EOSIO transaction using a transaction ID. -The example in this how-to retrieves transaction information associated with the creation of the account **bob**. +The example in this how-to retrieves transaction information associated with the creation of the account **bob**. ## Before you begin @@ -10,7 +10,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand how transactions work in an EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](https://developers.eos.io/welcome/latest/protocol-guides/transactions_protocol) section. +* Understand how transactions work in an EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](/protocol-guides/02_transactions_protocol.md) section. ## Command Reference @@ -25,7 +25,7 @@ The following step shows how to retrieve transaction information associated with ```sh cleos get transaction 870a6b6e3882061ff0f64016e1eedfdd9439e2499bf978c3fb29fcedadada9b1 ``` -* Where `870a6b6e38...dada9b1`= The transaction ID associated with the creation of account **bob**. +* Where `870a6b6e38...dada9b1`= The transaction ID associated with the creation of account **bob**. **Example Output** @@ -179,7 +179,7 @@ The `cleos` command returns detailed information of the transaction: ## Summary -By following these instructions, you are able to retrieve transaction information using a transaction ID. +By following these instructions, you are able to retrieve transaction information using a transaction ID. ## Trobleshooting @@ -195,4 +195,4 @@ Error Details: History API plugin is not enabled ``` -To troubleshoot this error, enable the [history plugin](../../01_nodeos/03_plugins/history_plugin/index.md) and [history API plugin](../../01_nodeos/03_plugins/history_api_plugin/index.md), then run the command again. +To troubleshoot this error, enable the [history plugin](../../01_nodeos/03_plugins/history_plugin/index.md) and [history API plugin](../../01_nodeos/03_plugins/history_api_plugin/index.md), then run the command again. diff --git a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md index 19a8ee0d7d..d2cf0d0f4c 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md +++ b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md @@ -1,18 +1,18 @@ ## Overview -This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an EOSIO blockchain. ## Before you Begin Make sure you meet the following requirements: -* Create a default wallet using the `cleos wallet create` command. See the [How to Create a Wallet](../02_how-to-guides/how-to-create-a-wallet.md) section for instructions. +* Create a default wallet using the `cleos wallet create` command. See the [How to Create a Wallet](../02_how-to-guides/how-to-create-a-wallet.md) section for instructions. * Open and unlock the created wallet. * Familiarize with the [`cleos wallet import`](../03_command-reference/wallet/import.md) command. * Install the currently supported version of `cleos`. [[info | Note]] | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand what a [public key](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private key](https://developers.eos.io/welcome/latest/glossary/index/#private-key) is. +* Understand what a [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) is. ## Command Reference @@ -31,7 +31,7 @@ cleos wallet import private key: ``` -2. Enter the private key and hit Enter. +2. Enter the private key and hit Enter. ```sh *** ``` @@ -44,4 +44,4 @@ imported private key for: EOS8FBXJUfbANf3xeDWPoJxnip3Ych9HjzLBr1VaXRQFdkVAxwLE7 ## Summary -By following these instructions, you are able to import a private key to the default wallet. +By following these instructions, you are able to import a private key to the default wallet. diff --git a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md index 7a9bb7348f..2241458075 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an EOSIO blockchain. The example in this how-to guide displays all public keys and public/private key pairs stored within the existing default wallet. @@ -8,13 +8,13 @@ The example in this how-to guide displays all public keys and public/private key Make sure you meet the following requirements: -* Create a default wallet using the `cleos wallet create` command. See the [How to Create a Wallet](../02_how-to-guides/how-to-create-a-wallet.md) section for instructions. +* Create a default wallet using the `cleos wallet create` command. See the [How to Create a Wallet](../02_how-to-guides/how-to-create-a-wallet.md) section for instructions. * [Create a keypair](../03_command-reference/wallet/create_key.md) within the default wallet. * Familiarize with the [`cleos wallet`](../03_command-reference/wallet/index.md) commands. * Install the currently supported version of `cleos`. [[info | Note]] | `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand what a [public key](https://developers.eos.io/welcome/latest/glossary/index/#public-key) and [private key](https://developers.eos.io/welcome/latest/glossary/index/#private-key) is. +* Understand what a [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) is. ## Command Reference @@ -71,7 +71,7 @@ cleos wallet private_keys password: ``` -6. Enter the generated password when you created the default wallet: +6. Enter the generated password when you created the default wallet: ```sh *** ``` @@ -86,7 +86,7 @@ password: [[ ``` [[caution | Warning]] -| Never reveal your private keys in a production environment. +| Never reveal your private keys in a production environment. [[info | Note]] | If the above commands does not list any keys, make sure you have created keypairs and imported private keys to your wallet. diff --git a/docs/02_cleos/03_command-reference/get/account.md b/docs/02_cleos/03_command-reference/get/account.md old mode 100755 new mode 100644 index 8f38ebd6c9..4bc32d82cc --- a/docs/02_cleos/03_command-reference/get/account.md +++ b/docs/02_cleos/03_command-reference/get/account.md @@ -17,10 +17,10 @@ cleos get account eosio ``` ```console privileged: true -permissions: +permissions: owner 1: 1 EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV active 1: 1 EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV -memory: +memory: quota: -1 bytes used: 1.22 Mb net bandwidth: (averaged over 3 days) @@ -106,4 +106,4 @@ cleos get account eosio --json ``` ## See Also -- [Accounts and Permissions](https://developers.eos.io/welcome/latest/protocol/accounts_and_permissions) protocol document. +- [Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) protocol document. diff --git a/docs/02_cleos/03_command-reference/net/peers.md b/docs/02_cleos/03_command-reference/net/peers.md old mode 100755 new mode 100644 index 81b5adc612..359f89f792 --- a/docs/02_cleos/03_command-reference/net/peers.md +++ b/docs/02_cleos/03_command-reference/net/peers.md @@ -111,4 +111,4 @@ cleos -u http://127.0.0.1:8001 net peers ] ``` -**Note:** The `last_handshake` field contains the chain state of each connected peer as of the last handshake message with the node. For more information read the [Handshake Message](https://developers.eos.io/welcome/latest/protocol/network_peer_protocol#421-handshake-message) in the *Network Peer Protocol* document. +**Note:** The `last_handshake` field contains the chain state of each connected peer as of the last handshake message with the node. For more information read the [Handshake Message](/protocol-guides/03_network_peer_protocol.md#421-handshake-message) in the *Network Peer Protocol* document. diff --git a/docs/02_cleos/03_command-reference/net/status.md b/docs/02_cleos/03_command-reference/net/status.md old mode 100755 new mode 100644 index 55b9052a4b..4ed8a84bd0 --- a/docs/02_cleos/03_command-reference/net/status.md +++ b/docs/02_cleos/03_command-reference/net/status.md @@ -67,4 +67,4 @@ cleos -u http://127.0.0.1:8002 net status localhost:9001 } ``` -**Note:** The `last_handshake` field contains the chain state of the specified peer as of the last handshake message with the node. For more information read the [Handshake Message](https://developers.eos.io/welcome/latest/protocol/network_peer_protocol#421-handshake-message) in the *Network Peer Protocol* document. +**Note:** The `last_handshake` field contains the chain state of the specified peer as of the last handshake message with the node. For more information read the [Handshake Message](/protocol-guides/03_network_peer_protocol.md#421-handshake-message) in the *Network Peer Protocol* document. diff --git a/docs/02_cleos/03_command-reference/set/set-account.md b/docs/02_cleos/03_command-reference/set/set-account.md old mode 100755 new mode 100644 index e4ed9f6e32..304db1bb0d --- a/docs/02_cleos/03_command-reference/set/set-account.md +++ b/docs/02_cleos/03_command-reference/set/set-account.md @@ -88,4 +88,4 @@ The authority JSON object ... ``` ## See Also -- [Accounts and Permissions](https://developers.eos.io/welcome/latest/protocol/accounts_and_permissions) protocol document. +- [Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) protocol document. diff --git a/docs/02_cleos/03_command-reference/set/set-action.md b/docs/02_cleos/03_command-reference/set/set-action.md old mode 100755 new mode 100644 index cb8199739b..5b050d53b0 --- a/docs/02_cleos/03_command-reference/set/set-action.md +++ b/docs/02_cleos/03_command-reference/set/set-action.md @@ -40,7 +40,7 @@ cleos set action permission `-f,--force-unique` - force the transaction to be unique. this will consume extra bandwidth and remove any protections against accidently issuing the same transaction multiple times -`-s,--skip-sign` Specify if unlocked wallet keys +`-s,--skip-sign` Specify if unlocked wallet keys should be used to sign transaction `-j,--json` print result as json @@ -65,9 +65,9 @@ should be used to sign transaction #Link a `voteproducer` action to the 'voting' permissions cleos set action permission sandwichfarm eosio.system voteproducer voting -p sandwichfarm@voting -#Now can execute the transaction with the previously set permissions. +#Now can execute the transaction with the previously set permissions. cleos system voteproducer approve sandwichfarm someproducer -p sandwichfarm@voting ``` ## See Also -- [Accounts and Permissions](https://developers.eos.io/welcome/latest/protocol/accounts_and_permissions) protocol document. +- [Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) protocol document. diff --git a/docs/index.md b/docs/index.md index 76a5441fcd..0e98757754 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,7 +16,7 @@ Additional EOSIO Resources: * [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. [//]: # (THIS IS A COMMENT REMOVING BROKEN LINKS) -[//]: #Upgrade-Guide-20_upgrade-guide/index.md-EOSIO-version/protocol-upgrade-guide. +[//]: # (Upgrade-Guide-20_upgrade-guide/index.md-EOSIO-version/protocol-upgrade-guide.) [//]: # (Release Notes 30_release-notes/index.md - All release notes for this EOSIO version.) [[info | What's Next?]] diff --git a/tutorials/bios-boot-tutorial/README.md b/tutorials/bios-boot-tutorial/README.md index 970bcf8df4..c40a326470 100644 --- a/tutorials/bios-boot-tutorial/README.md +++ b/tutorials/bios-boot-tutorial/README.md @@ -47,5 +47,3 @@ $ git clone https://github.com/AntelopeIO/leap $ cd ./leap/tutorials/bios-boot-tutorial/ $ python3 bios-boot-tutorial.py --cleos=cleos --nodeos=nodeos --keosd=keosd --contracts-dir="${CONTRACTS_DIRECTORY}" -w -a ``` - -See [Developer Portal: Bios Boot Sequence](https://developers.eos.io/welcome/latest/tutorials/bios-boot-sequence) for additional information. From de0756acce535e58ef52e77d2be517b92901725a Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Fri, 5 Aug 2022 13:26:50 -0700 Subject: [PATCH 103/111] small fixes per review comments --- docs/01_nodeos/03_plugins/net_api_plugin/index.md | 2 +- docs/01_nodeos/03_plugins/net_plugin/index.md | 6 +++--- docs/01_nodeos/07_concepts/05_storage-and-read-modes.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/01_nodeos/03_plugins/net_api_plugin/index.md b/docs/01_nodeos/03_plugins/net_api_plugin/index.md index bf6bdfbf0d..658e643a0a 100644 --- a/docs/01_nodeos/03_plugins/net_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/net_api_plugin/index.md @@ -8,7 +8,7 @@ The `net_api_plugin` provides four RPC API endpoints: * connections * status -See [Net API Reference Documentation](http://docs.eosnetwork.com/reference/mandel-plugins/net_api.html). +See [Net API Reference Documentation](https://docs.eosnetwork.com/reference/mandel-plugins/net_api.html). [[caution | Caution]] | This plugin exposes endpoints that allow management of p2p connections. Running this plugin on a publicly accessible node is not recommended as it can be exploited. diff --git a/docs/01_nodeos/03_plugins/net_plugin/index.md b/docs/01_nodeos/03_plugins/net_plugin/index.md index a7762c922c..48bf266325 100644 --- a/docs/01_nodeos/03_plugins/net_plugin/index.md +++ b/docs/01_nodeos/03_plugins/net_plugin/index.md @@ -35,9 +35,9 @@ Config Options for eosio::net_plugin: indicates to node that only transactions 'trx' or blocks 'blk' should be sent. Examples: - p2p.domain.io:9876 - p2p.trx.domaine.io:9876:trx - p2p.blk.domain.io:9876:blk + p2p.example.org:9876 + p2p.trx.example.org:9876:trx + p2p.blk.example.org:9876:blk --p2p-max-nodes-per-host arg (=1) Maximum number of client nodes from any single IP address diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index 08f1f7ba81..c942a3bcb2 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -17,7 +17,7 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain ## EOSIO Interfaces -EOSIO provides a set of [services](../../) and [interfaces](http://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +EOSIO provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API From cd5a76f49f7d075c4a8fe530afb147078e4f08b6 Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 13:57:13 -0400 Subject: [PATCH 104/111] replace EOSIO refs with Antelope if applicable :doc --- .../00_build-unsupported-os.md | 2 +- docs/00_install/01_build-from-source/index.md | 2 +- docs/00_install/index.md | 14 +++++++------- .../02_node-setups/00_producing-node.md | 8 ++++---- .../02_node-setups/01_non-producing-node.md | 8 ++++---- .../00_local-single-node-testnet.md | 4 ++-- .../01_local-multi-node-testnet.md | 8 ++++---- .../03_development-environment/index.md | 2 +- .../01_nodeos/03_plugins/chain_plugin/index.md | 2 +- .../01_nodeos/03_plugins/login_plugin/index.md | 2 +- .../03_plugins/producer_plugin/index.md | 4 ++-- ...10_how-to-fast-start-without-old-history.md | 2 +- ...ow-to-replay-or-resync-with-full-history.md | 2 +- ...how-to-create-snapshot-with-full-history.md | 2 +- ...ow-to-restore-snapshot-with-full-history.md | 2 +- .../03_plugins/trace_api_plugin/index.md | 8 ++++---- docs/01_nodeos/06_logging/index.md | 4 ++-- .../07_concepts/05_storage-and-read-modes.md | 6 +++--- .../07_concepts/10_context-free-data/index.md | 2 +- docs/01_nodeos/08_troubleshooting/index.md | 4 ++-- docs/01_nodeos/index.md | 6 +++--- .../02_how-to-guides/how-to-create-a-wallet.md | 2 +- .../how-to-create-an-account.md | 10 +++++----- .../how-to-create-key-pairs.md | 6 +++--- .../how-to-delegate-CPU-resource.md | 6 +++--- .../how-to-delegate-net-resource.md | 6 +++--- .../how-to-deploy-a-smart-contract.md | 2 +- .../how-to-get-account-information.md | 10 +++++----- .../how-to-get-block-information.md | 4 ++-- .../how-to-get-transaction-information.md | 6 +++--- .../02_how-to-guides/how-to-import-a-key.md | 4 ++-- .../how-to-list-all-key-pairs.md | 4 ++-- .../03_command-reference/create/account.md | 2 +- .../03_command-reference/net/connect.md | 2 +- .../03_command-reference/net/disconnect.md | 2 +- .../02_cleos/03_command-reference/net/peers.md | 2 +- .../03_command-reference/net/status.md | 2 +- .../03_command-reference/set/set-account.md | 2 +- docs/02_cleos/04_troubleshooting.md | 2 +- docs/02_cleos/index.md | 6 +++--- docs/03_keosd/index.md | 4 ++-- docs/10_utilities/index.md | 6 +++--- docs/index.md | 18 +++++++++--------- 43 files changed, 101 insertions(+), 101 deletions(-) diff --git a/docs/00_install/01_build-from-source/00_build-unsupported-os.md b/docs/00_install/01_build-from-source/00_build-unsupported-os.md index a9988c0215..e5cffe252d 100644 --- a/docs/00_install/01_build-from-source/00_build-unsupported-os.md +++ b/docs/00_install/01_build-from-source/00_build-unsupported-os.md @@ -1,5 +1,5 @@ --- -content_title: Build EOSIO from Source on Other Unix-based OS +content_title: Build Antelope from Source on Other Unix-based OS --- **Please keep in mind that instructions for building from source on other unsupported operating systems provided here should be considered experimental and provided AS-IS on a best-effort basis and may not be fully featured.** diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index d2a817d01b..7cffd45e4a 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -1,5 +1,5 @@ --- -content_title: Build EOSIO from Source +content_title: Build Antelope from Source --- The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests. diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 23a61b3271..1d711083d3 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -1,26 +1,26 @@ --- -content_title: EOSIO Software Installation +content_title: Antelope Software Installation --- -The best way to install and use the EOSIO software is to build it from source: +The best way to install and use the Antelope software is to build it from source: -* [Build EOSIO from Source](01_build-from-source/index.md) +* [Build Antelope from Source](01_build-from-source/index.md) ## Supported Operating Systems -EOSIO currently supports the following operating systems: +Antelope currently supports the following operating systems: 1. Ubuntu 18.04 2. Ubuntu 20.04 3. Ubuntu 22.04 [[info | Note]] -| It may be possible to build and install EOSIO on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported. +| It may be possible to build and install Antelope on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported. -* [Build EOSIO on Other Unix-based Systems](01_build-from-source/00_build-unsupported-os.md) +* [Build Antelope on Other Unix-based Systems](01_build-from-source/00_build-unsupported-os.md) ## Docker Utilities for Node Execution (D.U.N.E.) -If you are using different operating system or prefer not to build EOSIO from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring EOSIO and doing contract development pretty much instantly +If you are using different operating system or prefer not to build Antelope from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring Antelope and doing contract development pretty much instantly * [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/eosnetworkfoundation/DUNE) diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index 7bb7d2a2ba..edcc593276 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -7,15 +7,15 @@ content_title: Producing Node Setup ## Goal -This section describes how to set up a producing node within the EOSIO network. A producing node, as its name implies, is a node that is configured to produce blocks in an `EOSIO` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). +This section describes how to set up a producing node within the Antelope network. A producing node, as its name implies, is a node that is configured to produce blocks in an `Antelope` based blockchain. This functionality if provided through the `producer_plugin` as well as other [Nodeos Plugins](../../03_plugins/index.md). ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) -[//]: # ( If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -53,7 +53,7 @@ producer-name = youraccount You will need to set the private key for your producer. The public key should have an authority for the producer account defined above. `signature-provider` is defined with a 3-field tuple: -* `public-key` - A valid EOSIO public key in form of a string. +* `public-key` - A valid Antelope public key in form of a string. * `provider-spec` - It's a string formatted like `:` * `provider-type` - KEY or KEOSD diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index b85a014c34..b0e5c9cc31 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -4,15 +4,15 @@ content_title: Non-producing Node Setup ## Goal -This section describes how to set up a non-producing node within the EOSIO network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `EOSIO` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. +This section describes how to set up a non-producing node within the Antelope network. A non-producing node is a node that is not configured to produce blocks, instead it is connected and synchronized with other peers from an `Antelope` based blockchain, exposing one or more services publicly or privately by enabling one or more [Nodeos Plugins](../../03_plugins/index.md), except the `producer_plugin`. ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT NEXT LINK CONTAINS A BROKEN LINK ) -[//]: # ( If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -41,4 +41,4 @@ nodeos ... --p2p-peer-address=106.10.42.238:9876 ### 2. Enable one or more available plugins -Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the EOSIO RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. +Each available plugin is listed and detailed in the [Nodeos Plugins](../../03_plugins/index.md) section. When `nodeos` starts, it will expose the functionality provided by the enabled plugins it was started with. For example, if you start `nodeos` with [`state_history_plugin`](../../03_plugins/state_history_plugin/index.md) enabled, you will have a non-producing node that offers full blockchain history. If you start `nodeos` with [`http_plugin`](../../03_plugins/http_plugin/index.md) enabled, you will have a non-producing node which exposes the Antelope RPC API. Therefore, you can extend the basic functionality provided by a non-producing node by enabling any number of existing plugins on top of it. Another aspect to consider is that some plugins have dependencies to other plugins. Therefore, you need to satisfy all dependencies for a plugin in order to enable it. diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index 4b0f8d1b56..a55d817774 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -12,11 +12,11 @@ This section describes how to set up a single-node blockchain configuration runn ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # (THIS IS A COMMENT, NEXT LINK HAS BROKEN LINK) -[//]: # (If you built EOSIO using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) +[//]: # (If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 698f0414de..52a7c8dfb8 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -10,7 +10,7 @@ This section describes how to set up a multi-node blockchain configuration runni ## Before you begin -* [Install the EOSIO software](../../../00_install/index.md) before starting this section. +* [Install the Antelope software](../../../00_install/index.md) before starting this section. * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. @@ -20,7 +20,7 @@ Open four "terminal" windows and perform the following steps: 1. [Start the Wallet Manager](#1-start-the-wallet-manager) 2. [Create a Default Wallet](#2-create-a-default-wallet) -3. [Loading the EOSIO Key](#3-loading-the-eosio-key) +3. [Loading the Antelope Key](#3-loading-the-eosio-key) 4. [Start the First Producer Node](#4-start-the-first-producer-node) 5. [Start the Second Producer Node](#5-start-the-second-producer-node) 6. [Get Nodes Info](#6-get-nodes-info) @@ -66,7 +66,7 @@ Without password imported keys will not be retrievable. `keosd` will generate some status output in its window. We will continue to use this second window for subsequent `cleos` commands. -### 3. Loading the EOSIO Key +### 3. Loading the Antelope Key The private blockchain launched in the steps above is created with a default initial key which must be loaded into the wallet. @@ -90,7 +90,7 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node -The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the EOSIO binaries. +The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the Antelope binaries. To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index 9305397d45..4ed1302c63 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -23,7 +23,7 @@ Try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundatio ## Third-Party Testnets -The following third-party testnets are available for testing EOSIO dApps and smart contracts: +The following third-party testnets are available for testing Antelope dApps and smart contracts: * Jungle Testnet [monitor](https://monitor.jungletestnet.io/), [website](https://jungletestnet.io/) * [CryptoKylin Testnet](https://www.cryptokylin.io/) diff --git a/docs/01_nodeos/03_plugins/chain_plugin/index.md b/docs/01_nodeos/03_plugins/chain_plugin/index.md index 9da5921080..1d284edffa 100644 --- a/docs/01_nodeos/03_plugins/chain_plugin/index.md +++ b/docs/01_nodeos/03_plugins/chain_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `chain_plugin` is a core plugin required to process and aggregate chain data on an EOSIO node. +The `chain_plugin` is a core plugin required to process and aggregate chain data on an Antelope node. ## Usage diff --git a/docs/01_nodeos/03_plugins/login_plugin/index.md b/docs/01_nodeos/03_plugins/login_plugin/index.md index 68df9d4c1e..09ebf2be74 100644 --- a/docs/01_nodeos/03_plugins/login_plugin/index.md +++ b/docs/01_nodeos/03_plugins/login_plugin/index.md @@ -1,6 +1,6 @@ ## Description -The `login_plugin` supports the concept of applications authenticating with the EOSIO blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. +The `login_plugin` supports the concept of applications authenticating with the Antelope blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority. ## Usage diff --git a/docs/01_nodeos/03_plugins/producer_plugin/index.md b/docs/01_nodeos/03_plugins/producer_plugin/index.md index 66e1b0077f..6fce1fd71f 100644 --- a/docs/01_nodeos/03_plugins/producer_plugin/index.md +++ b/docs/01_nodeos/03_plugins/producer_plugin/index.md @@ -49,7 +49,7 @@ Config Options for eosio::producer_plugin: = Where: is a string form of - a vaild EOSIO public + a vaild Antelope public key is a string in the @@ -59,7 +59,7 @@ Config Options for eosio::producer_plugin: is KEY, or KEOSD KEY: is a string form of - a valid EOSIO + a valid Antelope private key which maps to the provided public key diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md index 962b9e711c..43c9536410 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/10_how-to-fast-start-without-old-history.md @@ -8,7 +8,7 @@ This procedure records the current chain state and future history, without previ ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md index 9f0a7308f0..8b29bf6919 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/20_how-to-replay-or-resync-with-full-history.md @@ -8,7 +8,7 @@ This procedure records the entire chain history. ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md index 19d69e9c28..a81bfe15f5 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/30_how-to-create-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure creates a database containing the chain state, with full history ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md index 52e3b27e5e..364b2f91f7 100644 --- a/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md +++ b/docs/01_nodeos/03_plugins/state_history_plugin/40_how-to-restore-snapshot-with-full-history.md @@ -8,7 +8,7 @@ This procedure restores an existing snapshot with full history, so the node can ## Before you begin -* Make sure [EOSIO is installed](../../../00_install/index.md). +* Make sure [Antelope is installed](../../../00_install/index.md). * Learn about [Using Nodeos](../../02_usage/index.md). * Get familiar with [state_history_plugin](../../03_plugins/state_history_plugin/index.md). diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md index 74d1215ec0..b9822780fd 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/index.md @@ -5,11 +5,11 @@ The `trace_api_plugin` provides a consumer-focused long-term API for retrieving ## Purpose -While integrating applications such as block explorers and exchanges with an EOSIO blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: +While integrating applications such as block explorers and exchanges with an Antelope blockchain, the user might require a complete transcript of actions processed by the blockchain, including those spawned from the execution of smart contracts and scheduled transactions. The `trace_api_plugin` serves this need. The purpose of the plugin is to provide: * A transcript of retired actions and related metadata * A consumer-focused long-term API to retrieve blocks -* Maintainable resource commitments at the EOSIO nodes +* Maintainable resource commitments at the Antelope nodes Therefore, one crucial goal of the `trace_api_plugin` is to improve the maintenance of node resources (file system, disk space, memory used, etc.). This goal is different from the existing `history_plugin` which provides far more configurable filtering and querying capabilities, or the existing `state_history_plugin` which provides a binary streaming interface to access structural chain data, action data, as well as state deltas. @@ -101,7 +101,7 @@ nodeos ... --plugin eosio::chain_plugin [options] \ ## Configuration Example -Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some EOSIO reference contracts: +Here is a `nodeos` configuration example for the `trace_api_plugin` when tracing some Antelope reference contracts: ```sh nodeos --data-dir data_dir --config-dir config_dir --trace-dir traces_dir @@ -191,7 +191,7 @@ If resource usage cannot be effectively managed via the `trace-minimum-irreversi ## Manual Maintenance -The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed EOSIO system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). +The `trace-dir` option defines the directory on the filesystem where the trace log files are stored by the `trace_api_plugin`. These files are stable once the LIB block has progressed past a given slice and then can be deleted at any time to reclaim filesystem space. The deployed Antelope system will tolerate any out-of-process management system that removes some or all of these files in this directory regardless of what data they represent, or whether there is a running `nodeos` instance accessing them or not. Data which would nominally be available, but is no longer so due to manual maintenance, will result in a HTTP 404 response from the appropriate API endpoint(s). [[info | For node operators]] | Node operators can take full control over the lifetime of the historical data available in their nodes via the `trace-api-plugin` and the `trace-minimum-irreversible-history-blocks` and `trace-minimum-uncompressed-irreversible-history-blocks` options in conjunction with any external filesystem resource manager. diff --git a/docs/01_nodeos/06_logging/index.md b/docs/01_nodeos/06_logging/index.md index 8a7670e7fb..910db0928a 100644 --- a/docs/01_nodeos/06_logging/index.md +++ b/docs/01_nodeos/06_logging/index.md @@ -6,7 +6,7 @@ Logging for `nodeos` is controlled by the `logging.json` file. CLI options can b ## Appenders -The logging library built into EOSIO supports two appender types: +The logging library built into Antelope supports two appender types: - [Console](#console) - [GELF](#gelf) (Graylog Extended Log Format) @@ -74,7 +74,7 @@ Example: ## Loggers -The logging library built into EOSIO currently supports the following loggers: +The logging library built into Antelope currently supports the following loggers: - `default` - the default logger, always enabled. - `net_plugin_impl` - detailed logging for the net plugin. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index c942a3bcb2..0965fdf298 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -2,7 +2,7 @@ content_title: Storage and Read Modes --- -The EOSIO platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) +The Antelope platform stores blockchain information in various data structures at various stages of a transaction's lifecycle. Some of these are described below. The producing node is the `nodeos` instance run by the block producer who is currently creating blocks for the blockchain (which changes every 6 seconds, producing 12 blocks in sequence before switching to another producer.) ## Blockchain State and Storage @@ -15,9 +15,9 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain * The `pending block` is an in memory block containing transactions as they are processed and pushed into the block; this will/may eventually become the head block. If the `nodeos` instance is the producing node, the pending block is distributed to other `nodeos` instances. * Outside the chain state, block data is cached in RAM until it becomes final/irreversible; especifically the signed block itself. After the last irreversible block (LIB) catches up to the block, that block is then retrieved from the irreversible blocks log. -## EOSIO Interfaces +## Antelope Interfaces -EOSIO provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +Antelope provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API diff --git a/docs/01_nodeos/07_concepts/10_context-free-data/index.md b/docs/01_nodeos/07_concepts/10_context-free-data/index.md index 0a31072bcb..5ee2aeebba 100644 --- a/docs/01_nodeos/07_concepts/10_context-free-data/index.md +++ b/docs/01_nodeos/07_concepts/10_context-free-data/index.md @@ -4,7 +4,7 @@ link_text: Context-Free Data --- ## Overview -The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, EOSIO blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. +The immutable nature of the blockchain allows data to be stored securely while also enforcing the integrity of such data. However, this benefit also complicates the removal of non-essential data from the blockchain. Consequently, Antelope blockchains contain a special section within the transaction, called the *context-free data*. As its name implies, data stored in the context-free data section is considered free of previous contexts or dependencies, which makes their potential removal possible. More importantly, such removal can be performed safely without compromising the integrity of the blockchain. ## Concept The goal of context-free data is to allow blockchain applications the option to store non-essential information within a transaction. Some examples of context-free data include: diff --git a/docs/01_nodeos/08_troubleshooting/index.md b/docs/01_nodeos/08_troubleshooting/index.md index 7aa22031d8..2d813a018b 100644 --- a/docs/01_nodeos/08_troubleshooting/index.md +++ b/docs/01_nodeos/08_troubleshooting/index.md @@ -28,7 +28,7 @@ Command Line Options for eosio::chain_plugin: Start `nodeos` with `--shared-memory-size-mb 1024`. A 1 GB shared memory file allows approximately half a million transactions. -### What version of EOSIO am I running/connecting to? +### What version of Antelope am I running/connecting to? If defaults can be used, then `cleos get info` will output a block that contains a field called `server_version`. If your `nodeos` is not using the defaults, then you need to know the URL of the `nodeos`. In that case, use the following with your `nodeos` URL: @@ -44,4 +44,4 @@ cleos --url http://localhost:8888 get info | grep server_version ### Error 3070000: WASM Exception Error -If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an EOSIO-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. +If you try to deploy the `eosio.bios` contract or `eosio.system` contract in an attempt to boot an Antelope-based blockchain and you get the following error or similar: `Publishing contract... Error 3070000: WASM Exception Error Details: env.set_proposed_producers_ex unresolveable`, it is because you have to activate the `PREACTIVATE_FEATURE` protocol first. diff --git a/docs/01_nodeos/index.md b/docs/01_nodeos/index.md index 9877dc16a9..c31e5f3a82 100644 --- a/docs/01_nodeos/index.md +++ b/docs/01_nodeos/index.md @@ -4,11 +4,11 @@ content_title: Nodeos ## Introduction -`nodeos` is the core service daemon that runs on every EOSIO node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. +`nodeos` is the core service daemon that runs on every Antelope node. It can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. ## Installation -`nodeos` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [EOSIO Software Installation](../00_install/index.md) section. +`nodeos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [Antelope Software Installation](../00_install/index.md) section. ## Explore @@ -23,4 +23,4 @@ Navigate the sections below to configure and use `nodeos`. * [Troubleshooting](08_troubleshooting/index.md) - Common `nodeos` troubleshooting questions. [[info | Access Node]] -| A local or remote EOSIO access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. +| A local or remote Antelope access node running `nodeos` is required for a client application or smart contract to interact with the blockchain. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md index 06e3ff199b..a69e76c768 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-a-wallet.md @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. * Understand [Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) in the protocol documents. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md index 1fd79840ff..69030e4477 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-an-account.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to create a new EOSIO blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. +This how-to guide provides instructions on how to create a new Antelope blockchain account using the `cleos` CLI tool. You can use accounts to deploy smart contracts and perform other related blockchain operations. Create one or multiple accounts as part of your development environment setup. The example in this how-to guide creates a new account named **bob**, authorized by the default system account **eosio**, using the `cleos` CLI tool. @@ -10,8 +10,8 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about [EOSIO Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) +| The cleos tool is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install the cleos tool. +* Learn about [Antelope Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) * Learn about Asymmetric Cryptography - [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) pairs. * Create public/private keypairs for the `owner` and `active` permissions of an account. @@ -34,7 +34,7 @@ cleos create account eosio bob EOS87TQktA5RVse2EguhztfQVEh6XXxBmgkU8b4Y5YnGvtYAo * `bob` = the name of the new account conforming to [account naming conventions](/protocol-guides/04_accounts_and_permissions.md#2-accounts) * `EOS87TQ...AoLGNN` = the owner public key or permission level for the new account (**required**) [[info | Note]] -| To create a new account in the EOSIO blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created EOSIO blockchain, the default system account used to create a new account is **eosio**. +| To create a new account in the Antelope blockchain, an existing account, also referred to as a creator account, is required to authorize the creation of a new account. For a newly created Antelope blockchain, the default system account used to create a new account is **eosio**. **Example Output** @@ -46,4 +46,4 @@ warning: transaction executed locally, but may not be confirmed by the network y ### Summary -By following these instructions, you are able to create a new EOSIO account in your blockchain environment. +By following these instructions, you are able to create a new Antelope account in your blockchain environment. diff --git a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md index e3e298aefe..16615039c5 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-create-key-pairs.md @@ -1,14 +1,14 @@ ## Overview -This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to create a keypair consisting of a public key and a private key for signing transactions in an Antelope blockchain. ## Before you begin Make sure you meet the following requirements: * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. -* Learn about asymmetric cryptography (public and private keypair) in the context of an EOSIO blockchain. +| The cleos tool is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install the cleos tool. +* Learn about asymmetric cryptography (public and private keypair) in the context of an Antelope blockchain. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 00d977278a..65003d0e2e 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. -* Understand [CPU bandwidth](/glossary.md#cpu) in an EOSIO blockchain. -* Understand [NET bandwidth](/glossary.md#net) in an EOSIO blockchain. +* Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. +* Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index c3bd8d8bd8..6db305abdb 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -10,12 +10,12 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. -* Understand [NET bandwidth](/glossary.md#net) in an EOSIO blockchain. -* Understand [CPU bandwidth](/glossary.md#cpu) in an EOSIO blockchain. +* Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. +* Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md index 32fcce2c00..c7f0bfb18d 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md +++ b/docs/02_cleos/02_how-to-guides/how-to-deploy-a-smart-contract.md @@ -1,6 +1,6 @@ ## Goal -Deploy an EOSIO contract +Deploy an Antelope contract ## Before you begin diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md index 1213c0ac51..79d320a8aa 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-account-information.md @@ -1,15 +1,15 @@ ## Overview -This how-to guide provides instructions on how to query infomation of an EOSIO account. The example in this how-to guide retrieves information of the `eosio` account. +This how-to guide provides instructions on how to query infomation of an Antelope account. The example in this how-to guide retrieves information of the `eosio` account. ## Before you begin * Install the currently supported version of `cleos` [[info | Note]] -| The cleos tool is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install the cleos tool. +| The cleos tool is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install the cleos tool. -* Acquire functional understanding of [EOSIO Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) +* Acquire functional understanding of [Antelope Accounts and Permissions](/protocol-guides/04_accounts_and_permissions.md) ## Command Reference @@ -28,7 +28,7 @@ cleos get account eosio ``` **Where**: -* `eosio` = The name of the default system account in the EOSIO blockchain. +* `eosio` = The name of the default system account in the Antelope blockchain. **Example Output** @@ -53,4 +53,4 @@ cpu bandwidth: ``` [[info | Account Fields]] -| Depending on the EOSIO network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. +| Depending on the Antelope network you are connected, you might see different fields associated with an account. That depends on which system contract has been deployed on the network. diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md index 216413ed1e..9914cc40b1 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-block-information.md @@ -10,10 +10,10 @@ Make sure to meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what a [block](/glossary.md#block) is and its role in the blockchain. -* Understand the [block lifecycle](/protocol-guides/01_consensus_protocol.md#5-block-lifecycle) in the EOSIO consensus protocol. +* Understand the [block lifecycle](/protocol-guides/01_consensus_protocol.md#5-block-lifecycle) in the Antelope consensus protocol. ## Steps diff --git a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md index 717d6b225a..e40a2e2225 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md +++ b/docs/02_cleos/02_how-to-guides/how-to-get-transaction-information.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to retrieve infomation of an EOSIO transaction using a transaction ID. +This how-to guide provides instructions on how to retrieve infomation of an Antelope transaction using a transaction ID. The example in this how-to retrieves transaction information associated with the creation of the account **bob**. @@ -9,8 +9,8 @@ The example in this how-to retrieves transaction information associated with the Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. -* Understand how transactions work in an EOSIO blockchain. For more information on transactions, see the [Transactions Protocol](/protocol-guides/02_transactions_protocol.md) section. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. +* Understand how transactions work in an Antelope blockchain. For more information on transactions, see the [Transactions Protocol](/protocol-guides/02_transactions_protocol.md) section. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md index d2cf0d0f4c..cf17414d4b 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md +++ b/docs/02_cleos/02_how-to-guides/how-to-import-a-key.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to import a private key into the `keosd` default wallet. You can use the private key to authorize transactions in an Antelope blockchain. ## Before you Begin @@ -11,7 +11,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet import`](../03_command-reference/wallet/import.md) command. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) is. ## Command Reference diff --git a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md index 2241458075..afcf1956c3 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md +++ b/docs/02_cleos/02_how-to-guides/how-to-list-all-key-pairs.md @@ -1,6 +1,6 @@ ## Overview -This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an EOSIO blockchain. +This how-to guide provides instructions on how to list all public keys and public/private key pairs within the `keosd` default wallet. You can use the public and private keys to authorize transactions in an Antelope blockchain. The example in this how-to guide displays all public keys and public/private key pairs stored within the existing default wallet. @@ -13,7 +13,7 @@ Make sure you meet the following requirements: * Familiarize with the [`cleos wallet`](../03_command-reference/wallet/index.md) commands. * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../00_install/index.md) will also install `cleos`. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. * Understand what a [public key](/glossary.md#public-key) and [private key](/glossary.md#private-key) is. ## Command Reference diff --git a/docs/02_cleos/03_command-reference/create/account.md b/docs/02_cleos/03_command-reference/create/account.md index 976c986f56..2dce43ba81 100755 --- a/docs/02_cleos/03_command-reference/create/account.md +++ b/docs/02_cleos/03_command-reference/create/account.md @@ -30,7 +30,7 @@ Options: ``` ## Command -A set of EOSIO keys is required to create an account. The EOSIO keys can be generated by using `cleos create key`. +A set of Antelope keys is required to create an account. The Antelope keys can be generated by using `cleos create key`. ```sh cleos create account inita tester EOS4toFS3YXEQCkuuw1aqDLrtHim86Gz9u3hBdcBw5KNPZcursVHq EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA diff --git a/docs/02_cleos/03_command-reference/net/connect.md b/docs/02_cleos/03_command-reference/net/connect.md index 646762cf1d..777a9c4852 100755 --- a/docs/02_cleos/03_command-reference/net/connect.md +++ b/docs/02_cleos/03_command-reference/net/connect.md @@ -30,7 +30,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/disconnect.md b/docs/02_cleos/03_command-reference/net/disconnect.md index d375c4b239..1cd269e83b 100755 --- a/docs/02_cleos/03_command-reference/net/disconnect.md +++ b/docs/02_cleos/03_command-reference/net/disconnect.md @@ -28,7 +28,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/peers.md b/docs/02_cleos/03_command-reference/net/peers.md index 359f89f792..39bdc5190e 100644 --- a/docs/02_cleos/03_command-reference/net/peers.md +++ b/docs/02_cleos/03_command-reference/net/peers.md @@ -27,7 +27,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/net/status.md b/docs/02_cleos/03_command-reference/net/status.md index 4ed8a84bd0..5a179e1705 100644 --- a/docs/02_cleos/03_command-reference/net/status.md +++ b/docs/02_cleos/03_command-reference/net/status.md @@ -30,7 +30,7 @@ Make sure you meet the following requirements: * Install the currently supported version of `cleos`. [[info | Note]] -| `cleos` is bundled with the EOSIO software. [Installing EOSIO](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. +| `cleos` is bundled with the Antelope software. [Installing Antelope](../../../00_install/index.md) will also install the `cleos` and `keosd` command line tools. * You have access to a producing node instance with the [`net_api_plugin`](../../../01_nodeos/03_plugins/net_api_plugin/index.md) loaded. ## Examples diff --git a/docs/02_cleos/03_command-reference/set/set-account.md b/docs/02_cleos/03_command-reference/set/set-account.md index 304db1bb0d..a06a4383eb 100644 --- a/docs/02_cleos/03_command-reference/set/set-account.md +++ b/docs/02_cleos/03_command-reference/set/set-account.md @@ -2,7 +2,7 @@ set parameters dealing with account permissions [[info | JSON input]] -| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the EOSIO software. +| This command involves specifying JSON input which depends on underlying class definitions. Therefore, such JSON input is subject to change in future versions of the Antelope software. ## Positionals - `account` _TEXT_ - The account to set/delete a permission authority for diff --git a/docs/02_cleos/04_troubleshooting.md b/docs/02_cleos/04_troubleshooting.md index 63250119e9..68a673b4f3 100644 --- a/docs/02_cleos/04_troubleshooting.md +++ b/docs/02_cleos/04_troubleshooting.md @@ -20,4 +20,4 @@ Replace API_ENDPOINT and PORT with your remote `nodeos` API endpoint detail ## "Missing Authorizations" -That means you are not using the required authorizations. Most likely you are not using correct EOSIO account or permission level to sign the transaction +That means you are not using the required authorizations. Most likely you are not using correct Antelope account or permission level to sign the transaction diff --git a/docs/02_cleos/index.md b/docs/02_cleos/index.md index fbe3ca8d30..c0d320ad80 100644 --- a/docs/02_cleos/index.md +++ b/docs/02_cleos/index.md @@ -4,11 +4,11 @@ content_title: Cleos ## Introduction -`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test EOSIO smart contracts. +`cleos` is a command line tool that interfaces with the REST API exposed by `nodeos`. Developers can also use `cleos` to deploy and test Antelope smart contracts. ## Installation -`cleos` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [EOSIO Software Installation](../00_install/index.md) section. +`cleos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Using Cleos @@ -23,7 +23,7 @@ cleos --help ``` ```console -Command Line Interface to EOSIO Client +Command Line Interface to Antelope Client Usage: cleos [OPTIONS] SUBCOMMAND Options: diff --git a/docs/03_keosd/index.md b/docs/03_keosd/index.md index cfd45cb9de..7142237112 100644 --- a/docs/03_keosd/index.md +++ b/docs/03_keosd/index.md @@ -8,11 +8,11 @@ content_title: Keosd ## Installation -`keosd` is distributed as part of the [EOSIO software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [EOSIO Software Installation](../00_install/index.md) section. +`keosd` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Operation When a wallet is unlocked with the corresponding password, `cleos` can request `keosd` to sign a transaction with the appropriate private keys. Also, `keosd` provides support for hardware-based wallets such as Secure Encalve and YubiHSM. [[info | Audience]] -| `keosd` is intended to be used by EOSIO developers only. +| `keosd` is intended to be used by Antelope developers only. diff --git a/docs/10_utilities/index.md b/docs/10_utilities/index.md index 747c95cb72..35e014ffb2 100644 --- a/docs/10_utilities/index.md +++ b/docs/10_utilities/index.md @@ -1,9 +1,9 @@ --- -content_title: EOSIO Utilities -link_text: EOSIO Utilities +content_title: Antelope Utilities +link_text: Antelope Utilities --- -This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other EOSIO software: +This section contains documentation for additional utilities that complement or extend `nodeos` and potentially other Antelope software: * [eosio-blocklog](eosio-blocklog.md) - Low-level utility for node operators to interact with block log files. * [trace_api_util](trace_api_util.md) - Low-level utility for performing tasks associated with the [Trace API](../01_nodeos/03_plugins/trace_api_plugin/index.md). diff --git a/docs/index.md b/docs/index.md index 0e98757754..cad35b6b99 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,23 +1,23 @@ --- -content_title: EOSIO Overview +content_title: Antelope Overview --- -EOSIO is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. EOSIO comes with a number of programs. The primary ones included in EOSIO are the following: +Antelope is the next-generation blockchain platform for creating and deploying smart contracts and distributed applications. Antelope comes with a number of programs. The primary ones included in Antelope are the following: * [Nodeos](01_nodeos/index.md) - Core service daemon that runs a node for block production, API endpoints, or local development. * [Cleos](02_cleos/index.md) - Command line interface to interact with the blockchain (via `nodeos`) and manage wallets (via `keosd`). -* [Keosd](03_keosd/index.md) - Component that manages EOSIO keys in wallets and provides a secure enclave for digital signing. +* [Keosd](03_keosd/index.md) - Component that manages Antelope keys in wallets and provides a secure enclave for digital signing. The basic relationship between these components is illustrated in the diagram below. -![EOSIO components](mandel_components.png) +![Antelope components](mandel_components.png) -Additional EOSIO Resources: -* [EOSIO Utilities](10_utilities/index.md) - Utilities that complement the EOSIO software. +Additional Antelope Resources: +* [Antelope Utilities](10_utilities/index.md) - Utilities that complement the Antelope software. [//]: # (THIS IS A COMMENT REMOVING BROKEN LINKS) -[//]: # (Upgrade-Guide-20_upgrade-guide/index.md-EOSIO-version/protocol-upgrade-guide.) -[//]: # (Release Notes 30_release-notes/index.md - All release notes for this EOSIO version.) +[//]: # (Upgrade-Guide-20_upgrade-guide/index.md-antelope-version/protocol-upgrade-guide.) +[//]: # (Release Notes 30_release-notes/index.md - All release notes for this Antelope version.) [[info | What's Next?]] -| [Install the EOSIO Software](00_install/index.md) before exploring the sections above. +| [Install the Antelope Software](00_install/index.md) before exploring the sections above. From 1f0b40f1aa6b89196ebf5bf226ba791fc3993d7e Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 15:47:48 -0400 Subject: [PATCH 105/111] fix existing docs.eosnetwork.com links :doc --- docs/01_nodeos/03_plugins/net_api_plugin/index.md | 2 +- docs/01_nodeos/07_concepts/05_storage-and-read-modes.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/01_nodeos/03_plugins/net_api_plugin/index.md b/docs/01_nodeos/03_plugins/net_api_plugin/index.md index 658e643a0a..af16d5c918 100644 --- a/docs/01_nodeos/03_plugins/net_api_plugin/index.md +++ b/docs/01_nodeos/03_plugins/net_api_plugin/index.md @@ -8,7 +8,7 @@ The `net_api_plugin` provides four RPC API endpoints: * connections * status -See [Net API Reference Documentation](https://docs.eosnetwork.com/reference/mandel-plugins/net_api.html). +See [Net API Reference Documentation](https://docs.eosnetwork.com/leap-plugins/latest/net.api/). [[caution | Caution]] | This plugin exposes endpoints that allow management of p2p connections. Running this plugin on a publicly accessible node is not recommended as it can be exploited. diff --git a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md index 0965fdf298..8fb138d5f3 100644 --- a/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md +++ b/docs/01_nodeos/07_concepts/05_storage-and-read-modes.md @@ -17,7 +17,7 @@ Every `nodeos` instance creates some internal files to housekeep the blockchain ## Antelope Interfaces -Antelope provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/reference/mandel-cdt/files.html) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. +Antelope provides a set of [services](../../) and [interfaces](https://docs.eosnetwork.com/cdt/latest/reference/Files/) that enable contract developers to persist state across action, and consequently transaction, boundaries. Contracts may use these services and interfaces for various purposes. For example, `eosio.token` contract keeps balances for all users in the chain database. Each instance of `nodeos` keeps the database in memory, so contracts can read and write data with ease. ### Nodeos RPC API From 2599b8d0d9c0dab6962c1d5c66bb6d94a525a9a4 Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 16:07:17 -0400 Subject: [PATCH 106/111] curate github and eosnetwork.com links :doc --- docs/00_install/01_build-from-source/00_build-unsupported-os.md | 2 +- docs/00_install/01_build-from-source/index.md | 2 +- docs/00_install/index.md | 2 +- docs/01_nodeos/02_usage/03_development-environment/index.md | 2 +- docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md | 2 +- docs/01_nodeos/index.md | 2 +- docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md | 2 +- docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md | 2 +- docs/02_cleos/index.md | 2 +- docs/03_keosd/index.md | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/00_install/01_build-from-source/00_build-unsupported-os.md b/docs/00_install/01_build-from-source/00_build-unsupported-os.md index e5cffe252d..e0d3c19331 100644 --- a/docs/00_install/01_build-from-source/00_build-unsupported-os.md +++ b/docs/00_install/01_build-from-source/00_build-unsupported-os.md @@ -6,7 +6,7 @@ content_title: Build Antelope from Source on Other Unix-based OS ### Using DUNE -For the official multi-platform support try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) which runs in an ubuntu image via a docker container. +For the official multi-platform support try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) which runs in an ubuntu image via a docker container. **A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes. diff --git a/docs/00_install/01_build-from-source/index.md b/docs/00_install/01_build-from-source/index.md index 7cffd45e4a..b2a4a63513 100644 --- a/docs/00_install/01_build-from-source/index.md +++ b/docs/00_install/01_build-from-source/index.md @@ -6,7 +6,7 @@ The shell scripts previously recommended for building the software have been rem ### Using DUNE -As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) for the easiest way to get started, and for multi-platform support. +As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started, and for multi-platform support. ### Building From Source diff --git a/docs/00_install/index.md b/docs/00_install/index.md index 1d711083d3..4e9bf6eff2 100644 --- a/docs/00_install/index.md +++ b/docs/00_install/index.md @@ -23,4 +23,4 @@ Antelope currently supports the following operating systems: If you are using different operating system or prefer not to build Antelope from source you can try our Docker - based set of utilities called DUNE that can get you started with exploring Antelope and doing contract development pretty much instantly -* [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/eosnetworkfoundation/DUNE) +* [Docker Utilities for Node Execution (D.U.N.E.)](https://github.com/AntelopeIO/DUNE) diff --git a/docs/01_nodeos/02_usage/03_development-environment/index.md b/docs/01_nodeos/02_usage/03_development-environment/index.md index 4ed1302c63..f5efbeef4f 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/index.md +++ b/docs/01_nodeos/02_usage/03_development-environment/index.md @@ -19,7 +19,7 @@ While this option can technically be used for smart contract development, it may ## Official Testing Node -Try [Docker Utilities for Node Execution](https://github.com/eosnetworkfoundation/DUNE) for the easiest way to get started, and for multi-platform support. +Try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started, and for multi-platform support. ## Third-Party Testnets diff --git a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md index efbb5a0204..8b784d0a34 100644 --- a/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md +++ b/docs/01_nodeos/03_plugins/txn_test_gen_plugin/index.md @@ -4,7 +4,7 @@ The `txn_test_gen_plugin` is used for transaction test purposes. [[info | For More Information]] -For more information, check the [txn_test_gen_plugin/README.md](https://github.com/eosnetworkfoundation/mandel/tree/main/plugins/txn_test_gen_plugin) on the EOSIO/eos repository. +For more information, check the [txn_test_gen_plugin/README.md](https://github.com/AntelopeIO/leap/tree/main/plugins/txn_test_gen_plugin) on the `AntelopeIO/leap` repository. ## Usage diff --git a/docs/01_nodeos/index.md b/docs/01_nodeos/index.md index c31e5f3a82..51d749230e 100644 --- a/docs/01_nodeos/index.md +++ b/docs/01_nodeos/index.md @@ -8,7 +8,7 @@ content_title: Nodeos ## Installation -`nodeos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `nodeos`, visit the [Antelope Software Installation](../00_install/index.md) section. +`nodeos` is distributed as part of the [Antelope software suite](https://github.com/AntelopeIO/leap). To install `nodeos`, visit the [Antelope Software Installation](../00_install/index.md) section. ## Explore diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md index 65003d0e2e..ab15bdbfe2 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-CPU-resource.md @@ -12,7 +12,7 @@ Make sure you meet the following requirements: [[info | Note]] | `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. -* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. +* Ensure the reference system contracts from [`reference-contracts`](https://github.com/AntelopeIO/reference-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. * Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. * Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. diff --git a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md index 6db305abdb..c009cb31ca 100644 --- a/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md +++ b/docs/02_cleos/02_how-to-guides/how-to-delegate-net-resource.md @@ -12,7 +12,7 @@ Make sure you meet the following requirements: [[info | Note]] | `cleos` is bundled with the Antelope software. [Installing Antelope](../../00_install/index.md) will also install `cleos`. -* Ensure the reference system contracts from [`eosio.contracts`](https://github.com/eosnetworkfoundation/mandel-contracts) repository is deployed and used to manage system resources. +* Ensure the reference system contracts from [`reference-contracts`](https://github.com/AntelopeIO/reference-contracts) repository is deployed and used to manage system resources. * Understand what an [account](/glossary.md#account) is and its role in the blockchain. * Understand [NET bandwidth](/glossary.md#net) in an Antelope blockchain. * Understand [CPU bandwidth](/glossary.md#cpu) in an Antelope blockchain. diff --git a/docs/02_cleos/index.md b/docs/02_cleos/index.md index c0d320ad80..e779146036 100644 --- a/docs/02_cleos/index.md +++ b/docs/02_cleos/index.md @@ -8,7 +8,7 @@ content_title: Cleos ## Installation -`cleos` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `cleos` just visit the [Antelope Software Installation](../00_install/index.md) section. +`cleos` is distributed as part of the [Antelope software suite](https://github.com/AntelopeIO/leap). To install `cleos` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Using Cleos diff --git a/docs/03_keosd/index.md b/docs/03_keosd/index.md index 7142237112..69bcdcd487 100644 --- a/docs/03_keosd/index.md +++ b/docs/03_keosd/index.md @@ -8,7 +8,7 @@ content_title: Keosd ## Installation -`keosd` is distributed as part of the [Antelope software suite](https://github.com/eosnetworkfoundation/mandel). To install `keosd` just visit the [Antelope Software Installation](../00_install/index.md) section. +`keosd` is distributed as part of the [Antelope software suite](https://github.com/AntelopeIO/leap). To install `keosd` just visit the [Antelope Software Installation](../00_install/index.md) section. ## Operation From 9c8e0d0e76cab15d1780a3ef6e7fbc0c25751248 Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 21 Sep 2022 17:28:56 -0400 Subject: [PATCH 107/111] replace applicable eosio refs to antelope :doc --- docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md | 2 +- .../02_usage/02_node-setups/01_non-producing-node.md | 2 +- .../00_local-single-node-testnet.md | 2 +- .../03_development-environment/01_local-multi-node-testnet.md | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md index edcc593276..d53636153e 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/00_producing-node.md @@ -15,7 +15,7 @@ This section describes how to set up a producing node within the Antelope networ * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT LINK BELOW IS BROKEN ) -[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-antelope-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md index b0e5c9cc31..87c0f69493 100644 --- a/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md +++ b/docs/01_nodeos/02_usage/02_node-setups/01_non-producing-node.md @@ -12,7 +12,7 @@ This section describes how to set up a non-producing node within the Antelope ne * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # ( THIS IS A COMMENT NEXT LINK CONTAINS A BROKEN LINK ) -[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md ) +[//]: # ( If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-antelope-binaries.md ) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md index a55d817774..e94c037d02 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/00_local-single-node-testnet.md @@ -16,7 +16,7 @@ This section describes how to set up a single-node blockchain configuration runn * It is assumed that `nodeos`, `cleos`, and `keosd` are accessible through the path. [//]: # (THIS IS A COMMENT, NEXT LINK HAS BROKEN LINK) -[//]: # (If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-eosio-binaries.md .) +[//]: # (If you built Antelope using shell scripts, make sure to run the Install Script ../../../00_install/01_build-from-source/01_shell-scripts/03_install-antelope-binaries.md .) * Know how to pass [Nodeos options](../../02_usage/00_nodeos-options.md) to enable or disable functionality. diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index 52a7c8dfb8..e14591bb26 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -20,7 +20,7 @@ Open four "terminal" windows and perform the following steps: 1. [Start the Wallet Manager](#1-start-the-wallet-manager) 2. [Create a Default Wallet](#2-create-a-default-wallet) -3. [Loading the Antelope Key](#3-loading-the-eosio-key) +3. [Loading the Antelope Key](#3-loading-the-antelope-key) 4. [Start the First Producer Node](#4-start-the-first-producer-node) 5. [Start the Second Producer Node](#5-start-the-second-producer-node) 6. [Get Nodes Info](#6-get-nodes-info) @@ -90,7 +90,9 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node + To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: From fcafd0cb1f93ff7e9551b02bdd5163785d973485 Mon Sep 17 00:00:00 2001 From: Luis Date: Thu, 22 Sep 2022 01:22:58 -0400 Subject: [PATCH 108/111] make html comment MDX-compatible for doc6s parsing :doc --- .../01_local-multi-node-testnet.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md index e14591bb26..30d2b4a1d0 100644 --- a/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md +++ b/docs/01_nodeos/02_usage/03_development-environment/01_local-multi-node-testnet.md @@ -90,9 +90,8 @@ This creates a special producer, known as the "bios" producer. Assuming everythi ### 5. Start the Second Producer Node - +[//]: # (don't render for now) +[//]: # (The following commands assume that you are running this tutorial from the `eos\build` directory, from which you ran `./eosio_build.sh` to build the Antelope binaries.) To start additional nodes, you must first load the `eosio.bios` contract. This contract enables you to have direct control over the resource allocation of other accounts and to access other privileged API calls. Return to the second terminal window and run the following command to load the contract: From 55d9bb551cfb6102be94542539c363a0973f7704 Mon Sep 17 00:00:00 2001 From: Luis Date: Thu, 22 Sep 2022 09:50:07 -0400 Subject: [PATCH 109/111] add manual links to plugins API reference --- .../03_plugins/chain_api_plugin/api-reference/index.md | 2 +- .../03_plugins/db_size_api_plugin/api-reference/index.md | 2 +- docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md | 2 +- .../03_plugins/producer_api_plugin/api-reference/index.md | 2 +- .../03_plugins/trace_api_plugin/api-reference/index.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md index 6451c70868..f49aa2c390 100644 --- a/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/chain_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Chain API Reference](https://docs.eosnetwork.com/leap-plugins/latest/chain.api/) diff --git a/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md index 6451c70868..7b7810fe72 100644 --- a/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/db_size_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[DB Size API Reference](https://docs.eosnetwork.com/leap-plugins/latest/db_size.api/) diff --git a/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md index 6451c70868..842ba652eb 100644 --- a/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/net_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Net API Reference](https://docs.eosnetwork.com/leap-plugins/latest/net.api/) diff --git a/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md index 6451c70868..80bcc0b7fd 100644 --- a/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/producer_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Producer API Reference](https://docs.eosnetwork.com/leap-plugins/latest/producer.api/) diff --git a/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md b/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md index 6451c70868..07a171ca7d 100644 --- a/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md +++ b/docs/01_nodeos/03_plugins/trace_api_plugin/api-reference/index.md @@ -1 +1 @@ - +[Trace API Reference](https://docs.eosnetwork.com/leap-plugins/latest/trace.api/) From dfbc9cda6dd5ca8a714f5e3da1f320d04d9de13c Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Mon, 26 Sep 2022 15:44:35 -0700 Subject: [PATCH 110/111] trace_api docs show all schemas returned - shorted description refered back to developer docs - allow return types for get_blocks any of BlockTraceV0, BlockTraceV1, BlockTraceV2 - BlockTraceV2 can return either Transaction Type V1 or Transaction Type V2 - allow return types for get_transaction_trace any of TransactionTraceV0, TransactionTraceV1, TransactionTraceV2 --- .../trace_api_plugin/trace_api.swagger.yaml | 121 ++---------------- 1 file changed, 10 insertions(+), 111 deletions(-) diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index 1531dae149..46bb143496 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: title: Trace API - description: This plubing must specifiy one option `trace-rpc-abi` or `no-trace-abis`. These options are provided at nodeos startup on the command line or in config.ini file. Configuration option `trace-rpc-abi` There must be at least one ABI specified OR the flag trace-no-abis must be used. ABIs are specified as "Key=Value" pairs in the form = Where can be an absolute path to a file containing a valid JSON-encoded ABI a relative path from `data-dir` to a file containing a valid JSON-encoded ABI. Configuration option `trace-no-abis` use to indicate that the RPC responses + description: See developer documentation at https://docs.eosnetwork.com for information on enabling this plugin. version: 1.0.0 license: name: MIT @@ -47,7 +47,10 @@ paths: content: application/json: schema: - $ref: "#/component/schema/BLOCK_TRACE" + oneOf: + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV0.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV1.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV2.yaml" "400": description: Error - requested block number is invalid (not a number, larger than max int) content: @@ -115,7 +118,11 @@ paths: content: application/json: schema: - $ref: "#/component/schema/TRANSACTION_TRACE" + oneOf: + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV0.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV1.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV2.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV3.yaml" "400": description: Error - requested block number is invalid (not a number, larger than max int) content: @@ -210,114 +217,6 @@ component: memo: type: string example: "first transfer" - TRANSACTION_HEADER: - type: object - properties: - expiration: - type: string - example: "2019-06-18T00:00:00" - ref_block_num: - type: integer - example: 25 - ref_block_prefix: - type: integer - example: 61809694 - max_net_usage_words: - type: integer - example: 0 - max_cpu_usage_ms: - type: integer - example: 0 - delay_sec: - type: integer - example: 0 - TRANSACTION_TRACE: - type: object - properties: - id: - type: string - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - block_num: - type: integer - example: 31 - block_time: - type: string - example: "2019-06-18T00:00:00" - producer_block_id: - type: string - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - actions: - type: array - items: - $ref: "#/component/schema/TRACE" - status: - type: string - example: executed - cpu_usage_us: - type: integer - example: 669 - net_usage_words: - type: integer - example: 6 - signatures: - type: array - items: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/CppSignature.yaml" - transaction_header: - type: object - $ref: "#/component/schema/TRANSACTION_HEADER" - BLOCK_TRACE: - type: object - properties: - id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - number: - type: integer - example: 31 - previous_id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - status: - type: string - enum: - - "irreversible" - - "executed" - - "pending" - example: executed - timestamp: - type: string - example: "2019-06-18T00:00:00" - producer: - type: string - example: myproducer - transaction_mroot: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - action_mroot: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - schedule_version: - type: integer - example: 1 - transactions: - type: array - items: - type: object - properties: - id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - block_num: - type: integer - example: 31 - block_time: - type: string - example: "2019-06-18T00:00:00" - producer_block_id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - actions: - type: array - items: - $ref: "#/component/schema/TRACE" - transaction_header: - type: object - $ref: "#/component/schema/TRANSACTION_HEADER" ERROR_DETAILS: type: object properties: From c0efca061756d7eb99e20c33ca9ab132ef60c990 Mon Sep 17 00:00:00 2001 From: Eric Passmore Date: Mon, 26 Sep 2022 15:56:28 -0700 Subject: [PATCH 111/111] trace_api docs show all schemas returned - shorted description refered back to developer docs - allow return types for get_blocks any of BlockTraceV0, BlockTraceV1, BlockTraceV2 - BlockTraceV2 can return either Transaction Type V1 or Transaction Type V2 - allow return types for get_transaction_trace any of TransactionTraceV0, TransactionTraceV1, TransactionTraceV2 --- .../trace_api_plugin/trace_api.swagger.yaml | 121 ++---------------- 1 file changed, 10 insertions(+), 111 deletions(-) diff --git a/plugins/trace_api_plugin/trace_api.swagger.yaml b/plugins/trace_api_plugin/trace_api.swagger.yaml index 1531dae149..46bb143496 100644 --- a/plugins/trace_api_plugin/trace_api.swagger.yaml +++ b/plugins/trace_api_plugin/trace_api.swagger.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: title: Trace API - description: This plubing must specifiy one option `trace-rpc-abi` or `no-trace-abis`. These options are provided at nodeos startup on the command line or in config.ini file. Configuration option `trace-rpc-abi` There must be at least one ABI specified OR the flag trace-no-abis must be used. ABIs are specified as "Key=Value" pairs in the form = Where can be an absolute path to a file containing a valid JSON-encoded ABI a relative path from `data-dir` to a file containing a valid JSON-encoded ABI. Configuration option `trace-no-abis` use to indicate that the RPC responses + description: See developer documentation at https://docs.eosnetwork.com for information on enabling this plugin. version: 1.0.0 license: name: MIT @@ -47,7 +47,10 @@ paths: content: application/json: schema: - $ref: "#/component/schema/BLOCK_TRACE" + oneOf: + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV0.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV1.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/BlockTraceV2.yaml" "400": description: Error - requested block number is invalid (not a number, larger than max int) content: @@ -115,7 +118,11 @@ paths: content: application/json: schema: - $ref: "#/component/schema/TRANSACTION_TRACE" + oneOf: + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV0.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV1.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV2.yaml" + - $ref: "https://docs.eosnetwork.com/openapi/v2.0/TransactionTraceV3.yaml" "400": description: Error - requested block number is invalid (not a number, larger than max int) content: @@ -210,114 +217,6 @@ component: memo: type: string example: "first transfer" - TRANSACTION_HEADER: - type: object - properties: - expiration: - type: string - example: "2019-06-18T00:00:00" - ref_block_num: - type: integer - example: 25 - ref_block_prefix: - type: integer - example: 61809694 - max_net_usage_words: - type: integer - example: 0 - max_cpu_usage_ms: - type: integer - example: 0 - delay_sec: - type: integer - example: 0 - TRANSACTION_TRACE: - type: object - properties: - id: - type: string - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - block_num: - type: integer - example: 31 - block_time: - type: string - example: "2019-06-18T00:00:00" - producer_block_id: - type: string - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - actions: - type: array - items: - $ref: "#/component/schema/TRACE" - status: - type: string - example: executed - cpu_usage_us: - type: integer - example: 669 - net_usage_words: - type: integer - example: 6 - signatures: - type: array - items: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/CppSignature.yaml" - transaction_header: - type: object - $ref: "#/component/schema/TRANSACTION_HEADER" - BLOCK_TRACE: - type: object - properties: - id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - number: - type: integer - example: 31 - previous_id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - status: - type: string - enum: - - "irreversible" - - "executed" - - "pending" - example: executed - timestamp: - type: string - example: "2019-06-18T00:00:00" - producer: - type: string - example: myproducer - transaction_mroot: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - action_mroot: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - schedule_version: - type: integer - example: 1 - transactions: - type: array - items: - type: object - properties: - id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - block_num: - type: integer - example: 31 - block_time: - type: string - example: "2019-06-18T00:00:00" - producer_block_id: - $ref: "https://docs.eosnetwork.com/openapi/v2.0/Sha256.yaml" - actions: - type: array - items: - $ref: "#/component/schema/TRACE" - transaction_header: - type: object - $ref: "#/component/schema/TRANSACTION_HEADER" ERROR_DETAILS: type: object properties:

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 DeZ^8I literal 0 HcmV?d00001 diff --git a/unittests/snapshots/snap_v4.bin.json.gz b/unittests/snapshots/snap_v4.bin.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..bb21c1ec57c191cbab53336fa80237f9a55c33f0 GIT binary patch literal 196716 zcmeI530PCt+O}=AjwrR_tfZ|2;s7eB$dFVibwpHD1c5k51Q}%vNorA05KvK3h6GT7 ziVzhQ5J*%+RE97|3=kngfIwmhA!Poyq5VEhG-7-D{im|7>zuVW$yza4Wq9_p@Ar9O zVIxN_&1%{^WT={{*?qCf$m6>$xP@*H+702UE5?!>3#<4CPvC|TM6uyd ztM4DXba1A#w9zRzHkdI-wqxTyw;%kboqXAIK6d!H2iBV3glpm?-Zv~~={(L5KAxUB z+j3G`IAO-kXiuKaEL)dhb};v&<(B(&#|arbAB3i>ARAH;UWYa934y3 zKb`1a6@7481Ig6c!~wI^P;nEMq8Q*OIK4Q};8| zC-eo{4f_=lDLDj}(gj_X1-mQ^a1$<0k{|mKR^&WSh^T2wXv3#pk;h%W7Tfj zg-f<+HjHXJm|=H)tUWVs>Z_$zD2+A7&539G5+BUdq^3^M+AQ0(r%yiFLioKLC4Y2m znvQ&XQu?L%qdt=o_p*qUeTHU>Eei~`ZO>X*v;AOb#=Or*!%6_dufODvW8V1 zyq97-x@uv=-jbUxN0SXEM3gU@zU<;PY?RvC@|>+P8O3vUo;mRTF9-Kd`L<<6z-xzSrVs`{AC;3TL2TeXjV5^P%g; z=r}%2xVfm%aN?M4KPNpqQEHem+I8`s1)*KpZAOLhIrxl{DOr{U_+u+Gw}qdY`u&6S z&}i)WTA4(azc%QSN6yclx4U;d)WR%sm{^P=j+CF7`n0J&dI4*g4!!k=&3Czs1AZ|X z^)^j&`1RO}oAbv;%$gO9%6%{~aNalY8PuZQT=$#&?_Xd89Q2&P{-!{g#kKZ_!_UtN(Gxti$ZRxRqy z4V`??TJt3_Z-Pt114pZu_kR2({ne!VY0qxva;sN$cZ(*ngRO3jX(%1}Tg%!mmLro@ zv}ECLOJ=(Trp~yJd;(jkQ9EJhJPUM)X3%+hgE_jwIF=h5CqUMptIktso?^{KvzX*JJW zWb=xy_obO=kJU=q2aBr+INNS(>JZO7qbrEov}>whIB5!hsN3XW&55w=Ez7eGdNoo4 zYeR=S&%n{+1<{NxxQc1;_B;c>+(=OfcQei;JQ6!S3GbijHGP~Ral(w7H8V0+HvtY`J=oR&vhi7M&Dh2*ZY!&j&sGrmvn7%cEP=1%COY1 zCgU}!yS!^s=DZxjsIaahMhjT%zE>~wxjsQRq}B#IHwBANOxe%#Z{8z5L+mPU+L2D{ zC8g^lJuq8)LV~?Uc{EN5D->DiM;^fS@Xc*|eZrPrY}kVH)K0swteo!p72jvLlQwJ= z8GUG`eOu-djd8QqeqG_**cg8O_QK(Mds|4Sy-w$jYI9!k+F-9yMv8Rlu4nNB)CvZb{hX{Ah z)EruJ>HwP8+j~quZVQZY@J&E>=~cfBU;G-vCjaZi6|rWg!wSD*>}`33^$#HFOW*iV zSINJB61Fk{H>qd}xA$R94vbm5$~meB7ITRA^6 z9iN9>!aaJ}OrBe%crDToW0&0!+nqy0+<{vGWpG;3#mccD}mN8~y!!!5+J#zSPlbp#L zZwo27r9|&ix-awAMG7Xwe+nbV7Zb_a�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 E2jHes(EtDd literal 0 HcmV?d00001 diff --git a/unittests/snapshots/snap_v6.bin.json.gz b/unittests/snapshots/snap_v6.bin.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..b513f97b1e4e40e755ea2479dab087eb6d3bc031 GIT binary patch literal 196716 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