mirror of https://github.com/monero-project/monero
Merge 950b58ab0b
into c8214782fb
This commit is contained in:
commit
bd9fa79f15
|
@ -106,5 +106,7 @@ namespace math_helper
|
|||
class once_a_time_milliseconds: public once_a_time<get_constant_interval<default_interval * (uint64_t)1000>, start_immediate> {};
|
||||
template<typename get_interval, bool start_immediate = true>
|
||||
class once_a_time_seconds_range: public once_a_time<get_interval, start_immediate> {};
|
||||
template<typename get_interval, bool start_immediate = false>
|
||||
class once_a_time_range: public once_a_time<get_interval, start_immediate> {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,6 +220,15 @@ namespace config
|
|||
uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)2000000000); // 2 * pow(10, 9)
|
||||
uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8)
|
||||
|
||||
// Both below are in nanoseconds. Onion connections are randomly dropped within this
|
||||
// range and successive onion connections are delayed within this range
|
||||
time_t const RANDOM_CONNECTION_DROP_LOWER = 2 * 60 * 1000000;
|
||||
time_t const RANDOM_CONNECTION_DROP_UPPER = 4 * 60 * 1000000;
|
||||
uint8_t const ACQUIRE_PEERS_RECONNECT_SCALING_FACTOR = 4;
|
||||
|
||||
// Onion circuit will expire after not being used for this many minutes
|
||||
uint8_t const DEFAULT_ONION_CIRCUIT_EXPIRY = 10;
|
||||
|
||||
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18;
|
||||
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 19;
|
||||
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 42;
|
||||
|
|
|
@ -98,6 +98,16 @@ namespace levin
|
|||
return std::chrono::steady_clock::duration{crypto::rand_range(rep(0), range.count())};
|
||||
}
|
||||
|
||||
bool set_connection_can_broadcast_txs_to_peer(std::shared_ptr<connections> p2p, boost::uuids::uuid conn, bool val, bool exclusive_peers) {
|
||||
if (exclusive_peers && !val)
|
||||
return true;
|
||||
return p2p->for_connection(conn, [&](detail::p2p_context& context)
|
||||
{
|
||||
context.can_broadcast_txs_to_peer = val;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t get_median_remote_height(connections& p2p)
|
||||
{
|
||||
std::vector<uint64_t> remote_heights;
|
||||
|
@ -616,8 +626,9 @@ namespace levin
|
|||
std::shared_ptr<detail::zone> zone_;
|
||||
const std::size_t channel_;
|
||||
const i_core_events* core_;
|
||||
bool exclusive_peers_;
|
||||
|
||||
static void wait(const std::chrono::steady_clock::time_point start, std::shared_ptr<detail::zone> zone, const std::size_t index, const i_core_events* core)
|
||||
static void wait(const std::chrono::steady_clock::time_point start, std::shared_ptr<detail::zone> zone, const std::size_t index, const i_core_events* core, bool exclusive_peers)
|
||||
{
|
||||
if (!zone)
|
||||
return;
|
||||
|
@ -625,7 +636,7 @@ namespace levin
|
|||
noise_channel& channel = zone->channels.at(index);
|
||||
channel.next_noise.expires_at(start + noise_min_delay + random_duration(noise_delay_range));
|
||||
channel.next_noise.async_wait(
|
||||
channel.strand.wrap(send_noise{std::move(zone), index, core})
|
||||
channel.strand.wrap(send_noise{std::move(zone), index, core, exclusive_peers})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -643,12 +654,20 @@ namespace levin
|
|||
const auto start = std::chrono::steady_clock::now();
|
||||
noise_channel& channel = zone_->channels.at(channel_);
|
||||
|
||||
bool can_broadcast = true;
|
||||
zone_->p2p->for_connection(channel.connection, [&](detail::p2p_context& context){
|
||||
can_broadcast = context.can_broadcast_txs_to_peer;
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!channel.connection.is_nil())
|
||||
{
|
||||
epee::byte_slice message = nullptr;
|
||||
if (!channel.active.empty())
|
||||
if (can_broadcast && !channel.active.empty())
|
||||
{
|
||||
message = channel.active.take_slice(zone_->noise.size());
|
||||
else if (!channel.queue.empty())
|
||||
}
|
||||
else if (can_broadcast && !channel.queue.empty())
|
||||
{
|
||||
channel.active = channel.queue.front().clone();
|
||||
message = channel.active.take_slice(zone_->noise.size());
|
||||
|
@ -658,8 +677,12 @@ namespace levin
|
|||
|
||||
if (zone_->p2p->send(std::move(message), channel.connection))
|
||||
{
|
||||
if (!channel.queue.empty() && channel.active.empty())
|
||||
if (can_broadcast && !channel.queue.empty() && channel.active.empty())
|
||||
{
|
||||
channel.queue.pop_front();
|
||||
if (zone_->nzone == epee::net_utils::zone::tor)
|
||||
set_connection_can_broadcast_txs_to_peer(zone_->p2p, channel.connection, false, exclusive_peers_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -676,7 +699,7 @@ namespace levin
|
|||
}
|
||||
}
|
||||
|
||||
wait(start, std::move(zone_), channel_, core_);
|
||||
wait(start, std::move(zone_), channel_, core_, exclusive_peers_);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -713,7 +736,7 @@ namespace levin
|
|||
};
|
||||
} // anonymous
|
||||
|
||||
notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core)
|
||||
notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core, bool exclusive_peers)
|
||||
: zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), zone, pad_txs))
|
||||
, core_(std::addressof(core))
|
||||
{
|
||||
|
@ -731,7 +754,7 @@ namespace levin
|
|||
start_epoch{zone_, min_epoch, epoch_range, out_count, core_}();
|
||||
|
||||
for (std::size_t channel = 0; channel < zone_->channels.size(); ++channel)
|
||||
send_noise::wait(now, zone_, channel, core_);
|
||||
send_noise::wait(now, zone_, channel, core_, exclusive_peers);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace levin
|
|||
{}
|
||||
|
||||
//! Construct an instance with available notification `zones`.
|
||||
explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core);
|
||||
explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core, bool exclusive_peers);
|
||||
|
||||
notify(const notify&) = delete;
|
||||
notify(notify&&) = default;
|
||||
|
|
|
@ -112,13 +112,15 @@ namespace nodetool
|
|||
p2p_connection_context_t()
|
||||
: peer_id(0),
|
||||
support_flags(0),
|
||||
m_in_timedsync(false)
|
||||
m_in_timedsync(false),
|
||||
can_broadcast_txs_to_peer(true)
|
||||
{}
|
||||
|
||||
peerid_type peer_id;
|
||||
uint32_t support_flags;
|
||||
bool m_in_timedsync;
|
||||
std::set<epee::net_utils::network_address> sent_addresses;
|
||||
bool can_broadcast_txs_to_peer;
|
||||
};
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
|
@ -146,12 +148,14 @@ namespace nodetool
|
|||
config_t()
|
||||
: m_net_config(),
|
||||
m_peer_id(1),
|
||||
m_support_flags(0)
|
||||
m_support_flags(0),
|
||||
can_broadcast_txs_to_peer(true)
|
||||
{}
|
||||
|
||||
network_config m_net_config;
|
||||
uint64_t m_peer_id;
|
||||
uint32_t m_support_flags;
|
||||
bool can_broadcast_txs_to_peer;
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<config_t> config;
|
||||
|
||||
|
@ -255,7 +259,8 @@ namespace nodetool
|
|||
is_closing(false),
|
||||
m_network_id(),
|
||||
m_enable_dns_seed_nodes(true),
|
||||
max_connections(1)
|
||||
max_connections(1),
|
||||
m_make_next_tor_connection_after(0)
|
||||
{}
|
||||
virtual ~node_server();
|
||||
|
||||
|
@ -281,6 +286,8 @@ namespace nodetool
|
|||
void get_public_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white);
|
||||
void get_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white);
|
||||
|
||||
bool extend_make_next_connection_after(epee::net_utils::zone zone, bool acquire_peers);
|
||||
|
||||
void change_max_out_public_peers(size_t count);
|
||||
uint32_t get_max_out_public_peers() const;
|
||||
void change_max_in_public_peers(size_t count);
|
||||
|
@ -419,6 +426,8 @@ namespace nodetool
|
|||
bool gray_peerlist_housekeeping();
|
||||
bool check_incoming_connections();
|
||||
|
||||
bool drop_random_outgoing_tor_connection();
|
||||
|
||||
void kill() { ///< will be called e.g. from deinit()
|
||||
_info("Killing the net_node");
|
||||
is_closing = true;
|
||||
|
@ -474,6 +483,10 @@ namespace nodetool
|
|||
epee::math_helper::once_a_time_seconds<3600, false> m_incoming_connections_interval;
|
||||
epee::math_helper::once_a_time_seconds<7000> m_dns_blocklist_interval;
|
||||
|
||||
template<uint64_t mini, uint64_t maxi> struct get_random_interval { public: uint64_t operator()() const { return crypto::rand_range(mini, maxi); } };
|
||||
epee::math_helper::once_a_time_range<get_random_interval<::config::RANDOM_CONNECTION_DROP_LOWER, ::config::RANDOM_CONNECTION_DROP_UPPER>> m_drop_random_outgoing_tor_connection_interval;
|
||||
time_t m_make_next_tor_connection_after;
|
||||
|
||||
std::list<epee::net_utils::network_address> m_priority_peers;
|
||||
std::vector<epee::net_utils::network_address> m_exclusive_peers;
|
||||
std::atomic_flag m_fallback_seed_nodes_added;
|
||||
|
@ -516,6 +529,7 @@ namespace nodetool
|
|||
bool m_enable_dns_blocklist;
|
||||
|
||||
uint32_t max_connections;
|
||||
|
||||
};
|
||||
|
||||
const int64_t default_limit_up = P2P_DEFAULT_LIMIT_RATE_UP; // kB/s
|
||||
|
|
|
@ -452,7 +452,7 @@ namespace nodetool
|
|||
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
|
||||
m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4);
|
||||
public_zone.m_notifier = cryptonote::levin::notify{
|
||||
public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core()
|
||||
public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core(), !m_exclusive_peers.empty()
|
||||
};
|
||||
|
||||
if (command_line::has_arg(vm, arg_p2p_add_peer))
|
||||
|
@ -605,7 +605,7 @@ namespace nodetool
|
|||
}
|
||||
|
||||
zone.m_notifier = cryptonote::levin::notify{
|
||||
zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core()
|
||||
zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core(), !m_exclusive_peers.empty()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1366,6 +1366,8 @@ namespace nodetool
|
|||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp)
|
||||
{
|
||||
bool one_conn_below_max = false;
|
||||
|
||||
network_zone& zone = m_network_zones.at(na.get_zone());
|
||||
if (zone.m_connect == nullptr) // outgoing connections in zone not possible
|
||||
return false;
|
||||
|
@ -1377,6 +1379,10 @@ namespace nodetool
|
|||
{
|
||||
return false;
|
||||
}
|
||||
else if (zone.m_current_number_of_out_peers == zone.m_config.m_net_config.max_out_connection_count - 1)
|
||||
{
|
||||
one_conn_below_max = true;
|
||||
}
|
||||
else if (zone.m_current_number_of_out_peers > zone.m_config.m_net_config.max_out_connection_count)
|
||||
{
|
||||
zone.m_net_server.get_config_object().del_out_connections(1);
|
||||
|
@ -1384,6 +1390,9 @@ namespace nodetool
|
|||
return false;
|
||||
}
|
||||
|
||||
if (na.get_zone() == epee::net_utils::zone::tor && time(nullptr) < m_make_next_tor_connection_after) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MDEBUG("Connecting to " << na.str() << "(peer_type=" << peer_type << ", last_seen: "
|
||||
<< (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
|
||||
|
@ -1441,6 +1450,17 @@ namespace nodetool
|
|||
zone.m_notifier.on_handshake_complete(con->m_connection_id, con->m_is_income);
|
||||
zone.m_notifier.new_out_connection();
|
||||
|
||||
if (na.get_zone() == epee::net_utils::zone::tor) {
|
||||
if (one_conn_below_max)
|
||||
{
|
||||
extend_make_next_connection_after(na.get_zone(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
extend_make_next_connection_after(na.get_zone(), true);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK.");
|
||||
return true;
|
||||
}
|
||||
|
@ -1804,6 +1824,35 @@ namespace nodetool
|
|||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::extend_make_next_connection_after(epee::net_utils::zone zone,
|
||||
bool acquire_peers) {
|
||||
if (zone == epee::net_utils::zone::public_ || !m_exclusive_peers.empty())
|
||||
return false;
|
||||
|
||||
auto scaling_factor = 1;
|
||||
if (acquire_peers)
|
||||
scaling_factor = ::config::ACQUIRE_PEERS_RECONNECT_SCALING_FACTOR;
|
||||
|
||||
auto offset = crypto::rand_range<time_t>(::config::RANDOM_CONNECTION_DROP_LOWER / scaling_factor,
|
||||
::config::RANDOM_CONNECTION_DROP_UPPER / scaling_factor) / 1000000;
|
||||
|
||||
if (zone == epee::net_utils::zone::tor)
|
||||
{
|
||||
if (m_make_next_tor_connection_after > time(nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_make_next_tor_connection_after = time(nullptr) + offset;
|
||||
}
|
||||
else if (zone == epee::net_utils::zone::i2p)
|
||||
{
|
||||
return false; // not implemented
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::connections_maker()
|
||||
{
|
||||
using zone_type = epee::net_utils::zone;
|
||||
|
@ -1816,6 +1865,10 @@ namespace nodetool
|
|||
bool one_succeeded = false;
|
||||
for(auto& zone : m_network_zones)
|
||||
{
|
||||
if (zone.first == zone_type::tor && m_make_next_tor_connection_after > time(nullptr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t start_conn_count = get_outgoing_connections_count(zone.second);
|
||||
if(!zone.second.m_peerlist.get_white_peers_count() && !connect_to_seed(zone.first))
|
||||
{
|
||||
|
@ -1827,7 +1880,6 @@ namespace nodetool
|
|||
size_t base_expected_white_connections = (zone.second.m_config.m_net_config.max_out_connection_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
|
||||
|
||||
// carefully avoid `continue` in nested loop
|
||||
|
||||
size_t conn_count = get_outgoing_connections_count(zone.second);
|
||||
while(conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
|
||||
{
|
||||
|
@ -1865,12 +1917,25 @@ namespace nodetool
|
|||
conn_count = new_conn_count;
|
||||
}
|
||||
|
||||
if (start_conn_count == get_outgoing_connections_count(zone.second) && start_conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
|
||||
// max out connections set too high for available peers or connection issue
|
||||
if (get_outgoing_connections_count(zone.second) <= start_conn_count && start_conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
|
||||
{
|
||||
// add check if tor and not yet ready to connecct, if so avoid trying seeds.
|
||||
MINFO("Failed to connect to any, trying seeds");
|
||||
if (!connect_to_seed(zone.first))
|
||||
{
|
||||
// stop signal sent, extend as a precaution
|
||||
extend_make_next_connection_after(zone.first, false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// extend when no connection is made, prevents immediate new connection after peer drop
|
||||
// acquire peers false because usually this will be max connections reached or set too high for available peers
|
||||
// this will make a temporary connection issue worse
|
||||
extend_make_next_connection_after(zone.first, false);
|
||||
|
||||
// this is really stop_signal_not_sent
|
||||
one_succeeded = true;
|
||||
}
|
||||
|
||||
|
@ -2017,6 +2082,43 @@ namespace nodetool
|
|||
m_peerlist_store_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::store_config, this));
|
||||
m_incoming_connections_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::check_incoming_connections, this));
|
||||
m_dns_blocklist_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::update_dns_blocklist, this));
|
||||
if (m_exclusive_peers.empty())
|
||||
m_drop_random_outgoing_tor_connection_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::drop_random_outgoing_tor_connection, this));
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::drop_random_outgoing_tor_connection()
|
||||
{
|
||||
std::vector<p2p_connection_context> outgoing_tor_connections;
|
||||
auto tor_zone = m_network_zones.find(epee::net_utils::zone::tor);
|
||||
|
||||
if (tor_zone != m_network_zones.end()) {
|
||||
tor_zone->second.m_net_server.get_config_object().foreach_connection([&](p2p_connection_context &cntx) {
|
||||
if (!cntx.m_is_income) {
|
||||
outgoing_tor_connections.push_back(cntx);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
for (auto &cntx : outgoing_tor_connections) {
|
||||
if (!cntx.can_broadcast_txs_to_peer) {
|
||||
drop_connection(cntx);
|
||||
// should use random auth for each connection but no socks5
|
||||
// possible to use same circuit twice if drop initiated by remote
|
||||
block_host(cntx.m_remote_address, (::config::DEFAULT_ONION_CIRCUIT_EXPIRY + 1) * 60, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto len = outgoing_tor_connections.size()) {
|
||||
auto index_to_drop = crypto::rand_idx(len);
|
||||
drop_connection(outgoing_tor_connections[index_to_drop]);
|
||||
block_host(outgoing_tor_connections[index_to_drop].m_remote_address,
|
||||
(::config::DEFAULT_ONION_CIRCUIT_EXPIRY + 1) * 60, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
|
|
@ -358,7 +358,7 @@ namespace
|
|||
noise = epee::levin::make_noise_notify(noise_size);
|
||||
epee::net_utils::zone zone = is_public ? epee::net_utils::zone::public_ : epee::net_utils::zone::i2p;
|
||||
receiver_.notifier.reset(
|
||||
new cryptonote::levin::notify{io_service_, connections_, std::move(noise), zone, pad_txs, events_}
|
||||
new cryptonote::levin::notify{io_service_, connections_, std::move(noise), zone, pad_txs, events_, false}
|
||||
);
|
||||
return receiver_.notifier;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue