From dc7b75a7b300177c5436b02e85a4eec98d96a7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Sun, 23 Jun 2024 21:16:21 +0200 Subject: [PATCH 1/9] Memory bound block cementing --- nano/core_test/confirming_set.cpp | 12 +++-- nano/lib/stats_enums.hpp | 4 ++ nano/lib/thread_roles.cpp | 2 +- nano/lib/thread_roles.hpp | 2 +- nano/node/confirming_set.cpp | 88 ++++++++++++++++++++----------- nano/node/confirming_set.hpp | 35 +++++++----- nano/node/fwd.hpp | 1 + nano/node/node.cpp | 2 +- nano/node/nodeconfig.hpp | 2 + nano/secure/ledger.cpp | 39 ++++++++++---- nano/secure/ledger.hpp | 18 ++++--- nano/slow_test/node.cpp | 3 +- 12 files changed, 140 insertions(+), 68 deletions(-) diff --git a/nano/core_test/confirming_set.cpp b/nano/core_test/confirming_set.cpp index f2fe621065..4b2bf03df2 100644 --- a/nano/core_test/confirming_set.cpp +++ b/nano/core_test/confirming_set.cpp @@ -19,13 +19,15 @@ using namespace std::chrono_literals; TEST (confirming_set, construction) { auto ctx = nano::test::context::ledger_empty (); - nano::confirming_set confirming_set (ctx.ledger (), ctx.stats ()); + nano::confirming_set_config config{}; + nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; } TEST (confirming_set, add_exists) { auto ctx = nano::test::context::ledger_send_receive (); - nano::confirming_set confirming_set (ctx.ledger (), ctx.stats ()); + nano::confirming_set_config config{}; + nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; auto send = ctx.blocks ()[0]; confirming_set.add (send->hash ()); ASSERT_TRUE (confirming_set.exists (send->hash ())); @@ -34,7 +36,8 @@ TEST (confirming_set, add_exists) TEST (confirming_set, process_one) { auto ctx = nano::test::context::ledger_send_receive (); - nano::confirming_set confirming_set (ctx.ledger (), ctx.stats ()); + nano::confirming_set_config config{}; + nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; std::atomic count = 0; std::mutex mutex; std::condition_variable condition; @@ -50,7 +53,8 @@ TEST (confirming_set, process_one) TEST (confirming_set, process_multiple) { auto ctx = nano::test::context::ledger_send_receive (); - nano::confirming_set confirming_set (ctx.ledger (), ctx.stats ()); + nano::confirming_set_config config{}; + nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; std::atomic count = 0; std::mutex mutex; std::condition_variable condition; diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index 6bec768d2e..460005389c 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -93,6 +93,7 @@ enum class detail { _invalid = 0, // Default value, should not be used + // common all, ok, test, @@ -122,6 +123,7 @@ enum class detail confirmed, unconfirmed, cemented, + cooldown, // processing queue queue, @@ -455,7 +457,9 @@ enum class detail // confirming_set notify_cemented, notify_already_cemented, + notify_intermediate, already_cemented, + cementing_hash, // election_state passive, diff --git a/nano/lib/thread_roles.cpp b/nano/lib/thread_roles.cpp index 2948caa217..2831c72038 100644 --- a/nano/lib/thread_roles.cpp +++ b/nano/lib/thread_roles.cpp @@ -61,7 +61,7 @@ std::string nano::thread_role::get_string (nano::thread_role::name role) case nano::thread_role::name::rpc_process_container: thread_role_name_string = "RPC process"; break; - case nano::thread_role::name::confirmation_height_processing: + case nano::thread_role::name::confirmation_height: thread_role_name_string = "Conf height"; break; case nano::thread_role::name::confirmation_height_notifications: diff --git a/nano/lib/thread_roles.hpp b/nano/lib/thread_roles.hpp index b6e3196cac..eef15632fa 100644 --- a/nano/lib/thread_roles.hpp +++ b/nano/lib/thread_roles.hpp @@ -25,7 +25,7 @@ enum class name signature_checking, rpc_request_processor, rpc_process_container, - confirmation_height_processing, + confirmation_height, confirmation_height_notifications, worker, bootstrap_worker, diff --git a/nano/node/confirming_set.cpp b/nano/node/confirming_set.cpp index ee72858b52..ca69035617 100644 --- a/nano/node/confirming_set.cpp +++ b/nano/node/confirming_set.cpp @@ -5,7 +5,8 @@ #include #include -nano::confirming_set::confirming_set (nano::ledger & ledger_a, nano::stats & stats_a) : +nano::confirming_set::confirming_set (confirming_set_config const & config_a, nano::ledger & ledger_a, nano::stats & stats_a) : + config{ config_a }, ledger{ ledger_a }, stats{ stats_a }, notification_workers{ 1, nano::thread_role::name::confirmation_height_notifications } @@ -13,14 +14,8 @@ nano::confirming_set::confirming_set (nano::ledger & ledger_a, nano::stats & sta batch_cemented.add ([this] (auto const & notification) { for (auto const & [block, confirmation_root] : notification.cemented) { - stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify_cemented); cemented_observers.notify (block); } - for (auto const & hash : notification.already_cemented) - { - stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify_already_cemented); - block_already_cemented_observers.notify (hash); - } }); } @@ -53,7 +48,7 @@ void nano::confirming_set::start () debug_assert (!thread.joinable ()); thread = std::thread{ [this] () { - nano::thread_role::set (nano::thread_role::name::confirmation_height_processing); + nano::thread_role::set (nano::thread_role::name::confirmation_height); run (); } }; } @@ -132,41 +127,72 @@ void nano::confirming_set::run_batch (std::unique_lock & lock) lock.unlock (); + auto notify = [this, &cemented, &already] () { + cemented_notification notification{}; + notification.cemented.swap (cemented); + notification.already_cemented.swap (already); + + // Wait for the worker thread if too many notifications are queued + while (notification_workers.num_queued_tasks () >= config.max_queued_notifications) + { + stats.inc (nano::stat::type::confirming_set, nano::stat::detail::cooldown); + std::this_thread::sleep_for (100ms); + } + + notification_workers.push_task ([this, notification = std::move (notification)] () { + stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify); + batch_cemented.notify (notification); + }); + }; + + // We might need to issue multiple notifications if the block we're confirming implicitly confirms more + auto notify_maybe = [this, &cemented, &already, ¬ify] (auto & transaction) { + if (cemented.size () >= config.max_blocks) + { + stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify_intermediate); + transaction.commit (); + notify (); + transaction.renew (); + } + }; + { auto transaction = ledger.tx_begin_write ({ nano::tables::confirmation_height }, nano::store::writer::confirmation_height); for (auto const & hash : batch) { - transaction.refresh_if_needed (); - - auto added = ledger.confirm (transaction, hash); - if (!added.empty ()) + do { - // Confirming this block may implicitly confirm more - for (auto & block : added) + transaction.refresh_if_needed (); + + stats.inc (nano::stat::type::confirming_set, nano::stat::detail::cementing_hash); + + // Issue notifications here, so that `cemented` set is not too large before we add more blocks + notify_maybe (transaction); + + auto added = ledger.confirm (transaction, hash, config.max_blocks); + if (!added.empty ()) { - cemented.emplace_back (block, hash); + // Confirming this block may implicitly confirm more + stats.add (nano::stat::type::confirming_set, nano::stat::detail::cemented, added.size ()); + for (auto & block : added) + { + cemented.emplace_back (block, hash); + } } - - stats.add (nano::stat::type::confirming_set, nano::stat::detail::cemented, added.size ()); - } - else - { - already.push_back (hash); - stats.inc (nano::stat::type::confirming_set, nano::stat::detail::already_cemented); - } + else + { + stats.inc (nano::stat::type::confirming_set, nano::stat::detail::already_cemented); + already.push_back (hash); + } + } while (!ledger.confirmed.block_exists (transaction, hash)); } } - cemented_notification notification{ - .cemented = std::move (cemented), - .already_cemented = std::move (already) - }; + notify (); - notification_workers.push_task ([this, notification = std::move (notification)] () { - stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify); - batch_cemented.notify (notification); - }); + release_assert (cemented.empty ()); + release_assert (already.empty ()); } std::unique_ptr nano::confirming_set::collect_container_info (std::string const & name) const diff --git a/nano/node/confirming_set.hpp b/nano/node/confirming_set.hpp index d6b8350de4..cb33915518 100644 --- a/nano/node/confirming_set.hpp +++ b/nano/node/confirming_set.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -12,14 +13,17 @@ namespace nano { -class node; -class block; -class ledger; -class stats; -} - -namespace nano +class confirming_set_config final { +public: + // TODO: Serialization & deserialization + +public: + /** Maximum number of dependent blocks to be stored in memory during processing */ + size_t max_blocks{ 64 * 128 }; + size_t max_queued_notifications{ 8 }; +}; + /** * Set of blocks to be durably confirmed */ @@ -29,13 +33,14 @@ class confirming_set final friend class confirmation_height_pruned_source_Test; public: - confirming_set (nano::ledger &, nano::stats &); + confirming_set (confirming_set_config const &, nano::ledger &, nano::stats &); ~confirming_set (); - // Adds a block to the set of blocks to be confirmed - void add (nano::block_hash const & hash); void start (); void stop (); + + // Adds a block to the set of blocks to be confirmed + void add (nano::block_hash const & hash); // Added blocks will remain in this set until after ledger has them marked as confirmed. bool exists (nano::block_hash const & hash) const; std::size_t size () const; @@ -54,16 +59,18 @@ class confirming_set final nano::observer_set batch_cemented; nano::observer_set> cemented_observers; - nano::observer_set block_already_cemented_observers; + +private: // Dependencies + confirming_set_config const & config; + nano::ledger & ledger; + nano::stats & stats; private: void run (); void run_batch (std::unique_lock &); std::deque next_batch (size_t max_count); - nano::ledger & ledger; - nano::stats & stats; - +private: std::unordered_set set; nano::thread_pool notification_workers; diff --git a/nano/node/fwd.hpp b/nano/node/fwd.hpp index 0da465ae22..ecdb9d5b6e 100644 --- a/nano/node/fwd.hpp +++ b/nano/node/fwd.hpp @@ -7,6 +7,7 @@ namespace nano { class active_elections; +class block; class ledger; class local_vote_history; class logger; diff --git a/nano/node/node.cpp b/nano/node/node.cpp index a2521e49cf..2da912e2df 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -186,7 +186,7 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy application_path (application_path_a), port_mapping (*this), block_processor (*this), - confirming_set_impl{ std::make_unique (ledger, stats) }, + confirming_set_impl{ std::make_unique (config.confirming_set, ledger, stats) }, confirming_set{ *confirming_set_impl }, active_impl{ std::make_unique (*this, confirming_set, block_processor) }, active{ *active_impl }, diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 1b9fd403bc..19acd56ab7 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -152,6 +153,7 @@ class node_config nano::request_aggregator_config request_aggregator; nano::message_processor_config message_processor; nano::network_config network; + nano::confirming_set_config confirming_set; public: std::string serialize_frontiers_confirmation (nano::frontiers_confirmation_mode) const; diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index f42f02aac2..2c5f915038 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -804,38 +804,59 @@ nano::uint128_t nano::ledger::account_receivable (secure::transaction const & tr return result; } -std::deque> nano::ledger::confirm (secure::write_transaction const & transaction, nano::block_hash const & hash) +// Both stack and result set are bounded to limit maximum memory usage +// Callers must ensure that the target block was confirmed, and if not, call this function multiple times +std::deque> nano::ledger::confirm (secure::write_transaction const & transaction, nano::block_hash const & hash, size_t max_blocks) { std::deque> result; - std::stack stack; - stack.push (hash); + + std::deque stack; + stack.push_back (hash); while (!stack.empty ()) { - auto hash = stack.top (); + auto hash = stack.back (); auto block = any.block_get (transaction, hash); release_assert (block); + auto dependents = dependent_blocks (transaction, *block); for (auto const & dependent : dependents) { if (!dependent.is_zero () && !confirmed.block_exists_or_pruned (transaction, dependent)) { - stack.push (dependent); + stack.push_back (dependent); + + // Limit the stack size to avoid excessive memory usage + // This will forget the bottom of the dependency tree + if (stack.size () > max_blocks) + { + stack.pop_front (); + } } } - if (stack.top () == hash) + + if (stack.back () == hash) { - stack.pop (); + stack.pop_back (); if (!confirmed.block_exists_or_pruned (transaction, hash)) { - result.push_back (block); + // We must only confirm blocks that have their dependencies confirmed + debug_assert (dependents_confirmed (transaction, *block)); confirm (transaction, *block); + result.push_back (block); } } else { - // unconfirmed dependencies were added + // Unconfirmed dependencies were added + } + + // Early return might leave parts of the dependency tree unconfirmed + if (result.size () >= max_blocks) + { + break; } } + return result; } diff --git a/nano/secure/ledger.hpp b/nano/secure/ledger.hpp index 3e13256d29..99336c56ba 100644 --- a/nano/secure/ledger.hpp +++ b/nano/secure/ledger.hpp @@ -59,9 +59,9 @@ class ledger final std::string block_text (char const *); std::string block_text (nano::block_hash const &); std::pair hash_root_random (secure::transaction const &) const; - std::optional pending_info (secure::transaction const & transaction, nano::pending_key const & key) const; - std::deque> confirm (secure::write_transaction const & transaction, nano::block_hash const & hash); - nano::block_status process (secure::write_transaction const & transaction, std::shared_ptr block); + std::optional pending_info (secure::transaction const &, nano::pending_key const & key) const; + std::deque> confirm (secure::write_transaction const &, nano::block_hash const & hash, size_t max_blocks = 1024 * 128); + nano::block_status process (secure::write_transaction const &, std::shared_ptr block); bool rollback (secure::write_transaction const &, nano::block_hash const &, std::vector> &); bool rollback (secure::write_transaction const &, nano::block_hash const &); void update_account (secure::write_transaction const &, nano::account const &, nano::account_info const &, nano::account_info const &); @@ -70,26 +70,32 @@ class ledger final bool dependents_confirmed (secure::transaction const &, nano::block const &) const; bool is_epoch_link (nano::link const &) const; std::array dependent_blocks (secure::transaction const &, nano::block const &) const; - std::shared_ptr find_receive_block_by_send_hash (secure::transaction const & transaction, nano::account const & destination, nano::block_hash const & send_block_hash); + std::shared_ptr find_receive_block_by_send_hash (secure::transaction const &, nano::account const & destination, nano::block_hash const & send_block_hash); nano::account const & epoch_signer (nano::link const &) const; nano::link const & epoch_link (nano::epoch) const; bool migrate_lmdb_to_rocksdb (std::filesystem::path const &) const; bool bootstrap_weight_reached () const; static nano::epoch version (nano::block const & block); - nano::epoch version (secure::transaction const & transaction, nano::block_hash const & hash) const; - std::unique_ptr collect_container_info (std::string const & name) const; + nano::epoch version (secure::transaction const &, nano::block_hash const & hash) const; uint64_t cemented_count () const; uint64_t block_count () const; uint64_t account_count () const; uint64_t pruned_count () const; + + std::unique_ptr collect_container_info (std::string const & name) const; + +public: static nano::uint128_t const unit; + nano::ledger_constants & constants; nano::store::component & store; nano::ledger_cache cache; nano::stats & stats; + std::unordered_map bootstrap_weights; uint64_t bootstrap_weight_max_blocks{ 1 }; mutable std::atomic check_bootstrap_weights; + bool pruning{ false }; private: diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index 960a205a64..1ea6065a40 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -1145,7 +1145,8 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections) nano::block_hash block_hash_being_processed{ 0 }; nano::store::write_queue write_queue{ false }; - nano::confirming_set confirming_set{ ledger, stats }; + nano::confirming_set_config confirming_set_config{}; + nano::confirming_set confirming_set{ confirming_set_config, ledger, stats }; auto const num_accounts = 100000; From 7438c95fbdd33245f05179c7df9078a92fe3bde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:16:49 +0200 Subject: [PATCH 2/9] Rename file to `ledger_context` --- nano/core_test/confirming_set.cpp | 2 +- nano/core_test/ledger.cpp | 2 +- nano/test_common/CMakeLists.txt | 4 ++-- nano/test_common/{ledger.cpp => ledger_context.cpp} | 2 +- nano/test_common/{ledger.hpp => ledger_context.hpp} | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename nano/test_common/{ledger.cpp => ledger_context.cpp} (98%) rename nano/test_common/{ledger.hpp => ledger_context.hpp} (100%) diff --git a/nano/core_test/confirming_set.cpp b/nano/core_test/confirming_set.cpp index 4b2bf03df2..861a431e3d 100644 --- a/nano/core_test/confirming_set.cpp +++ b/nano/core_test/confirming_set.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 850ddab934..78e23c3b7f 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/nano/test_common/CMakeLists.txt b/nano/test_common/CMakeLists.txt index 0f0b9d3c4a..56d6a53a4c 100644 --- a/nano/test_common/CMakeLists.txt +++ b/nano/test_common/CMakeLists.txt @@ -2,8 +2,8 @@ add_library( test_common chains.hpp chains.cpp - ledger.hpp - ledger.cpp + ledger_context.hpp + ledger_context.cpp make_store.hpp make_store.cpp network.hpp diff --git a/nano/test_common/ledger.cpp b/nano/test_common/ledger_context.cpp similarity index 98% rename from nano/test_common/ledger.cpp rename to nano/test_common/ledger_context.cpp index 63ca93a2b4..01f5016032 100644 --- a/nano/test_common/ledger.cpp +++ b/nano/test_common/ledger_context.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include nano::test::context::ledger_context::ledger_context (std::deque> && blocks) : store_m{ nano::make_store (logger, nano::unique_path (), nano::dev::constants) }, diff --git a/nano/test_common/ledger.hpp b/nano/test_common/ledger_context.hpp similarity index 100% rename from nano/test_common/ledger.hpp rename to nano/test_common/ledger_context.hpp From 18b635c158124dcf668888ba56323d0ada1dd57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Wed, 26 Jun 2024 20:14:01 +0200 Subject: [PATCH 3/9] Namespace rename and reindent --- nano/core_test/confirming_set.cpp | 8 +- nano/core_test/ledger.cpp | 192 ++++++++++++++-------------- nano/test_common/ledger_context.cpp | 22 ++-- nano/test_common/ledger_context.hpp | 61 ++++----- 4 files changed, 139 insertions(+), 144 deletions(-) diff --git a/nano/core_test/confirming_set.cpp b/nano/core_test/confirming_set.cpp index 861a431e3d..31ca879511 100644 --- a/nano/core_test/confirming_set.cpp +++ b/nano/core_test/confirming_set.cpp @@ -18,14 +18,14 @@ using namespace std::chrono_literals; TEST (confirming_set, construction) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); nano::confirming_set_config config{}; nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; } TEST (confirming_set, add_exists) { - auto ctx = nano::test::context::ledger_send_receive (); + auto ctx = nano::test::ledger_send_receive (); nano::confirming_set_config config{}; nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; auto send = ctx.blocks ()[0]; @@ -35,7 +35,7 @@ TEST (confirming_set, add_exists) TEST (confirming_set, process_one) { - auto ctx = nano::test::context::ledger_send_receive (); + auto ctx = nano::test::ledger_send_receive (); nano::confirming_set_config config{}; nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; std::atomic count = 0; @@ -52,7 +52,7 @@ TEST (confirming_set, process_one) TEST (confirming_set, process_multiple) { - auto ctx = nano::test::context::ledger_send_receive (); + auto ctx = nano::test::ledger_send_receive (); nano::confirming_set_config config{}; nano::confirming_set confirming_set{ config, ctx.ledger (), ctx.stats () }; std::atomic count = 0; diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 78e23c3b7f..7cdd810834 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -32,13 +32,13 @@ TEST (ledger, store_error) // Don't test this in rocksdb mode GTEST_SKIP (); } - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); } // Ledger can be initialized and returns a basic query for an empty account TEST (ledger, empty) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_read (); @@ -50,7 +50,7 @@ TEST (ledger, empty) // Ledger can be initialized and returns a basic query for an empty account TEST (ledger, confirmed_unconfirmed_view) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & unconfirmed = ledger; auto & confirmed = ledger.confirmed; @@ -59,7 +59,7 @@ TEST (ledger, confirmed_unconfirmed_view) // Genesis account should have the max balance on empty initialization TEST (ledger, genesis_balance) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -80,7 +80,7 @@ TEST (ledger, genesis_balance) TEST (ledger, process_modifies_sideband) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto & pool = ctx.pool (); @@ -102,7 +102,7 @@ TEST (ledger, process_modifies_sideband) // Create a send block and publish it. TEST (ledger, process_send) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -205,7 +205,7 @@ TEST (ledger, process_send) TEST (ledger, process_receive) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -288,7 +288,7 @@ TEST (ledger, process_receive) TEST (ledger, rollback_receiver) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -337,7 +337,7 @@ TEST (ledger, rollback_receiver) TEST (ledger, rollback_representation) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -427,7 +427,7 @@ TEST (ledger, rollback_representation) TEST (ledger, receive_rollback) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -455,7 +455,7 @@ TEST (ledger, receive_rollback) TEST (ledger, process_duplicate) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -489,7 +489,7 @@ TEST (ledger, process_duplicate) TEST (ledger, representative_genesis) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -500,14 +500,14 @@ TEST (ledger, representative_genesis) TEST (ledger, weight) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); } TEST (ledger, representative_change) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -544,7 +544,7 @@ TEST (ledger, representative_change) TEST (ledger, send_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); nano::keypair key2; @@ -576,7 +576,7 @@ TEST (ledger, send_fork) TEST (ledger, receive_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); nano::keypair key2; @@ -633,7 +633,7 @@ TEST (ledger, receive_fork) TEST (ledger, open_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); nano::keypair key2; @@ -734,7 +734,7 @@ TEST (ledger, rep_cache_min_weight) TEST (ledger, representation) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto & rep_weights = ledger.cache.rep_weights; @@ -907,7 +907,7 @@ TEST (ledger, double_open) TEST (ledger, double_receive) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1244,7 +1244,7 @@ TEST (ledger, successor) TEST (ledger, fail_change_old) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1266,7 +1266,7 @@ TEST (ledger, fail_change_old) TEST (ledger, fail_change_gap_previous) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1286,7 +1286,7 @@ TEST (ledger, fail_change_gap_previous) TEST (ledger, fail_state_bad_signature) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1308,7 +1308,7 @@ TEST (ledger, fail_state_bad_signature) TEST (ledger, fail_epoch_bad_signature) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1334,7 +1334,7 @@ TEST (ledger, fail_epoch_bad_signature) TEST (ledger, fail_change_bad_signature) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1354,7 +1354,7 @@ TEST (ledger, fail_change_bad_signature) TEST (ledger, fail_change_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1384,7 +1384,7 @@ TEST (ledger, fail_change_fork) TEST (ledger, fail_send_old) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1407,7 +1407,7 @@ TEST (ledger, fail_send_old) TEST (ledger, fail_send_gap_previous) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1428,7 +1428,7 @@ TEST (ledger, fail_send_gap_previous) TEST (ledger, fail_send_bad_signature) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1449,7 +1449,7 @@ TEST (ledger, fail_send_bad_signature) TEST (ledger, fail_send_negative_spend) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1479,7 +1479,7 @@ TEST (ledger, fail_send_negative_spend) TEST (ledger, fail_send_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1509,7 +1509,7 @@ TEST (ledger, fail_send_fork) TEST (ledger, fail_open_old) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1539,7 +1539,7 @@ TEST (ledger, fail_open_old) TEST (ledger, fail_open_gap_source) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1560,7 +1560,7 @@ TEST (ledger, fail_open_gap_source) TEST (ledger, fail_open_bad_signature) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1590,7 +1590,7 @@ TEST (ledger, fail_open_bad_signature) TEST (ledger, fail_open_fork_previous) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1638,7 +1638,7 @@ TEST (ledger, fail_open_fork_previous) TEST (ledger, fail_open_account_mismatch) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1669,7 +1669,7 @@ TEST (ledger, fail_open_account_mismatch) TEST (ledger, fail_receive_old) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1716,7 +1716,7 @@ TEST (ledger, fail_receive_old) TEST (ledger, fail_receive_gap_source) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1766,7 +1766,7 @@ TEST (ledger, fail_receive_gap_source) TEST (ledger, fail_receive_overreceive) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1806,7 +1806,7 @@ TEST (ledger, fail_receive_overreceive) TEST (ledger, fail_receive_bad_signature) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1856,7 +1856,7 @@ TEST (ledger, fail_receive_bad_signature) TEST (ledger, fail_receive_gap_previous_opened) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1906,7 +1906,7 @@ TEST (ledger, fail_receive_gap_previous_opened) TEST (ledger, fail_receive_gap_previous_unopened) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -1946,7 +1946,7 @@ TEST (ledger, fail_receive_gap_previous_unopened) TEST (ledger, fail_receive_fork_previous) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2007,7 +2007,7 @@ TEST (ledger, fail_receive_fork_previous) TEST (ledger, fail_receive_received_source) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2087,7 +2087,7 @@ TEST (ledger, fail_receive_received_source) TEST (ledger, latest_empty) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); nano::keypair key; @@ -2098,7 +2098,7 @@ TEST (ledger, latest_empty) TEST (ledger, latest_root) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2121,7 +2121,7 @@ TEST (ledger, latest_root) TEST (ledger, change_representative_move_representation) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); nano::keypair key1; @@ -2163,7 +2163,7 @@ TEST (ledger, change_representative_move_representation) TEST (ledger, send_open_receive_rollback) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2252,7 +2252,7 @@ TEST (ledger, send_open_receive_rollback) TEST (ledger, bootstrap_rep_weight) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); nano::keypair key2; @@ -2299,7 +2299,7 @@ TEST (ledger, bootstrap_rep_weight) TEST (ledger, block_destination_source) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2389,7 +2389,7 @@ TEST (ledger, block_destination_source) TEST (ledger, state_account) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2411,7 +2411,7 @@ TEST (ledger, state_account) TEST (ledger, state_send_receive) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2468,7 +2468,7 @@ TEST (ledger, state_send_receive) TEST (ledger, state_receive) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2516,7 +2516,7 @@ TEST (ledger, state_receive) TEST (ledger, state_rep_change) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2550,7 +2550,7 @@ TEST (ledger, state_rep_change) TEST (ledger, state_open) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2605,7 +2605,7 @@ TEST (ledger, state_open) // Make sure old block types can't be inserted after a state block. TEST (ledger, send_after_state_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2636,7 +2636,7 @@ TEST (ledger, send_after_state_fail) // Make sure old block types can't be inserted after a state block. TEST (ledger, receive_after_state_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2666,7 +2666,7 @@ TEST (ledger, receive_after_state_fail) // Make sure old block types can't be inserted after a state block. TEST (ledger, change_after_state_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2696,7 +2696,7 @@ TEST (ledger, change_after_state_fail) TEST (ledger, state_unreceivable_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2733,7 +2733,7 @@ TEST (ledger, state_unreceivable_fail) TEST (ledger, state_receive_bad_amount_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2770,7 +2770,7 @@ TEST (ledger, state_receive_bad_amount_fail) TEST (ledger, state_no_link_amount_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2803,7 +2803,7 @@ TEST (ledger, state_no_link_amount_fail) TEST (ledger, state_receive_wrong_account_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2843,7 +2843,7 @@ TEST (ledger, state_receive_wrong_account_fail) TEST (ledger, state_open_state_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2886,7 +2886,7 @@ TEST (ledger, state_open_state_fork) TEST (ledger, state_state_open_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2930,7 +2930,7 @@ TEST (ledger, state_state_open_fork) TEST (ledger, state_open_previous_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2963,7 +2963,7 @@ TEST (ledger, state_open_previous_fail) TEST (ledger, state_open_source_fail) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -2996,7 +2996,7 @@ TEST (ledger, state_open_source_fail) TEST (ledger, state_send_change) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3030,7 +3030,7 @@ TEST (ledger, state_send_change) TEST (ledger, state_receive_change) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3082,7 +3082,7 @@ TEST (ledger, state_receive_change) TEST (ledger, state_open_old) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3116,7 +3116,7 @@ TEST (ledger, state_open_old) TEST (ledger, state_receive_old) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3169,7 +3169,7 @@ TEST (ledger, state_receive_old) TEST (ledger, state_rollback_send) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3207,7 +3207,7 @@ TEST (ledger, state_rollback_send) TEST (ledger, state_rollback_receive) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3249,7 +3249,7 @@ TEST (ledger, state_rollback_receive) TEST (ledger, state_rollback_received_send) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3292,7 +3292,7 @@ TEST (ledger, state_rollback_received_send) TEST (ledger, state_rep_change_rollback) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3319,7 +3319,7 @@ TEST (ledger, state_rep_change_rollback) TEST (ledger, state_open_rollback) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3361,7 +3361,7 @@ TEST (ledger, state_open_rollback) TEST (ledger, state_send_change_rollback) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3389,7 +3389,7 @@ TEST (ledger, state_send_change_rollback) TEST (ledger, state_receive_change_rollback) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3428,7 +3428,7 @@ TEST (ledger, state_receive_change_rollback) TEST (ledger, epoch_blocks_v1_general) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3571,7 +3571,7 @@ TEST (ledger, epoch_blocks_v1_general) TEST (ledger, epoch_blocks_v2_general) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3736,7 +3736,7 @@ TEST (ledger, epoch_blocks_v2_general) TEST (ledger, epoch_blocks_receive_upgrade) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -3944,7 +3944,7 @@ TEST (ledger, epoch_blocks_receive_upgrade) TEST (ledger, epoch_blocks_fork) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -4471,7 +4471,7 @@ TEST (ledger, unchecked_receive) TEST (ledger, confirmation_height_not_updated) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -4544,7 +4544,7 @@ TEST (ledger, zero_rep) TEST (ledger, work_validation) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto & pool = ctx.pool (); @@ -4633,7 +4633,7 @@ TEST (ledger, work_validation) TEST (ledger, dependents_confirmed) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -4743,7 +4743,7 @@ TEST (ledger, dependents_confirmed_pruning) TEST (ledger, block_confirmed) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto transaction = ledger.tx_begin_write (); @@ -4770,7 +4770,7 @@ TEST (ledger, block_confirmed) TEST (ledger, cache) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto & stats = ctx.stats (); @@ -5487,7 +5487,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb) TEST (ledger, is_send_genesis) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); @@ -5496,7 +5496,7 @@ TEST (ledger, is_send_genesis) TEST (ledger, is_send_state) { - auto ctx = nano::test::context::ledger_send_receive (); + auto ctx = nano::test::ledger_send_receive (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); @@ -5506,7 +5506,7 @@ TEST (ledger, is_send_state) TEST (ledger, is_send_legacy) { - auto ctx = nano::test::context::ledger_send_receive_legacy (); + auto ctx = nano::test::ledger_send_receive_legacy (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = store.tx_begin_read (); @@ -5516,7 +5516,7 @@ TEST (ledger, is_send_legacy) TEST (ledger, head_block) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); auto tx = ledger.tx_begin_read (); @@ -5526,14 +5526,14 @@ TEST (ledger, head_block) // Test that nullopt can be returned when there are no receivable entries TEST (ledger_receivable, upper_bound_account_none) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); ASSERT_EQ (ctx.ledger ().any.receivable_end (), ctx.ledger ().any.receivable_upper_bound (ctx.ledger ().tx_begin_read (), 0)); } // Test behavior of ledger::receivable_upper_bound when there are receivable entries for multiple accounts TEST (ledger_receivable, upper_bound_account_key) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); nano::block_builder builder; nano::keypair key; auto send1 = builder @@ -5581,7 +5581,7 @@ TEST (ledger_receivable, upper_bound_account_key) // Test that multiple receivable entries for the same account TEST (ledger_receivable, key_two) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); nano::block_builder builder; nano::keypair key; auto send1 = builder @@ -5620,13 +5620,13 @@ TEST (ledger_receivable, key_two) TEST (ledger_receivable, any_none) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); ASSERT_FALSE (ctx.ledger ().any.receivable_exists (ctx.ledger ().tx_begin_read (), nano::dev::genesis_key.pub)); } TEST (ledger_receivable, any_one) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); nano::block_builder builder; nano::keypair key; auto send1 = builder @@ -5646,7 +5646,7 @@ TEST (ledger_receivable, any_one) TEST (ledger_transaction, write_refresh) { - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); nano::block_builder builder; nano::keypair key; auto send1 = builder @@ -5683,7 +5683,7 @@ TEST (ledger_transaction, write_wait_order) { nano::test::system system; - auto ctx = nano::test::context::ledger_empty (); + auto ctx = nano::test::ledger_empty (); std::atomic acquired1{ false }; std::atomic acquired2{ false }; diff --git a/nano/test_common/ledger_context.cpp b/nano/test_common/ledger_context.cpp index 01f5016032..b7f59b938e 100644 --- a/nano/test_common/ledger_context.cpp +++ b/nano/test_common/ledger_context.cpp @@ -3,7 +3,7 @@ #include #include -nano::test::context::ledger_context::ledger_context (std::deque> && blocks) : +nano::test::ledger_context::ledger_context (std::deque> && blocks) : store_m{ nano::make_store (logger, nano::unique_path (), nano::dev::constants) }, stats_m{ logger }, ledger_m{ *store_m, stats_m, nano::dev::constants }, @@ -20,37 +20,41 @@ nano::test::context::ledger_context::ledger_context (std::deque> const & nano::test::context::ledger_context::blocks () const +std::deque> const & nano::test::ledger_context::blocks () const { return blocks_m; } -nano::work_pool & nano::test::context::ledger_context::pool () +nano::work_pool & nano::test::ledger_context::pool () { return pool_m; } -auto nano::test::context::ledger_empty () -> ledger_context +/* + * Ledger facotries + */ + +auto nano::test::ledger_empty () -> ledger_context { return ledger_context{}; } -auto nano::test::context::ledger_send_receive () -> ledger_context +auto nano::test::ledger_send_receive () -> ledger_context { std::deque> blocks; nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; @@ -80,7 +84,7 @@ auto nano::test::context::ledger_send_receive () -> ledger_context return ledger_context{ std::move (blocks) }; } -auto nano::test::context::ledger_send_receive_legacy () -> ledger_context +auto nano::test::ledger_send_receive_legacy () -> ledger_context { std::deque> blocks; nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; diff --git a/nano/test_common/ledger_context.hpp b/nano/test_common/ledger_context.hpp index f996a9a4b9..3334559978 100644 --- a/nano/test_common/ledger_context.hpp +++ b/nano/test_common/ledger_context.hpp @@ -4,44 +4,35 @@ #include #include #include +#include -namespace nano +namespace nano::test { -namespace store +class ledger_context { - class component; -} -namespace test -{ - namespace context - { - class ledger_context - { - public: - /** 'blocks' initialises the ledger with each block in-order - Blocks must all return process_result::progress when processed */ - ledger_context (std::deque> && blocks = std::deque>{}); - nano::ledger & ledger (); - nano::store::component & store (); - nano::stats & stats (); - std::deque> const & blocks () const; - nano::work_pool & pool (); +public: + /** 'blocks' initialises the ledger with each block in-order + Blocks must all return process_result::progress when processed */ + ledger_context (std::deque> && blocks = std::deque>{}); + nano::ledger & ledger (); + nano::store::component & store (); + nano::stats & stats (); + std::deque> const & blocks () const; + nano::work_pool & pool (); - private: - nano::logger logger; - std::unique_ptr store_m; - nano::stats stats_m; - nano::ledger ledger_m; - std::deque> blocks_m; - nano::work_pool pool_m; - }; +private: + nano::logger logger; + std::unique_ptr store_m; + nano::stats stats_m; + nano::ledger ledger_m; + std::deque> blocks_m; + nano::work_pool pool_m; +}; - /** Only a genesis block */ - ledger_context ledger_empty (); - /** Send/receive pair of state blocks on the genesis account*/ - ledger_context ledger_send_receive (); - /** Send/receive pair of legacy blocks on the genesis account*/ - ledger_context ledger_send_receive_legacy (); - } -} +/** Only a genesis block */ +ledger_context ledger_empty (); +/** Send/receive pair of state blocks on the genesis account*/ +ledger_context ledger_send_receive (); +/** Send/receive pair of legacy blocks on the genesis account*/ +ledger_context ledger_send_receive_legacy (); } From 290b273faa2e5bf54b0ec342a9d235f9d8b67f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:23:52 +0200 Subject: [PATCH 4/9] Binary tree ledger context --- nano/test_common/ledger_context.cpp | 80 ++++++++++++++++++++++++++++- nano/test_common/ledger_context.hpp | 2 + 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/nano/test_common/ledger_context.cpp b/nano/test_common/ledger_context.cpp index b7f59b938e..6c68069ca9 100644 --- a/nano/test_common/ledger_context.cpp +++ b/nano/test_common/ledger_context.cpp @@ -16,7 +16,7 @@ nano::test::ledger_context::ledger_context (std::deque ledger_context blocks.push_back (receive); return ledger_context{ std::move (blocks) }; } + +auto nano::test::ledger_binary_tree (unsigned height) -> ledger_context +{ + std::deque> blocks; + nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; + + using account_block_pair = std::pair>; + std::deque previous; + previous.push_back ({ nano::dev::genesis_key, nano::dev::genesis }); + + for (unsigned level = 0; level < height; ++level) + { + std::deque current; + for (auto const & [key, root] : previous) + { + auto balance = root->balance_field ().value_or (nano::dev::constants.genesis_amount); + + nano::keypair target1, target2; + nano::block_builder builder; + + auto send1 = builder.state () + .make_block () + .account (key.pub) + .previous (root->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (balance.number () / 2) + .link (target1.pub) + .sign (key.prv, key.pub) + .work (*pool.generate (root->hash ())) + .build (); + + auto send2 = builder.state () + .make_block () + .account (key.pub) + .previous (send1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (0) + .link (target2.pub) + .sign (key.prv, key.pub) + .work (*pool.generate (send1->hash ())) + .build (); + + auto open1 = builder.state () + .make_block () + .account (target1.pub) + .previous (0) + .representative (nano::dev::genesis_key.pub) + .balance (balance.number () - balance.number () / 2) + .link (send1->hash ()) + .sign (target1.prv, target1.pub) + .work (*pool.generate (target1.pub)) + .build (); + + auto open2 = builder.state () + .make_block () + .account (target2.pub) + .previous (0) + .representative (nano::dev::genesis_key.pub) + .balance (balance.number () / 2) + .link (send2->hash ()) + .sign (target2.prv, target2.pub) + .work (*pool.generate (target2.pub)) + .build (); + + blocks.push_back (send1); + blocks.push_back (send2); + blocks.push_back (open1); + blocks.push_back (open2); + + current.push_back ({ target1, open1 }); + current.push_back ({ target2, open2 }); + } + previous.clear (); + previous.swap (current); + } + + return ledger_context{ std::move (blocks) }; +} diff --git a/nano/test_common/ledger_context.hpp b/nano/test_common/ledger_context.hpp index 3334559978..d4317a2f9c 100644 --- a/nano/test_common/ledger_context.hpp +++ b/nano/test_common/ledger_context.hpp @@ -35,4 +35,6 @@ ledger_context ledger_empty (); ledger_context ledger_send_receive (); /** Send/receive pair of legacy blocks on the genesis account*/ ledger_context ledger_send_receive_legacy (); +/** Full binary tree of state blocks */ +ledger_context ledger_binary_tree (unsigned height); } From 0049dc8c730ae1f9f6aaced81523a949863ba072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Wed, 26 Jun 2024 23:01:01 +0200 Subject: [PATCH 5/9] Tests --- nano/core_test/ledger.cpp | 95 ++++++++++++++++++ nano/node/confirming_set.cpp | 2 +- nano/test_common/ledger_context.cpp | 144 +++++++++++++++++++++++++++- nano/test_common/ledger_context.hpp | 8 +- 4 files changed, 243 insertions(+), 6 deletions(-) diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 7cdd810834..1156ad11a8 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -5523,6 +5523,101 @@ TEST (ledger, head_block) ASSERT_EQ (*nano::dev::genesis, *ledger.any.block_get (tx, ledger.any.account_head (tx, nano::dev::genesis_key.pub))); } +// Tests that a fairly complex ledger topology can be cemented in a single batch +TEST (ledger, cement_unbounded) +{ + auto ctx = nano::test::ledger_diamond (5); + auto & ledger = ctx.ledger (); + auto bottom = ctx.blocks ().back (); + auto confirmed = ledger.confirm (ledger.tx_begin_write (), bottom->hash ()); + ASSERT_TRUE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + // Check that all blocks got confirmed in a single call + ASSERT_TRUE (std::all_of (ctx.blocks ().begin (), ctx.blocks ().end (), [&] (auto const & block) { + return std::find_if (confirmed.begin (), confirmed.end (), [&] (auto const & block2) { + return block2->hash () == block->hash (); + }) + != confirmed.end (); + })); +} + +// Tests that bounded cementing works when recursion stack is large +TEST (ledger, cement_bounded) +{ + auto ctx = nano::test::ledger_single_chain (64); + auto & ledger = ctx.ledger (); + auto bottom = ctx.blocks ().back (); + + // This should only cement some of the dependencies + auto confirmed1 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 3); + ASSERT_FALSE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_EQ (confirmed1.size (), 3); + // Only topmost dependencies should get cemented during this call + ASSERT_TRUE (std::all_of (confirmed1.begin (), confirmed1.end (), [&] (auto const & block) { + return ledger.dependents_confirmed (ledger.tx_begin_read (), *block); + })); + + // This should cement a few more dependencies + auto confirmed2 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 16); + ASSERT_FALSE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_EQ (confirmed2.size (), 16); + // Only topmost dependencies should get cemented during this call + ASSERT_TRUE (std::all_of (confirmed2.begin (), confirmed2.end (), [&] (auto const & block) { + return ledger.dependents_confirmed (ledger.tx_begin_read (), *block); + })); + + // This should cement the remaining dependencies + auto confirmed3 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 64); + ASSERT_TRUE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_LE (confirmed3.size (), 64); + // Every block in the ledger should be cemented + ASSERT_TRUE (std::all_of (ctx.blocks ().begin (), ctx.blocks ().end (), [&] (auto const & block) { + return ledger.confirmed.block_exists (ledger.tx_begin_read (), block->hash ()); + })); +} + +// Tests that bounded cementing works when mumber of blocks is large but tree height is small (recursion stack is small) +TEST (ledger, cement_bounded_diamond) +{ + auto ctx = nano::test::ledger_diamond (4); + auto & ledger = ctx.ledger (); + auto bottom = ctx.blocks ().back (); + + // This should only cement some of the dependencies + auto confirmed1 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 3); + ASSERT_FALSE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_EQ (confirmed1.size (), 3); + // Only topmost dependencies should get cemented during this call + ASSERT_TRUE (std::all_of (confirmed1.begin (), confirmed1.end (), [&] (auto const & block) { + return ledger.dependents_confirmed (ledger.tx_begin_read (), *block); + })); + + // This should cement a few more dependencies + auto confirmed2 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 16); + ASSERT_FALSE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_EQ (confirmed2.size (), 16); + // Only topmost dependencies should get cemented during this call + ASSERT_TRUE (std::all_of (confirmed2.begin (), confirmed2.end (), [&] (auto const & block) { + return ledger.dependents_confirmed (ledger.tx_begin_read (), *block); + })); + + // A few more bounded calls should confirm the whole tree + auto confirmed3 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 64); + ASSERT_FALSE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_EQ (confirmed3.size (), 64); + // Only topmost dependencies should get cemented during this call + ASSERT_TRUE (std::all_of (confirmed2.begin (), confirmed2.end (), [&] (auto const & block) { + return ledger.dependents_confirmed (ledger.tx_begin_read (), *block); + })); + + auto confirmed4 = ledger.confirm (ledger.tx_begin_write (), bottom->hash (), /* max cementing batch size */ 64); + ASSERT_TRUE (ledger.confirmed.block_exists (ledger.tx_begin_read (), bottom->hash ())); + ASSERT_LT (confirmed4.size (), 64); + // Every block in the ledger should be cemented + ASSERT_TRUE (std::all_of (ctx.blocks ().begin (), ctx.blocks ().end (), [&] (auto const & block) { + return ledger.confirmed.block_exists (ledger.tx_begin_read (), block->hash ()); + })); +} + // Test that nullopt can be returned when there are no receivable entries TEST (ledger_receivable, upper_bound_account_none) { diff --git a/nano/node/confirming_set.cpp b/nano/node/confirming_set.cpp index ca69035617..9a8f436e77 100644 --- a/nano/node/confirming_set.cpp +++ b/nano/node/confirming_set.cpp @@ -158,7 +158,6 @@ void nano::confirming_set::run_batch (std::unique_lock & lock) { auto transaction = ledger.tx_begin_write ({ nano::tables::confirmation_height }, nano::store::writer::confirmation_height); - for (auto const & hash : batch) { do @@ -184,6 +183,7 @@ void nano::confirming_set::run_batch (std::unique_lock & lock) { stats.inc (nano::stat::type::confirming_set, nano::stat::detail::already_cemented); already.push_back (hash); + debug_assert (ledger.confirmed.block_exists (transaction, hash)); } } while (!ledger.confirmed.block_exists (transaction, hash)); } diff --git a/nano/test_common/ledger_context.cpp b/nano/test_common/ledger_context.cpp index 6c68069ca9..578aaa6342 100644 --- a/nano/test_common/ledger_context.cpp +++ b/nano/test_common/ledger_context.cpp @@ -109,7 +109,7 @@ auto nano::test::ledger_send_receive_legacy () -> ledger_context return ledger_context{ std::move (blocks) }; } -auto nano::test::ledger_binary_tree (unsigned height) -> ledger_context +auto nano::test::ledger_diamond (unsigned height) -> ledger_context { std::deque> blocks; nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; @@ -118,11 +118,15 @@ auto nano::test::ledger_binary_tree (unsigned height) -> ledger_context std::deque previous; previous.push_back ({ nano::dev::genesis_key, nano::dev::genesis }); + // Expanding tree for (unsigned level = 0; level < height; ++level) { std::deque current; - for (auto const & [key, root] : previous) + while (!previous.empty ()) { + auto const [key, root] = previous.front (); + previous.pop_front (); + auto balance = root->balance_field ().value_or (nano::dev::constants.genesis_amount); nano::keypair target1, target2; @@ -184,5 +188,141 @@ auto nano::test::ledger_binary_tree (unsigned height) -> ledger_context previous.swap (current); } + // Contracting tree + while (previous.size () > 1) + { + std::deque current; + while (!previous.empty ()) + { + auto const [key1, root1] = previous.front (); + previous.pop_front (); + auto const [key2, root2] = previous.front (); + previous.pop_front (); + + nano::keypair target; + nano::block_builder builder; + + auto balance1 = root1->balance_field ().value ().number (); + auto balance2 = root2->balance_field ().value ().number (); + + auto send1 = builder.state () + .make_block () + .account (key1.pub) + .previous (root1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (0) + .link (target.pub) + .sign (key1.prv, key1.pub) + .work (*pool.generate (root1->hash ())) + .build (); + + auto send2 = builder.state () + .make_block () + .account (key2.pub) + .previous (root2->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (0) + .link (target.pub) + .sign (key2.prv, key2.pub) + .work (*pool.generate (root2->hash ())) + .build (); + + auto receive1 = builder.state () + .make_block () + .account (target.pub) + .previous (0) + .representative (nano::dev::genesis_key.pub) + .balance (balance1) + .link (send1->hash ()) + .sign (target.prv, target.pub) + .work (*pool.generate (target.pub)) + .build (); + + auto receive2 = builder.state () + .make_block () + .account (target.pub) + .previous (receive1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (balance1 + balance2) + .link (send2->hash ()) + .sign (target.prv, target.pub) + .work (*pool.generate (receive1->hash ())) + .build (); + + blocks.push_back (send1); + blocks.push_back (send2); + blocks.push_back (receive1); + blocks.push_back (receive2); + + current.push_back ({ target, receive2 }); + } + previous.clear (); + previous.swap (current); + } + return ledger_context{ std::move (blocks) }; } + +auto nano::test::ledger_single_chain (unsigned height) -> nano::test::ledger_context +{ + std::deque> blocks; + nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; + + nano::block_builder builder; + auto previous = nano::dev::genesis; + for (unsigned i = 0; i < height / 4; ++i) + { + auto send1 = builder.state () + .make_block () + .account (nano::dev::genesis_key.pub) + .previous (previous->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - 1) + .link (nano::dev::genesis_key.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*pool.generate (previous->hash ())) + .build (); + + auto send2 = builder.state () + .make_block () + .account (nano::dev::genesis_key.pub) + .previous (send1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - 2) + .link (nano::dev::genesis_key.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*pool.generate (send1->hash ())) + .build (); + + auto receive1 = builder.state () + .make_block () + .account (nano::dev::genesis_key.pub) + .previous (send2->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount - 1) + .link (send1->hash ()) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*pool.generate (send2->hash ())) + .build (); + + auto receive2 = builder.state () + .make_block () + .account (nano::dev::genesis_key.pub) + .previous (receive1->hash ()) + .representative (nano::dev::genesis_key.pub) + .balance (nano::dev::constants.genesis_amount) + .link (send2->hash ()) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*pool.generate (receive1->hash ())) + .build (); + + blocks.push_back (send1); + blocks.push_back (send2); + blocks.push_back (receive1); + blocks.push_back (receive2); + + previous = receive2; + } + + return ledger_context{ std::move (blocks) }; +} \ No newline at end of file diff --git a/nano/test_common/ledger_context.hpp b/nano/test_common/ledger_context.hpp index d4317a2f9c..8edca08508 100644 --- a/nano/test_common/ledger_context.hpp +++ b/nano/test_common/ledger_context.hpp @@ -31,10 +31,12 @@ class ledger_context /** Only a genesis block */ ledger_context ledger_empty (); -/** Send/receive pair of state blocks on the genesis account*/ +/** Send/receive pair of state blocks on the genesis account */ ledger_context ledger_send_receive (); -/** Send/receive pair of legacy blocks on the genesis account*/ +/** Send/receive pair of legacy blocks on the genesis account */ ledger_context ledger_send_receive_legacy (); /** Full binary tree of state blocks */ -ledger_context ledger_binary_tree (unsigned height); +ledger_context ledger_diamond (unsigned height); +/** Single chain of state blocks with send and receives to itself */ +ledger_context ledger_single_chain (unsigned height); } From 59f6b313b3cb91a0a5c0d3c9c0a5b1aeb45b7b52 Mon Sep 17 00:00:00 2001 From: gr0vity-dev <85646666+gr0vity-dev@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:43:16 +0200 Subject: [PATCH 6/9] Add New Bucket for Specific Amount Range (#4661) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add additional bucket for amounts between Ӿ0.000001 and Ӿ0.0003 include Ӿ0.000001 into new bucket * Adjust testcases to account for the additional bucket --------- Co-authored-by: gr0vity --- nano/core_test/scheduler_buckets.cpp | 10 +++++----- nano/node/scheduler/buckets.cpp | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/nano/core_test/scheduler_buckets.cpp b/nano/core_test/scheduler_buckets.cpp index dfb68e200a..a29c2967bb 100644 --- a/nano/core_test/scheduler_buckets.cpp +++ b/nano/core_test/scheduler_buckets.cpp @@ -112,7 +112,7 @@ TEST (buckets, construction) nano::scheduler::buckets buckets; ASSERT_EQ (0, buckets.size ()); ASSERT_TRUE (buckets.empty ()); - ASSERT_EQ (62, buckets.bucket_count ()); + ASSERT_EQ (63, buckets.bucket_count ()); } TEST (buckets, insert_Gxrb) @@ -120,7 +120,7 @@ TEST (buckets, insert_Gxrb) nano::scheduler::buckets buckets; buckets.push (1000, block0 (), nano::Gxrb_ratio); ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (1, buckets.bucket_size (48)); + ASSERT_EQ (1, buckets.bucket_size (49)); } TEST (buckets, insert_Mxrb) @@ -128,7 +128,7 @@ TEST (buckets, insert_Mxrb) nano::scheduler::buckets buckets; buckets.push (1000, block1 (), nano::Mxrb_ratio); ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (1, buckets.bucket_size (13)); + ASSERT_EQ (1, buckets.bucket_size (14)); } // Test two blocks with the same priority @@ -138,7 +138,7 @@ TEST (buckets, insert_same_priority) buckets.push (1000, block0 (), nano::Gxrb_ratio); buckets.push (1000, block2 (), nano::Gxrb_ratio); ASSERT_EQ (2, buckets.size ()); - ASSERT_EQ (2, buckets.bucket_size (48)); + ASSERT_EQ (2, buckets.bucket_size (49)); } // Test the same block inserted multiple times @@ -148,7 +148,7 @@ TEST (buckets, insert_duplicate) buckets.push (1000, block0 (), nano::Gxrb_ratio); buckets.push (1000, block0 (), nano::Gxrb_ratio); ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (1, buckets.bucket_size (48)); + ASSERT_EQ (1, buckets.bucket_size (49)); } TEST (buckets, insert_older) diff --git a/nano/node/scheduler/buckets.cpp b/nano/node/scheduler/buckets.cpp index ee54394152..18194dc610 100644 --- a/nano/node/scheduler/buckets.cpp +++ b/nano/node/scheduler/buckets.cpp @@ -27,7 +27,7 @@ void nano::scheduler::buckets::seek () void nano::scheduler::buckets::setup_buckets (uint64_t maximum) { - auto const size_expected = 62; + auto const size_expected = 63; auto bucket_max = std::max (1u, maximum / size_expected); auto build_region = [&] (uint128_t const & begin, uint128_t const & end, size_t count) { auto width = (end - begin) / count; @@ -36,7 +36,8 @@ void nano::scheduler::buckets::setup_buckets (uint64_t maximum) buckets_m.push_back (std::make_unique (begin + i * width, bucket_max)); } }; - build_region (0, uint128_t{ 1 } << 88, 1); + build_region (0, uint128_t{ 1 } << 79, 1); + build_region (uint128_t{ 1 } << 79, uint128_t{ 1 } << 88, 1); build_region (uint128_t{ 1 } << 88, uint128_t{ 1 } << 92, 2); build_region (uint128_t{ 1 } << 92, uint128_t{ 1 } << 96, 4); build_region (uint128_t{ 1 } << 96, uint128_t{ 1 } << 100, 8); From fd023dcafcc608d733628ef9a4488a12ca4c663d Mon Sep 17 00:00:00 2001 From: RickiNano <81099017+RickiNano@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:44:19 +0200 Subject: [PATCH 7/9] Update RocksDb to V9.2.2 (#4652) --- submodules/rocksdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/rocksdb b/submodules/rocksdb index cb7a5e02ed..41214f0b4e 160000 --- a/submodules/rocksdb +++ b/submodules/rocksdb @@ -1 +1 @@ -Subproject commit cb7a5e02edeb883193eb5b4901d5943f58e9add9 +Subproject commit 41214f0b4e05aa8123583968df039c0d35228a4f From bc9bc82a8d63ca995e2c1ab3b67766686a7d39bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20W=C3=B3jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:00:11 +0200 Subject: [PATCH 8/9] Log node status periodically (#4676) * Fix alignment * Log node status periodically * Log detailed peer and connections info * Logging consistency --- nano/lib/logging_enums.hpp | 1 + nano/lib/thread_roles.cpp | 3 + nano/lib/thread_roles.hpp | 1 + nano/node/CMakeLists.txt | 6 +- nano/node/active_elections.cpp | 8 ++ nano/node/active_elections.hpp | 3 +- nano/node/monitor.cpp | 132 +++++++++++++++++++++++++++ nano/node/monitor.hpp | 52 +++++++++++ nano/node/node.cpp | 11 ++- nano/node/node.hpp | 4 + nano/node/nodeconfig.cpp | 10 ++ nano/node/nodeconfig.hpp | 2 + nano/node/repcrawler.cpp | 18 ++-- nano/node/transport/tcp_listener.cpp | 6 ++ nano/node/transport/tcp_listener.hpp | 14 +-- 15 files changed, 250 insertions(+), 21 deletions(-) create mode 100644 nano/node/monitor.cpp create mode 100644 nano/node/monitor.hpp diff --git a/nano/lib/logging_enums.hpp b/nano/lib/logging_enums.hpp index b2b00b350c..7eecf47cf4 100644 --- a/nano/lib/logging_enums.hpp +++ b/nano/lib/logging_enums.hpp @@ -80,6 +80,7 @@ enum class type peer_history, message_processor, local_block_broadcaster, + monitor, // bootstrap bulk_pull_client, diff --git a/nano/lib/thread_roles.cpp b/nano/lib/thread_roles.cpp index 2831c72038..76f467cd0e 100644 --- a/nano/lib/thread_roles.cpp +++ b/nano/lib/thread_roles.cpp @@ -157,6 +157,9 @@ std::string nano::thread_role::get_string (nano::thread_role::name role) case nano::thread_role::name::vote_router: thread_role_name_string = "Vote router"; break; + case nano::thread_role::name::monitor: + thread_role_name_string = "Monitor"; + break; default: debug_assert (false && "nano::thread_role::get_string unhandled thread role"); } diff --git a/nano/lib/thread_roles.hpp b/nano/lib/thread_roles.hpp index eef15632fa..5896318c42 100644 --- a/nano/lib/thread_roles.hpp +++ b/nano/lib/thread_roles.hpp @@ -59,6 +59,7 @@ enum class name port_mapping, stats, vote_router, + monitor, }; std::string_view to_string (name); diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index 535f917b67..37646b575b 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -101,6 +101,10 @@ add_library( make_store.cpp message_processor.hpp message_processor.cpp + messages.hpp + messages.cpp + monitor.hpp + monitor.cpp network.hpp network.cpp nodeconfig.hpp @@ -196,8 +200,6 @@ add_library( websocketconfig.cpp websocket_stream.hpp websocket_stream.cpp - messages.hpp - messages.cpp xorshift.hpp) target_link_libraries( diff --git a/nano/node/active_elections.cpp b/nano/node/active_elections.cpp index aa183428e8..3f7d7baeec 100644 --- a/nano/node/active_elections.cpp +++ b/nano/node/active_elections.cpp @@ -515,6 +515,14 @@ std::size_t nano::active_elections::size () const return roots.size (); } +std::size_t nano::active_elections::size (nano::election_behavior behavior) const +{ + nano::lock_guard lock{ mutex }; + auto count = count_by_behavior[behavior]; + debug_assert (count >= 0); + return static_cast (count); +} + bool nano::active_elections::publish (std::shared_ptr const & block_a) { nano::unique_lock lock{ mutex }; diff --git a/nano/node/active_elections.hpp b/nano/node/active_elections.hpp index a4cb478a38..96e47def58 100644 --- a/nano/node/active_elections.hpp +++ b/nano/node/active_elections.hpp @@ -120,6 +120,7 @@ class active_elections final bool erase (nano::qualified_root const &); bool empty () const; std::size_t size () const; + std::size_t size (nano::election_behavior) const; bool publish (std::shared_ptr const &); /** @@ -172,7 +173,7 @@ class active_elections final std::chrono::seconds const election_time_to_live; /** Keeps track of number of elections by election behavior (normal, hinted, optimistic) */ - nano::enum_array count_by_behavior; + nano::enum_array count_by_behavior{}; nano::condition_variable condition; bool stopped{ false }; diff --git a/nano/node/monitor.cpp b/nano/node/monitor.cpp new file mode 100644 index 0000000000..15b98b89d4 --- /dev/null +++ b/nano/node/monitor.cpp @@ -0,0 +1,132 @@ +#include "nano/secure/ledger.hpp" + +#include +#include +#include +#include + +nano::monitor::monitor (nano::monitor_config const & config_a, nano::node & node_a) : + config{ config_a }, + node{ node_a }, + logger{ node_a.logger } +{ +} + +nano::monitor::~monitor () +{ + debug_assert (!thread.joinable ()); +} + +void nano::monitor::start () +{ + if (!config.enabled) + { + return; + } + + thread = std::thread ([this] () { + nano::thread_role::set (nano::thread_role::name::monitor); + run (); + }); +} + +void nano::monitor::stop () +{ + { + nano::lock_guard guard{ mutex }; + stopped = true; + } + condition.notify_all (); + if (thread.joinable ()) + { + thread.join (); + } +} + +void nano::monitor::run () +{ + std::unique_lock lock{ mutex }; + while (!stopped) + { + run_one (); + condition.wait_until (lock, std::chrono::steady_clock::now () + config.interval, [this] { return stopped; }); + } +} + +void nano::monitor::run_one () +{ + // Node status: + // - blocks (confirmed, total) + // - blocks rate (over last 5m, peak over last 5m) + // - peers + // - stake (online, peered, trended, quorum needed) + // - elections active (normal, hinted, optimistic) + // - election stats over last 5m (confirmed, dropped) + + auto const now = std::chrono::steady_clock::now (); + auto blocks_cemented = node.ledger.cemented_count (); + auto blocks_total = node.ledger.block_count (); + + // Wait for node to warm up before logging + if (last_time != std::chrono::steady_clock::time_point{}) + { + // TODO: Maybe emphasize somehow that confirmed doesn't need to be equal to total; backlog is OK + logger.info (nano::log::type::monitor, "Blocks confirmed: {} | total: {}", + blocks_cemented, + blocks_total); + + // Calculate the rates + auto elapsed_seconds = std::chrono::duration_cast (now - last_time).count (); + auto blocks_confirmed_rate = static_cast (blocks_cemented - last_blocks_cemented) / elapsed_seconds; + auto blocks_checked_rate = static_cast (blocks_total - last_blocks_total) / elapsed_seconds; + + logger.info (nano::log::type::monitor, "Blocks rate (average over last {}s): confirmed {:.2f}/s | total {:.2f}/s", + elapsed_seconds, + blocks_confirmed_rate, + blocks_checked_rate); + + logger.info (nano::log::type::monitor, "Peers: {} (realtime: {} | bootstrap: {} | inbound connections: {} | outbound connections: {})", + node.network.size (), + node.tcp_listener.realtime_count (), + node.tcp_listener.bootstrap_count (), + node.tcp_listener.connection_count (nano::transport::tcp_listener::connection_type::inbound), + node.tcp_listener.connection_count (nano::transport::tcp_listener::connection_type::outbound)); + + logger.info (nano::log::type::monitor, "Quorum: {} (stake peered: {} | stake online: {})", + nano::uint128_union{ node.online_reps.delta () }.format_balance (Mxrb_ratio, 1, true), + nano::uint128_union{ node.rep_crawler.total_weight () }.format_balance (Mxrb_ratio, 1, true), + nano::uint128_union{ node.online_reps.online () }.format_balance (Mxrb_ratio, 1, true)); + + logger.info (nano::log::type::monitor, "Elections active: {} (priority: {} | hinted: {} | optimistic: {})", + node.active.size (), + node.active.size (nano::election_behavior::priority), + node.active.size (nano::election_behavior::hinted), + node.active.size (nano::election_behavior::optimistic)); + } + + last_time = now; + last_blocks_cemented = blocks_cemented; + last_blocks_total = blocks_total; +} + +/* + * monitor_config + */ + +nano::error nano::monitor_config::serialize (nano::tomlconfig & toml) const +{ + toml.put ("enable", enabled, "Enable or disable periodic node status logging\ntype:bool"); + toml.put ("interval", interval.count (), "Interval between status logs\ntype:seconds"); + + return toml.get_error (); +} + +nano::error nano::monitor_config::deserialize (nano::tomlconfig & toml) +{ + toml.get ("enabled", enabled); + auto interval_l = interval.count (); + toml.get ("interval", interval_l); + interval = std::chrono::seconds{ interval_l }; + + return toml.get_error (); +} \ No newline at end of file diff --git a/nano/node/monitor.hpp b/nano/node/monitor.hpp new file mode 100644 index 0000000000..a76f753bbc --- /dev/null +++ b/nano/node/monitor.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +#include +#include + +using namespace std::chrono_literals; + +namespace nano +{ +class monitor_config final +{ +public: + nano::error deserialize (nano::tomlconfig &); + nano::error serialize (nano::tomlconfig &) const; + +public: + bool enabled{ true }; + std::chrono::seconds interval{ 60s }; +}; + +class monitor final +{ +public: + monitor (monitor_config const &, nano::node &); + ~monitor (); + + void start (); + void stop (); + +private: // Dependencies + monitor_config const & config; + nano::node & node; + nano::logger & logger; + +private: + void run (); + void run_one (); + + std::chrono::steady_clock::time_point last_time{}; + + size_t last_blocks_cemented{ 0 }; + size_t last_blocks_total{ 0 }; + + bool stopped{ false }; + nano::condition_variable condition; + mutable nano::mutex mutex; + std::thread thread; +}; +} \ No newline at end of file diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 05ea923576..eaa141884d 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -223,6 +224,8 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy process_live_dispatcher{ ledger, scheduler.priority, vote_cache, websocket }, peer_history_impl{ std::make_unique (config.peer_history, store, network, logger, stats) }, peer_history{ *peer_history_impl }, + monitor_impl{ std::make_unique (config.monitor, *this) }, + monitor{ *monitor_impl }, startup_time (std::chrono::steady_clock::now ()), node_seq (seq) { @@ -371,7 +374,7 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy auto const network_label = network_params.network.get_current_network_as_string (); - logger.info (nano::log::type::node, "Node starting, version: {}", NANO_VERSION_STRING); + logger.info (nano::log::type::node, "Version: {}", NANO_VERSION_STRING); logger.info (nano::log::type::node, "Build information: {}", BUILD_INFO); logger.info (nano::log::type::node, "Active network: {}", network_label); logger.info (nano::log::type::node, "Database backend: {}", store.vendor_get ()); @@ -445,7 +448,7 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy ledger.bootstrap_weights = bootstrap_weights.second; - logger.info (nano::log::type::node, "************************************ Bootstrap weights ************************************"); + logger.info (nano::log::type::node, "******************************************** Bootstrap weights ********************************************"); // Sort the weights std::vector> sorted_weights (ledger.bootstrap_weights.begin (), ledger.bootstrap_weights.end ()); @@ -460,7 +463,7 @@ nano::node::node (std::shared_ptr io_ctx_a, std::filesy nano::uint128_union (rep.second).format_balance (Mxrb_ratio, 0, true)); } - logger.info (nano::log::type::node, "************************************ ================= ************************************"); + logger.info (nano::log::type::node, "******************************************** ================= ********************************************"); } } @@ -721,6 +724,7 @@ void nano::node::start () local_block_broadcaster.start (); peer_history.start (); vote_router.start (); + monitor.start (); add_initial_peers (); } @@ -770,6 +774,7 @@ void nano::node::stop () local_block_broadcaster.stop (); message_processor.stop (); network.stop (); // Stop network last to avoid killing in-use sockets + monitor.stop (); // work pool is not stopped on purpose due to testing setup diff --git a/nano/node/node.hpp b/nano/node/node.hpp index 10494aa83d..6b8d2eec94 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -45,6 +45,7 @@ namespace nano class active_elections; class confirming_set; class message_processor; +class monitor; class node; class vote_processor; class vote_cache_processor; @@ -216,7 +217,10 @@ class node final : public std::enable_shared_from_this nano::process_live_dispatcher process_live_dispatcher; std::unique_ptr peer_history_impl; nano::peer_history & peer_history; + std::unique_ptr monitor_impl; + nano::monitor & monitor; +public: std::chrono::steady_clock::time_point const startup_time; std::chrono::seconds unchecked_cutoff = std::chrono::seconds (7 * 24 * 60 * 60); // Week std::atomic unresponsive_work_peers{ false }; diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index 0eef9a5674..10adbddeaa 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -249,6 +249,10 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const message_processor.serialize (message_processor_l); toml.put_child ("message_processor", message_processor_l); + nano::tomlconfig monitor_l; + monitor.serialize (monitor_l); + toml.put_child ("monitor", monitor_l); + return toml.get_error (); } @@ -366,6 +370,12 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) message_processor.deserialize (config_l); } + if (toml.has_key ("monitor")) + { + auto config_l = toml.get_required_child ("monitor"); + monitor.deserialize (config_l); + } + if (toml.has_key ("work_peers")) { work_peers.clear (); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 2f01e8d194..f6abaa8ab7 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,7 @@ class node_config nano::network_config network; nano::local_block_broadcaster_config local_block_broadcaster; nano::confirming_set_config confirming_set; + nano::monitor_config monitor; public: std::string serialize_frontiers_confirmation (nano::frontiers_confirmation_mode) const; diff --git a/nano/node/repcrawler.cpp b/nano/node/repcrawler.cpp index f2e22f3575..f6cca66b5f 100644 --- a/nano/node/repcrawler.cpp +++ b/nano/node/repcrawler.cpp @@ -83,7 +83,7 @@ void nano::rep_crawler::validate_and_process (nano::unique_lock & l nano::uint128_t const rep_weight = node.ledger.weight (vote->account); if (rep_weight < minimum) { - logger.debug (nano::log::type::rep_crawler, "Ignoring vote from account {} with too little voting weight: {}", + logger.debug (nano::log::type::rep_crawler, "Ignoring vote from account: {} with too little voting weight: {}", vote->account.to_account (), nano::util::to_str (rep_weight)); continue; @@ -121,11 +121,11 @@ void nano::rep_crawler::validate_and_process (nano::unique_lock & l if (inserted) { - logger.info (nano::log::type::rep_crawler, "Found representative {} at {}", vote->account.to_account (), channel->to_string ()); + logger.info (nano::log::type::rep_crawler, "Found representative: {} at: {}", vote->account.to_account (), channel->to_string ()); } if (updated) { - logger.warn (nano::log::type::rep_crawler, "Updated representative {} at {} (was at: {})", vote->account.to_account (), channel->to_string (), prev_channel->to_string ()); + logger.warn (nano::log::type::rep_crawler, "Updated representative: {} at: {} (was at: {})", vote->account.to_account (), channel->to_string (), prev_channel->to_string ()); } } } @@ -202,7 +202,7 @@ void nano::rep_crawler::cleanup () erase_if (reps, [this] (rep_entry const & rep) { if (!rep.channel->alive ()) { - logger.info (nano::log::type::rep_crawler, "Evicting representative {} with dead channel at {}", rep.account.to_account (), rep.channel->to_string ()); + logger.info (nano::log::type::rep_crawler, "Evicting representative: {} with dead channel at: {}", rep.account.to_account (), rep.channel->to_string ()); stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::channel_dead); return true; // Erase } @@ -215,12 +215,12 @@ void nano::rep_crawler::cleanup () { if (query.replies == 0) { - logger.debug (nano::log::type::rep_crawler, "Aborting unresponsive query for block {} from {}", query.hash.to_string (), query.channel->to_string ()); + logger.debug (nano::log::type::rep_crawler, "Aborting unresponsive query for block: {} from: {}", query.hash.to_string (), query.channel->to_string ()); stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_timeout); } else { - logger.debug (nano::log::type::rep_crawler, "Completion of query with {} replies for block {} from {}", query.replies, query.hash.to_string (), query.channel->to_string ()); + logger.debug (nano::log::type::rep_crawler, "Completion of query with: {} replies for block: {} from: {}", query.replies, query.hash.to_string (), query.channel->to_string ()); stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_completion); } return true; // Erase @@ -350,7 +350,7 @@ void nano::rep_crawler::query (std::vectorto_string ()); + logger.debug (nano::log::type::rep_crawler, "Sending query for block: {} to: {}", hash_root.first.to_string (), channel->to_string ()); stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_sent); auto const & [hash, root] = hash_root; @@ -368,7 +368,7 @@ void nano::rep_crawler::query (std::vectorto_string ()); + logger.debug (nano::log::type::rep_crawler, "Ignoring duplicate query for block: {} to: {}", hash_root.first.to_string (), channel->to_string ()); stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::query_duplicate); } } @@ -404,7 +404,7 @@ bool nano::rep_crawler::process (std::shared_ptr const & vote, std:: }); if (found) { - logger.debug (nano::log::type::rep_crawler, "Processing response for block {} from {}", target_hash.to_string (), channel->to_string ()); + logger.debug (nano::log::type::rep_crawler, "Processing response for block: {} from: {}", target_hash.to_string (), channel->to_string ()); stats.inc (nano::stat::type::rep_crawler, nano::stat::detail::response); // Track response time diff --git a/nano/node/transport/tcp_listener.cpp b/nano/node/transport/tcp_listener.cpp index b97c116854..06c49332ad 100644 --- a/nano/node/transport/tcp_listener.cpp +++ b/nano/node/transport/tcp_listener.cpp @@ -499,6 +499,12 @@ size_t nano::transport::tcp_listener::connection_count () const return connections.size (); } +size_t nano::transport::tcp_listener::connection_count (connection_type type) const +{ + nano::lock_guard lock{ mutex }; + return count_per_type (type); +} + size_t nano::transport::tcp_listener::attempt_count () const { nano::lock_guard lock{ mutex }; diff --git a/nano/node/transport/tcp_listener.hpp b/nano/node/transport/tcp_listener.hpp index 094560477a..55d0603d88 100644 --- a/nano/node/transport/tcp_listener.hpp +++ b/nano/node/transport/tcp_listener.hpp @@ -53,6 +53,13 @@ class tcp_config */ class tcp_listener final { +public: + enum class connection_type + { + inbound, + outbound, + }; + public: tcp_listener (uint16_t port, tcp_config const &, nano::node &); ~tcp_listener (); @@ -69,6 +76,7 @@ class tcp_listener final nano::tcp_endpoint endpoint () const; size_t connection_count () const; + size_t connection_count (connection_type) const; size_t attempt_count () const; size_t realtime_count () const; size_t bootstrap_count () const; @@ -104,12 +112,6 @@ class tcp_listener final error, }; - enum class connection_type - { - inbound, - outbound, - }; - asio::awaitable connect_impl (asio::ip::tcp::endpoint); asio::awaitable connect_socket (asio::ip::tcp::endpoint); From 4f450ae5119094800e58b44b109584cacf6f2f05 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Wed, 10 Jul 2024 12:13:41 +0100 Subject: [PATCH 9/9] Raise file descriptor limit at entry points rather than just within daemon code. (#4677) --- nano/core_test/entry.cpp | 4 +--- nano/lib/utility.cpp | 14 ++++++++++++-- nano/lib/utility.hpp | 5 +++++ nano/nano_node/daemon.cpp | 11 +---------- nano/nano_node/entry.cpp | 2 ++ nano/nano_rpc/entry.cpp | 1 + nano/nano_wallet/entry.cpp | 1 + nano/qt_test/entry.cpp | 1 + nano/rpc_test/entry.cpp | 1 + nano/slow_test/entry.cpp | 1 + 10 files changed, 26 insertions(+), 15 deletions(-) diff --git a/nano/core_test/entry.cpp b/nano/core_test/entry.cpp index 423f3731b8..9d08284dd0 100644 --- a/nano/core_test/entry.cpp +++ b/nano/core_test/entry.cpp @@ -6,8 +6,6 @@ #include -constexpr std::size_t OPEN_FILE_DESCRIPTORS_LIMIT = 16384; - namespace nano { namespace test @@ -19,8 +17,8 @@ void force_nano_dev_network (); GTEST_API_ int main (int argc, char ** argv) { + nano::initialize_file_descriptor_limit (); nano::logger::initialize_for_tests (nano::log_config::tests_default ()); - nano::set_file_descriptor_limit (OPEN_FILE_DESCRIPTORS_LIMIT); nano::force_nano_dev_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; testing::InitGoogleTest (&argc, argv); diff --git a/nano/lib/utility.cpp b/nano/lib/utility.cpp index 869828bd04..64d51efaca 100644 --- a/nano/lib/utility.cpp +++ b/nano/lib/utility.cpp @@ -35,7 +35,7 @@ void nano::set_file_descriptor_limit (std::size_t limit) rlimit fd_limit{}; if (-1 == getrlimit (RLIMIT_NOFILE, &fd_limit)) { - std::cerr << "Unable to get current limits for the number of open file descriptors: " << std::strerror (errno); + std::cerr << "WARNING: Unable to get current limits for the number of open file descriptors: " << std::strerror (errno); return; } @@ -47,12 +47,22 @@ void nano::set_file_descriptor_limit (std::size_t limit) fd_limit.rlim_cur = std::min (static_cast (limit), fd_limit.rlim_max); if (-1 == setrlimit (RLIMIT_NOFILE, &fd_limit)) { - std::cerr << "Unable to set limits for the number of open file descriptors: " << std::strerror (errno); + std::cerr << "WARNING: Unable to set limits for the number of open file descriptors: " << std::strerror (errno); return; } #endif } +void nano::initialize_file_descriptor_limit () +{ + nano::set_file_descriptor_limit (DEFAULT_FILE_DESCRIPTOR_LIMIT); + auto limit = nano::get_file_descriptor_limit (); + if (limit < DEFAULT_FILE_DESCRIPTOR_LIMIT) + { + std::cerr << "WARNING: Current file descriptor limit of " << limit << " is lower than the " << DEFAULT_FILE_DESCRIPTOR_LIMIT << " recommended. Node was unable to change it." << std::endl; + } +} + nano::container_info_composite::container_info_composite (std::string const & name) : name (name) { diff --git a/nano/lib/utility.hpp b/nano/lib/utility.hpp index 35d19892dd..ecbc35ee13 100644 --- a/nano/lib/utility.hpp +++ b/nano/lib/utility.hpp @@ -134,6 +134,11 @@ void create_load_memory_address_files (); */ std::size_t get_file_descriptor_limit (); void set_file_descriptor_limit (std::size_t limit); +/** + * This should be called from entry points. It sets the file descriptor limit to the maximum allowed and logs any errors. + */ +constexpr std::size_t DEFAULT_FILE_DESCRIPTOR_LIMIT = 16384; +void initialize_file_descriptor_limit (); void remove_all_files_in_dir (std::filesystem::path const & dir); void move_all_files_to_dir (std::filesystem::path const & from, std::filesystem::path const & to); diff --git a/nano/nano_node/daemon.cpp b/nano/nano_node/daemon.cpp index 6752bde692..45eaea5509 100644 --- a/nano/nano_node/daemon.cpp +++ b/nano/nano_node/daemon.cpp @@ -54,8 +54,6 @@ void install_abort_signal_handler () sigaction (SIGABRT, &sa, NULL); #endif } - -constexpr std::size_t OPEN_FILE_DESCRIPTORS_LIMIT = 16384; } void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flags const & flags) @@ -105,14 +103,7 @@ void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flag // Print info about number of logical cores detected, those are used to decide how many IO, worker and signature checker threads to spawn logger.info (nano::log::type::daemon, "Hardware concurrency: {} ( configured: {} )", std::thread::hardware_concurrency (), nano::hardware_concurrency ()); - - nano::set_file_descriptor_limit (OPEN_FILE_DESCRIPTORS_LIMIT); - auto const file_descriptor_limit = nano::get_file_descriptor_limit (); - logger.info (nano::log::type::daemon, "File descriptors limit: {}", file_descriptor_limit); - if (file_descriptor_limit < OPEN_FILE_DESCRIPTORS_LIMIT) - { - logger.warn (nano::log::type::daemon, "File descriptors limit is lower than the {} recommended. Node was unable to change it.", OPEN_FILE_DESCRIPTORS_LIMIT); - } + logger.info (nano::log::type::daemon, "File descriptors limit: {}", nano::get_file_descriptor_limit ()); // for the daemon start up, if the user hasn't specified a port in // the config, we must use the default peering port for the network diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 205a8d2af9..c86228a04b 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -55,11 +55,13 @@ class address_library_pair bool operator< (const address_library_pair & other) const; bool operator== (const address_library_pair & other) const; }; + } int main (int argc, char * const * argv) { nano::set_umask (); // Make sure the process umask is set before any files are created + nano::initialize_file_descriptor_limit (); nano::logger::initialize (nano::log_config::cli_default ()); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; diff --git a/nano/nano_rpc/entry.cpp b/nano/nano_rpc/entry.cpp index 11cea70432..c54b335869 100644 --- a/nano/nano_rpc/entry.cpp +++ b/nano/nano_rpc/entry.cpp @@ -84,6 +84,7 @@ void run (std::filesystem::path const & data_path, std::vector cons int main (int argc, char * const * argv) { nano::set_umask (); // Make sure the process umask is set before any files are created + nano::initialize_file_descriptor_limit (); nano::logger::initialize (nano::log_config::cli_default ()); boost::program_options::options_description description ("Command line options"); diff --git a/nano/nano_wallet/entry.cpp b/nano/nano_wallet/entry.cpp index 65be63a226..25b29947fb 100644 --- a/nano/nano_wallet/entry.cpp +++ b/nano/nano_wallet/entry.cpp @@ -237,6 +237,7 @@ int run_wallet (QApplication & application, int argc, char * const * argv, std:: int main (int argc, char * const * argv) { nano::set_umask (); // Make sure the process umask is set before any files are created + nano::initialize_file_descriptor_limit (); nano::logger::initialize (nano::log_config::cli_default ()); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; diff --git a/nano/qt_test/entry.cpp b/nano/qt_test/entry.cpp index e8976178c4..b3ce57fd8f 100644 --- a/nano/qt_test/entry.cpp +++ b/nano/qt_test/entry.cpp @@ -17,6 +17,7 @@ void force_nano_dev_network (); int main (int argc, char ** argv) { + nano::initialize_file_descriptor_limit (); nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; diff --git a/nano/rpc_test/entry.cpp b/nano/rpc_test/entry.cpp index 2a94b7d9e7..806f07645b 100644 --- a/nano/rpc_test/entry.cpp +++ b/nano/rpc_test/entry.cpp @@ -15,6 +15,7 @@ void force_nano_dev_network (); int main (int argc, char ** argv) { + nano::initialize_file_descriptor_limit (); nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); nano::set_use_memory_pools (false); diff --git a/nano/slow_test/entry.cpp b/nano/slow_test/entry.cpp index 0b9a0ca758..096c7dc6a9 100644 --- a/nano/slow_test/entry.cpp +++ b/nano/slow_test/entry.cpp @@ -14,6 +14,7 @@ void force_nano_dev_network (); int main (int argc, char ** argv) { + nano::initialize_file_descriptor_limit (); nano::logger::initialize_for_tests (nano::log_config::tests_default ()); nano::force_nano_dev_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard;