From 9112636c22458ceb5c2fe6cdfe7f80c76ccae924 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Fri, 19 Mar 2021 15:18:01 +0100 Subject: [PATCH] Remove bootstrap restarting code (#3149) * This removes bootstrap restarting code as it is ineffective and can cause unnecessary restarting of the bootstrap process. * bulk.genesis_pruning test improvements * Fix TSAN warning in test active_transactions.confirm_frontier * Remove now unused variables and options Co-authored-by: Sergey Kroshnin --- nano/core_test/active_transactions.cpp | 10 +- nano/core_test/bootstrap.cpp | 155 +------------- nano/node/bootstrap/bootstrap.cpp | 7 +- nano/node/bootstrap/bootstrap.hpp | 5 +- nano/node/bootstrap/bootstrap_attempt.cpp | 13 -- nano/node/bootstrap/bootstrap_attempt.hpp | 3 - nano/node/bootstrap/bootstrap_connections.cpp | 10 +- nano/node/bootstrap/bootstrap_legacy.cpp | 200 +----------------- nano/node/bootstrap/bootstrap_legacy.hpp | 8 +- nano/node/json_handler.cpp | 3 +- 10 files changed, 15 insertions(+), 399 deletions(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index fd849766..46fa06c1 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -88,17 +88,21 @@ TEST (active_transactions, confirm_frontier) } nano::genesis genesis; - auto send = nano::send_block_builder () + nano::state_block_builder builder; + auto send = builder + .account (nano::dev_genesis_key.pub) .previous (genesis.hash ()) - .destination (nano::public_key ()) + .representative (nano::dev_genesis_key.pub) .balance (nano::genesis_amount - 100) + .link (nano::public_key ()) .sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub) .work (*system.work.generate (genesis.hash ())) .build_shared (); + auto send_copy = builder.make_block ().from (*send).build_shared (); ASSERT_EQ (nano::process_result::progress, node1.process (*send).code); node1.confirmation_height_processor.add (send); ASSERT_TIMELY (5s, node1.ledger.block_confirmed (node1.store.tx_begin_read (), send->hash ())); - ASSERT_EQ (nano::process_result::progress, node2.process (*send).code); + ASSERT_EQ (nano::process_result::progress, node2.process (*send_copy).code); ASSERT_TIMELY (5s, !node2.active.empty ()); // Save election to check request count afterwards auto election2 = node2.active.election (send->qualified_root ()); diff --git a/nano/core_test/bootstrap.cpp b/nano/core_test/bootstrap.cpp index db3c8d97..058aa989 100644 --- a/nano/core_test/bootstrap.cpp +++ b/nano/core_test/bootstrap.cpp @@ -354,157 +354,6 @@ TEST (bootstrap_processor, DISABLED_pull_requeue_network_error) ASSERT_EQ (0, node1->stats.count (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_failed_account, nano::stat::dir::in)); // Requeue is not increasing failed attempts } -TEST (bootstrap_processor, frontiers_unconfirmed) -{ - nano::system system; - nano::node_config node_config (nano::get_available_port (), system.logging); - node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; - node_config.tcp_io_timeout = std::chrono::seconds (2); - nano::node_flags node_flags; - node_flags.disable_bootstrap_bulk_pull_server = true; - node_flags.disable_bootstrap_bulk_push_client = true; - node_flags.disable_legacy_bootstrap = true; - node_flags.disable_lazy_bootstrap = true; - node_flags.disable_wallet_bootstrap = true; - node_flags.disable_rep_crawler = true; - auto node1 = system.add_node (node_config, node_flags); - nano::genesis genesis; - nano::keypair key1, key2; - // Generating invalid chain - auto send1 (std::make_shared (nano::dev_genesis_key.pub, genesis.hash (), nano::dev_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key1.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (genesis.hash ()))); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); - auto send2 (std::make_shared (nano::dev_genesis_key.pub, send1->hash (), nano::dev_genesis_key.pub, nano::genesis_amount - 2 * nano::Gxrb_ratio, key2.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send1->hash ()))); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); - auto open1 (std::make_shared (key1.pub, 0, key1.pub, nano::Gxrb_ratio, send1->hash (), key1.prv, key1.pub, *system.work.generate (key1.pub))); - ASSERT_EQ (nano::process_result::progress, node1->process (*open1).code); - auto open2 (std::make_shared (key2.pub, 0, key2.pub, nano::Gxrb_ratio, send2->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub))); - ASSERT_EQ (nano::process_result::progress, node1->process (*open2).code); - - node_config.peering_port = nano::get_available_port (); - node_flags.disable_bootstrap_bulk_pull_server = false; - node_flags.disable_rep_crawler = false; - auto node2 = system.add_node (node_config, node_flags); - // Generating valid chain - auto send3 (std::make_shared (nano::dev_genesis_key.pub, genesis.hash (), nano::dev_genesis_key.pub, nano::genesis_amount - nano::xrb_ratio, key1.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (genesis.hash ()))); - ASSERT_EQ (nano::process_result::progress, node2->process (*send3).code); - auto open3 (std::make_shared (key1.pub, 0, key1.pub, nano::xrb_ratio, send3->hash (), key1.prv, key1.pub, *system.work.generate (key1.pub))); - ASSERT_EQ (nano::process_result::progress, node2->process (*open3).code); - system.wallet (1)->insert_adhoc (nano::dev_genesis_key.prv); - - // Ensure node2 can generate votes - node2->block_confirm (send3); - ASSERT_TIMELY (10s, node2->ledger.cache.cemented_count == 3 && node2->confirmation_height_processor.current ().is_zero ()); - - // Test node to restart bootstrap - node_config.peering_port = nano::get_available_port (); - node_flags.disable_legacy_bootstrap = false; - auto node3 = system.add_node (node_config, node_flags); - ASSERT_TIMELY (5s, node3->rep_crawler.representative_count () != 0); - //Add single excluded peers record (2 records are required to drop peer) - node3->network.excluded_peers.add (nano::transport::map_endpoint_to_tcp (node1->network.endpoint ()), 0); - ASSERT_FALSE (node3->network.excluded_peers.check (nano::transport::map_endpoint_to_tcp (node1->network.endpoint ()))); - node3->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); - ASSERT_TIMELY (15s, !node3->bootstrap_initiator.in_progress ()); - ASSERT_FALSE (node3->ledger.block_exists (send1->hash ())); - ASSERT_FALSE (node3->ledger.block_exists (open1->hash ())); - ASSERT_EQ (1, node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in)); // failed request from node1 - ASSERT_FALSE (node3->network.excluded_peers.check (nano::transport::map_endpoint_to_tcp (node1->network.endpoint ()))); // Banning from bootstrap is disabled -} - -TEST (bootstrap_processor, frontiers_confirmed) -{ - nano::system system; - nano::node_config node_config (nano::get_available_port (), system.logging); - node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; - node_config.tcp_io_timeout = std::chrono::seconds (2); - nano::node_flags node_flags; - node_flags.disable_bootstrap_bulk_pull_server = true; - node_flags.disable_bootstrap_bulk_push_client = true; - node_flags.disable_legacy_bootstrap = true; - node_flags.disable_lazy_bootstrap = true; - node_flags.disable_wallet_bootstrap = true; - node_flags.disable_rep_crawler = true; - auto node1 = system.add_node (node_config, node_flags); - nano::genesis genesis; - nano::keypair key1, key2; - // Generating valid chain - auto send1 (std::make_shared (nano::dev_genesis_key.pub, genesis.hash (), nano::dev_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key1.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (genesis.hash ()))); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); - auto send2 (std::make_shared (nano::dev_genesis_key.pub, send1->hash (), nano::dev_genesis_key.pub, nano::genesis_amount - 2 * nano::Gxrb_ratio, key2.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send1->hash ()))); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); - auto open1 (std::make_shared (key1.pub, 0, key1.pub, nano::Gxrb_ratio, send1->hash (), key1.prv, key1.pub, *system.work.generate (key1.pub))); - ASSERT_EQ (nano::process_result::progress, node1->process (*open1).code); - auto open2 (std::make_shared (key2.pub, 0, key2.pub, nano::Gxrb_ratio, send2->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub))); - ASSERT_EQ (nano::process_result::progress, node1->process (*open2).code); - system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv); - - // Confirm all blocks so node1 is free to generate votes - node1->block_confirm (send1); - ASSERT_TIMELY (10s, node1->ledger.cache.cemented_count == 5 && node1->confirmation_height_processor.current ().is_zero ()); - - // Test node to bootstrap - node_config.peering_port = nano::get_available_port (); - node_flags.disable_legacy_bootstrap = false; - node_flags.disable_rep_crawler = false; - auto node2 = system.add_node (node_config, node_flags); - ASSERT_TIMELY (5s, node2->rep_crawler.representative_count () != 0); - node2->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); - ASSERT_TIMELY (10s, node2->bootstrap_initiator.current_attempt () == nullptr || node2->bootstrap_initiator.current_attempt ()->frontiers_confirmed); - ASSERT_EQ (1, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_successful, nano::stat::dir::in)); // Successful request from node1 - ASSERT_EQ (0, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in)); -} - -TEST (bootstrap_processor, frontiers_unconfirmed_threshold) -{ - nano::system system; - nano::node_config node_config (nano::get_available_port (), system.logging); - node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; - node_config.tcp_io_timeout = std::chrono::seconds (2); - node_config.bootstrap_fraction_numerator = 4; - nano::node_flags node_flags; - node_flags.disable_bootstrap_bulk_pull_server = true; - node_flags.disable_bootstrap_bulk_push_client = true; - node_flags.disable_legacy_bootstrap = true; - node_flags.disable_lazy_bootstrap = true; - node_flags.disable_wallet_bootstrap = true; - node_flags.disable_rep_crawler = true; - auto node1 = system.add_node (node_config, node_flags); - nano::genesis genesis; - nano::keypair key1, key2; - // Generating invalid chain - auto threshold (node1->gap_cache.bootstrap_threshold () + 1); - ASSERT_LT (threshold, node1->online_reps.delta ()); - auto send1 (std::make_shared (nano::dev_genesis_key.pub, genesis.hash (), nano::dev_genesis_key.pub, nano::genesis_amount - threshold, key1.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (genesis.hash ()))); - ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code); - auto send2 (std::make_shared (nano::dev_genesis_key.pub, send1->hash (), nano::dev_genesis_key.pub, nano::genesis_amount - threshold - nano::Gxrb_ratio, key2.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send1->hash ()))); - ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code); - auto open1 (std::make_shared (key1.pub, 0, key1.pub, threshold, send1->hash (), key1.prv, key1.pub, *system.work.generate (key1.pub))); - ASSERT_EQ (nano::process_result::progress, node1->process (*open1).code); - auto open2 (std::make_shared (key2.pub, 0, key2.pub, nano::Gxrb_ratio, send2->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub))); - ASSERT_EQ (nano::process_result::progress, node1->process (*open2).code); - system.wallet (0)->insert_adhoc (key1.prv); // Small representative - - // Test node with large representative - node_config.peering_port = nano::get_available_port (); - auto node2 = system.add_node (node_config, node_flags); - system.wallet (1)->insert_adhoc (nano::dev_genesis_key.prv); - - // Test node to bootstrap - node_config.peering_port = nano::get_available_port (); - node_flags.disable_legacy_bootstrap = false; - node_flags.disable_rep_crawler = false; - auto node3 = system.add_node (node_config, node_flags); - ASSERT_EQ (nano::process_result::progress, node3->process (*send1).code); - ASSERT_EQ (nano::process_result::progress, node3->process (*open1).code); // Change known representative weight - ASSERT_TIMELY (5s, node3->rep_crawler.representative_count () == 2); - node3->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); - ASSERT_TIMELY (15s, node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in) == 1); - ASSERT_FALSE (node3->ledger.block_exists (send2->hash ())); - ASSERT_FALSE (node3->ledger.block_exists (open2->hash ())); - ASSERT_EQ (1, node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in)); // failed confirmation - ASSERT_EQ (0, node3->stats.count (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_successful, nano::stat::dir::in)); -} - TEST (bootstrap_processor, push_diamond) { nano::system system; @@ -1494,8 +1343,7 @@ TEST (bulk, genesis_pruning) // Bootstrap with missing blocks for node2 node2->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); node2->network.merge_peer (node1->network.endpoint ()); - // 2 bootstraps including test bootstrap & restart after frontier confirmation failure - ASSERT_TIMELY (25s, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::initiate, nano::stat::dir::out) >= 2 && !node2->bootstrap_initiator.in_progress ()); + ASSERT_TIMELY (25s, node2->stats.count (nano::stat::type::bootstrap, nano::stat::detail::initiate, nano::stat::dir::out) >= 1 && !node2->bootstrap_initiator.in_progress ()); // node2 still missing blocks ASSERT_EQ (1, node2->ledger.cache.block_count); { @@ -1509,7 +1357,6 @@ TEST (bulk, genesis_pruning) ASSERT_EQ (3, node2->ledger.cache.block_count); // New bootstrap ASSERT_TIMELY (5s, node2->bootstrap_initiator.connections->connections_count == 0); - node2->network.excluded_peers.remove (nano::transport::map_endpoint_to_tcp (node1->network.endpoint ())); node2->bootstrap_initiator.bootstrap (node1->network.endpoint (), false); ASSERT_TIMELY (10s, node2->latest (nano::dev_genesis_key.pub) == node1->latest (nano::dev_genesis_key.pub)); ASSERT_EQ (node2->latest (nano::dev_genesis_key.pub), node1->latest (nano::dev_genesis_key.pub)); diff --git a/nano/node/bootstrap/bootstrap.cpp b/nano/node/bootstrap/bootstrap.cpp index ce611384..d25402d8 100644 --- a/nano/node/bootstrap/bootstrap.cpp +++ b/nano/node/bootstrap/bootstrap.cpp @@ -49,7 +49,7 @@ void nano::bootstrap_initiator::bootstrap (bool force, std::string id_a, uint32_ } } -void nano::bootstrap_initiator::bootstrap (nano::endpoint const & endpoint_a, bool add_to_peers, bool frontiers_confirmed, std::string id_a) +void nano::bootstrap_initiator::bootstrap (nano::endpoint const & endpoint_a, bool add_to_peers, std::string id_a) { if (add_to_peers) { @@ -70,15 +70,10 @@ void nano::bootstrap_initiator::bootstrap (nano::endpoint const & endpoint_a, bo auto legacy_attempt (std::make_shared (node.shared (), attempts.incremental++, id_a, std::numeric_limits::max ())); attempts_list.push_back (legacy_attempt); attempts.add (legacy_attempt); - if (frontiers_confirmed) - { - node.network.excluded_peers.remove (nano::transport::map_endpoint_to_tcp (endpoint_a)); - } if (!node.network.excluded_peers.check (nano::transport::map_endpoint_to_tcp (endpoint_a))) { connections->add_connection (endpoint_a); } - legacy_attempt->frontiers_confirmed = frontiers_confirmed; } condition.notify_all (); } diff --git a/nano/node/bootstrap/bootstrap.hpp b/nano/node/bootstrap/bootstrap.hpp index 5ba580c3..e4ac6170 100644 --- a/nano/node/bootstrap/bootstrap.hpp +++ b/nano/node/bootstrap/bootstrap.hpp @@ -81,7 +81,7 @@ class bootstrap_initiator final public: explicit bootstrap_initiator (nano::node &); ~bootstrap_initiator (); - void bootstrap (nano::endpoint const &, bool add_to_peers = true, bool frontiers_confirmed = false, std::string id_a = ""); + void bootstrap (nano::endpoint const &, bool add_to_peers = true, std::string id_a = ""); void bootstrap (bool force = false, std::string id_a = "", uint32_t const frontiers_age_a = std::numeric_limits::max ()); void bootstrap_lazy (nano::hash_or_account const &, bool force = false, bool confirmed = true, std::string id_a = ""); void bootstrap_wallet (std::deque &); @@ -127,9 +127,6 @@ public: static constexpr double bootstrap_minimum_frontier_blocks_per_sec = 1000.0; static constexpr double bootstrap_minimum_termination_time_sec = 30.0; static constexpr unsigned bootstrap_max_new_connections = 32; - static constexpr size_t bootstrap_max_confirm_frontiers = 70; - static constexpr double required_frontier_confirmation_ratio = 0.8; - static constexpr unsigned frontier_confirmation_blocks_limit = 128 * 1024; static constexpr unsigned requeued_pulls_limit = 256; static constexpr unsigned requeued_pulls_limit_dev = 1; static constexpr unsigned requeued_pulls_processed_blocks_factor = 4096; diff --git a/nano/node/bootstrap/bootstrap_attempt.cpp b/nano/node/bootstrap/bootstrap_attempt.cpp index d85c05cb..eb385e91 100644 --- a/nano/node/bootstrap/bootstrap_attempt.cpp +++ b/nano/node/bootstrap/bootstrap_attempt.cpp @@ -12,9 +12,6 @@ #include -constexpr size_t nano::bootstrap_limits::bootstrap_max_confirm_frontiers; -constexpr double nano::bootstrap_limits::required_frontier_confirmation_ratio; -constexpr unsigned nano::bootstrap_limits::frontier_confirmation_blocks_limit; constexpr unsigned nano::bootstrap_limits::requeued_pulls_limit; constexpr unsigned nano::bootstrap_limits::requeued_pulls_limit_dev; @@ -116,11 +113,6 @@ std::string nano::bootstrap_attempt::mode_text () return mode_text; } -void nano::bootstrap_attempt::restart_condition () -{ - debug_assert (mode == nano::bootstrap_mode::legacy); -} - void nano::bootstrap_attempt::add_frontier (nano::pull_info const &) { debug_assert (mode == nano::bootstrap_mode::legacy); @@ -137,11 +129,6 @@ bool nano::bootstrap_attempt::request_bulk_push_target (std::pair const & block_a, nano::account const & known_account_a, uint64_t pull_blocks, nano::bulk_pull::count_t max_blocks, bool block_expected, unsigned retry_limit) { nano::unchecked_info info (block_a, known_account_a, 0, nano::signature_verification::unknown); diff --git a/nano/node/bootstrap/bootstrap_attempt.hpp b/nano/node/bootstrap/bootstrap_attempt.hpp index ffdb9fec..63bf3b6a 100644 --- a/nano/node/bootstrap/bootstrap_attempt.hpp +++ b/nano/node/bootstrap/bootstrap_attempt.hpp @@ -23,11 +23,9 @@ public: void pull_finished (); bool should_log (); std::string mode_text (); - virtual void restart_condition (); virtual void add_frontier (nano::pull_info const &); virtual void add_bulk_push_target (nano::block_hash const &, nano::block_hash const &); virtual bool request_bulk_push_target (std::pair &); - virtual void add_recent_pull (nano::block_hash const &); virtual void lazy_start (nano::hash_or_account const &, bool confirmed = true); virtual void lazy_add (nano::pull_info const &); virtual void lazy_requeue (nano::block_hash const &, nano::block_hash const &, bool); @@ -51,7 +49,6 @@ public: std::string id; std::chrono::steady_clock::time_point attempt_start{ std::chrono::steady_clock::now () }; std::atomic frontiers_received{ false }; - std::atomic frontiers_confirmed{ false }; nano::bootstrap_mode mode; nano::mutex mutex; nano::condition_variable condition; diff --git a/nano/node/bootstrap/bootstrap_connections.cpp b/nano/node/bootstrap/bootstrap_connections.cpp index 6ff484ce..7a1faa87 100644 --- a/nano/node/bootstrap/bootstrap_connections.cpp +++ b/nano/node/bootstrap/bootstrap_connections.cpp @@ -356,10 +356,6 @@ void nano::bootstrap_connections::request_pull (nano::unique_lock & } if (attempt_l != nullptr) { - if (attempt_l->mode == nano::bootstrap_mode::legacy) - { - attempt_l->add_recent_pull (pull.head); - } // The bulk_pull_client destructor attempt to requeue_pull which can cause a deadlock if this is the last reference // Dispatch request in an external thread in case it needs to be destroyed node.background ([connection_l, attempt_l, pull]() { @@ -388,11 +384,7 @@ void nano::bootstrap_connections::requeue_pull (nano::pull_info const & pull_a, if (attempt_l != nullptr) { ++attempt_l->requeued_pulls; - if (attempt_l->mode == nano::bootstrap_mode::legacy) - { - attempt_l->restart_condition (); - } - else if (attempt_l->mode == nano::bootstrap_mode::lazy) + if (attempt_l->mode == nano::bootstrap_mode::lazy) { pull.count = attempt_l->lazy_batch_size (); } diff --git a/nano/node/bootstrap/bootstrap_legacy.cpp b/nano/node/bootstrap/bootstrap_legacy.cpp index 0742ff3a..a34273e1 100644 --- a/nano/node/bootstrap/bootstrap_legacy.cpp +++ b/nano/node/bootstrap/bootstrap_legacy.cpp @@ -115,196 +115,6 @@ bool nano::bootstrap_attempt_legacy::request_bulk_push_target (std::pair lock (mutex); - recent_pulls_head.push_back (head_a); - if (recent_pulls_head.size () > nano::bootstrap_limits::bootstrap_max_confirm_frontiers) - { - recent_pulls_head.pop_front (); - } -} - -void nano::bootstrap_attempt_legacy::restart_condition () -{ - /* Conditions to start frontiers confirmation: - - not completed frontiers confirmation - - more than 256 pull retries usually indicating issues with requested pulls - - or 128k processed blocks indicating large bootstrap */ - if (!frontiers_confirmation_pending && !frontiers_confirmed && (requeued_pulls > (!node->network_params.network.is_dev_network () ? nano::bootstrap_limits::requeued_pulls_limit : nano::bootstrap_limits::requeued_pulls_limit_dev) || total_blocks > nano::bootstrap_limits::frontier_confirmation_blocks_limit)) - { - frontiers_confirmation_pending = true; - } -} - -void nano::bootstrap_attempt_legacy::attempt_restart_check (nano::unique_lock & lock_a) -{ - if (frontiers_confirmation_pending) - { - auto confirmed (confirm_frontiers (lock_a)); - debug_assert (lock_a.owns_lock ()); - if (!confirmed) - { - node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_failed, nano::stat::dir::in); - node->logger.try_log (boost::str (boost::format ("Frontier confirmation failed for peer %1% after %2% seconds bootstrap attempt") % endpoint_frontier_request % std::chrono::duration_cast (std::chrono::steady_clock::now () - attempt_start).count ())); - lock_a.unlock (); - stop (); - lock_a.lock (); - // Start new bootstrap connection - auto node_l (node->shared ()); - auto this_l (shared_from_this ()); - auto duration (std::chrono::duration_cast (std::chrono::steady_clock::now () - attempt_start).count ()); - auto frontiers_age_l (frontiers_age != std::numeric_limits::max () ? frontiers_age + duration : frontiers_age); - node->background ([node_l, this_l, frontiers_age_l]() { - node_l->bootstrap_initiator.remove_attempt (this_l); - auto id_l (this_l->id); - // Delay after removing current attempt - node_l->workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (50), [node_l, id_l, frontiers_age_l]() { - node_l->bootstrap_initiator.bootstrap (true, id_l, frontiers_age_l); - }); - }); - } - else - { - node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::frontier_confirmation_successful, nano::stat::dir::in); - } - frontiers_confirmed = confirmed; - frontiers_confirmation_pending = false; - } -} - -bool nano::bootstrap_attempt_legacy::confirm_frontiers (nano::unique_lock & lock_a) -{ - bool confirmed (false); - debug_assert (!frontiers_confirmed); - condition.wait (lock_a, [& stopped = stopped] { return !stopped; }); - auto this_l (shared_from_this ()); - std::vector frontiers; - lock_a.unlock (); - nano::unique_lock pulls_lock (node->bootstrap_initiator.connections->mutex); - for (auto i (node->bootstrap_initiator.connections->pulls.begin ()), end (node->bootstrap_initiator.connections->pulls.end ()); i != end && frontiers.size () != nano::bootstrap_limits::bootstrap_max_confirm_frontiers; ++i) - { - if (!i->head.is_zero () && i->bootstrap_id == incremental_id && std::find (frontiers.begin (), frontiers.end (), i->head) == frontiers.end ()) - { - frontiers.push_back (i->head); - } - } - pulls_lock.unlock (); - lock_a.lock (); - for (auto i (recent_pulls_head.begin ()), end (recent_pulls_head.end ()); i != end && frontiers.size () != nano::bootstrap_limits::bootstrap_max_confirm_frontiers; ++i) - { - if (!i->is_zero () && std::find (frontiers.begin (), frontiers.end (), *i) == frontiers.end ()) - { - frontiers.push_back (*i); - } - } - lock_a.unlock (); - auto frontiers_count (frontiers.size ()); - if (frontiers_count > 0) - { - const size_t reps_limit = 20; - auto representatives (node->rep_crawler.representatives ()); - auto reps_weight (node->rep_crawler.total_weight ()); - auto representatives_copy (representatives); - nano::uint128_t total_weight (0); - // Select random peers from bottom 50% of principal representatives - if (representatives.size () > 1) - { - std::reverse (representatives.begin (), representatives.end ()); - representatives.resize (representatives.size () / 2); - for (auto i = static_cast (representatives.size () - 1); i > 0; --i) - { - auto k = nano::random_pool::generate_word32 (0, i); - std::swap (representatives[i], representatives[k]); - } - if (representatives.size () > reps_limit) - { - representatives.resize (reps_limit); - } - } - for (auto const & rep : representatives) - { - total_weight += rep.weight.number (); - } - // Select peers with total 25% of reps stake from top 50% of principal representatives - representatives_copy.resize (representatives_copy.size () / 2); - while (total_weight < reps_weight / 4) // 25% - { - auto k = nano::random_pool::generate_word32 (0, static_cast (representatives_copy.size () - 1)); - auto rep (representatives_copy[k]); - if (std::find (representatives.begin (), representatives.end (), rep) == representatives.end ()) - { - representatives.push_back (rep); - total_weight += rep.weight.number (); - } - } - // Start requests - for (auto i (0), max_requests (20); i <= max_requests && !confirmed && !stopped; ++i) - { - std::unordered_map, std::deque>> batched_confirm_req_bundle; - std::deque> request; - // Find confirmed frontiers (tally > 12.5% of reps stake, 60% of requestsed reps responded - for (auto ii (frontiers.begin ()); ii != frontiers.end ();) - { - if (node->ledger.block_or_pruned_exists (*ii)) - { - ii = frontiers.erase (ii); - } - else - { - auto existing (node->active.find_inactive_votes_cache (*ii)); - nano::uint128_t tally; - for (auto & [voter, timestamp] : existing.voters) - { - tally += node->ledger.weight (voter); - } - if (existing.status.confirmed || (tally > reps_weight / 8 && existing.voters.size () >= representatives.size () * 0.6)) // 12.5% of weight, 60% of reps - { - ii = frontiers.erase (ii); - } - else - { - for (auto const & rep : representatives) - { - if (std::find_if (existing.voters.begin (), existing.voters.end (), [&rep](auto const & item_a) { return item_a.first == rep.account; }) == existing.voters.end ()) - { - release_assert (!ii->is_zero ()); - auto rep_request (batched_confirm_req_bundle.find (rep.channel)); - if (rep_request == batched_confirm_req_bundle.end ()) - { - std::deque> insert_root_hash = { std::make_pair (*ii, *ii) }; - batched_confirm_req_bundle.emplace (rep.channel, insert_root_hash); - } - else - { - rep_request->second.emplace_back (*ii, *ii); - } - } - } - ++ii; - } - } - } - auto confirmed_count (frontiers_count - frontiers.size ()); - if (confirmed_count >= frontiers_count * nano::bootstrap_limits::required_frontier_confirmation_ratio) // 80% of frontiers confirmed - { - confirmed = true; - } - else if (i < max_requests) - { - node->network.broadcast_confirm_req_batched_many (batched_confirm_req_bundle); - std::this_thread::sleep_for (std::chrono::milliseconds (!node->network_params.network.is_dev_network () ? 500 : 25)); - } - } - if (!confirmed) - { - node->logger.always_log (boost::str (boost::format ("Failed to confirm frontiers for bootstrap attempt. %1% of %2% frontiers were not confirmed") % frontiers.size () % frontiers_count)); - } - } - lock_a.lock (); - return confirmed; -} - bool nano::bootstrap_attempt_legacy::request_frontier (nano::unique_lock & lock_a, bool first_attempt) { auto result (true); @@ -371,10 +181,8 @@ bool nano::bootstrap_attempt_legacy::request_frontier (nano::unique_lock & lock_a) { frontiers_received = false; - frontiers_confirmed = false; total_blocks = 0; requeued_pulls = 0; - recent_pulls_head.clear (); auto frontier_failure (true); uint64_t frontier_attempts (0); while (!stopped && frontier_failure) @@ -397,9 +205,7 @@ void nano::bootstrap_attempt_legacy::run () while (still_pulling ()) { // clang-format off - condition.wait (lock, [&stopped = stopped, &pulling = pulling, &frontiers_confirmation_pending = frontiers_confirmation_pending] { return stopped || pulling == 0 || frontiers_confirmation_pending; }); - // clang-format on - attempt_restart_check (lock); + condition.wait (lock, [&stopped = stopped, &pulling = pulling] { return stopped || pulling == 0; }); } // Flushing may resolve forks which can add more pulls node->logger.try_log ("Flushing unchecked blocks"); @@ -430,6 +236,4 @@ void nano::bootstrap_attempt_legacy::get_information (boost::property_tree::ptre nano::lock_guard lock (mutex); tree_a.put ("frontier_pulls", std::to_string (frontier_pulls.size ())); tree_a.put ("frontiers_received", static_cast (frontiers_received)); - tree_a.put ("frontiers_confirmed", static_cast (frontiers_confirmed)); - tree_a.put ("frontiers_confirmation_pending", static_cast (frontiers_confirmation_pending)); -} \ No newline at end of file +} diff --git a/nano/node/bootstrap/bootstrap_legacy.hpp b/nano/node/bootstrap/bootstrap_legacy.hpp index cae60ab4..b4728bdb 100644 --- a/nano/node/bootstrap/bootstrap_legacy.hpp +++ b/nano/node/bootstrap/bootstrap_legacy.hpp @@ -25,20 +25,14 @@ public: void add_frontier (nano::pull_info const &) override; void add_bulk_push_target (nano::block_hash const &, nano::block_hash const &) override; bool request_bulk_push_target (std::pair &) override; - void add_recent_pull (nano::block_hash const &) override; void run_start (nano::unique_lock &); - void restart_condition () override; - void attempt_restart_check (nano::unique_lock &); - bool confirm_frontiers (nano::unique_lock &); void get_information (boost::property_tree::ptree &) override; nano::tcp_endpoint endpoint_frontier_request; std::weak_ptr frontiers; std::weak_ptr push; std::deque frontier_pulls; - std::deque recent_pulls_head; std::vector> bulk_push_targets; std::atomic account_count{ 0 }; - std::atomic frontiers_confirmation_pending{ false }; uint32_t frontiers_age; }; -} \ No newline at end of file +} diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index b6d69e95..22210403 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -1688,7 +1688,6 @@ void nano::json_handler::bootstrap () { std::string address_text = request.get ("address"); std::string port_text = request.get ("port"); - const bool bypass_frontier_confirmation = request.get ("bypass_frontier_confirmation", false); boost::system::error_code address_ec; auto address (boost::asio::ip::make_address_v6 (address_text, address_ec)); if (!address_ec) @@ -1699,7 +1698,7 @@ void nano::json_handler::bootstrap () if (!node.flags.disable_legacy_bootstrap) { std::string bootstrap_id (request.get ("id", "")); - node.bootstrap_initiator.bootstrap (nano::endpoint (address, port), true, bypass_frontier_confirmation, bootstrap_id); + node.bootstrap_initiator.bootstrap (nano::endpoint (address, port), true, bootstrap_id); response_l.put ("success", ""); } else