Adding forked votes to inactive vote cache. (#2463)
There's no guarantee that the first block we observe is the winning fork. This change processes all votes for a particular election instead of just the ones for thee first block observed.
This commit is contained in:
		
					parent
					
						
							
								dbed9815c4
							
						
					
				
			
			
				commit
				
					
						97e164f10f
					
				
			
		
					 5 changed files with 56 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -411,6 +411,37 @@ TEST (active_transactions, inactive_votes_cache)
 | 
			
		|||
	ASSERT_EQ (1, system.nodes[0]->stats.count (nano::stat::type::election, nano::stat::detail::vote_cached));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST (active_transactions, inactive_votes_cache_fork)
 | 
			
		||||
{
 | 
			
		||||
	nano::system system (1);
 | 
			
		||||
	nano::block_hash latest (system.nodes[0]->latest (nano::test_genesis_key.pub));
 | 
			
		||||
	nano::keypair key;
 | 
			
		||||
	auto send1 (std::make_shared<nano::send_block> (latest, key.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (latest)));
 | 
			
		||||
	auto send2 (std::make_shared<nano::send_block> (latest, key.pub, nano::genesis_amount - 200, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (latest)));
 | 
			
		||||
	auto vote (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 0, std::vector<nano::block_hash> (1, send1->hash ())));
 | 
			
		||||
	system.nodes[0]->vote_processor.vote (vote, std::make_shared<nano::transport::channel_udp> (system.nodes[0]->network.udp_channels, system.nodes[0]->network.endpoint (), system.nodes[0]->network_params.protocol.protocol_version));
 | 
			
		||||
	auto channel1 (system.nodes [0]->network.udp_channels.create (system.nodes [0]->network.endpoint ()));
 | 
			
		||||
	system.deadline_set (5s);
 | 
			
		||||
	while (system.nodes[0]->active.inactive_votes_cache_size () != 1)
 | 
			
		||||
	{
 | 
			
		||||
		ASSERT_NO_ERROR (system.poll ());
 | 
			
		||||
	}
 | 
			
		||||
	system.nodes[0]->network.process_message (nano::publish (send2), channel1);
 | 
			
		||||
	system.nodes[0]->block_processor.flush ();
 | 
			
		||||
	ASSERT_NE (nullptr, system.nodes[0]->block (send2->hash ()));
 | 
			
		||||
	system.nodes[0]->network.process_message (nano::publish (send1), channel1);
 | 
			
		||||
	system.nodes[0]->block_processor.flush ();
 | 
			
		||||
	bool confirmed (false);
 | 
			
		||||
	system.deadline_set (5s);
 | 
			
		||||
	while (!confirmed)
 | 
			
		||||
	{
 | 
			
		||||
		auto transaction (system.nodes[0]->store.tx_begin_read ());
 | 
			
		||||
		confirmed = system.nodes[0]->block (send1->hash ()) != nullptr && system.nodes[0]->ledger.block_confirmed (transaction, send1->hash ());
 | 
			
		||||
		ASSERT_NO_ERROR (system.poll ());
 | 
			
		||||
	}
 | 
			
		||||
	ASSERT_EQ (1, system.nodes[0]->stats.count (nano::stat::type::election, nano::stat::detail::vote_cached));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST (active_transactions, inactive_votes_cache_existing_vote)
 | 
			
		||||
{
 | 
			
		||||
	nano::system system;
 | 
			
		||||
| 
						 | 
				
			
			@ -457,7 +488,7 @@ TEST (active_transactions, inactive_votes_cache_existing_vote)
 | 
			
		|||
	// Attempt to change vote with inactive_votes_cache
 | 
			
		||||
	node->active.add_inactive_votes_cache (send->hash (), key.pub);
 | 
			
		||||
	ASSERT_EQ (1, node->active.find_inactive_votes_cache (send->hash ()).voters.size ());
 | 
			
		||||
	election->insert_inactive_votes_cache ();
 | 
			
		||||
	election->insert_inactive_votes_cache (send->hash ());
 | 
			
		||||
	// Check that election data is not changed
 | 
			
		||||
	ASSERT_EQ (2, election->last_votes.size ());
 | 
			
		||||
	auto last_vote2 (election->last_votes[key.pub]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -523,7 +523,7 @@ bool nano::active_transactions::add (std::shared_ptr<nano::block> block_a, bool
 | 
			
		|||
			roots.get<tag_root> ().emplace (nano::conflict_info{ root, difficulty, difficulty, election });
 | 
			
		||||
			blocks.insert (std::make_pair (hash, election));
 | 
			
		||||
			adjust_difficulty (hash);
 | 
			
		||||
			election->insert_inactive_votes_cache ();
 | 
			
		||||
			election->insert_inactive_votes_cache (hash);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return error;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -218,6 +218,7 @@ bool nano::election::publish (std::shared_ptr<nano::block> block_a)
 | 
			
		|||
			if (blocks.find (block_a->hash ()) == blocks.end ())
 | 
			
		||||
			{
 | 
			
		||||
				blocks.insert (std::make_pair (block_a->hash (), block_a));
 | 
			
		||||
				insert_inactive_votes_cache (block_a->hash ());
 | 
			
		||||
				confirm_if_quorum ();
 | 
			
		||||
				node.network.flood_block (block_a, false);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -296,13 +297,12 @@ void nano::election::clear_blocks ()
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::election::insert_inactive_votes_cache ()
 | 
			
		||||
void nano::election::insert_inactive_votes_cache (nano::block_hash const & hash_a)
 | 
			
		||||
{
 | 
			
		||||
	auto winner_hash (status.winner->hash ());
 | 
			
		||||
	auto cache (node.active.find_inactive_votes_cache (winner_hash));
 | 
			
		||||
	auto cache (node.active.find_inactive_votes_cache (hash_a));
 | 
			
		||||
	for (auto & rep : cache.voters)
 | 
			
		||||
	{
 | 
			
		||||
		auto inserted (last_votes.emplace (rep, nano::vote_info{ std::chrono::steady_clock::time_point::min (), 0, winner_hash }));
 | 
			
		||||
		auto inserted (last_votes.emplace (rep, nano::vote_info{ std::chrono::steady_clock::time_point::min (), 0, hash_a }));
 | 
			
		||||
		if (inserted.second)
 | 
			
		||||
		{
 | 
			
		||||
			node.stats.inc (nano::stat::type::election, nano::stat::detail::vote_cached);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ public:
 | 
			
		|||
	void update_dependent ();
 | 
			
		||||
	void clear_dependent ();
 | 
			
		||||
	void clear_blocks ();
 | 
			
		||||
	void insert_inactive_votes_cache ();
 | 
			
		||||
	void insert_inactive_votes_cache (nano::block_hash const &);
 | 
			
		||||
	void stop ();
 | 
			
		||||
	nano::node & node;
 | 
			
		||||
	std::unordered_map<nano::account, nano::vote_info> last_votes;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -551,12 +551,6 @@ void nano::node::process_fork (nano::transaction const & transaction_a, std::sha
 | 
			
		|||
		std::shared_ptr<nano::block> ledger_block (ledger.forked_block (transaction_a, *block_a));
 | 
			
		||||
		if (ledger_block && !block_confirmed_or_being_confirmed (transaction_a, ledger_block->hash ()))
 | 
			
		||||
		{
 | 
			
		||||
			// Clear inactive votes cache for forks
 | 
			
		||||
			{
 | 
			
		||||
				nano::lock_guard<std::mutex> lock (active.mutex);
 | 
			
		||||
				active.erase_inactive_votes_cache (ledger_block->hash ());
 | 
			
		||||
				active.erase_inactive_votes_cache (block_a->hash ());
 | 
			
		||||
			}
 | 
			
		||||
			std::weak_ptr<nano::node> this_w (shared_from_this ());
 | 
			
		||||
			if (!active.start (ledger_block, false, [this_w, root](std::shared_ptr<nano::block>) {
 | 
			
		||||
					if (auto this_l = this_w.lock ())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue