cryptonote_protocol_handler: search for syncing peers in "cruise mode"
When all our outgoing peer slots are filled, we cycle one peer at a time looking for syncing peers until we have at least two such peers. This brings two advantages: - Peers without incoming connections will find more syncing peers that before, thereby strengthening network decentralization - Peers will have more resistance to isolation attacks, as they are more likely to find a "good" peer than they were before
This commit is contained in:
parent
31bdf7bd11
commit
eef164f7cc
|
@ -114,6 +114,7 @@
|
||||||
#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds
|
#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds
|
||||||
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
|
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
|
||||||
#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2
|
#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2
|
||||||
|
#define P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT 2
|
||||||
#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s
|
#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s
|
||||||
#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s
|
#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,7 @@ namespace cryptonote
|
||||||
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
|
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
|
||||||
bool kick_idle_peers();
|
bool kick_idle_peers();
|
||||||
bool check_standby_peers();
|
bool check_standby_peers();
|
||||||
|
bool update_sync_search();
|
||||||
int try_add_next_blocks(cryptonote_connection_context &context);
|
int try_add_next_blocks(cryptonote_connection_context &context);
|
||||||
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe);
|
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe);
|
||||||
void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
|
void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
|
||||||
|
@ -153,6 +154,7 @@ namespace cryptonote
|
||||||
block_queue m_block_queue;
|
block_queue m_block_queue;
|
||||||
epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker;
|
epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker;
|
||||||
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
|
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
|
||||||
|
epee::math_helper::once_a_time_seconds<101> m_sync_search_checker;
|
||||||
std::atomic<unsigned int> m_max_out_peers;
|
std::atomic<unsigned int> m_max_out_peers;
|
||||||
tools::PerformanceTimer m_sync_timer, m_add_timer;
|
tools::PerformanceTimer m_sync_timer, m_add_timer;
|
||||||
uint64_t m_last_add_end_time;
|
uint64_t m_last_add_end_time;
|
||||||
|
|
|
@ -1371,6 +1371,7 @@ skip:
|
||||||
{
|
{
|
||||||
m_idle_peer_kicker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::kick_idle_peers, this));
|
m_idle_peer_kicker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::kick_idle_peers, this));
|
||||||
m_standby_checker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::check_standby_peers, this));
|
m_standby_checker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::check_standby_peers, this));
|
||||||
|
m_sync_search_checker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::update_sync_search, this));
|
||||||
return m_core.on_idle();
|
return m_core.on_idle();
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -1400,6 +1401,47 @@ skip:
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
template<class t_core>
|
template<class t_core>
|
||||||
|
bool t_cryptonote_protocol_handler<t_core>::update_sync_search()
|
||||||
|
{
|
||||||
|
const uint64_t target = m_core.get_target_blockchain_height();
|
||||||
|
const uint64_t height = m_core.get_current_blockchain_height();
|
||||||
|
if (target > height) // if we're not synced yet, don't do it
|
||||||
|
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());
|
||||||
|
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;
|
||||||
|
if (context.m_state == cryptonote_connection_context::state_synchronizing)
|
||||||
|
++n_syncing;
|
||||||
|
if (context.m_state == cryptonote_connection_context::state_normal)
|
||||||
|
{
|
||||||
|
++n_synced;
|
||||||
|
if (!context.m_anchor)
|
||||||
|
last_synced_peer_id = 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())
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<class t_core>
|
||||||
bool t_cryptonote_protocol_handler<t_core>::check_standby_peers()
|
bool t_cryptonote_protocol_handler<t_core>::check_standby_peers()
|
||||||
{
|
{
|
||||||
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool
|
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool
|
||||||
|
|
Loading…
Reference in New Issue