Skip to content

Commit 090ae92

Browse files
refactor: move CInstantSendManager::AskNodesForLockedTx into PeerManager
**This does change the logic!** We no longer prioritize asking MNs. This is probably fine? I don't specifically recall why we wanted to ask MNs besides potentially that they may be higher performing or better connected? We can potentially restore this logic once we bring masternode connection logic into Peer Does also change logic, by short-circuiting once peersToAsk is full. This commit has the added benefit of reducing contention on m_nodes_mutex due to no-longer calling connman.ForEachNode not once but twice This may slightly increase contention on m_peer_mutex; but that should be an ok tradeoff for not only removing dependencies, but also reducing contention on a much more contested RecursiveMutex
1 parent 69995ee commit 090ae92

File tree

5 files changed

+70
-54
lines changed

5 files changed

+70
-54
lines changed

src/llmq/context.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CConnman& connman, CDeterm
4646
isman{[&]() -> llmq::CInstantSendManager* const {
4747
assert(llmq::quorumInstantSendManager == nullptr);
4848
llmq::quorumInstantSendManager = std::make_unique<llmq::CInstantSendManager>(*llmq::chainLocksHandler,
49-
chainman.ActiveChainstate(),
50-
connman, *qman, *sigman, *shareman,
51-
sporkman, mempool, mn_sync, peerman,
49+
chainman.ActiveChainstate(), *qman,
50+
*sigman, *shareman, sporkman,
51+
mempool, mn_sync, peerman,
5252
is_masternode, unit_tests, wipe);
5353
return llmq::quorumInstantSendManager.get();
5454
}()},

src/llmq/instantsend.cpp

+2-42
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has
10471047
// bump mempool counter to make sure newly locked txes are picked up by getblocktemplate
10481048
mempool.AddTransactionsUpdated(1);
10491049
} else {
1050-
AskNodesForLockedTx(islock->txid, connman, *m_peerman, m_is_masternode);
1050+
m_peerman->AskPeersForTransaction(islock->txid, m_is_masternode);
10511051
}
10521052
}
10531053

@@ -1321,7 +1321,7 @@ void CInstantSendManager::RemoveMempoolConflictsForLock(const uint256& hash, con
13211321
for (const auto& p : toDelete) {
13221322
RemoveConflictedTx(*p.second);
13231323
}
1324-
AskNodesForLockedTx(islock.txid, connman, *m_peerman, m_is_masternode);
1324+
m_peerman->AskPeersForTransaction(islock.txid, m_is_masternode);
13251325
}
13261326
}
13271327

@@ -1426,46 +1426,6 @@ void CInstantSendManager::RemoveConflictingLock(const uint256& islockHash, const
14261426
}
14271427
}
14281428

1429-
void CInstantSendManager::AskNodesForLockedTx(const uint256& txid, const CConnman& connman, PeerManager& peerman,
1430-
bool is_masternode)
1431-
{
1432-
std::vector<CNode*> nodesToAskFor;
1433-
nodesToAskFor.reserve(4);
1434-
1435-
auto maybe_add_to_nodesToAskFor = [&peerman, &nodesToAskFor, &txid](CNode* pnode) {
1436-
if (nodesToAskFor.size() >= 4) {
1437-
return;
1438-
}
1439-
if (peerman.IsInvInFilter(pnode->GetId(), txid)) {
1440-
pnode->AddRef();
1441-
nodesToAskFor.emplace_back(pnode);
1442-
}
1443-
};
1444-
1445-
connman.ForEachNode([&](CNode* pnode) {
1446-
// Check masternodes first
1447-
if (pnode->m_masternode_connection) maybe_add_to_nodesToAskFor(pnode);
1448-
});
1449-
connman.ForEachNode([&](CNode* pnode) {
1450-
// Check non-masternodes next
1451-
if (!pnode->m_masternode_connection) maybe_add_to_nodesToAskFor(pnode);
1452-
});
1453-
{
1454-
LOCK(cs_main);
1455-
for (const CNode* pnode : nodesToAskFor) {
1456-
LogPrintf("CInstantSendManager::%s -- txid=%s: asking other peer %d for correct TX\n", __func__,
1457-
txid.ToString(), pnode->GetId());
1458-
1459-
CInv inv(MSG_TX, txid);
1460-
peerman.RequestObject(pnode->GetId(), inv, GetTime<std::chrono::microseconds>(), is_masternode,
1461-
/* fForce = */ true);
1462-
}
1463-
}
1464-
for (CNode* pnode : nodesToAskFor) {
1465-
pnode->Release();
1466-
}
1467-
}
1468-
14691429
void CInstantSendManager::ProcessPendingRetryLockTxs()
14701430
{
14711431
const auto retryTxs = WITH_LOCK(cs_pendingRetry, return pendingRetryTxs);

src/llmq/instantsend.h

+14-8
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ class CInstantSendManager : public CRecoveredSigsListener
199199

200200
CChainLocksHandler& clhandler;
201201
CChainState& m_chainstate;
202-
CConnman& connman;
203202
CQuorumManager& qman;
204203
CSigningManager& sigman;
205204
CSigSharesManager& shareman;
@@ -254,13 +253,21 @@ class CInstantSendManager : public CRecoveredSigsListener
254253
std::unordered_set<uint256, StaticSaltedHasher> pendingRetryTxs GUARDED_BY(cs_pendingRetry);
255254

256255
public:
257-
explicit CInstantSendManager(CChainLocksHandler& _clhandler, CChainState& chainstate, CConnman& _connman,
258-
CQuorumManager& _qman, CSigningManager& _sigman, CSigSharesManager& _shareman,
259-
CSporkManager& sporkman, CTxMemPool& _mempool, const CMasternodeSync& mn_sync,
260-
const std::unique_ptr<PeerManager>& peerman, bool is_masternode, bool unitTests, bool fWipe) :
256+
explicit CInstantSendManager(CChainLocksHandler& _clhandler, CChainState& chainstate, CQuorumManager& _qman,
257+
CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkman,
258+
CTxMemPool& _mempool, const CMasternodeSync& mn_sync,
259+
const std::unique_ptr<PeerManager>& peerman, bool is_masternode, bool unitTests,
260+
bool fWipe) :
261261
db(unitTests, fWipe),
262-
clhandler(_clhandler), m_chainstate(chainstate), connman(_connman), qman(_qman), sigman(_sigman),
263-
shareman(_shareman), spork_manager(sporkman), mempool(_mempool), m_mn_sync(mn_sync), m_peerman(peerman),
262+
clhandler(_clhandler),
263+
m_chainstate(chainstate),
264+
qman(_qman),
265+
sigman(_sigman),
266+
shareman(_shareman),
267+
spork_manager(sporkman),
268+
mempool(_mempool),
269+
m_mn_sync(mn_sync),
270+
m_peerman(peerman),
264271
m_is_masternode{is_masternode}
265272
{
266273
workInterrupt.reset();
@@ -314,7 +321,6 @@ class CInstantSendManager : public CRecoveredSigsListener
314321
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
315322
void ResolveBlockConflicts(const uint256& islockHash, const CInstantSendLock& islock)
316323
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
317-
static void AskNodesForLockedTx(const uint256& txid, const CConnman& connman, PeerManager& peerman, bool is_masternode);
318324
void ProcessPendingRetryLockTxs()
319325
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
320326

src/net_processing.cpp

+48-1
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ class PeerManagerImpl final : public PeerManager
619619
bool is_masternode, bool fForce = false) override EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
620620
size_t GetRequestedObjectCount(NodeId nodeid) const override EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
621621
bool IsInvInFilter(NodeId nodeid, const uint256& hash) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
622-
622+
void AskPeersForTransaction(const uint256& txid, bool is_masternode) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
623623
private:
624624
/** Helpers to process result of external handlers of message */
625625
void ProcessPeerMsgRet(const PeerMsgRet& ret, CNode& pfrom) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
@@ -634,6 +634,11 @@ class PeerManagerImpl final : public PeerManager
634634
/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
635635
void ReattemptInitialBroadcast(CScheduler& scheduler) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
636636

637+
/**
638+
* Private implementation of IsInvInFilter which does not call GetPeerRef; to be prefered when the PeerRef is available.
639+
*/
640+
bool IsInvInFilter(const PeerRef& peer, const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
641+
637642
/** Get a shared pointer to the Peer object.
638643
* May return an empty shared_ptr if the Peer object can't be found. */
639644
PeerRef GetPeerRef(NodeId id) const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
@@ -2242,9 +2247,51 @@ void PeerManagerImpl::SendPings()
22422247
for(auto& it : m_peer_map) it.second->m_ping_queued = true;
22432248
}
22442249

2250+
void PeerManagerImpl::AskPeersForTransaction(const uint256& txid, bool is_masternode)
2251+
{
2252+
std::vector<PeerRef> peersToAsk;
2253+
peersToAsk.reserve(4);
2254+
2255+
auto maybe_add_to_nodesToAskFor = [&](const PeerRef& peer) {
2256+
if (peersToAsk.size() >= 4) {
2257+
return false;
2258+
}
2259+
if (IsInvInFilter(peer, txid)) {
2260+
peersToAsk.emplace_back(peer);
2261+
}
2262+
return true;
2263+
};
2264+
2265+
{
2266+
LOCK(m_peer_mutex);
2267+
// TODO consider prioritizing MNs again, once that flag is moved into Peer
2268+
for (const auto& [_, peer] : m_peer_map) {
2269+
if (!maybe_add_to_nodesToAskFor(peer)) {
2270+
break;
2271+
}
2272+
}
2273+
}
2274+
{
2275+
CInv inv(MSG_TX, txid);
2276+
LOCK(cs_main);
2277+
for (PeerRef& peer : peersToAsk) {
2278+
LogPrintf("PeerManagerImpl::%s -- txid=%s: asking other peer %d for correct TX\n", __func__,
2279+
txid.ToString(), peer->m_id);
2280+
2281+
RequestObject(peer->m_id, inv, GetTime<std::chrono::microseconds>(), is_masternode,
2282+
/*fForce=*/true);
2283+
}
2284+
}
2285+
}
2286+
22452287
bool PeerManagerImpl::IsInvInFilter(NodeId nodeid, const uint256& hash) const
22462288
{
22472289
PeerRef peer = GetPeerRef(nodeid);
2290+
return IsInvInFilter(peer, hash);
2291+
}
2292+
2293+
bool PeerManagerImpl::IsInvInFilter(const PeerRef& peer, const uint256& hash) const
2294+
{
22482295
if (peer == nullptr)
22492296
return false;
22502297
if (auto tx_relay = peer->GetTxRelay(); tx_relay != nullptr) {

src/net_processing.h

+3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ class PeerManager : public CValidationInterface, public NetEventsInterface
9090
/** Is an inventory in the known inventory filter. Used by InstantSend. */
9191
virtual bool IsInvInFilter(NodeId nodeid, const uint256& hash) const = 0;
9292

93+
/** Ask a number of our peers, which have a transaction in their inventory, for the transaction. */
94+
virtual void AskPeersForTransaction(const uint256& txid, bool is_masternode) = 0;
95+
9396
/** Broadcast inventory message to a specific peer. */
9497
virtual void PushInventory(NodeId nodeid, const CInv& inv) = 0;
9598

0 commit comments

Comments
 (0)