@@ -280,9 +280,17 @@ struct Peer {
280
280
std::atomic<CAmount> m_fee_filter_received{0 };
281
281
};
282
282
283
+ Mutex m_tx_relay_mutex;
284
+
283
285
/* * Transaction relay data. Will be a nullptr if we're not relaying
284
- * transactions with this peer (e.g. if it's a block-relay-only peer) */
285
- std::unique_ptr<TxRelay> m_tx_relay;
286
+ * transactions with this peer (e.g. if it's a block-relay-only peer).
287
+ * Users should access this with the GetTxRelay() getter. */
288
+ std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY (m_tx_relay_mutex);
289
+
290
+ TxRelay* GetTxRelay ()
291
+ {
292
+ return WITH_LOCK (m_tx_relay_mutex, return m_tx_relay.get ());
293
+ };
286
294
287
295
/* * A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */
288
296
std::vector<CAddress> m_addrs_to_send;
@@ -896,10 +904,11 @@ static void PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& ins
896
904
897
905
static void AddKnownTx (Peer& peer, const uint256& hash)
898
906
{
899
- if (peer.m_tx_relay != nullptr ) {
900
- LOCK (peer.m_tx_relay ->m_tx_inventory_mutex );
901
- peer.m_tx_relay ->m_tx_inventory_known_filter .insert (hash);
902
- }
907
+ auto tx_relay = peer.GetTxRelay ();
908
+ if (!tx_relay) return ;
909
+
910
+ LOCK (tx_relay->m_tx_inventory_mutex );
911
+ tx_relay->m_tx_inventory_known_filter .insert (hash);
903
912
}
904
913
905
914
std::chrono::microseconds PeerManagerImpl::NextInvToInbounds (std::chrono::microseconds now,
@@ -1392,9 +1401,9 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
1392
1401
ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start .load ();
1393
1402
}
1394
1403
1395
- if (peer->m_tx_relay != nullptr ) {
1396
- stats.m_relay_txs = WITH_LOCK (peer-> m_tx_relay -> m_bloom_filter_mutex , return peer-> m_tx_relay ->m_relay_txs );
1397
- stats.m_fee_filter_received = peer-> m_tx_relay ->m_fee_filter_received .load ();
1404
+ if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
1405
+ stats.m_relay_txs = WITH_LOCK (tx_relay-> m_bloom_filter_mutex , return tx_relay ->m_relay_txs );
1406
+ stats.m_fee_filter_received = tx_relay ->m_fee_filter_received .load ();
1398
1407
} else {
1399
1408
stats.m_relay_txs = false ;
1400
1409
stats.m_fee_filter_received = 0 ;
@@ -1810,12 +1819,13 @@ void PeerManagerImpl::RelayTransaction(const uint256& txid, const uint256& wtxid
1810
1819
LOCK (m_peer_mutex);
1811
1820
for (auto & it : m_peer_map) {
1812
1821
Peer& peer = *it.second ;
1813
- if (!peer.m_tx_relay ) continue ;
1822
+ auto tx_relay = peer.GetTxRelay ();
1823
+ if (!tx_relay) continue ;
1814
1824
1815
1825
const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
1816
- LOCK (peer. m_tx_relay ->m_tx_inventory_mutex );
1817
- if (!peer. m_tx_relay ->m_tx_inventory_known_filter .contains (hash)) {
1818
- peer. m_tx_relay ->m_tx_inventory_to_send .insert (hash);
1826
+ LOCK (tx_relay ->m_tx_inventory_mutex );
1827
+ if (!tx_relay ->m_tx_inventory_known_filter .contains (hash)) {
1828
+ tx_relay ->m_tx_inventory_to_send .insert (hash);
1819
1829
}
1820
1830
};
1821
1831
}
@@ -1966,11 +1976,11 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
1966
1976
} else if (inv.IsMsgFilteredBlk ()) {
1967
1977
bool sendMerkleBlock = false ;
1968
1978
CMerkleBlock merkleBlock;
1969
- if (peer.m_tx_relay != nullptr ) {
1970
- LOCK (peer. m_tx_relay ->m_bloom_filter_mutex );
1971
- if (peer. m_tx_relay ->m_bloom_filter ) {
1979
+ if (auto tx_relay = peer.GetTxRelay (); tx_relay != nullptr ) {
1980
+ LOCK (tx_relay ->m_bloom_filter_mutex );
1981
+ if (tx_relay ->m_bloom_filter ) {
1972
1982
sendMerkleBlock = true ;
1973
- merkleBlock = CMerkleBlock (*pblock, *peer. m_tx_relay ->m_bloom_filter );
1983
+ merkleBlock = CMerkleBlock (*pblock, *tx_relay ->m_bloom_filter );
1974
1984
}
1975
1985
}
1976
1986
if (sendMerkleBlock) {
@@ -2053,13 +2063,15 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2053
2063
{
2054
2064
AssertLockNotHeld (cs_main);
2055
2065
2066
+ auto tx_relay = peer.GetTxRelay ();
2067
+
2056
2068
std::deque<CInv>::iterator it = peer.m_getdata_requests .begin ();
2057
2069
std::vector<CInv> vNotFound;
2058
2070
const CNetMsgMaker msgMaker (pfrom.GetCommonVersion ());
2059
2071
2060
2072
const auto now{GetTime<std::chrono::seconds>()};
2061
2073
// Get last mempool request time
2062
- const auto mempool_req = peer. m_tx_relay != nullptr ? peer. m_tx_relay ->m_last_mempool_req .load () : std::chrono::seconds::min ();
2074
+ const auto mempool_req = tx_relay != nullptr ? tx_relay ->m_last_mempool_req .load () : std::chrono::seconds::min ();
2063
2075
2064
2076
// Process as many TX items from the front of the getdata queue as
2065
2077
// possible, since they're common and it's efficient to batch process
@@ -2072,7 +2084,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2072
2084
2073
2085
const CInv &inv = *it++;
2074
2086
2075
- if (peer. m_tx_relay == nullptr ) {
2087
+ if (tx_relay == nullptr ) {
2076
2088
// Ignore GETDATA requests for transactions from blocks-only peers.
2077
2089
continue ;
2078
2090
}
@@ -2100,7 +2112,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2100
2112
}
2101
2113
for (const uint256& parent_txid : parent_ids_to_add) {
2102
2114
// Relaying a transaction with a recent but unconfirmed parent.
2103
- if (WITH_LOCK (peer. m_tx_relay ->m_tx_inventory_mutex , return !peer. m_tx_relay ->m_tx_inventory_known_filter .contains (parent_txid))) {
2115
+ if (WITH_LOCK (tx_relay ->m_tx_inventory_mutex , return !tx_relay ->m_tx_inventory_known_filter .contains (parent_txid))) {
2104
2116
LOCK (cs_main);
2105
2117
State (pfrom.GetId ())->m_recently_announced_invs .insert (parent_txid);
2106
2118
}
@@ -2736,10 +2748,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
2736
2748
// set nodes not capable of serving the complete blockchain history as "limited nodes"
2737
2749
pfrom.m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
2738
2750
2739
- if (peer->m_tx_relay != nullptr ) {
2751
+ if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
2740
2752
{
2741
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
2742
- peer-> m_tx_relay ->m_relay_txs = fRelay ; // set to true after we get the first filter* message
2753
+ LOCK (tx_relay ->m_bloom_filter_mutex );
2754
+ tx_relay ->m_relay_txs = fRelay ; // set to true after we get the first filter* message
2743
2755
}
2744
2756
if (fRelay ) pfrom.m_relays_txs = true ;
2745
2757
}
@@ -3069,7 +3081,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3069
3081
3070
3082
// Reject tx INVs when the -blocksonly setting is enabled, or this is a
3071
3083
// block-relay-only peer
3072
- bool reject_tx_invs{m_ignore_incoming_txs || (peer->m_tx_relay == nullptr )};
3084
+ bool reject_tx_invs{m_ignore_incoming_txs || (peer->GetTxRelay () == nullptr )};
3073
3085
3074
3086
// Allow peers with relay permission to send data other than blocks in blocks only mode
3075
3087
if (pfrom.HasPermission (NetPermissionFlags::Relay)) {
@@ -3346,7 +3358,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3346
3358
// Stop processing the transaction early if
3347
3359
// 1) We are in blocks only mode and peer has no relay permission
3348
3360
// 2) This peer is a block-relay-only peer
3349
- if ((m_ignore_incoming_txs && !pfrom.HasPermission (NetPermissionFlags::Relay)) || (peer->m_tx_relay == nullptr )) {
3361
+ if ((m_ignore_incoming_txs && !pfrom.HasPermission (NetPermissionFlags::Relay)) || (peer->GetTxRelay () == nullptr )) {
3350
3362
LogPrint (BCLog::NET, " transaction sent in violation of protocol peer=%d\n " , pfrom.GetId ());
3351
3363
pfrom.fDisconnect = true ;
3352
3364
return ;
@@ -3958,9 +3970,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3958
3970
return ;
3959
3971
}
3960
3972
3961
- if (peer->m_tx_relay != nullptr ) {
3962
- LOCK (peer-> m_tx_relay ->m_tx_inventory_mutex );
3963
- peer-> m_tx_relay ->m_send_mempool = true ;
3973
+ if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
3974
+ LOCK (tx_relay ->m_tx_inventory_mutex );
3975
+ tx_relay ->m_send_mempool = true ;
3964
3976
}
3965
3977
return ;
3966
3978
}
@@ -4053,16 +4065,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4053
4065
{
4054
4066
// There is no excuse for sending a too-large filter
4055
4067
Misbehaving (pfrom.GetId (), 100 , " too-large bloom filter" );
4056
- }
4057
- else if (peer->m_tx_relay != nullptr )
4058
- {
4068
+ } else if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
4059
4069
{
4060
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
4061
- peer-> m_tx_relay ->m_bloom_filter .reset (new CBloomFilter (filter));
4062
- peer-> m_tx_relay ->m_relay_txs = true ;
4070
+ LOCK (tx_relay ->m_bloom_filter_mutex );
4071
+ tx_relay ->m_bloom_filter .reset (new CBloomFilter (filter));
4072
+ tx_relay ->m_relay_txs = true ;
4063
4073
}
4064
4074
pfrom.m_bloom_filter_loaded = true ;
4065
- pfrom.m_relays_txs = true ;
4066
4075
}
4067
4076
return ;
4068
4077
}
@@ -4081,10 +4090,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4081
4090
bool bad = false ;
4082
4091
if (vData.size () > MAX_SCRIPT_ELEMENT_SIZE) {
4083
4092
bad = true ;
4084
- } else if (peer->m_tx_relay != nullptr ) {
4085
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
4086
- if (peer-> m_tx_relay ->m_bloom_filter ) {
4087
- peer-> m_tx_relay ->m_bloom_filter ->insert (vData);
4093
+ } else if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
4094
+ LOCK (tx_relay ->m_bloom_filter_mutex );
4095
+ if (tx_relay ->m_bloom_filter ) {
4096
+ tx_relay ->m_bloom_filter ->insert (vData);
4088
4097
} else {
4089
4098
bad = true ;
4090
4099
}
@@ -4101,14 +4110,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4101
4110
pfrom.fDisconnect = true ;
4102
4111
return ;
4103
4112
}
4104
- if (peer->m_tx_relay == nullptr ) {
4105
- return ;
4106
- }
4113
+ auto tx_relay = peer->GetTxRelay ();
4114
+ if (!tx_relay) return ;
4107
4115
4108
4116
{
4109
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
4110
- peer-> m_tx_relay ->m_bloom_filter = nullptr ;
4111
- peer-> m_tx_relay ->m_relay_txs = true ;
4117
+ LOCK (tx_relay ->m_bloom_filter_mutex );
4118
+ tx_relay ->m_bloom_filter = nullptr ;
4119
+ tx_relay ->m_relay_txs = true ;
4112
4120
}
4113
4121
pfrom.m_bloom_filter_loaded = false ;
4114
4122
pfrom.m_relays_txs = true ;
@@ -4119,8 +4127,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4119
4127
CAmount newFeeFilter = 0 ;
4120
4128
vRecv >> newFeeFilter;
4121
4129
if (MoneyRange (newFeeFilter)) {
4122
- if (peer->m_tx_relay != nullptr ) {
4123
- peer-> m_tx_relay ->m_fee_filter_received = newFeeFilter;
4130
+ if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
4131
+ tx_relay ->m_fee_filter_received = newFeeFilter;
4124
4132
}
4125
4133
LogPrint (BCLog::NET, " received: feefilter of %s from peer=%d\n " , CFeeRate (newFeeFilter).ToString (), pfrom.GetId ());
4126
4134
}
@@ -4885,72 +4893,72 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
4885
4893
peer->m_blocks_for_inv_relay .clear ();
4886
4894
}
4887
4895
4888
- if (peer->m_tx_relay != nullptr ) {
4889
- LOCK (peer-> m_tx_relay ->m_tx_inventory_mutex );
4896
+ if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
4897
+ LOCK (tx_relay ->m_tx_inventory_mutex );
4890
4898
// Check whether periodic sends should happen
4891
4899
bool fSendTrickle = pto->HasPermission (NetPermissionFlags::NoBan);
4892
- if (peer-> m_tx_relay ->m_next_inv_send_time < current_time) {
4900
+ if (tx_relay ->m_next_inv_send_time < current_time) {
4893
4901
fSendTrickle = true ;
4894
4902
if (pto->IsInboundConn ()) {
4895
- peer-> m_tx_relay ->m_next_inv_send_time = NextInvToInbounds (current_time, INBOUND_INVENTORY_BROADCAST_INTERVAL);
4903
+ tx_relay ->m_next_inv_send_time = NextInvToInbounds (current_time, INBOUND_INVENTORY_BROADCAST_INTERVAL);
4896
4904
} else {
4897
- peer-> m_tx_relay ->m_next_inv_send_time = GetExponentialRand (current_time, OUTBOUND_INVENTORY_BROADCAST_INTERVAL);
4905
+ tx_relay ->m_next_inv_send_time = GetExponentialRand (current_time, OUTBOUND_INVENTORY_BROADCAST_INTERVAL);
4898
4906
}
4899
4907
}
4900
4908
4901
4909
// Time to send but the peer has requested we not relay transactions.
4902
4910
if (fSendTrickle ) {
4903
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
4904
- if (!peer-> m_tx_relay -> m_relay_txs ) peer-> m_tx_relay ->m_tx_inventory_to_send .clear ();
4911
+ LOCK (tx_relay ->m_bloom_filter_mutex );
4912
+ if (!tx_relay-> m_relay_txs ) tx_relay ->m_tx_inventory_to_send .clear ();
4905
4913
}
4906
4914
4907
4915
// Respond to BIP35 mempool requests
4908
- if (fSendTrickle && peer-> m_tx_relay ->m_send_mempool ) {
4916
+ if (fSendTrickle && tx_relay ->m_send_mempool ) {
4909
4917
auto vtxinfo = m_mempool.infoAll ();
4910
- peer-> m_tx_relay ->m_send_mempool = false ;
4911
- const CFeeRate filterrate{peer-> m_tx_relay ->m_fee_filter_received .load ()};
4918
+ tx_relay ->m_send_mempool = false ;
4919
+ const CFeeRate filterrate{tx_relay ->m_fee_filter_received .load ()};
4912
4920
4913
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
4921
+ LOCK (tx_relay ->m_bloom_filter_mutex );
4914
4922
4915
4923
for (const auto & txinfo : vtxinfo) {
4916
4924
const uint256& hash = peer->m_wtxid_relay ? txinfo.tx ->GetWitnessHash () : txinfo.tx ->GetHash ();
4917
4925
CInv inv (peer->m_wtxid_relay ? MSG_WTX : MSG_TX, hash);
4918
- peer-> m_tx_relay ->m_tx_inventory_to_send .erase (hash);
4926
+ tx_relay ->m_tx_inventory_to_send .erase (hash);
4919
4927
// Don't send transactions that peers will not put into their mempool
4920
4928
if (txinfo.fee < filterrate.GetFee (txinfo.vsize )) {
4921
4929
continue ;
4922
4930
}
4923
- if (peer-> m_tx_relay ->m_bloom_filter ) {
4924
- if (!peer-> m_tx_relay ->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
4931
+ if (tx_relay ->m_bloom_filter ) {
4932
+ if (!tx_relay ->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
4925
4933
}
4926
- peer-> m_tx_relay ->m_tx_inventory_known_filter .insert (hash);
4934
+ tx_relay ->m_tx_inventory_known_filter .insert (hash);
4927
4935
// Responses to MEMPOOL requests bypass the m_recently_announced_invs filter.
4928
4936
vInv.push_back (inv);
4929
4937
if (vInv.size () == MAX_INV_SZ) {
4930
4938
m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
4931
4939
vInv.clear ();
4932
4940
}
4933
4941
}
4934
- peer-> m_tx_relay ->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
4942
+ tx_relay ->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
4935
4943
}
4936
4944
4937
4945
// Determine transactions to relay
4938
4946
if (fSendTrickle ) {
4939
4947
// Produce a vector with all candidates for sending
4940
4948
std::vector<std::set<uint256>::iterator> vInvTx;
4941
- vInvTx.reserve (peer-> m_tx_relay ->m_tx_inventory_to_send .size ());
4942
- for (std::set<uint256>::iterator it = peer-> m_tx_relay -> m_tx_inventory_to_send .begin (); it != peer-> m_tx_relay ->m_tx_inventory_to_send .end (); it++) {
4949
+ vInvTx.reserve (tx_relay ->m_tx_inventory_to_send .size ());
4950
+ for (std::set<uint256>::iterator it = tx_relay-> m_tx_inventory_to_send .begin (); it != tx_relay ->m_tx_inventory_to_send .end (); it++) {
4943
4951
vInvTx.push_back (it);
4944
4952
}
4945
- const CFeeRate filterrate{peer-> m_tx_relay ->m_fee_filter_received .load ()};
4953
+ const CFeeRate filterrate{tx_relay ->m_fee_filter_received .load ()};
4946
4954
// Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
4947
4955
// A heap is used so that not all items need sorting if only a few are being sent.
4948
4956
CompareInvMempoolOrder compareInvMempoolOrder (&m_mempool, peer->m_wtxid_relay );
4949
4957
std::make_heap (vInvTx.begin (), vInvTx.end (), compareInvMempoolOrder);
4950
4958
// No reason to drain out at many times the network's capacity,
4951
4959
// especially since we have many peers and some will draw much shorter delays.
4952
4960
unsigned int nRelayedTransactions = 0 ;
4953
- LOCK (peer-> m_tx_relay ->m_bloom_filter_mutex );
4961
+ LOCK (tx_relay ->m_bloom_filter_mutex );
4954
4962
while (!vInvTx.empty () && nRelayedTransactions < INVENTORY_BROADCAST_MAX) {
4955
4963
// Fetch the top element from the heap
4956
4964
std::pop_heap (vInvTx.begin (), vInvTx.end (), compareInvMempoolOrder);
@@ -4959,9 +4967,9 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
4959
4967
uint256 hash = *it;
4960
4968
CInv inv (peer->m_wtxid_relay ? MSG_WTX : MSG_TX, hash);
4961
4969
// Remove it from the to-be-sent set
4962
- peer-> m_tx_relay ->m_tx_inventory_to_send .erase (it);
4970
+ tx_relay ->m_tx_inventory_to_send .erase (it);
4963
4971
// Check if not in the filter already
4964
- if (peer-> m_tx_relay ->m_tx_inventory_known_filter .contains (hash)) {
4972
+ if (tx_relay ->m_tx_inventory_known_filter .contains (hash)) {
4965
4973
continue ;
4966
4974
}
4967
4975
// Not in the mempool anymore? don't bother sending it.
@@ -4975,7 +4983,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
4975
4983
if (txinfo.fee < filterrate.GetFee (txinfo.vsize )) {
4976
4984
continue ;
4977
4985
}
4978
- if (peer-> m_tx_relay -> m_bloom_filter && !peer-> m_tx_relay ->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
4986
+ if (tx_relay-> m_bloom_filter && !tx_relay ->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
4979
4987
// Send
4980
4988
State (pto->GetId ())->m_recently_announced_invs .insert (hash);
4981
4989
vInv.push_back (inv);
@@ -5002,14 +5010,14 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5002
5010
m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
5003
5011
vInv.clear ();
5004
5012
}
5005
- peer-> m_tx_relay ->m_tx_inventory_known_filter .insert (hash);
5013
+ tx_relay ->m_tx_inventory_known_filter .insert (hash);
5006
5014
if (hash != txid) {
5007
5015
// Insert txid into m_tx_inventory_known_filter, even for
5008
5016
// wtxidrelay peers. This prevents re-adding of
5009
5017
// unconfirmed parents to the recently_announced
5010
5018
// filter, when a child tx is requested. See
5011
5019
// ProcessGetData().
5012
- peer-> m_tx_relay ->m_tx_inventory_known_filter .insert (txid);
5020
+ tx_relay ->m_tx_inventory_known_filter .insert (txid);
5013
5021
}
5014
5022
}
5015
5023
}
0 commit comments