diff --git a/nano/node/election.cpp b/nano/node/election.cpp index 40f1f2b864..c9db3286cf 100644 --- a/nano/node/election.cpp +++ b/nano/node/election.cpp @@ -274,7 +274,7 @@ bool nano::election::transition_time (nano::confirmation_solicitor & solicitor_a break; } - if (!confirmed_locked () && time_to_live () < std::chrono::steady_clock::now () - election_start) + if (!confirmed_locked () && has_expired ()) { // It is possible the election confirmed while acquiring the mutex // state_change returning true would indicate it @@ -292,16 +292,24 @@ bool nano::election::transition_time (nano::confirmation_solicitor & solicitor_a return result; } -std::chrono::milliseconds nano::election::time_to_live () const +bool nano::election::has_expired () const { + const auto now = std::chrono::steady_clock::now (); + + if (now > election_start + max_total_duration) + { + return true; + } + switch (behavior ()) { case election_behavior::manual: case election_behavior::priority: - return std::chrono::milliseconds (5 * 60 * 1000); + return now > last_vote_received + max_idle_duration_default; case election_behavior::hinted: + return now > last_vote_received + max_idle_duration_hinted; case election_behavior::optimistic: - return std::chrono::milliseconds (30 * 1000); + return now > last_vote_received + max_idle_duration_optimistic; } debug_assert (false); return {}; @@ -491,6 +499,8 @@ nano::vote_code nano::election::vote (nano::account const & rep, uint64_t timest nano::log::arg{ "vote_source", vote_source_a }, nano::log::arg{ "weight", weight }); + last_vote_received = std::chrono::steady_clock::now (); + if (!confirmed_locked ()) { confirm_if_quorum (lock); diff --git a/nano/node/election.hpp b/nano/node/election.hpp index 6111191e2b..6b9a186e37 100644 --- a/nano/node/election.hpp +++ b/nano/node/election.hpp @@ -64,6 +64,13 @@ class election final : public std::enable_shared_from_this std::function const &)> confirmation_action; std::function live_vote_action; +private: + // Election time to live + std::chrono::milliseconds max_total_duration = std::chrono::milliseconds (10 * 60 * 1000); + std::chrono::milliseconds max_idle_duration_default = std::chrono::milliseconds (30 * 1000); + std::chrono::milliseconds max_idle_duration_hinted = std::chrono::milliseconds (10 * 1000); + std::chrono::milliseconds max_idle_duration_optimistic = std::chrono::milliseconds (10 * 1000); + private: // State management static unsigned constexpr passive_duration_factor = 5; static unsigned constexpr active_request_count_min = 2; @@ -76,7 +83,8 @@ class election final : public std::enable_shared_from_this 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 = {}; + std::chrono::steady_clock::time_point last_vote_received = { std::chrono::steady_clock::now () }; bool valid_change (nano::election_state, nano::election_state) const; bool state_change (nano::election_state, nano::election_state); @@ -155,7 +163,7 @@ class election final : public std::enable_shared_from_this void remove_votes (nano::block_hash const &); void remove_block (nano::block_hash const &); bool replace_by_weight (nano::unique_lock & lock_a, nano::block_hash const &); - std::chrono::milliseconds time_to_live () const; + bool has_expired () const; /** * Calculates minimum time delay between subsequent votes when processing non-final votes */