Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/cryptonote_protocol/cryptonote_protocol_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,23 @@ namespace cryptonote
const block_queue &get_block_queue() const { return m_block_queue; }
void stop();
void on_connection_close(cryptonote_connection_context &context);
void set_max_out_peers(unsigned int max) { m_max_out_peers = max; }
void set_max_out_peers(epee::net_utils::zone zone, unsigned int max) { CRITICAL_REGION_LOCAL(m_max_out_peers_lock); m_max_out_peers[zone] = max; }
unsigned int get_max_out_peers(epee::net_utils::zone zone) const
{
CRITICAL_REGION_LOCAL(m_max_out_peers_lock);
const auto it = m_max_out_peers.find(zone);
if (it == m_max_out_peers.end())
{
MWARNING(epee::net_utils::zone_to_string(zone) << " max out peers not set, using default");
return P2P_DEFAULT_CONNECTIONS_COUNT;
}
return it->second;
}
bool no_sync() const { return m_no_sync; }
void set_no_sync(bool value) { m_no_sync = value; }
std::string get_peers_overview() const;
std::pair<uint32_t, uint32_t> get_next_needed_pruning_stripe() const;
bool needs_new_sync_connections() const;
bool needs_new_sync_connections(epee::net_utils::zone zone) const;
bool is_busy_syncing();

private:
Expand Down Expand Up @@ -171,7 +182,8 @@ namespace cryptonote
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
epee::math_helper::once_a_time_seconds<101> m_sync_search_checker;
epee::math_helper::once_a_time_seconds<43> m_bad_peer_checker;
std::atomic<unsigned int> m_max_out_peers;
std::unordered_map<epee::net_utils::zone, unsigned int> m_max_out_peers;
mutable epee::critical_section m_max_out_peers_lock;
tools::PerformanceTimer m_sync_timer, m_add_timer;
uint64_t m_last_add_end_time;
uint64_t m_sync_spans_downloaded, m_sync_old_spans_downloaded, m_sync_bad_spans_downloaded;
Expand Down
62 changes: 41 additions & 21 deletions src/cryptonote_protocol/cryptonote_protocol_handler.inl
Original file line number Diff line number Diff line change
Expand Up @@ -1776,33 +1776,49 @@ skip:
return true;

MTRACE("Checking for outgoing syncing peers...");
unsigned n_syncing = 0, n_synced = 0;
boost::uuids::uuid last_synced_peer_id(boost::uuids::nil_uuid());
std::unordered_map<epee::net_utils::zone, unsigned> n_syncing, n_synced;
std::unordered_map<epee::net_utils::zone, boost::uuids::uuid> last_synced_peer_id;
std::vector<epee::net_utils::zone> zones;
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool
{
if (!peer_id || context.m_is_income) // only consider connected outgoing peers
return true;

const epee::net_utils::zone zone = context.m_remote_address.get_zone();
if (n_syncing.find(zone) == n_syncing.end())
{
n_syncing[zone] = 0;
n_synced[zone] = 0;
last_synced_peer_id[zone] = boost::uuids::nil_uuid();
zones.push_back(zone);
}

if (context.m_state == cryptonote_connection_context::state_synchronizing)
++n_syncing;
++n_syncing[zone];
if (context.m_state == cryptonote_connection_context::state_normal)
{
++n_synced;
++n_synced[zone];
if (!context.m_anchor)
last_synced_peer_id = context.m_connection_id;
last_synced_peer_id[zone] = context.m_connection_id;
}
return true;
});
MTRACE(n_syncing << " syncing, " << n_synced << " synced");

// if we're at max out peers, and not enough are syncing
if (n_synced + n_syncing >= m_max_out_peers && n_syncing < P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT && last_synced_peer_id != boost::uuids::nil_uuid())
for (const auto& zone : zones)
{
if (!m_p2p->for_connection(last_synced_peer_id, [&](cryptonote_connection_context& ctx, nodetool::peerid_type peer_id, uint32_t f)->bool{
MINFO(ctx << "dropping synced peer, " << n_syncing << " syncing, " << n_synced << " synced");
drop_connection(ctx, false, false);
return true;
}))
MDEBUG("Failed to find peer we wanted to drop");
const unsigned int max_out_peers = get_max_out_peers(zone);
MTRACE("[" << epee::net_utils::zone_to_string(zone) << "] " << n_syncing[zone] << " syncing, " << n_synced[zone] << " synced, " << max_out_peers << " max out peers");

// if we're at max out peers, and not enough are syncing, drop the last sync'd non-anchor
if (n_synced[zone] + n_syncing[zone] >= max_out_peers && n_syncing[zone] < P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT && last_synced_peer_id[zone] != boost::uuids::nil_uuid())
{
if (!m_p2p->for_connection(last_synced_peer_id[zone], [&](cryptonote_connection_context& ctx, nodetool::peerid_type peer_id, uint32_t f)->bool{
MINFO(ctx << "dropping synced peer, " << n_syncing[zone] << " syncing, " << n_synced[zone] << " synced, " << max_out_peers << " max out peers");
drop_connection(ctx, false, false);
return true;
}))
MDEBUG("Failed to find peer we wanted to drop");
}
}

return true;
Expand Down Expand Up @@ -1987,11 +2003,13 @@ skip:
++n_peers_on_next_stripe;
return true;
});
// TODO: investigate tallying by zone and comparing to max out peers by zone
const unsigned int max_out_peers = get_max_out_peers(epee::net_utils::zone::public_);
const uint32_t distance = (peer_stripe + (1<<CRYPTONOTE_PRUNING_LOG_STRIPES) - next_stripe) % (1<<CRYPTONOTE_PRUNING_LOG_STRIPES);
if ((n_out_peers >= m_max_out_peers && n_peers_on_next_stripe == 0) || (distance > 1 && n_peers_on_next_stripe <= 2) || distance > 2)
if ((n_out_peers >= max_out_peers && n_peers_on_next_stripe == 0) || (distance > 1 && n_peers_on_next_stripe <= 2) || distance > 2)
{
MDEBUG(context << "we want seed " << next_stripe << ", and either " << n_out_peers << " is at max out peers ("
<< m_max_out_peers << ") or distance " << distance << " from " << next_stripe << " to " << peer_stripe <<
<< max_out_peers << ") or distance " << distance << " from " << next_stripe << " to " << peer_stripe <<
" is too large and we have only " << n_peers_on_next_stripe << " peers on next seed, dropping connection to make space");
return true;
}
Expand Down Expand Up @@ -2812,31 +2830,33 @@ skip:
}
return true;
});
const bool use_next = (n_next > m_max_out_peers / 2 && n_subsequent <= 1) || (n_next > 2 && n_subsequent == 0);
// TODO: investigate tallying by zone and comparing to max out peers by zone
const unsigned int max_out_peers = get_max_out_peers(epee::net_utils::zone::public_);
const bool use_next = (n_next > max_out_peers / 2 && n_subsequent <= 1) || (n_next > 2 && n_subsequent == 0);
const uint32_t ret_stripe = use_next ? subsequent_pruning_stripe: next_pruning_stripe;
MIDEBUG(const std::string po = get_peers_overview(), "get_next_needed_pruning_stripe: want height " << want_height << " (" <<
want_height_from_blockchain << " from blockchain, " << want_height_from_block_queue << " from block queue), stripe " <<
next_pruning_stripe << " (" << n_next << "/" << m_max_out_peers << " on it and " << n_subsequent << " on " <<
next_pruning_stripe << " (" << n_next << "/" << max_out_peers << " on it and " << n_subsequent << " on " <<
subsequent_pruning_stripe << ", " << n_others << " others) -> " << ret_stripe << " (+" <<
(ret_stripe - next_pruning_stripe + (1 << CRYPTONOTE_PRUNING_LOG_STRIPES)) % (1 << CRYPTONOTE_PRUNING_LOG_STRIPES) <<
"), current peers " << po);
return std::make_pair(next_pruning_stripe, ret_stripe);
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::needs_new_sync_connections() const
bool t_cryptonote_protocol_handler<t_core>::needs_new_sync_connections(epee::net_utils::zone zone) const
{
const uint64_t target = m_core.get_target_blockchain_height();
const uint64_t height = m_core.get_current_blockchain_height();
if (target && target <= height)
return false;
size_t n_out_peers = 0;
m_p2p->for_each_connection([&](cryptonote_connection_context& ctx, nodetool::peerid_type peer_id, uint32_t support_flags)->bool{
if (!ctx.m_is_income)
if (!ctx.m_is_income && ctx.m_remote_address.get_zone() == zone)
++n_out_peers;
return true;
});
if (n_out_peers >= m_max_out_peers)
if (n_out_peers >= get_max_out_peers(zone))
return false;
return true;
}
Expand Down
10 changes: 7 additions & 3 deletions src/p2p/net_node.inl
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ namespace nodetool
if ( !set_max_out_peers(public_zone, command_line::get_arg(vm, arg_out_peers) ) )
return false;
else
m_payload_handler.set_max_out_peers(public_zone.m_config.m_net_config.max_out_connection_count);
m_payload_handler.set_max_out_peers(epee::net_utils::zone::public_, public_zone.m_config.m_net_config.max_out_connection_count);


if ( !set_max_in_peers(public_zone, command_line::get_arg(vm, arg_in_peers) ) )
Expand Down Expand Up @@ -575,6 +575,8 @@ namespace nodetool

if (!set_max_out_peers(zone, proxy.max_connections))
return false;
else
m_payload_handler.set_max_out_peers(proxy.zone, proxy.max_connections);

epee::byte_slice this_noise = nullptr;
if (proxy.noise)
Expand Down Expand Up @@ -2758,7 +2760,7 @@ namespace nodetool
public_zone->second.m_config.m_net_config.max_out_connection_count = count;
if(current > count)
public_zone->second.m_net_server.get_config_object().del_out_connections(current - count);
m_payload_handler.set_max_out_peers(count);
m_payload_handler.set_max_out_peers(epee::net_utils::zone::public_, count);
}
}

Expand Down Expand Up @@ -2887,10 +2889,12 @@ namespace nodetool
{
if (m_offline) return true;
if (!m_exclusive_peers.empty()) return true;
if (m_payload_handler.needs_new_sync_connections()) return true;

for (auto& zone : m_network_zones)
{
if (m_payload_handler.needs_new_sync_connections(zone.first))
continue;

if (zone.second.m_net_server.is_stop_signal_sent())
return false;

Expand Down
4 changes: 2 additions & 2 deletions tests/unit_tests/node_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1026,12 +1026,12 @@ TEST(node_server, race_condition)
}
void stop() {}
void on_connection_close(context_t &context) {}
void set_max_out_peers(unsigned int max) {}
void set_max_out_peers(epee::net_utils::zone zone, unsigned int max) {}
bool no_sync() const { return {}; }
void set_no_sync(bool value) {}
string_t get_peers_overview() const { return {}; }
stripes_t get_next_needed_pruning_stripe() const { return {}; }
bool needs_new_sync_connections() const { return {}; }
bool needs_new_sync_connections(epee::net_utils::zone zone) const { return {}; }
bool is_busy_syncing() { return {}; }
};
using node_server_t = nodetool::node_server<protocol_t>;
Expand Down