Replace election::insert_inactive_votes_cache by election::vote (#3874)
		
	This commit is contained in:
		
					parent
					
						
							
								23bc00db85
							
						
					
				
			
			
				commit
				
					
						5c0106823f
					
				
			
		
					 7 changed files with 52 additions and 44 deletions
				
			
		|  | @ -337,10 +337,10 @@ TEST (active_transactions, inactive_votes_cache_existing_vote) | |||
| 	nano::unique_lock<nano::mutex> 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]); | ||||
|  |  | |||
|  | @ -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<nano::block> 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); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -197,6 +197,7 @@ private: | |||
| 	nano::inactive_cache_status inactive_votes_bootstrap_check (nano::unique_lock<nano::mutex> &, 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::mutex> &, 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; | ||||
|  |  | |||
|  | @ -364,15 +364,13 @@ std::shared_ptr<nano::block> 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<nano::mutex> 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<uint64_t>::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<nano::block> const & block_a) | |||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| std::size_t nano::election::insert_inactive_votes_cache (nano::inactive_cache_information const & cache_a) | ||||
| { | ||||
| 	nano::unique_lock<nano::mutex> 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::seconds> (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<nano::mutex> guard (mutex); | ||||
|  |  | |||
|  | @ -53,6 +53,14 @@ struct election_extended_status final | |||
| }; | ||||
| class election final : public std::enable_shared_from_this<nano::election> | ||||
| { | ||||
| 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<void (std::shared_ptr<nano::block> 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<nano::block> 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<nano::mutex> &); | ||||
| 
 | ||||
|  | @ -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; | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| #include <nano/node/election.hpp> | ||||
| #include <nano/node/inactive_cache_information.hpp> | ||||
| 
 | ||||
| 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<nano::election> 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; | ||||
| } | ||||
|  | @ -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<nano::election> election) const; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Piotr Wójcik
				Piotr Wójcik