From 9b89148e7067de3d55ac250e31244085fb0c2f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Mon, 13 Nov 2023 00:50:53 +0100 Subject: [PATCH] Adjust election block rebroadcasting --- nano/lib/config.hpp | 12 ++++++++---- nano/lib/stats_enums.hpp | 2 ++ nano/node/election.cpp | 27 +++++++++++++++++++++++++-- nano/node/election.hpp | 8 +++++--- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/nano/lib/config.hpp b/nano/lib/config.hpp index 5db3296c78..c7b148215a 100644 --- a/nano/lib/config.hpp +++ b/nano/lib/config.hpp @@ -211,7 +211,8 @@ class network_constants max_peers_per_subnetwork (default_max_peers_per_ip * 4), ipv6_subnetwork_prefix_for_limiting (64), // Equivalent to network prefix /64. peer_dump_interval (std::chrono::seconds (5 * 60)), - vote_broadcast_interval (15 * 1000) + vote_broadcast_interval (15 * 1000), + block_broadcast_interval (150 * 1000) { if (is_live_network ()) { @@ -243,7 +244,8 @@ class network_constants max_peers_per_ip = 20; max_peers_per_subnetwork = max_peers_per_ip * 4; peer_dump_interval = std::chrono::seconds (1); - vote_broadcast_interval = 500; + vote_broadcast_interval = 500ms; + block_broadcast_interval = 500ms; telemetry_request_cooldown = 500ms; telemetry_cache_cutoff = 2000ms; telemetry_request_interval = 500ms; @@ -288,8 +290,10 @@ class network_constants size_t max_peers_per_subnetwork; size_t ipv6_subnetwork_prefix_for_limiting; std::chrono::seconds peer_dump_interval; - /** Time to wait before vote rebroadcasts for active elections (milliseconds) */ - uint64_t vote_broadcast_interval; + + /** Time to wait before rebroadcasts for active elections */ + std::chrono::milliseconds vote_broadcast_interval; + std::chrono::milliseconds block_broadcast_interval; /** We do not reply to telemetry requests made within cooldown period */ std::chrono::milliseconds telemetry_request_cooldown{ 1000 * 15 }; diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index b6373996ca..a5a63390d3 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -155,6 +155,8 @@ enum class detail : uint8_t generate_vote, generate_vote_normal, generate_vote_final, + broadcast_block_initial, + broadcast_block_repeat, // election types normal, diff --git a/nano/node/election.cpp b/nano/node/election.cpp index a8f03dae5a..bc7e759993 100644 --- a/nano/node/election.cpp +++ b/nano/node/election.cpp @@ -183,13 +183,35 @@ bool nano::election::failed () const return state_m == nano::election::state_t::expired_unconfirmed; } +bool nano::election::broadcast_block_predicate () const +{ + debug_assert (!mutex.try_lock ()); + + // Broadcast the block if enough time has passed since the last broadcast (or it's the first broadcast) + if (last_block + node.config.network_params.network.block_broadcast_interval < std::chrono::steady_clock::now ()) + { + return true; + } + // Or the current election winner has changed + if (status.winner->hash () != last_block_hash) + { + return true; + } + return false; +} + void nano::election::broadcast_block (nano::confirmation_solicitor & solicitor_a) { - if (base_latency () * 15 < std::chrono::steady_clock::now () - last_block) + debug_assert (!mutex.try_lock ()); + + if (broadcast_block_predicate ()) { if (!solicitor_a.broadcast (*this)) { + node.stats.inc (nano::stat::type::election, last_block_hash.is_zero () ? nano::stat::detail::broadcast_block_initial : nano::stat::detail::broadcast_block_repeat); + last_block = std::chrono::steady_clock::now (); + last_block_hash = status.winner->hash (); } } } @@ -237,6 +259,7 @@ bool nano::election::transition_time (nano::confirmation_solicitor & solicitor_a break; case nano::election::state_t::confirmed: result = true; // Return true to indicate this election should be cleaned up + broadcast_block (solicitor_a); // Ensure election winner is broadcasted state_change (nano::election::state_t::confirmed, nano::election::state_t::expired_confirmed); break; case nano::election::state_t::expired_unconfirmed: @@ -535,7 +558,7 @@ void nano::election::broadcast_vote_locked (nano::unique_lock & loc { debug_assert (lock.owns_lock ()); - if (std::chrono::steady_clock::now () < last_vote + std::chrono::milliseconds (node.config.network_params.network.vote_broadcast_interval)) + if (std::chrono::steady_clock::now () < last_vote + node.config.network_params.network.vote_broadcast_interval) { return; } diff --git a/nano/node/election.hpp b/nano/node/election.hpp index 8c025f654a..1e7667eba4 100644 --- a/nano/node/election.hpp +++ b/nano/node/election.hpp @@ -105,10 +105,11 @@ class election final : public std::enable_shared_from_this std::chrono::steady_clock::duration state_start{ std::chrono::steady_clock::now ().time_since_epoch () }; // These are modified while not holding the mutex from transition_time only - std::chrono::steady_clock::time_point last_block = { std::chrono::steady_clock::now () }; - std::chrono::steady_clock::time_point last_req = {}; + std::chrono::steady_clock::time_point last_block{}; + nano::block_hash last_block_hash{ 0 }; + std::chrono::steady_clock::time_point last_req{}; /** The last time vote for this election was generated */ - std::chrono::steady_clock::time_point last_vote = {}; + std::chrono::steady_clock::time_point last_vote{}; bool valid_change (nano::election::state_t, nano::election::state_t) const; bool state_change (nano::election::state_t, nano::election::state_t); @@ -169,6 +170,7 @@ class election final : public std::enable_shared_from_this bool confirmed_locked (nano::unique_lock & lock) const; // lock_a does not own the mutex on return void confirm_once (nano::unique_lock & lock_a, nano::election_status_type = nano::election_status_type::active_confirmed_quorum); + bool broadcast_block_predicate () const; void broadcast_block (nano::confirmation_solicitor &); void send_confirm_req (nano::confirmation_solicitor &); /**