From 5c0106823f53b8fc8a7f70703793e5e0c1053c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20W=C3=B3jcik?= <3044353+fikumikudev@users.noreply.github.com> Date: Tue, 2 Aug 2022 16:04:00 +0200 Subject: [PATCH] Replace `election::insert_inactive_votes_cache` by `election::vote` (#3874) --- nano/core_test/active_transactions.cpp | 4 +- nano/node/active_transactions.cpp | 4 +- nano/node/active_transactions.hpp | 1 + nano/node/election.cpp | 54 ++++++++---------------- nano/node/election.hpp | 12 ++++-- nano/node/inactive_cache_information.cpp | 15 +++++++ nano/node/inactive_cache_information.hpp | 6 +++ 7 files changed, 52 insertions(+), 44 deletions(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index c344f45f..3a7a1183 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -337,10 +337,10 @@ TEST (active_transactions, inactive_votes_cache_existing_vote) nano::unique_lock active_lock (node.active.mutex); node.active.add_inactive_votes_cache (active_lock, send->hash (), key.pub, 0); active_lock.unlock (); - auto cache (node.active.find_inactive_votes_cache (send->hash ())); + const auto cache (node.active.find_inactive_votes_cache (send->hash ())); active_lock.lock (); ASSERT_EQ (1, cache.voters.size ()); - election->insert_inactive_votes_cache (cache); + cache.fill (election); // Check that election data is not changed ASSERT_EQ (2, election->votes ().size ()); auto last_vote2 (election->votes ()[key.pub]); diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 7058fa42..d42d1fa3 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -391,7 +391,7 @@ nano::election_insertion_result nano::active_transactions::insert_impl (nano::un } auto const cache = find_inactive_votes_cache_impl (hash); lock_a.unlock (); - result.election->insert_inactive_votes_cache (cache); + cache.fill (result.election); node.observers.active_started.notify (hash); node.stats.inc (nano::stat::type::election, nano::stat::detail::election_start); vacancy_update (); @@ -624,7 +624,7 @@ bool nano::active_transactions::publish (std::shared_ptr const & bl blocks.emplace (block_a->hash (), election); auto const cache = find_inactive_votes_cache_impl (block_a->hash ()); lock.unlock (); - election->insert_inactive_votes_cache (cache); + cache.fill (election); node.stats.inc (nano::stat::type::election, nano::stat::detail::election_block_conflict); } } diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index c12bd35b..a0c4baa4 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -197,6 +197,7 @@ private: nano::inactive_cache_status inactive_votes_bootstrap_check (nano::unique_lock &, nano::account const &, nano::block_hash const &, nano::inactive_cache_status const &); nano::inactive_cache_status inactive_votes_bootstrap_check_impl (nano::unique_lock &, nano::uint128_t const &, std::size_t, nano::block_hash const &, nano::inactive_cache_status const &); nano::inactive_cache_information find_inactive_votes_cache_impl (nano::block_hash const &); + boost::thread thread; friend class election; diff --git a/nano/node/election.cpp b/nano/node/election.cpp index 7b02e56b..08c0f133 100644 --- a/nano/node/election.cpp +++ b/nano/node/election.cpp @@ -364,15 +364,13 @@ std::shared_ptr nano::election::find (nano::block_hash const & hash return result; } -nano::election_vote_result nano::election::vote (nano::account const & rep, uint64_t timestamp_a, nano::block_hash const & block_hash_a) +nano::election_vote_result nano::election::vote (nano::account const & rep, uint64_t timestamp_a, nano::block_hash const & block_hash_a, vote_source vote_source_a) { auto replay = false; auto weight = node.ledger.weight (rep); auto should_process = false; if (node.network_params.network.is_dev_network () || weight > node.minimum_principal_weight ()) { - const auto cooldown = cooldown_time (weight); - nano::unique_lock lock (mutex); auto last_vote_it (last_votes.find (rep)); @@ -386,7 +384,15 @@ nano::election_vote_result nano::election::vote (nano::account const & rep, uint if (last_vote_l.timestamp < timestamp_a || (last_vote_l.timestamp == timestamp_a && last_vote_l.hash < block_hash_a)) { auto max_vote = timestamp_a == std::numeric_limits::max () && last_vote_l.timestamp < timestamp_a; - auto past_cooldown = last_vote_l.time <= std::chrono::steady_clock::now () - std::chrono::seconds (cooldown); + + bool past_cooldown = true; + // Only cooldown live votes + if (vote_source_a == vote_source::live) + { + const auto cooldown = cooldown_time (weight); + past_cooldown = last_vote_l.time <= std::chrono::steady_clock::now () - cooldown; + } + should_process = max_vote || past_cooldown; } else @@ -396,9 +402,14 @@ nano::election_vote_result nano::election::vote (nano::account const & rep, uint } if (should_process) { - node.stats.inc (nano::stat::type::election, nano::stat::detail::vote_new); last_votes[rep] = { std::chrono::steady_clock::now (), timestamp_a, block_hash_a }; - live_vote_action (rep); + if (vote_source_a == vote_source::live) + { + live_vote_action (rep); + } + + node.stats.inc (nano::stat::type::election, vote_source_a == vote_source::live ? nano::stat::detail::vote_new : nano::stat::detail::vote_cached); + if (!confirmed ()) { confirm_if_quorum (lock); @@ -450,37 +461,6 @@ bool nano::election::publish (std::shared_ptr const & block_a) return result; } -std::size_t nano::election::insert_inactive_votes_cache (nano::inactive_cache_information const & cache_a) -{ - nano::unique_lock lock (mutex); - for (auto const & [rep, timestamp] : cache_a.voters) - { - auto inserted (last_votes.emplace (rep, nano::vote_info{ std::chrono::steady_clock::time_point::min (), timestamp, cache_a.hash })); - if (inserted.second) - { - node.stats.inc (nano::stat::type::election, nano::stat::detail::vote_cached); - } - } - if (!confirmed ()) - { - if (!cache_a.voters.empty ()) - { - auto delay (std::chrono::duration_cast (std::chrono::steady_clock::now () - cache_a.arrival)); - if (delay > late_blocks_delay) - { - node.stats.inc (nano::stat::type::election, nano::stat::detail::late_block); - node.stats.add (nano::stat::type::election, nano::stat::detail::late_block_seconds, nano::stat::dir::in, delay.count (), true); - } - } - if (last_votes.size () > 1) // null account - { - // Even if no votes were in cache, they could be in the election - confirm_if_quorum (lock); - } - } - return cache_a.voters.size (); -} - nano::election_extended_status nano::election::current_status () const { nano::lock_guard guard (mutex); diff --git a/nano/node/election.hpp b/nano/node/election.hpp index 22f236c8..6d2a0685 100644 --- a/nano/node/election.hpp +++ b/nano/node/election.hpp @@ -53,6 +53,14 @@ struct election_extended_status final }; class election final : public std::enable_shared_from_this { +public: + enum class vote_source + { + live, + cache, + }; + +private: // Minimum time between broadcasts of the current winner of an election, as a backup to requesting confirmations std::chrono::milliseconds base_latency () const; std::function const &)> confirmation_action; @@ -108,9 +116,8 @@ public: // Interface * Process vote. Internally uses cooldown to throttle non-final votes * If the election reaches consensus, it will be confirmed */ - nano::election_vote_result vote (nano::account const & representative, uint64_t timestamp, nano::block_hash const & block_hash); + nano::election_vote_result vote (nano::account const & representative, uint64_t timestamp, nano::block_hash const & block_hash, vote_source = vote_source::live); bool publish (std::shared_ptr const & block_a); - std::size_t insert_inactive_votes_cache (nano::inactive_cache_information const &); // Confirm this block if quorum is met void confirm_if_quorum (nano::unique_lock &); @@ -150,7 +157,6 @@ private: nano::node & node; mutable nano::mutex mutex; - static std::chrono::seconds constexpr late_blocks_delay{ 5 }; static std::size_t constexpr max_blocks{ 10 }; friend class active_transactions; diff --git a/nano/node/inactive_cache_information.cpp b/nano/node/inactive_cache_information.cpp index cf905aaa..2207c838 100644 --- a/nano/node/inactive_cache_information.cpp +++ b/nano/node/inactive_cache_information.cpp @@ -1,3 +1,4 @@ +#include #include using namespace std::chrono; @@ -15,3 +16,17 @@ std::string nano::inactive_cache_information::to_string () const } return ss.str (); } + +std::size_t nano::inactive_cache_information::fill (std::shared_ptr election) const +{ + std::size_t inserted = 0; + for (auto const & [rep, timestamp] : voters) + { + auto [is_replay, processed] = election->vote (rep, timestamp, hash, nano::election::vote_source::cache); + if (processed) + { + inserted++; + } + } + return inserted; +} \ No newline at end of file diff --git a/nano/node/inactive_cache_information.hpp b/nano/node/inactive_cache_information.hpp index 78259901..557a38e0 100644 --- a/nano/node/inactive_cache_information.hpp +++ b/nano/node/inactive_cache_information.hpp @@ -31,6 +31,12 @@ public: } std::string to_string () const; + + /** + * Inserts votes stored in this entry into an election + * @return number of votes inserted + */ + std::size_t fill (std::shared_ptr election) const; }; }