Tally votes on conflicting block with no inactive votes (#2744)
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.
This commit is contained in:
parent
7966efd652
commit
e31cdebc87
3 changed files with 38 additions and 5 deletions
|
|
@ -1089,3 +1089,31 @@ TEST (active_transactions, restart_dropped)
|
||||||
// Wait for the election to complete
|
// Wait for the election to complete
|
||||||
ASSERT_TIMELY (5s, node.ledger.cache.cemented_count == 2);
|
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 ());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,11 @@ bool nano::election::publish (std::shared_ptr<nano::block> block_a)
|
||||||
if (existing == blocks.end ())
|
if (existing == blocks.end ())
|
||||||
{
|
{
|
||||||
blocks.emplace (std::make_pair (block_a->hash (), block_a));
|
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);
|
node.network.flood_block (block_a, nano::buffer_drop_policy::no_limiter_drop);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -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));
|
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 }));
|
auto inserted (last_votes.emplace (rep, nano::vote_info{ std::chrono::steady_clock::time_point::min (), 0, hash_a }));
|
||||||
if (inserted.second)
|
if (inserted.second)
|
||||||
|
|
@ -597,6 +601,7 @@ void nano::election::insert_inactive_votes_cache (nano::block_hash const & hash_
|
||||||
}
|
}
|
||||||
confirm_if_quorum ();
|
confirm_if_quorum ();
|
||||||
}
|
}
|
||||||
|
return cache.voters.size ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nano::election::prioritized () const
|
bool nano::election::prioritized () const
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ public:
|
||||||
size_t last_votes_size ();
|
size_t last_votes_size ();
|
||||||
void update_dependent ();
|
void update_dependent ();
|
||||||
void adjust_dependent_difficulty ();
|
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;
|
bool prioritized () const;
|
||||||
void prioritize_election (nano::vote_generator_session &);
|
void prioritize_election (nano::vote_generator_session &);
|
||||||
// Erase all blocks from active and, if not confirmed, clear digests from network filters
|
// Erase all blocks from active and, if not confirmed, clear digests from network filters
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue