Skip to content

Commit

Permalink
Stop tracking interested/participating nodes and send/announce to MNA…
Browse files Browse the repository at this point in the history
…UTH peers (#2798)

* Pass CNode* to IsMasternodeQuorumNode and let it also check verifiedProRegTxHash

This makes IsMasternodeQuorumNode return true on incoming peer connections
as well.

* Let GetMasternodeQuorumNodes also take verifiedProRegTxHash into account

This makes it return NodeIds for incoming peer connections as well.

* Remove AddParticipatingNode and the need for it

This was needed in the past when we were unable to identify incoming
connections from other quorum members. Now that we have MNAUTH, we can
easily identify all connected members.

* Don't track interestedIn quorums in CSigSharesNodeState anymore

Same as with the previous commit, we're now able to easily identify which
nodes to announce sig shares to.

* Remove unused CConnman::GetMasternodeQuorumAddresses
  • Loading branch information
codablock authored and UdjinM6 committed Mar 22, 2019
1 parent f20620b commit 15c720d
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 95 deletions.
23 changes: 7 additions & 16 deletions src/llmq/quorums_dkgsession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1244,26 +1244,17 @@ void CDKGSession::MarkBadMember(size_t idx)
member->bad = true;
}

void CDKGSession::AddParticipatingNode(NodeId nodeId)
{
LOCK(invCs);
g_connman->ForNode(nodeId, [&](CNode* pnode) {
if (!participatingNodes.emplace(pnode->addr).second) {
return true;
}

for (const auto& inv : invSet) {
pnode->PushInventory(inv);
}
return true;
});
}

void CDKGSession::RelayInvToParticipants(const CInv& inv) const
{
LOCK(invCs);
g_connman->ForEachNode([&](CNode* pnode) {
if (participatingNodes.count(pnode->addr)) {
bool relay = false;
if (pnode->qwatch) {
relay = true;
} else if (!pnode->verifiedProRegTxHash.IsNull() && membersMap.count(pnode->verifiedProRegTxHash)) {
relay = true;
}
if (relay) {
pnode->PushInventory(inv);
}
});
Expand Down
2 changes: 0 additions & 2 deletions src/llmq/quorums_dkgsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@ class CDKGSession
std::map<uint256, CDKGJustification> justifications;
std::map<uint256, CDKGPrematureCommitment> prematureCommitments;
std::set<CInv> invSet;
std::set<CService> participatingNodes;

std::vector<size_t> pendingContributionVerifications;

Expand Down Expand Up @@ -336,7 +335,6 @@ class CDKGSession
bool AreWeMember() const { return !myProTxHash.IsNull(); }
void MarkBadMember(size_t idx);

void AddParticipatingNode(NodeId nodeId);
void RelayInvToParticipants(const CInv& inv) const;

public:
Expand Down
14 changes: 0 additions & 14 deletions src/llmq/quorums_dkgsessionhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,6 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
}
}

for (const auto& p : preverifiedMessages) {
NodeId nodeId = p.first;
if (badNodes.count(nodeId)) {
continue;
}
session.AddParticipatingNode(nodeId);
}

return true;
}

Expand Down Expand Up @@ -492,12 +484,6 @@ void CDKGSessionHandler::HandleDKGRound()
}
LogPrint("llmq", debugMsg);
g_connman->AddMasternodeQuorumNodes(params.type, curQuorumHash, connections);

auto participatingNodesTmp = g_connman->GetMasternodeQuorumAddresses(params.type, curQuorumHash);
LOCK(curSession->invCs);
for (auto& p : participatingNodesTmp) {
curSession->participatingNodes.emplace(p.first);
}
}
}

Expand Down
4 changes: 0 additions & 4 deletions src/llmq/quorums_dkgsessionmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ void CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strComm

if (strCommand == NetMsgType::QWATCH) {
pfrom->qwatch = true;
for (auto& p : dkgSessionHandlers) {
LOCK2(p.second.cs, p.second.curSession->invCs);
p.second.curSession->participatingNodes.emplace(pfrom->addr);
}
return;
}

Expand Down
50 changes: 12 additions & 38 deletions src/llmq/quorums_signing_shares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,13 +644,7 @@ void CSigSharesManager::ProcessPendingSigSharesFromNode(NodeId nodeId,

cxxtimer::Timer t(true);
for (auto& sigShare : sigShares) {
// he sent us some valid sig shares, so he must be part of this quorum and is thus interested in our sig shares as well
// if this is the first time we received a sig share from this node, we won't announce the currently locally known sig shares to him.
// only the upcoming sig shares will be announced to him. this means the first signing session for a fresh quorum will be a bit
// slower than for older ones. TODO: fix this (risk of DoS when announcing all at once?)
auto quorumKey = std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash);
nodeState.interestedIn.emplace(quorumKey);

ProcessSigShare(nodeId, sigShare, connman, quorums.at(quorumKey));
}
t.stop();
Expand All @@ -670,10 +664,6 @@ void CSigSharesManager::ProcessSigShare(NodeId nodeId, const CSigShare& sigShare
std::set<NodeId> quorumNodes;
if (sigShare.quorumMember == quorum->GetMemberIndex(activeMasternodeInfo.proTxHash)) {
quorumNodes = connman.GetMasternodeQuorumNodes((Consensus::LLMQType) sigShare.llmqType, sigShare.quorumHash);
// make sure node states are created for these nodes (we might have not received any message from these yet)
for (auto otherNodeId : quorumNodes) {
nodeStates[otherNodeId].interestedIn.emplace(std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash));
}
}

if (quorumSigningManager->HasRecoveredSigForId(llmqType, sigShare.id)) {
Expand Down Expand Up @@ -702,12 +692,9 @@ void CSigSharesManager::ProcessSigShare(NodeId nodeId, const CSigShare& sigShare
if (!quorumNodes.empty()) {
// don't announce and wait for other nodes to request this share and directly send it to them
// there is no way the other nodes know about this share as this is the one created on this node
// this will also indicate interest to the other nodes in sig shares for this quorum
for (auto& p : nodeStates) {
if (!quorumNodes.count(p.first) && !p.second.interestedIn.count(std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash))) {
continue;
}
auto& session = p.second.GetOrCreateSessionFromShare(sigShare);
for (auto otherNodeId : quorumNodes) {
auto& nodeState = nodeStates[otherNodeId];
auto& session = nodeState.GetOrCreateSessionFromShare(sigShare);
session.quorum = quorum;
session.requested.Set(sigShare.quorumMember, true);
session.knows.Set(sigShare.quorumMember, true);
Expand Down Expand Up @@ -942,7 +929,7 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_map<NodeId, st
{
AssertLockHeld(cs);

std::unordered_set<std::pair<Consensus::LLMQType, uint256>, StaticSaltedHasher> quorumNodesPrepared;
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, std::unordered_set<NodeId>, StaticSaltedHasher> quorumNodesMap;

this->sigSharesToAnnounce.ForEach([&](const SigShareKey& sigShareKey, bool) {
auto& signHash = sigShareKey.first;
Expand All @@ -952,30 +939,20 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_map<NodeId, st
return;
}

// announce to the nodes which we know through the intra-quorum-communication system
auto quorumKey = std::make_pair((Consensus::LLMQType)sigShare->llmqType, sigShare->quorumHash);
if (quorumNodesPrepared.emplace(quorumKey).second) {
// make sure we announce to at least the nodes which we know through the inter-quorum-communication system
auto it = quorumNodesMap.find(quorumKey);
if (it == quorumNodesMap.end()) {
auto nodeIds = g_connman->GetMasternodeQuorumNodes(quorumKey.first, quorumKey.second);
for (auto nodeId : nodeIds) {
auto& nodeState = nodeStates[nodeId];
nodeState.interestedIn.emplace(quorumKey);
}
it = quorumNodesMap.emplace(std::piecewise_construct, std::forward_as_tuple(quorumKey), std::forward_as_tuple(nodeIds.begin(), nodeIds.end())).first;
}

for (auto& p : nodeStates) {
auto nodeId = p.first;
auto& nodeState = p.second;
auto& quorumNodes = it->second;

if (nodeState.banned) {
continue;
}
for (auto& nodeId : quorumNodes) {
auto& nodeState = nodeStates[nodeId];

if (!nodeState.interestedIn.count(quorumKey)) {
// node is not interested in this sig share
// we only consider nodes to be interested if they sent us valid sig share before
// the sig share that we sign by ourself circumvents the inv system and is directly sent to all quorum members
// which are known by the deterministic inter-quorum-communication system. This is also the sig share that
// will tell the other nodes that we are interested in future sig shares
if (nodeState.banned) {
continue;
}

Expand All @@ -997,9 +974,6 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_map<NodeId, st
});

// don't announce these anymore
// nodes which did not send us a valid sig share before were left out now, but this is ok as it only results in slower
// propagation for the first signing session of a fresh quorum. The sig shares should still arrive on all nodes due to
// the deterministic inter-quorum-communication system
this->sigSharesToAnnounce.Clear();
}

Expand Down
4 changes: 0 additions & 4 deletions src/llmq/quorums_signing_shares.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,6 @@ class CSigSharesNodeState
SigShareMap<CSigShare> pendingIncomingSigShares;
SigShareMap<int64_t> requestedSigShares;

// elements are added whenever we receive a valid sig share from this node
// this triggers us to send inventory items to him as he seems to be interested in these
std::unordered_set<std::pair<Consensus::LLMQType, uint256>, StaticSaltedHasher> interestedIn;

bool banned{false};

Session& GetOrCreateSessionFromShare(const CSigShare& sigShare);
Expand Down
2 changes: 1 addition & 1 deletion src/masternode-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman)
#endif // ENABLE_WALLET

connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) {
if (pnode->fMasternode && !connman.IsMasternodeQuorumNode(pnode->addr)) {
if (pnode->fMasternode && !connman.IsMasternodeQuorumNode(pnode)) {
#ifdef ENABLE_WALLET
bool fFound = false;
for (const auto& dmn : vecDmns) {
Expand Down
29 changes: 15 additions & 14 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2749,29 +2749,25 @@ std::set<uint256> CConnman::GetMasternodeQuorums(Consensus::LLMQType llmqType)
return result;
}

std::map<CService, uint256> CConnman::GetMasternodeQuorumAddresses(Consensus::LLMQType llmqType, const uint256& quorumHash) const
{
LOCK(cs_vPendingMasternodes);
auto it = masternodeQuorumNodes.find(std::make_pair(llmqType, quorumHash));
if (it == masternodeQuorumNodes.end()) {
return {};
}
return it->second;
}

std::set<NodeId> CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const
{
LOCK2(cs_vNodes, cs_vPendingMasternodes);
auto it = masternodeQuorumNodes.find(std::make_pair(llmqType, quorumHash));
if (it == masternodeQuorumNodes.end()) {
return {};
}
std::set<uint256> proRegTxHashes;
for (auto& p : it->second) {
proRegTxHashes.emplace(p.second);
}

std::set<NodeId> nodes;
for (const auto pnode : vNodes) {
if (pnode->fDisconnect) {
continue;
}
if (!pnode->qwatch && !it->second.count(pnode->addr)) {
if (!pnode->qwatch && !it->second.count(pnode->addr) &&
(pnode->verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(pnode->verifiedProRegTxHash))) {
continue;
}
nodes.emplace(pnode->id);
Expand All @@ -2785,12 +2781,17 @@ void CConnman::RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const u
masternodeQuorumNodes.erase(std::make_pair(llmqType, quorumHash));
}

bool CConnman::IsMasternodeQuorumNode(const CService& addr)
bool CConnman::IsMasternodeQuorumNode(const CNode* pnode)
{
LOCK(cs_vPendingMasternodes);
for (const auto& p : masternodeQuorumNodes) {
if (p.second.count(addr)) {
return true;
for (const auto& p2 : p.second) {
if (p2.first == (CService)pnode->addr) {
return true;
}
if (!pnode->verifiedProRegTxHash.IsNull() && p2.second == pnode->verifiedProRegTxHash) {
return true;
}
}
}
return false;
Expand Down
3 changes: 1 addition & 2 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,10 @@ class CConnman
bool AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::map<CService, uint256>& addresses);
bool HasMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash);
std::set<uint256> GetMasternodeQuorums(Consensus::LLMQType llmqType);
std::map<CService, uint256> GetMasternodeQuorumAddresses(Consensus::LLMQType llmqType, const uint256& quorumHash) const;
// also returns QWATCH nodes
std::set<NodeId> GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const;
void RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash);
bool IsMasternodeQuorumNode(const CService& addr);
bool IsMasternodeQuorumNode(const CNode* pnode);

size_t GetNodeCount(NumConnections num);
void GetNodeStats(std::vector<CNodeStats>& vstats);
Expand Down

0 comments on commit 15c720d

Please sign in to comment.