mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
feat(llmq): Ensure connections between IS quorums (#4917)
* fix(llmq): Ensure connections between quorums Every masternode will now "watch" a single node from _every other_ quorum in addition to intra-quorum connections. This should make propagation of recsigs produced by one quorum to other quorums much more reliable. * fix: Do this only for masternodes which participate in IS quorums * refactor: rename `CQuorumManager::EnsureQuorumConnections` to better match the actual behaviour (and avoid confusion with `CLLMQUtils::EnsureQuorumConnections`) * refactor: move IS quorums watch logic into `CQuorumManager::CheckQuorumConnections` avoid calling slow `ScanQuorums` (no caching atm) inside the loop * tests: check that inter-quorum connections are added * use `ranges::any_of`
This commit is contained in:
parent
a1f54a6079
commit
9e22801878
@ -243,7 +243,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial
|
||||
}
|
||||
|
||||
for (auto& params : Params().GetConsensus().llmqs) {
|
||||
EnsureQuorumConnections(params, pindexNew);
|
||||
CheckQuorumConnections(params, pindexNew);
|
||||
}
|
||||
|
||||
{
|
||||
@ -262,7 +262,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial
|
||||
TriggerQuorumDataRecoveryThreads(pindexNew);
|
||||
}
|
||||
|
||||
void CQuorumManager::EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const
|
||||
void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const
|
||||
{
|
||||
auto lastQuorums = ScanQuorums(llmqParams.type, pindexNew, (size_t)llmqParams.keepOldConnections);
|
||||
|
||||
@ -289,11 +289,36 @@ void CQuorumManager::EnsureQuorumConnections(const Consensus::LLMQParams& llmqPa
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, curDkgHeight, curDkgBlock.ToString());
|
||||
}
|
||||
|
||||
const auto myProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
bool isISType = llmqParams.type == Params().GetConsensus().llmqTypeInstantSend ||
|
||||
llmqParams.type == Params().GetConsensus().llmqTypeDIP0024InstantSend;
|
||||
|
||||
bool watchOtherISQuorums = isISType && !myProTxHash.IsNull() &&
|
||||
ranges::any_of(lastQuorums, [&myProTxHash](const auto& old_quorum){
|
||||
return old_quorum->IsMember(myProTxHash);
|
||||
});
|
||||
|
||||
for (const auto& quorum : lastQuorums) {
|
||||
if (CLLMQUtils::EnsureQuorumConnections(llmqParams, quorum->m_quorum_base_block_index, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
if (CLLMQUtils::EnsureQuorumConnections(llmqParams, quorum->m_quorum_base_block_index, myProTxHash)) {
|
||||
if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
|
||||
}
|
||||
} else if (watchOtherISQuorums && !quorum->IsMember(myProTxHash)) {
|
||||
std::set<uint256> connections;
|
||||
const auto& cindexes = CLLMQUtils::CalcDeterministicWatchConnections(llmqParams.type, quorum->m_quorum_base_block_index, quorum->members.size(), 1);
|
||||
for (auto idx : cindexes) {
|
||||
connections.emplace(quorum->members[idx]->proTxHash);
|
||||
}
|
||||
if (!connections.empty()) {
|
||||
if (!g_connman->HasMasternodeQuorumNodes(llmqParams.type, quorum->m_quorum_base_block_index->GetBlockHash())) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] adding mn inter-quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
|
||||
g_connman->SetMasternodeQuorumNodes(llmqParams.type, quorum->m_quorum_base_block_index->GetBlockHash(), connections);
|
||||
g_connman->SetMasternodeQuorumRelayMembers(llmqParams.type, quorum->m_quorum_base_block_index->GetBlockHash(), connections);
|
||||
}
|
||||
if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn inter-quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& quorumHash : connmanQuorumsToDelete) {
|
||||
|
@ -224,7 +224,7 @@ public:
|
||||
|
||||
private:
|
||||
// all private methods here are cs_main-free
|
||||
void EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex *pindexNew) const;
|
||||
void CheckQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex *pindexNew) const;
|
||||
|
||||
CQuorumPtr BuildQuorumFromCommitment(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex) const EXCLUSIVE_LOCKS_REQUIRED(quorumsCacheCs);
|
||||
bool BuildQuorumContributions(const CFinalCommitmentPtr& fqc, const std::shared_ptr<CQuorum>& quorum) const;
|
||||
|
@ -701,13 +701,24 @@ std::set<size_t> CLLMQUtils::CalcDeterministicWatchConnections(Consensus::LLMQTy
|
||||
|
||||
bool CLLMQUtils::EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const uint256& myProTxHash)
|
||||
{
|
||||
if (!fMasternodeMode && !CLLMQUtils::IsWatchQuorumsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto members = GetAllQuorumMembers(llmqParams.type, pQuorumBaseBlockIndex);
|
||||
if (members.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isMember = std::find_if(members.begin(), members.end(), [&](const auto& dmn) { return dmn->proTxHash == myProTxHash; }) != members.end();
|
||||
|
||||
if (!isMember && !CLLMQUtils::IsWatchQuorumsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogPrint(BCLog::NET_NETCONN, "CLLMQUtils::%s -- isMember=%d for quorum %s:\n",
|
||||
__func__, isMember, pQuorumBaseBlockIndex->GetBlockHash().ToString());
|
||||
|
||||
std::set<uint256> connections;
|
||||
std::set<uint256> relayMembers;
|
||||
if (isMember) {
|
||||
|
@ -69,6 +69,20 @@ class LLMQConnections(DashTestFramework):
|
||||
|
||||
self.check_reconnects(4)
|
||||
|
||||
self.log.info("check that inter-quorum masternode conections are added")
|
||||
added = False
|
||||
for mn in self.mninfo:
|
||||
if len(mn.node.quorum("memberof", mn.proTxHash)) > 0:
|
||||
try:
|
||||
with mn.node.assert_debug_log(['adding mn inter-quorum connections']):
|
||||
self.mine_quorum()
|
||||
added = True
|
||||
except:
|
||||
pass # it's ok to not add connections sometimes
|
||||
if added:
|
||||
break
|
||||
assert added # no way we added none
|
||||
|
||||
def check_reconnects(self, expected_connection_count):
|
||||
self.log.info("disable and re-enable networking on all masternodes")
|
||||
for mn in self.mninfo:
|
||||
|
Loading…
Reference in New Issue
Block a user