Skip to content

Commit 9acac8d

Browse files
committed
tx-relay-v2: add maximum in_flight requests for each connection
1 parent ac4296c commit 9acac8d

File tree

5 files changed

+47
-11
lines changed

5 files changed

+47
-11
lines changed

src/cryptonote_basic/connection_context.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ namespace cryptonote
129129
void cryptonote_connection_context::add_requested_from_peer()
130130
{
131131
epee::write_lock w_lock(m_connection_stats->mutex);
132+
add_in_flight_requests();
132133
++m_connection_stats->requested_from_peer;
133134
}
134135

@@ -138,6 +139,25 @@ namespace cryptonote
138139
++m_connection_stats->sent;
139140
}
140141

142+
void cryptonote_connection_context::add_in_flight_requests()
143+
{
144+
epee::write_lock w_lock(m_connection_stats->mutex);
145+
++m_connection_stats->in_flight_requests;
146+
}
147+
148+
void cryptonote_connection_context::remove_in_flight_request()
149+
{
150+
epee::write_lock w_lock(m_connection_stats->mutex);
151+
if (m_connection_stats->in_flight_requests > 0)
152+
--m_connection_stats->in_flight_requests;
153+
}
154+
155+
bool cryptonote_connection_context::can_process_additional_request(size_t requests)
156+
{
157+
epee::read_lock r_lock(m_connection_stats->mutex);
158+
return (m_connection_stats->in_flight_requests + requests) < P2P_MAX_IN_FLIGHT_REQUESTS;
159+
}
160+
141161
size_t cryptonote_connection_context::get_announcement_size() const
142162
{
143163
epee::read_lock r_lock(m_connection_stats->mutex);
@@ -184,6 +204,12 @@ namespace cryptonote
184204
return m_connection_stats->missed;
185205
}
186206

207+
size_t cryptonote_connection_context::get_in_flight_requests() const
208+
{
209+
epee::read_lock r_lock(m_connection_stats->mutex);
210+
return m_connection_stats->in_flight_requests;
211+
}
212+
187213
std::string cryptonote_connection_context::get_info() const
188214
{
189215
epee::read_lock r_lock(m_connection_stats->mutex);

src/cryptonote_basic/connection_context.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ namespace cryptonote
131131
size_t requested_from_peer = 0;
132132
size_t sent = 0;
133133
size_t missed = 0;
134+
size_t in_flight_requests = 0;
134135
};
135136
std::shared_ptr<connection_statistics> m_connection_stats;
136137

@@ -141,6 +142,9 @@ namespace cryptonote
141142
void add_requested_from_me();
142143
void add_requested_from_peer();
143144
void add_sent();
145+
void add_in_flight_requests();
146+
void remove_in_flight_request();
147+
bool can_process_additional_request(size_t requests = 1);
144148

145149
size_t get_announcement_size() const;
146150
size_t get_received() const;
@@ -149,6 +153,7 @@ namespace cryptonote
149153
size_t get_sent() const;
150154
size_t get_total() const;
151155
size_t get_missed() const;
156+
size_t get_in_flight_requests() const;
152157
std::string get_info() const;
153158
bool missed_announced_tx(const crypto::hash &tx_hash);
154159
};

src/cryptonote_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#define P2P_DEFAULT_LIMIT_RATE_UP 8192 // kB/s
154154
#define P2P_DEFAULT_LIMIT_RATE_DOWN 32768 // kB/s
155155
#define P2P_REQUEST_FAILURE_THRESHOLD_PERCENTAGE 70 // if more than 70% of requests fail, the peer is dropped
156+
#define P2P_MAX_IN_FLIGHT_REQUESTS 100
156157

157158
#define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour
158159
#define P2P_IP_BLOCKTIME (60*60*24) //24 hour

src/cryptonote_protocol/cryptonote_protocol_handler.inl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,13 +904,17 @@ namespace cryptonote
904904
// Iterate over each advertised transaction hash and check our pool and our requested tracker.
905905
for (const auto &tx_hash : arg.t)
906906
{
907+
if (!context.can_process_additional_request())
908+
{
909+
LOG_ERROR_CCONTEXT("Too many in-flight requests, cannot accept");
910+
break;
911+
}
907912
// If we have the tx in our pool, also remove it from request manager and skip.
908913
if (m_core.pool_has_tx(tx_hash))
909914
{
910915
m_request_manager.remove_transaction(tx_hash);
911916
continue;
912917
}
913-
914918
bool need_request = m_request_manager.add_transaction(tx_hash, context.m_connection_id, now);
915919
context.add_announcement(tx_hash);
916920
if (need_request) {
@@ -1043,6 +1047,7 @@ namespace cryptonote
10431047
&& m_request_manager.already_requested_tx(tx_hash))
10441048
{
10451049
m_request_manager.remove_transaction(tx_hash);
1050+
context.remove_in_flight_request();
10461051
}
10471052
}
10481053

src/cryptonote_protocol/txrequestqueue.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
/**
4848
* \brief A queue of requests. The front of the queue shows the current request.
4949
*
50-
* This queue holds peers that have the requested transaction and keeps
50+
* This queue holds peers that have announced the transaction and keeps
5151
* track of the time the last request was made. It provides capabilities
5252
* to add a new peer and to retrieve the next peer that hasn't been requested.
5353
*/
@@ -72,8 +72,14 @@ class tx_request_queue {
7272
public:
7373
struct order {
7474
bool operator()(const tx_request &lhs, const tx_request &rhs) const {
75-
return lhs.from_connection_id != rhs.from_connection_id &&
76-
lhs.first_seen < rhs.first_seen;
75+
if (lhs.get_connection_id() == rhs.get_connection_id())
76+
return false; // same peer => equivalent (disallow duplicates)
77+
if (lhs.get_first_seen() < rhs.get_first_seen())
78+
return true;
79+
if (rhs.get_first_seen() < lhs.get_first_seen())
80+
return false;
81+
// tie-break to maintain strict weak ordering when first_seen is equal
82+
return lhs.get_connection_id() < rhs.get_connection_id();
7783
}
7884
};
7985

@@ -84,13 +90,6 @@ class tx_request_queue {
8490
: from_connection_id(other.from_connection_id),
8591
first_seen(other.first_seen), request_time(other.request_time) {}
8692

87-
bool operator==(const tx_request &other) const {
88-
return from_connection_id == other.get_connection_id();
89-
}
90-
bool operator!=(const tx_request &other) const {
91-
return from_connection_id != other.get_connection_id();
92-
}
93-
9493
const boost::uuids::uuid &get_connection_id() const {
9594
return from_connection_id;
9695
}

0 commit comments

Comments
 (0)