From 306f9b19ad5bce1f80bdaa72755270cff71a7acb Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Thu, 12 Mar 2020 09:55:54 +0000 Subject: [PATCH 1/5] Split election block broadcasting into directed and random floods --- nano/core_test/active_transactions.cpp | 10 +++++----- nano/node/confirmation_solicitor.cpp | 27 +++++++++++++++++++------- nano/node/confirmation_solicitor.hpp | 5 ++++- nano/node/network.cpp | 4 ++-- nano/node/network.hpp | 2 +- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 85b8eeb337..c0ae12b500 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -590,11 +590,7 @@ TEST (active_transactions, update_difficulty) node1.process_active (send1); node1.process_active (send2); node1.block_processor.flush (); - system.deadline_set (10s); - while (node1.active.size () != 2 || node2.active.size () != 2) - { - ASSERT_NO_ERROR (system.poll ()); - } + system.poll_until_true (10s, [&node1, &node2] {return node1.active.size () == 2 && node2.active.size () == 2;}); // Update work with higher difficulty auto work1 = node1.work_generate_blocking (send1->root (), difficulty1 + 1); auto work2 = node1.work_generate_blocking (send2->root (), difficulty2 + 1); @@ -609,6 +605,10 @@ TEST (active_transactions, update_difficulty) node1.process_active (send1); node1.process_active (send2); node1.block_processor.flush (); + // Share the updated blocks + node1.network.flood_block (send1); + node1.network.flood_block (send2); + system.deadline_set (10s); bool done (false); while (!done) diff --git a/nano/node/confirmation_solicitor.cpp b/nano/node/confirmation_solicitor.cpp index 5b83a97d62..0b98e0146b 100644 --- a/nano/node/confirmation_solicitor.cpp +++ b/nano/node/confirmation_solicitor.cpp @@ -7,6 +7,7 @@ nano::confirmation_solicitor::confirmation_solicitor (nano::network & network_a, max_confirm_req_batches (params_a.is_test_network () ? 1 : 20), max_block_broadcasts (params_a.is_test_network () ? 4 : 30), max_election_requests (30), +max_election_broadcasts (network_a.fanout () / 2), network (network_a) { } @@ -16,20 +17,32 @@ void nano::confirmation_solicitor::prepare (std::vector co debug_assert (!prepared); requests.clear (); rebroadcasted = 0; - representatives = representatives_a; + representatives_requests = representatives_broadcasts = representatives_a; prepared = true; } bool nano::confirmation_solicitor::broadcast (nano::election const & election_a) { debug_assert (prepared); - bool result (true); + bool error (true); if (rebroadcasted++ < max_block_broadcasts) { - network.flood_block (election_a.status.winner); - result = false; + nano::publish winner (election_a.status.winner); + unsigned count = 0; + // Directed broadcasting to principal representatives + for (auto i (representatives_broadcasts.begin ()), n (representatives_broadcasts.end ()); i != n && count < max_election_broadcasts; ++i) + { + if (election_a.last_votes.find (i->account) == election_a.last_votes.end ()) + { + i->channel->send (winner); + ++count; + } + } + // Random flood for block propagation + network.flood_message (winner, nano::buffer_drop_policy::limiter, 0.5f); + error = false; } - return result; + return error; } bool nano::confirmation_solicitor::add (nano::election const & election_a) @@ -37,7 +50,7 @@ bool nano::confirmation_solicitor::add (nano::election const & election_a) debug_assert (prepared); auto const max_channel_requests (max_confirm_req_batches * nano::network::confirm_req_hashes_max); unsigned count = 0; - for (auto i (representatives.begin ()); i != representatives.end () && count < max_election_requests;) + for (auto i (representatives_requests.begin ()); i != representatives_requests.end () && count < max_election_requests;) { bool full_queue (false); auto rep (*i); @@ -54,7 +67,7 @@ bool nano::confirmation_solicitor::add (nano::election const & election_a) full_queue = true; } } - i = !full_queue ? i + 1 : representatives.erase (i); + i = !full_queue ? i + 1 : representatives_requests.erase (i); } return count == 0; } diff --git a/nano/node/confirmation_solicitor.hpp b/nano/node/confirmation_solicitor.hpp index a9fd21d896..bce99b3233 100644 --- a/nano/node/confirmation_solicitor.hpp +++ b/nano/node/confirmation_solicitor.hpp @@ -28,12 +28,15 @@ class confirmation_solicitor final size_t const max_block_broadcasts; /** Maximum amount of requests to be sent per election */ size_t const max_election_requests; + /** Maximum amount of directed broadcasts to be sent per election */ + size_t const max_election_broadcasts; private: nano::network & network; unsigned rebroadcasted{ 0 }; - std::vector representatives; + std::vector representatives_requests; + std::vector representatives_broadcasts; using vector_root_hashes = std::vector>; std::unordered_map, vector_root_hashes> requests; bool prepared{ false }; diff --git a/nano/node/network.cpp b/nano/node/network.cpp index bb12834854..f849cd442b 100644 --- a/nano/node/network.cpp +++ b/nano/node/network.cpp @@ -148,9 +148,9 @@ void nano::network::send_node_id_handshake (std::shared_ptrsend (message); } -void nano::network::flood_message (nano::message const & message_a, nano::buffer_drop_policy drop_policy_a) +void nano::network::flood_message (nano::message const & message_a, nano::buffer_drop_policy const drop_policy_a, float const scale_a) { - for (auto & i : list (fanout ())) + for (auto & i : list (fanout (scale_a))) { i->send (message_a, nullptr, drop_policy_a); } diff --git a/nano/node/network.hpp b/nano/node/network.hpp index a1c8781011..153fc8fd2f 100644 --- a/nano/node/network.hpp +++ b/nano/node/network.hpp @@ -100,7 +100,7 @@ class network final ~network (); void start (); void stop (); - void flood_message (nano::message const &, nano::buffer_drop_policy = nano::buffer_drop_policy::limiter); + void flood_message (nano::message const &, nano::buffer_drop_policy const = nano::buffer_drop_policy::limiter, float const = 1.0f); void flood_keepalive () { nano::keepalive message; From 4ae4028385fd4365ae603aa2dcfe5cb940ff404d Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Thu, 12 Mar 2020 09:58:53 +0000 Subject: [PATCH 2/5] Formattting --- nano/core_test/active_transactions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index c0ae12b500..a1315392f2 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -590,7 +590,7 @@ TEST (active_transactions, update_difficulty) node1.process_active (send1); node1.process_active (send2); node1.block_processor.flush (); - system.poll_until_true (10s, [&node1, &node2] {return node1.active.size () == 2 && node2.active.size () == 2;}); + system.poll_until_true (10s, [&node1, &node2] { return node1.active.size () == 2 && node2.active.size () == 2; }); // Update work with higher difficulty auto work1 = node1.work_generate_blocking (send1->root (), difficulty1 + 1); auto work2 = node1.work_generate_blocking (send2->root (), difficulty2 + 1); From 0bc4b9879741e562721ad139adc175addee70d6b Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Thu, 12 Mar 2020 10:26:51 +0000 Subject: [PATCH 3/5] Assert no errror on system.poll_until_true (cc comment) --- nano/core_test/active_transactions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index a1315392f2..ea60fef8d9 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -590,7 +590,8 @@ TEST (active_transactions, update_difficulty) node1.process_active (send1); node1.process_active (send2); node1.block_processor.flush (); - system.poll_until_true (10s, [&node1, &node2] { return node1.active.size () == 2 && node2.active.size () == 2; }); + auto ec = system.poll_until_true (10s, [&node1, &node2] { return node1.active.size () == 2 && node2.active.size () == 2; }); + ASSERT_NO_ERROR (ec); // Update work with higher difficulty auto work1 = node1.work_generate_blocking (send1->root (), difficulty1 + 1); auto work2 = node1.work_generate_blocking (send2->root (), difficulty2 + 1); From 4da16b9bbb9a2c740a55b8283e5feee95c518b9e Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Thu, 12 Mar 2020 10:51:25 +0000 Subject: [PATCH 4/5] As one line --- nano/core_test/active_transactions.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index ea60fef8d9..4c5bb4ae37 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -590,8 +590,7 @@ TEST (active_transactions, update_difficulty) node1.process_active (send1); node1.process_active (send2); node1.block_processor.flush (); - auto ec = system.poll_until_true (10s, [&node1, &node2] { return node1.active.size () == 2 && node2.active.size () == 2; }); - ASSERT_NO_ERROR (ec); + ASSERT_NO_ERROR (system.poll_until_true (10s, [&node1, &node2] { return node1.active.size () == 2 && node2.active.size () == 2; })); // Update work with higher difficulty auto work1 = node1.work_generate_blocking (send1->root (), difficulty1 + 1); auto work2 = node1.work_generate_blocking (send2->root (), difficulty2 + 1); From 40734f97c71f6b179c6353b916da61ffb71b7f25 Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Sat, 14 Mar 2020 18:07:08 +0000 Subject: [PATCH 5/5] Simplify and explain the two copies (Serg comment) --- nano/node/confirmation_solicitor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nano/node/confirmation_solicitor.cpp b/nano/node/confirmation_solicitor.cpp index 0b98e0146b..823820d201 100644 --- a/nano/node/confirmation_solicitor.cpp +++ b/nano/node/confirmation_solicitor.cpp @@ -17,7 +17,9 @@ void nano::confirmation_solicitor::prepare (std::vector co debug_assert (!prepared); requests.clear (); rebroadcasted = 0; - representatives_requests = representatives_broadcasts = representatives_a; + /** Two copies are required as representatives can be erased from \p representatives_requests */ + representatives_requests = representatives_a; + representatives_broadcasts = representatives_a; prepared = true; }