Skip to content

Commit

Permalink
Tally votes on conflicting block with no inactive votes (#2744)
Browse files Browse the repository at this point in the history
Mostly applicable to tests, but consider this sequence of events:
- An election gets created for a processed block
- A vote arrives for a conflicting block; gets added to election, not inactive
- The conflicting block gets processed

Currently, `election::publish` calls `insert_inactive_votes_cache` but votes are not tallied since there was no inactive vote.

This fixes the above situation by calling `confirm_if_quorum` if no votes were cached when a new conflicting block is inserted.
  • Loading branch information
guilhermelawless committed Apr 28, 2020
1 parent 7966efd commit e31cdeb
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
30 changes: 29 additions & 1 deletion nano/core_test/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,4 +1088,32 @@ TEST (active_transactions, restart_dropped)
ASSERT_EQ (2, node.stats.count (nano::stat::type::election, nano::stat::detail::election_restart));
// Wait for the election to complete
ASSERT_TIMELY (5s, node.ledger.cache.cemented_count == 2);
}
}

// Ensures votes are tallied on election::publish even if no vote is inserted through inactive_votes_cache
TEST (active_transactions, conflicting_block_vote_existing_election)
{
nano::system system;
nano::node_flags node_flags;
node_flags.disable_request_loop = true;
auto & node = *system.add_node (node_flags);
nano::genesis genesis;
nano::keypair key;
auto send (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - 100, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
auto fork (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - 200, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
auto vote_fork (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 0, fork));

ASSERT_EQ (nano::process_result::progress, node.process_local (send).code);
ASSERT_EQ (1, node.active.size ());

// Vote for conflicting block, but the block does not yet exist in the ledger
node.active.vote (vote_fork);

// Block now gets processed
ASSERT_EQ (nano::process_result::fork, node.process_local (fork).code);

// Election must be confirmed
auto election (node.active.election (fork->qualified_root ()));
ASSERT_NE (nullptr, election);
ASSERT_TRUE (election->confirmed ());
}
11 changes: 8 additions & 3 deletions nano/node/election.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,11 @@ bool nano::election::publish (std::shared_ptr<nano::block> block_a)
if (existing == blocks.end ())
{
blocks.emplace (std::make_pair (block_a->hash (), block_a));
insert_inactive_votes_cache (block_a->hash ());
if (!insert_inactive_votes_cache (block_a->hash ()))
{
// Even if no votes were in cache, they could be in the election
confirm_if_quorum ();
}
node.network.flood_block (block_a, nano::buffer_drop_policy::no_limiter_drop);
}
else
Expand Down Expand Up @@ -576,10 +580,10 @@ void nano::election::cleanup ()
}
}

void nano::election::insert_inactive_votes_cache (nano::block_hash const & hash_a)
size_t nano::election::insert_inactive_votes_cache (nano::block_hash const & hash_a)
{
auto cache (node.active.find_inactive_votes_cache (hash_a));
for (auto & rep : cache.voters)
for (auto const & rep : cache.voters)
{
auto inserted (last_votes.emplace (rep, nano::vote_info{ std::chrono::steady_clock::time_point::min (), 0, hash_a }));
if (inserted.second)
Expand All @@ -597,6 +601,7 @@ void nano::election::insert_inactive_votes_cache (nano::block_hash const & hash_
}
confirm_if_quorum ();
}
return cache.voters.size ();
}

bool nano::election::prioritized () const
Expand Down
2 changes: 1 addition & 1 deletion nano/node/election.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class election final : public std::enable_shared_from_this<nano::election>
size_t last_votes_size ();
void update_dependent ();
void adjust_dependent_difficulty ();
void insert_inactive_votes_cache (nano::block_hash const &);
size_t insert_inactive_votes_cache (nano::block_hash const &);
bool prioritized () const;
void prioritize_election (nano::vote_generator_session &);
// Erase all blocks from active and, if not confirmed, clear digests from network filters
Expand Down

0 comments on commit e31cdeb

Please sign in to comment.