Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish prototype #2468

Merged
merged 9 commits into from
Jan 30, 2020
22 changes: 9 additions & 13 deletions nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1993,22 +1993,24 @@ TEST (node, rep_weight)
auto channel0 (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, endpoint0, node.network_params.protocol.protocol_version));
auto channel1 (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, endpoint1, node.network_params.protocol.protocol_version));
auto channel2 (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, endpoint2, node.network_params.protocol.protocol_version));
nano::amount amount100 (100);
nano::amount amount50 (50);
nano::amount amount_pr (150000 * nano::Mxrb_ratio);
nano::amount amount_non_pr (50);
node.network.udp_channels.insert (endpoint2, node.network_params.protocol.protocol_version);
node.network.udp_channels.insert (endpoint0, node.network_params.protocol.protocol_version);
node.network.udp_channels.insert (endpoint1, node.network_params.protocol.protocol_version);
nano::keypair keypair1;
nano::keypair keypair2;
node.rep_crawler.response (channel0, keypair1.pub, amount100);
node.rep_crawler.response (channel1, keypair2.pub, amount50);
node.rep_crawler.response (channel0, keypair1.pub, amount_pr);
node.rep_crawler.response (channel1, keypair2.pub, amount_non_pr);
ASSERT_EQ (2, node.rep_crawler.representative_count ());
// Make sure we get the rep with the most weight first
auto reps (node.rep_crawler.representatives (1));
ASSERT_EQ (1, reps.size ());
ASSERT_EQ (100, reps[0].weight.number ());
ASSERT_EQ (amount_pr, reps[0].weight.number ());
ASSERT_EQ (keypair1.pub, reps[0].account);
ASSERT_EQ (*channel0, reps[0].channel_ref ());
ASSERT_TRUE (node.rep_crawler.is_pr (*channel0));
ASSERT_FALSE (node.rep_crawler.is_pr (*channel1));
}

TEST (node, rep_remove)
Expand Down Expand Up @@ -2710,9 +2712,9 @@ TEST (node, fork_invalid_block_signature)
}
auto vote (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 0, send2));
auto vote_corrupt (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 0, send2_corrupt));
system.nodes[1]->network.flood_vote (vote_corrupt);
system.nodes[1]->network.flood_vote (vote_corrupt, 1.0f);
ASSERT_NO_ERROR (system.poll ());
system.nodes[1]->network.flood_vote (vote);
system.nodes[1]->network.flood_vote (vote, 1.0f);
while (system.nodes[0]->block (send1->hash ()))
{
ASSERT_NO_ERROR (system.poll ());
Expand Down Expand Up @@ -3153,11 +3155,6 @@ TEST (node, bidirectional_tcp)
confirmed = node1->ledger.block_confirmed (transaction1, send1->hash ()) && node2->ledger.block_confirmed (transaction2, send1->hash ());
ASSERT_NO_ERROR (system.poll ());
}
// Test block propagation from node 2
{
auto transaction (system.wallet (0)->wallets.tx_begin_write ());
system.wallet (0)->store.erase (transaction, nano::test_genesis_key.pub);
}
auto send2 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 2 * nano::Gxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *node1->work_generate_blocking (send1->hash ())));
node2->process_active (send2);
node2->block_processor.flush ();
Expand All @@ -3167,7 +3164,6 @@ TEST (node, bidirectional_tcp)
ASSERT_NO_ERROR (system.poll ());
}
// Test block confirmation from node 2
system.wallet (1)->insert_adhoc (nano::test_genesis_key.prv);
confirmed = false;
system.deadline_set (10s);
while (!confirmed)
Expand Down
2 changes: 1 addition & 1 deletion nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ nano::vote_code nano::active_transactions::vote (std::shared_ptr<nano::vote> vot
{
if (processed)
wezrule marked this conversation as resolved.
Show resolved Hide resolved
{
node.network.flood_vote (vote_a);
node.network.flood_vote (vote_a, 0.5f);
}
return replay ? nano::vote_code::replay : nano::vote_code::vote;
}
Expand Down
26 changes: 24 additions & 2 deletions nano/node/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,28 @@ void nano::network::flood_message (nano::message const & message_a, bool const i
}
}

void nano::network::flood_vote (std::shared_ptr<nano::vote> vote_a, float scale)
{
auto list (list_fanout (scale));
for (auto i (list.begin ()), n (list.end ()); i != n; ++i)
{
if (!node.rep_crawler.is_pr (**i))
wezrule marked this conversation as resolved.
Show resolved Hide resolved
{
(*i)->send (nano::confirm_ack (vote_a));
}
}
}

void nano::network::flood_vote_pr (std::shared_ptr<nano::vote> vote_a)
guilhermelawless marked this conversation as resolved.
Show resolved Hide resolved
{
nano::confirm_ack message (vote_a);
auto list = node.rep_crawler.principal_representatives ();
for (auto const & i: list)
guilhermelawless marked this conversation as resolved.
Show resolved Hide resolved
{
i.channel->send (message, nullptr, false);
}
}

void nano::network::flood_block_many (std::deque<std::shared_ptr<nano::block>> blocks_a, std::function<void()> callback_a, unsigned delay_a)
{
auto block_l (blocks_a.front ());
Expand Down Expand Up @@ -678,9 +700,9 @@ std::deque<std::shared_ptr<nano::transport::channel>> nano::network::list (size_
}

// Simulating with sqrt_broadcast_simulate shows we only need to broadcast to sqrt(total_peers) random peers in order to successfully publish to everyone with high probability
std::deque<std::shared_ptr<nano::transport::channel>> nano::network::list_fanout ()
std::deque<std::shared_ptr<nano::transport::channel>> nano::network::list_fanout (float scale)
{
auto result (list (size_sqrt ()));
auto result (list (static_cast<size_t> (std::ceil (scale * size_sqrt ()))));
wezrule marked this conversation as resolved.
Show resolved Hide resolved
return result;
}

Expand Down
9 changes: 3 additions & 6 deletions nano/node/network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,8 @@ class network final
random_fill (message.peers);
flood_message (message);
}
void flood_vote (std::shared_ptr<nano::vote> vote_a)
{
nano::confirm_ack message (vote_a);
flood_message (message);
}
void flood_vote (std::shared_ptr<nano::vote>, float scale);
void flood_vote_pr (std::shared_ptr<nano::vote>);
void flood_block (std::shared_ptr<nano::block> block_a, bool const is_droppable_a = true)
{
nano::publish publish (block_a);
Expand Down Expand Up @@ -137,7 +134,7 @@ class network final
bool reachout (nano::endpoint const &, bool = false);
std::deque<std::shared_ptr<nano::transport::channel>> list (size_t);
// A list of random peers sized for the configured rebroadcast fanout
std::deque<std::shared_ptr<nano::transport::channel>> list_fanout ();
std::deque<std::shared_ptr<nano::transport::channel>> list_fanout (float scale = 1.0f);
void random_fill (std::array<nano::endpoint, 8> &) const;
std::unordered_set<std::shared_ptr<nano::transport::channel>> random_set (size_t) const;
// Get the next peer for attempting a tcp bootstrap connection
Expand Down
27 changes: 27 additions & 0 deletions nano/node/repcrawler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ void nano::rep_crawler::query (std::shared_ptr<nano::transport::channel> channel
query (peers);
}

bool nano::rep_crawler::is_pr (nano::transport::channel const & channel_a) const
{
nano::lock_guard<std::mutex> lock (probable_reps_mutex);
auto existing = probable_reps.get<tag_channel_ref> ().find (channel_a);
bool result = false;
if (existing != probable_reps.get<tag_channel_ref> ().end ())
{
result = existing->weight > node.minimum_principal_weight ();
}
return result;
}

bool nano::rep_crawler::response (std::shared_ptr<nano::transport::channel> channel_a, nano::account const & rep_account_a, nano::amount const & weight_a)
{
auto updated_or_inserted (false);
Expand Down Expand Up @@ -259,6 +271,21 @@ std::vector<nano::representative> nano::rep_crawler::representatives (size_t cou
return result;
}

std::vector<nano::representative> nano::rep_crawler::principal_representatives (size_t count_a)
{
std::vector<representative> result;
auto minimum = node.minimum_principal_weight ();
nano::lock_guard<std::mutex> lock (probable_reps_mutex);
for (auto i (probable_reps.get<tag_weight> ().begin ()), n (probable_reps.get<tag_weight> ().end ()); i != n && result.size () < count_a; ++i)
{
if (i->weight > minimum)
{
result.push_back (*i);
}
}
return result;
}

std::vector<std::shared_ptr<nano::transport::channel>> nano::rep_crawler::representative_endpoints (size_t count_a)
{
std::vector<std::shared_ptr<nano::transport::channel>> result;
Expand Down
6 changes: 6 additions & 0 deletions nano/node/repcrawler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ class rep_crawler
/** Attempt to determine if the peer manages one or more representative accounts */
void query (std::shared_ptr<nano::transport::channel> channel_a);

/** Query if a peer manages a principle representative */
bool is_pr (nano::transport::channel const &) const;

/**
* Called when a non-replay vote on a block previously sent by query() is received. This indiciates
* with high probability that the endpoint is a representative node.
Expand All @@ -106,6 +109,9 @@ class rep_crawler
/** Request a list of the top \p count_a known representatives in descending order of weight. */
std::vector<representative> representatives (size_t count_a = std::numeric_limits<size_t>::max ());

/** Request a list of the top \p count_a known principal representatives in descending order of weight. */
std::vector<representative> principal_representatives (size_t count_a = std::numeric_limits<size_t>::max ());

/** Request a list of the top \p count_a known representative endpoints. */
std::vector<std::shared_ptr<nano::transport::channel>> representative_endpoints (size_t count_a);

Expand Down
4 changes: 3 additions & 1 deletion nano/node/voting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ void nano::vote_generator::send (nano::unique_lock<std::mutex> & lock_a)
auto transaction (store.tx_begin_read ());
wallets.foreach_representative ([this, &hashes_l, &transaction](nano::public_key const & pub_a, nano::raw_key const & prv_a) {
auto vote (this->store.vote_generate (transaction, pub_a, prv_a, hashes_l));
this->vote_processor.vote (vote, std::make_shared<nano::transport::channel_udp> (this->network.udp_channels, this->network.endpoint (), this->network_params.protocol.protocol_version));
this->votes_cache.add (vote);
this->network.flood_vote_pr (vote);
this->network.flood_vote (vote, 2.0f);
this->vote_processor.vote (vote, std::make_shared<nano::transport::channel_udp> (this->network.udp_channels, this->network.endpoint (), this->network_params.protocol.protocol_version));
});
}
lock_a.lock ();
Expand Down
4 changes: 4 additions & 0 deletions nano/node/wallet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ class wallet_representative_counts
public:
uint64_t voting{ 0 }; // Representatives with at least the configured minimum voting weight
uint64_t half_principal{ 0 }; // Representatives with at least 50% of principal representative requirements
bool have_half_rep () const
guilhermelawless marked this conversation as resolved.
Show resolved Hide resolved
{
return half_principal > 0;
}
};

/**
Expand Down