From 447356005bb70c49506e57f9a534cb49b810aa21 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Sun, 6 May 2018 14:09:19 +0100 Subject: [PATCH] Continuing to announce votes until quorum is met or the block can no longer be inserted. --- rai/core_test/ledger.cpp | 4 +- rai/core_test/node.cpp | 18 +++++--- rai/node/node.cpp | 94 +++++++++++++++------------------------- rai/node/node.hpp | 4 +- 4 files changed, 50 insertions(+), 70 deletions(-) diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index 62cd8ae7..9b8477b0 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -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 (); diff --git a/rai/core_test/node.cpp b/rai/core_test/node.cpp index 906b959d..986f60eb 100644 --- a/rai/core_test/node.cpp +++ b/rai/core_test/node.cpp @@ -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)); } diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 5140a040..619433c6 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -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 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 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> (node.peers.representatives (std::numeric_limits::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> (node.peers.representatives (std::numeric_limits::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> (*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> (*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) { diff --git a/rai/node/node.hpp b/rai/node/node.hpp index cf35ce32..6be52d6e 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -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 last_votes;