Skip to content

Commit df6cc76

Browse files
feat: rework message processing in CNode to prioritize quorum messages
This update introduces a new queue for quorum-priority messages, allowing for better handling of critical network messages. The `MarkReceivedMsgsForProcessing` function now classifies incoming messages into quorum and normal queues, while the `PollMessage` function prioritizes messages from the quorum queue when available. This change enhances the efficiency of message processing and ensures that important messages are handled promptly.
1 parent d56bff5 commit df6cc76

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

src/net.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4652,31 +4652,62 @@ void CNode::MarkReceivedMsgsForProcessing()
46524652
{
46534653
AssertLockNotHeld(m_msg_process_queue_mutex);
46544654

4655-
size_t nSizeAdded = 0;
4656-
for (const auto& msg : vRecvMsg) {
4655+
size_t nQuorumSizeAdded = 0;
4656+
size_t nNormalSizeAdded = 0;
4657+
std::list<CNetMessage> quorumMsgs;
4658+
std::list<CNetMessage> normalMsgs;
4659+
4660+
// Classify messages into quorum-priority and normal queues
4661+
for (auto it = vRecvMsg.begin(); it != vRecvMsg.end();) {
4662+
auto& msg = *it;
46574663
// vRecvMsg contains only completed CNetMessage
46584664
// the single possible partially deserialized message are held by TransportDeserializer
4659-
nSizeAdded += msg.m_raw_message_size;
4665+
if (IsQuorumPriorityMessage(msg.m_type)) {
4666+
quorumMsgs.splice(quorumMsgs.end(), vRecvMsg, it++);
4667+
nQuorumSizeAdded += msg.m_raw_message_size;
4668+
} else {
4669+
normalMsgs.splice(normalMsgs.end(), vRecvMsg, it++);
4670+
nNormalSizeAdded += msg.m_raw_message_size;
4671+
}
46604672
}
46614673

46624674
LOCK(m_msg_process_queue_mutex);
4663-
m_msg_process_queue.splice(m_msg_process_queue.end(), vRecvMsg);
4664-
m_msg_process_queue_size += nSizeAdded;
4665-
fPauseRecv = m_msg_process_queue_size > m_recv_flood_size;
4675+
// Splice classified messages into appropriate queues
4676+
m_msg_quorum_queue.splice(m_msg_quorum_queue.end(), quorumMsgs);
4677+
m_msg_quorum_queue_size += nQuorumSizeAdded;
4678+
m_msg_process_queue.splice(m_msg_process_queue.end(), normalMsgs);
4679+
m_msg_process_queue_size += nNormalSizeAdded;
4680+
// Compute backpressure over combined size of both queues
4681+
fPauseRecv = (m_msg_quorum_queue_size + m_msg_process_queue_size) > m_recv_flood_size;
46664682
}
46674683

46684684
std::optional<std::pair<CNetMessage, bool>> CNode::PollMessage()
46694685
{
46704686
LOCK(m_msg_process_queue_mutex);
4687+
4688+
// Prioritize quorum queue: pop from it first if non-empty
4689+
if (!m_msg_quorum_queue.empty()) {
4690+
std::list<CNetMessage> msgs;
4691+
// Just take one message from quorum queue
4692+
msgs.splice(msgs.begin(), m_msg_quorum_queue, m_msg_quorum_queue.begin());
4693+
m_msg_quorum_queue_size -= msgs.front().m_raw_message_size;
4694+
// Compute backpressure over combined size of both queues
4695+
fPauseRecv = (m_msg_quorum_queue_size + m_msg_process_queue_size) > m_recv_flood_size;
4696+
// Return true for 'more' if either queue has remaining messages
4697+
return std::make_pair(std::move(msgs.front()), !m_msg_quorum_queue.empty() || !m_msg_process_queue.empty());
4698+
}
4699+
4700+
// Fall back to normal queue if quorum queue is empty
46714701
if (m_msg_process_queue.empty()) return std::nullopt;
46724702

46734703
std::list<CNetMessage> msgs;
46744704
// Just take one message
46754705
msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
46764706
m_msg_process_queue_size -= msgs.front().m_raw_message_size;
4677-
fPauseRecv = m_msg_process_queue_size > m_recv_flood_size;
4707+
// Compute backpressure over combined size of both queues
4708+
fPauseRecv = (m_msg_quorum_queue_size + m_msg_process_queue_size) > m_recv_flood_size;
46784709

4679-
return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
4710+
return std::make_pair(std::move(msgs.front()), !m_msg_quorum_queue.empty() || !m_msg_process_queue.empty());
46804711
}
46814712

46824713
bool CConnman::NodeFullyConnected(const CNode* pnode)

src/net.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,8 @@ class CNode
10941094
Mutex m_msg_process_queue_mutex;
10951095
std::list<CNetMessage> m_msg_process_queue GUARDED_BY(m_msg_process_queue_mutex);
10961096
size_t m_msg_process_queue_size GUARDED_BY(m_msg_process_queue_mutex){0};
1097+
std::list<CNetMessage> m_msg_quorum_queue GUARDED_BY(m_msg_process_queue_mutex);
1098+
size_t m_msg_quorum_queue_size GUARDED_BY(m_msg_process_queue_mutex){0};
10971099

10981100
// Our address, as reported by the peer
10991101
CService addrLocal GUARDED_BY(m_addr_local_mutex);
@@ -2002,4 +2004,24 @@ class CExplicitNetCleanup
20022004
static void callCleanup();
20032005
};
20042006

2007+
// Helper function to determine if a message type should be prioritized in the quorum queue
2008+
inline bool IsQuorumPriorityMessage(const std::string& msg_type)
2009+
{
2010+
// LLMQ signing/data messages
2011+
if (msg_type == NetMsgType::QSIGSHARE ||
2012+
msg_type == NetMsgType::QBSIGSHARES ||
2013+
msg_type == NetMsgType::QSIGSHARESINV ||
2014+
msg_type == NetMsgType::QGETSIGSHARES ||
2015+
msg_type == NetMsgType::QSIGSESANN ||
2016+
msg_type == NetMsgType::QSIGREC) {
2017+
return true;
2018+
}
2019+
// High-level lock messages (ChainLocks, InstantSend locks)
2020+
if (msg_type == NetMsgType::CLSIG ||
2021+
msg_type == NetMsgType::ISDLOCK) {
2022+
return true;
2023+
}
2024+
return false;
2025+
}
2026+
20052027
#endif // BITCOIN_NET_H

0 commit comments

Comments
 (0)