Continuing to announce votes until quorum is met or the block can no longer be inserted.

This commit is contained in:
clemahieu 2018-05-06 14:09:19 +01:00
commit 447356005b
4 changed files with 50 additions and 70 deletions

View file

@ -586,14 +586,14 @@ TEST (system, generate_send_existing)
{
system.poll ();
++iterations1;
ASSERT_LT (iterations1, 20);
ASSERT_LT (iterations1, 200);
}
auto iterations2 (0);
while (system.nodes[0]->balance (rai::test_genesis_key.pub) != rai::genesis_amount)
{
system.poll ();
++iterations2;
ASSERT_LT (iterations2, 20);
ASSERT_LT (iterations2, 200);
}
system.stop ();
runner.join ();

View file

@ -211,15 +211,18 @@ TEST (node, node_receive_quorum)
++iterations;
ASSERT_LT (iterations, 200);
}
while (!system.nodes[0]->active.roots.empty ())
auto done (false);
while (!done)
{
auto info (system.nodes[0]->active.roots.find (previous));
ASSERT_NE (system.nodes[0]->active.roots.end (), info);
done = info->announcements > rai::active_transactions::contiguous_announcements;
system.poll ();
++iterations;
ASSERT_LT (iterations, 200);
}
ASSERT_TRUE (system.nodes[0]->balance (key.pub).is_zero ());
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
system.nodes[0]->block_confirm (send);
while (system.nodes[0]->balance (key.pub).is_zero ())
{
system.poll ();
@ -1578,7 +1581,7 @@ TEST (node, block_arrival_time)
ASSERT_EQ (rai::block_arrival::arrival_size_min * 2, node.block_arrival.arrival.size ());
}
TEST (node, confirm_quorom)
TEST (node, confirm_quorum)
{
rai::system system (24000, 1);
rai::genesis genesis;
@ -1598,13 +1601,16 @@ TEST (node, confirm_quorom)
++iterations;
ASSERT_LT (iterations, 200);
}
ASSERT_FALSE (system.nodes[0]->active.roots.empty ());
while (!system.nodes[0]->active.roots.empty ())
auto done (false);
while (!done)
{
ASSERT_FALSE (system.nodes[0]->active.roots.empty ());
auto info (system.nodes[0]->active.roots.find (send1->hash ()));
ASSERT_NE (system.nodes[0]->active.roots.end (), info);
done = info->announcements > rai::active_transactions::contiguous_announcements;
system.poll ();
++iterations;
ASSERT_LT (iterations, 200);
}
ASSERT_TRUE (system.nodes[0]->active.roots.empty ());
ASSERT_EQ (0, system.nodes[0]->balance (rai::test_genesis_key.pub));
}

View file

@ -3038,7 +3038,7 @@ void rai::election::compute_rep_votes (MDB_txn * transaction_a)
{
node.wallets.foreach_representative (transaction_a, [this, transaction_a](rai::public_key const & pub_a, rai::raw_key const & prv_a) {
auto vote (this->node.store.vote_generate (transaction_a, pub_a, prv_a, status.winner));
this->votes.vote (vote);
this->node.vote_processor.vote (vote, this->node.network.endpoint ());
});
}
@ -3122,11 +3122,6 @@ void rai::election::confirm_if_quorum (MDB_txn * transaction_a)
}
}
void rai::election::confirm_cutoff (MDB_txn * transaction_a)
{
confirm_once (transaction_a);
}
bool rai::election::vote (std::shared_ptr<rai::vote> vote_a)
{
assert (!rai::validate_message (vote_a->account, vote_a->hash (), vote_a->signature));
@ -3188,80 +3183,61 @@ void rai::active_transactions::announce_votes ()
rai::transaction transaction (node.store.environment, nullptr, false);
std::lock_guard<std::mutex> lock (mutex);
for (auto i (roots.begin ()), n (roots.end ()); i != n; ++i)
{
size_t announcements (0);
auto i (roots.begin ());
auto n (roots.end ());
// Announce our decision for up to `announcements_per_interval' conflicts
for (; i != n && announcements < announcements_per_interval; ++i)
auto election_l (i->election);
if (!node.store.root_exists (transaction, election_l->votes.id) || (election_l->confirmed && i->announcements >= contiguous_announcements - 1))
{
auto election_l (i->election);
node.background ([election_l]() { election_l->broadcast_winner (); });
if (i->announcements >= contiguous_announcements - 1)
if (election_l->confirmed)
{
// These blocks have reached the confirmation interval for forks
i->election->confirm_cutoff (transaction);
auto root_l (i->election->votes.id);
inactive.push_back (root_l);
confirmed.push_back (i->election->status);
if (confirmed.size () > election_history_size)
{
confirmed.pop_front ();
}
}
else
inactive.push_back (election_l->votes.id);
}
else
{
node.background ([election_l]() { election_l->broadcast_winner (); });
if (i->announcements % contiguous_announcements == 2)
{
unsigned announcements;
roots.modify (i, [&announcements](rai::conflict_info & info_a) {
announcements = ++info_a.announcements;
});
// If more than one full announcement interval has passed and no one has voted on this block, we need to synchronize
if (announcements > 1 && i->election->votes.rep_votes.size () <= 1)
auto reps (std::make_shared<std::vector<rai::peer_information>> (node.peers.representatives (std::numeric_limits<size_t>::max ())));
for (auto j (reps->begin ()), m (reps->end ()); j != m;)
{
node.bootstrap_initiator.bootstrap ();
}
else if (i->confirm_req_options.second != nullptr)
{
auto reps (std::make_shared<std::vector<rai::peer_information>> (node.peers.representatives (std::numeric_limits<size_t>::max ())));
for (auto j (reps->begin ()), m (reps->end ()); j != m;)
auto & rep_votes (i->election->votes.rep_votes);
auto rep_acct (j->probable_rep_account);
if (rep_votes.find (rep_acct) != rep_votes.end ())
{
auto & rep_votes (i->election->votes.rep_votes);
auto rep_acct (j->probable_rep_account);
if (rep_votes.find (rep_acct) != rep_votes.end ())
std::swap (*j, reps->back ());
reps->pop_back ();
m = reps->end ();
}
else
{
++j;
if (node.config.logging.vote_logging ())
{
std::swap (*j, reps->back ());
reps->pop_back ();
m = reps->end ();
}
else
{
++j;
if (node.config.logging.vote_logging ())
{
BOOST_LOG (node.log) << "Representative did not respond to confirm_req, retrying: " << rep_acct.to_account ();
}
BOOST_LOG (node.log) << "Representative did not respond to confirm_req, retrying: " << rep_acct.to_account ();
}
}
if (!reps->empty ())
}
if (!reps->empty ())
{
// broadcast_confirm_req_base modifies reps, so we clone it once to avoid aliasing
node.network.broadcast_confirm_req_base (i->confirm_req_options.first, std::make_shared<std::vector<rai::peer_information>> (*reps), 0);
if (i->confirm_req_options.second)
{
// broadcast_confirm_req_base modifies reps, so we clone it once to avoid aliasing
node.network.broadcast_confirm_req_base (i->confirm_req_options.first, std::make_shared<std::vector<rai::peer_information>> (*reps), 0);
node.network.broadcast_confirm_req_base (i->confirm_req_options.second, reps, 0);
}
}
}
}
// Mark remainder as 0 announcements sent
// This could happen if there's a flood of forks, the network will resolve them in increasing root hash order
// This is a DoS protection mechanism to rate-limit the amount of traffic for solving forks.
for (; i != n; ++i)
{
// Reset announcement count for conflicts above announcement cutoff
roots.modify (i, [](rai::conflict_info & info_a) {
info_a.announcements = 0;
});
}
roots.modify (i, [](rai::conflict_info & info_a) {
++info_a.announcements;
});
}
for (auto i (inactive.begin ()), n (inactive.end ()); i != n; ++i)
{

View file

@ -64,10 +64,8 @@ public:
void broadcast_winner ();
// Change our winner to agree with the network
void compute_rep_votes (MDB_txn *);
// Confirmation method 1, uncontested quorum
// Confirm this block if quorum is met
void confirm_if_quorum (MDB_txn *);
// Confirmation method 2, settling time
void confirm_cutoff (MDB_txn *);
rai::votes votes;
rai::node & node;
std::unordered_map<rai::account, rai::vote_info> last_votes;