Skip to content

Commit

Permalink
Merge develop, adding new parameter to limited_active_difficulty
Browse files Browse the repository at this point in the history
  • Loading branch information
guilhermelawless committed Apr 8, 2020
2 parents 017eb9e + 544d329 commit 2556560
Show file tree
Hide file tree
Showing 40 changed files with 808 additions and 350 deletions.
252 changes: 107 additions & 145 deletions nano/core_test/active_transactions.cpp

Large diffs are not rendered by default.

20 changes: 15 additions & 5 deletions nano/core_test/confirmation_height.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ TEST (confirmation_height, single)
ASSERT_EQ (1, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (1, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (1, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out));
ASSERT_EQ (2, node->ledger.cache.cemented_count);

ASSERT_EQ (0, node->active.election_winner_details_size ());
}
Expand Down Expand Up @@ -215,6 +216,7 @@ TEST (confirmation_height, multiple_accounts)
ASSERT_EQ (10, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (10, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (10, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out));
ASSERT_EQ (11, node->ledger.cache.cemented_count);

ASSERT_EQ (0, node->active.election_winner_details_size ());
};
Expand Down Expand Up @@ -292,6 +294,7 @@ TEST (confirmation_height, gap_bootstrap)
ASSERT_EQ (0, node1.stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (0, node1.stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (0, node1.stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out));
ASSERT_EQ (1, node1.ledger.cache.cemented_count);

ASSERT_EQ (0, node1.active.election_winner_details_size ());
};
Expand Down Expand Up @@ -378,6 +381,7 @@ TEST (confirmation_height, gap_live)
ASSERT_EQ (6, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (6, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (6, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out));
ASSERT_EQ (7, node->ledger.cache.cemented_count);

ASSERT_EQ (0, node->active.election_winner_details_size ());
};
Expand Down Expand Up @@ -753,6 +757,7 @@ TEST (confirmation_height, observers)
ASSERT_EQ (1, node1->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (1, node1->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (1, node1->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out));
ASSERT_EQ (2, node1->ledger.cache.cemented_count);
ASSERT_EQ (0, node1->active.election_winner_details_size ());
};

Expand Down Expand Up @@ -818,12 +823,14 @@ TEST (confirmation_height, modified_chain)
ASSERT_EQ (1, confirmation_height_info.height);
ASSERT_EQ (nano::genesis_hash, confirmation_height_info.frontier);
ASSERT_EQ (1, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::invalid_block, nano::stat::dir::in));
ASSERT_EQ (1, node->ledger.cache.cemented_count);
}
else
{
// A non-existent block is cemented, expected given these conditions but is of course incorrect.
ASSERT_EQ (2, confirmation_height_info.height);
ASSERT_EQ (send->hash (), confirmation_height_info.frontier);
ASSERT_EQ (2, node->ledger.cache.cemented_count);
}

ASSERT_EQ (0, node->active.election_winner_details_size ());
Expand Down Expand Up @@ -871,6 +878,7 @@ TEST (confirmation_height, pending_observer_callbacks)

ASSERT_EQ (2, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (2, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (3, node->ledger.cache.cemented_count);
ASSERT_EQ (0, node->active.election_winner_details_size ());
};

Expand Down Expand Up @@ -1172,7 +1180,7 @@ TEST (confirmation_height, callback_confirmed_history)
ASSERT_EQ (1, node->stats.count (nano::stat::type::observer, nano::stat::detail::observer_confirmation_inactive, nano::stat::dir::out));
ASSERT_EQ (2, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (2, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));

ASSERT_EQ (3, node->ledger.cache.cemented_count);
ASSERT_EQ (0, node->active.election_winner_details_size ());
};

Expand Down Expand Up @@ -1208,14 +1216,12 @@ TEST (confirmation_height, dependent_election)

add_callback_stats (*node);

// Start an election and vote, should confirm the block
node->block_confirm (send2);

{
// The write guard prevents the confirmation height processor doing any writes.
// Note: This test could still fail intermittently due to thread scheduling between active and confirmation height.
system.deadline_set (10s);
auto write_guard = node->write_database_queue.wait (nano::writer::testing);
// Start an election and vote, should confirm the block
node->block_confirm (send2);
while (!node->write_database_queue.contains (nano::writer::confirmation_height))
{
ASSERT_NO_ERROR (system.poll ());
Expand All @@ -1235,6 +1241,7 @@ TEST (confirmation_height, dependent_election)
ASSERT_EQ (1, node->stats.count (nano::stat::type::observer, nano::stat::detail::observer_confirmation_inactive, nano::stat::dir::out));
ASSERT_EQ (3, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (3, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (4, node->ledger.cache.cemented_count);

ASSERT_EQ (0, node->active.election_winner_details_size ());
};
Expand Down Expand Up @@ -1316,6 +1323,7 @@ TEST (confirmation_height, cemented_gap_below_receive)
ASSERT_EQ (9, node->stats.count (nano::stat::type::observer, nano::stat::detail::observer_confirmation_inactive, nano::stat::dir::out));
ASSERT_EQ (10, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (10, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (11, node->ledger.cache.cemented_count);
ASSERT_EQ (0, node->active.election_winner_details_size ());

// Check that the order of callbacks is correct
Expand Down Expand Up @@ -1408,6 +1416,7 @@ TEST (confirmation_height, cemented_gap_below_no_cache)
ASSERT_EQ (5, node->stats.count (nano::stat::type::observer, nano::stat::detail::observer_confirmation_inactive, nano::stat::dir::out));
ASSERT_EQ (6, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (6, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (7, node->ledger.cache.cemented_count);
};

test_mode (nano::confirmation_height_mode::bounded);
Expand Down Expand Up @@ -1488,6 +1497,7 @@ TEST (confirmation_height, election_winner_details_clearing)
ASSERT_EQ (2, node->stats.count (nano::stat::type::observer, nano::stat::detail::observer_confirmation_active_quorum, nano::stat::dir::out));
ASSERT_EQ (3, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
ASSERT_EQ (3, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
ASSERT_EQ (4, node->ledger.cache.cemented_count);
};

test_mode (nano::confirmation_height_mode::bounded);
Expand Down
39 changes: 21 additions & 18 deletions nano/core_test/conflicts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,24 +166,26 @@ TEST (conflicts, reprioritize)
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send1);
auto difficulty1 (send1->difficulty ());
auto multiplier1 (nano::normalized_multiplier (nano::difficulty::to_multiplier (difficulty1, nano::work_threshold (send1->work_version (), nano::block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */))), node1.network_params.network.publish_thresholds.epoch_1));
nano::send_block send1_copy (*send1);
node1.process_active (send1);
node1.block_processor.flush ();
{
nano::lock_guard<std::mutex> guard (node1.active.mutex);
auto existing1 (node1.active.roots.find (send1->qualified_root ()));
ASSERT_NE (node1.active.roots.end (), existing1);
ASSERT_EQ (difficulty1, existing1->difficulty);
ASSERT_EQ (multiplier1, existing1->multiplier);
}
node1.work_generate_blocking (send1_copy, difficulty1);
auto difficulty2 (send1_copy.difficulty ());
auto multiplier2 (nano::normalized_multiplier (nano::difficulty::to_multiplier (difficulty2, nano::work_threshold (send1_copy.work_version (), nano::block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */))), node1.network_params.network.publish_thresholds.epoch_1));
node1.process_active (std::make_shared<nano::send_block> (send1_copy));
node1.block_processor.flush ();
{
nano::lock_guard<std::mutex> guard (node1.active.mutex);
auto existing2 (node1.active.roots.find (send1->qualified_root ()));
ASSERT_NE (node1.active.roots.end (), existing2);
ASSERT_EQ (difficulty2, existing2->difficulty);
ASSERT_EQ (multiplier2, existing2->multiplier);
}
}

Expand Down Expand Up @@ -214,7 +216,7 @@ TEST (conflicts, dependency)
}
}

TEST (conflicts, adjusted_difficulty)
TEST (conflicts, adjusted_multiplier)
{
nano::system system (1);
auto & node1 (*system.nodes[0]);
Expand Down Expand Up @@ -250,35 +252,35 @@ TEST (conflicts, adjusted_difficulty)
{
ASSERT_NO_ERROR (system.poll ());
}
std::unordered_map<nano::block_hash, uint64_t> adjusted_difficulties;
std::unordered_map<nano::block_hash, double> adjusted_multipliers;
{
nano::lock_guard<std::mutex> guard (node1.active.mutex);
node1.active.update_adjusted_difficulty ();
node1.active.update_adjusted_multiplier ();
ASSERT_EQ (node1.active.roots.get<1> ().begin ()->election->status.winner->hash (), send1->hash ());
for (auto i (node1.active.roots.get<1> ().begin ()), n (node1.active.roots.get<1> ().end ()); i != n; ++i)
{
adjusted_difficulties.insert (std::make_pair (i->election->status.winner->hash (), i->adjusted_difficulty));
adjusted_multipliers.insert (std::make_pair (i->election->status.winner->hash (), i->adjusted_multiplier));
}
}
// genesis
ASSERT_GT (adjusted_difficulties.find (send1->hash ())->second, adjusted_difficulties.find (send2->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (send2->hash ())->second, adjusted_difficulties.find (receive1->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (send1->hash ())->second, adjusted_multipliers.find (send2->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (send2->hash ())->second, adjusted_multipliers.find (receive1->hash ())->second);
// key1
ASSERT_GT (adjusted_difficulties.find (send1->hash ())->second, adjusted_difficulties.find (open1->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (open1->hash ())->second, adjusted_difficulties.find (send3->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (send3->hash ())->second, adjusted_difficulties.find (send4->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (send1->hash ())->second, adjusted_multipliers.find (open1->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (open1->hash ())->second, adjusted_multipliers.find (send3->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (send3->hash ())->second, adjusted_multipliers.find (send4->hash ())->second);
//key2
ASSERT_GT (adjusted_difficulties.find (send3->hash ())->second, adjusted_difficulties.find (receive2->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (open_epoch1->hash ())->second, adjusted_difficulties.find (receive2->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (send3->hash ())->second, adjusted_multipliers.find (receive2->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (open_epoch1->hash ())->second, adjusted_multipliers.find (receive2->hash ())->second);
// key3
ASSERT_GT (adjusted_difficulties.find (send4->hash ())->second, adjusted_difficulties.find (open2->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (open2->hash ())->second, adjusted_difficulties.find (change1->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (send4->hash ())->second, adjusted_multipliers.find (open2->hash ())->second);
ASSERT_GT (adjusted_multipliers.find (open2->hash ())->second, adjusted_multipliers.find (change1->hash ())->second);
// Independent elections can have higher difficulty than adjusted tree
nano::keypair key4;
auto send5 (std::make_shared<nano::state_block> (key3.pub, change1->hash (), nano::test_genesis_key.pub, 0, key4.pub, key3.prv, key3.pub, *system.work.generate (change1->hash ()))); // Pending for open epoch block
node1.process_active (send5);
auto open_epoch2 (std::make_shared<nano::state_block> (key4.pub, 0, 0, 0, node1.ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (key4.pub, adjusted_difficulties.find (send1->hash ())->second)));
ASSERT_GT (open_epoch2->difficulty (), adjusted_difficulties.find (send1->hash ())->second);
auto open_epoch2 (std::make_shared<nano::state_block> (key4.pub, 0, 0, 0, node1.ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (key4.pub, nano::difficulty::from_multiplier ((adjusted_multipliers.find (send1->hash ())->second), node1.network_params.network.publish_thresholds.base))));
ASSERT_GT (open_epoch2->difficulty (), nano::difficulty::from_multiplier ((adjusted_multipliers.find (send1->hash ())->second), node1.network_params.network.publish_thresholds.base));
node1.process_active (open_epoch2);
node1.block_processor.flush ();
system.deadline_set (3s);
Expand All @@ -288,7 +290,8 @@ TEST (conflicts, adjusted_difficulty)
}
{
nano::lock_guard<std::mutex> guard (node1.active.mutex);
node1.active.update_adjusted_difficulty ();
node1.active.update_adjusted_multiplier ();
ASSERT_EQ (node1.active.roots.size (), 12);
ASSERT_EQ (node1.active.roots.get<1> ().begin ()->election->status.winner->hash (), open_epoch2->hash ());
}
}
1 change: 1 addition & 0 deletions nano/core_test/election.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ TEST (election, construction)
nano::system system (1);
nano::genesis genesis;
auto & node = *system.nodes[0];
genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false));
auto election = node.active.insert (genesis.open).election;
ASSERT_TRUE (election->idle ());
election->transition_active ();
Expand Down
56 changes: 46 additions & 10 deletions nano/core_test/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,32 +1049,32 @@ TEST (peer_exclusion, validate)
nano::peer_exclusion excluded_peers;
size_t fake_peers_count = 10;
auto max_size = excluded_peers.limited_size (fake_peers_count);
auto address (boost::asio::ip::address_v6::loopback ());
for (auto i = 0; i < max_size + 2; ++i)
{
nano::tcp_endpoint endpoint (address, i);
nano::tcp_endpoint endpoint (boost::asio::ip::address_v6::v4_mapped (boost::asio::ip::address_v4 (i)), 0);
ASSERT_FALSE (excluded_peers.check (endpoint));
ASSERT_EQ (1, excluded_peers.add (endpoint, fake_peers_count));
ASSERT_FALSE (excluded_peers.check (endpoint));
}
// The oldest one must have been removed
ASSERT_EQ (max_size + 1, excluded_peers.size ());
auto & peers_by_endpoint (excluded_peers.peers.get<nano::peer_exclusion::tag_endpoint> ());
ASSERT_EQ (peers_by_endpoint.end (), peers_by_endpoint.find (nano::tcp_endpoint (address, 0)));
nano::tcp_endpoint oldest (boost::asio::ip::address_v6::v4_mapped (boost::asio::ip::address_v4 (0x0)), 0);
ASSERT_EQ (peers_by_endpoint.end (), peers_by_endpoint.find (oldest.address ()));

auto to_seconds = [](std::chrono::steady_clock::time_point const & timepoint) {
return std::chrono::duration_cast<std::chrono::seconds> (timepoint.time_since_epoch ()).count ();
};
nano::tcp_endpoint first (address, 1);
ASSERT_NE (peers_by_endpoint.end (), peers_by_endpoint.find (first));
nano::tcp_endpoint second (address, 2);
nano::tcp_endpoint first (boost::asio::ip::address_v6::v4_mapped (boost::asio::ip::address_v4 (0x1)), 0);
ASSERT_NE (peers_by_endpoint.end (), peers_by_endpoint.find (first.address ()));
nano::tcp_endpoint second (boost::asio::ip::address_v6::v4_mapped (boost::asio::ip::address_v4 (0x2)), 0);
ASSERT_EQ (false, excluded_peers.check (second));
ASSERT_NEAR (to_seconds (std::chrono::steady_clock::now () + excluded_peers.exclude_time_hours), to_seconds (peers_by_endpoint.find (second)->exclude_until), 2);
ASSERT_NEAR (to_seconds (std::chrono::steady_clock::now () + excluded_peers.exclude_time_hours), to_seconds (peers_by_endpoint.find (second.address ())->exclude_until), 2);
ASSERT_EQ (2, excluded_peers.add (second, fake_peers_count));
ASSERT_EQ (peers_by_endpoint.end (), peers_by_endpoint.find (first));
ASSERT_NEAR (to_seconds (std::chrono::steady_clock::now () + excluded_peers.exclude_time_hours), to_seconds (peers_by_endpoint.find (second)->exclude_until), 2);
ASSERT_EQ (peers_by_endpoint.end (), peers_by_endpoint.find (first.address ()));
ASSERT_NEAR (to_seconds (std::chrono::steady_clock::now () + excluded_peers.exclude_time_hours), to_seconds (peers_by_endpoint.find (second.address ())->exclude_until), 2);
ASSERT_EQ (3, excluded_peers.add (second, fake_peers_count));
ASSERT_NEAR (to_seconds (std::chrono::steady_clock::now () + excluded_peers.exclude_time_hours * 3 * 2), to_seconds (peers_by_endpoint.find (second)->exclude_until), 2);
ASSERT_NEAR (to_seconds (std::chrono::steady_clock::now () + excluded_peers.exclude_time_hours * 3 * 2), to_seconds (peers_by_endpoint.find (second.address ())->exclude_until), 2);
ASSERT_EQ (max_size, excluded_peers.size ());

// Clear many entries if there are a low number of peers
Expand All @@ -1094,3 +1094,39 @@ TEST (peer_exclusion, validate)
ASSERT_EQ (sizeof (decltype (excluded_peers.peers)::value_type), child_info.sizeof_element);
}
}

TEST (network, tcp_no_connect_excluded_peers)
{
nano::system system (1);
auto node0 (system.nodes[0]);
ASSERT_EQ (0, node0->network.size ());
auto node1 (std::make_shared<nano::node> (system.io_ctx, nano::get_available_port (), nano::unique_path (), system.alarm, system.logging, system.work));
node1->start ();
system.nodes.push_back (node1);
auto endpoint1 (node1->network.endpoint ());
auto endpoint1_tcp (nano::transport::map_endpoint_to_tcp (endpoint1));
while (!node0->network.excluded_peers.check (endpoint1_tcp))
{
node0->network.excluded_peers.add (endpoint1_tcp, 1);
}
ASSERT_EQ (0, node0->stats.count (nano::stat::type::tcp, nano::stat::detail::tcp_excluded));
node1->network.merge_peer (node0->network.endpoint ());
ASSERT_TIMELY (5s, node0->stats.count (nano::stat::type::tcp, nano::stat::detail::tcp_excluded) >= 1);
ASSERT_EQ (nullptr, node0->network.find_channel (endpoint1));

// Should not actively reachout to excluded peers
ASSERT_TRUE (node0->network.reachout (endpoint1, true));

// Erasing from excluded peers should allow a connection
node0->network.excluded_peers.remove (endpoint1_tcp);
ASSERT_FALSE (node0->network.excluded_peers.check (endpoint1_tcp));

// Manually cleanup previous attempt
node1->network.cleanup (std::chrono::steady_clock::now ());
node1->network.syn_cookies.purge (std::chrono::steady_clock::now ());

// Ensure a successful connection
ASSERT_EQ (0, node0->network.size ());
node1->network.merge_peer (node0->network.endpoint ());
ASSERT_TIMELY (5s, node0->network.size () == 1);
}
Loading

0 comments on commit 2556560

Please sign in to comment.