Skip to content

Commit 96472dc

Browse files
committed
Fix data races triggered by functional tests.
Function CWallet::KeepKey requires locking as it has concurrent access to database and member nKeysLeftSinceAutoBackup. Avoid data race when reading setInventoryTxToSend size by locking the read. If locking happens after the read, the size may change. Lock cs_mnauth when reading verifiedProRegTxHash. Make fRPCRunning atomic as it can be read/written from different threads simultaneously. Make m_masternode_iqr_connection atomic as it can be read/written from different threads simultaneously. Use a recursive mutex to synchronize concurrent access to quorumVvec. Make m_masternode_connection atomic as it can be read/written from different threads simultaneously. Make m_masternode_probe_connection atomic as it can be read/written from different threads simultaneously. Use a recursive mutex in order to lock access to activeMasterNode. Use a recursive mutex to synchronize concurrent access to skShare.
1 parent 99ffdaa commit 96472dc

17 files changed

+133
-85
lines changed

src/coinjoin/coinjoin-server.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void CCoinJoinServer::ProcessMessage(CNode* pfrom, const std::string& strCommand
5656
LogPrint(BCLog::COINJOIN, "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CCoinJoin::DenominationToString(dsa.nDenom), dsa.txCollateral.ToString()); /* Continued */
5757

5858
auto mnList = deterministicMNManager->GetListAtChainTip();
59-
auto dmn = mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint);
59+
auto dmn = WITH_LOCK(activeMasternodeInfoCs, return mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint));
6060
if (!dmn) {
6161
PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST, connman);
6262
return;
@@ -68,7 +68,7 @@ void CCoinJoinServer::ProcessMessage(CNode* pfrom, const std::string& strCommand
6868
if (!lockRecv) return;
6969

7070
for (const auto& q : vecCoinJoinQueue) {
71-
if (q.masternodeOutpoint == activeMasternodeInfo.outpoint) {
71+
if (WITH_LOCK(activeMasternodeInfoCs, return q.masternodeOutpoint == activeMasternodeInfo.outpoint)) {
7272
// refuse to create another queue this often
7373
LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq is still in queue, refuse to mix\n");
7474
PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman);
@@ -334,7 +334,7 @@ void CCoinJoinServer::CommitFinalTransaction(CConnman& connman)
334334

335335
// create and sign masternode dstx transaction
336336
if (!CCoinJoin::GetDSTX(hashTx)) {
337-
CCoinJoinBroadcastTx dstxNew(finalTransaction, activeMasternodeInfo.outpoint, GetAdjustedTime());
337+
CCoinJoinBroadcastTx dstxNew(finalTransaction, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), GetAdjustedTime());
338338
dstxNew.Sign();
339339
CCoinJoin::AddDSTX(dstxNew);
340340
}
@@ -501,7 +501,7 @@ void CCoinJoinServer::CheckForCompleteQueue(CConnman& connman)
501501
if (nState == POOL_STATE_QUEUE && IsSessionReady()) {
502502
SetState(POOL_STATE_ACCEPTING_ENTRIES);
503503

504-
CCoinJoinQueue dsq(nSessionDenom, activeMasternodeInfo.outpoint, GetAdjustedTime(), true);
504+
CCoinJoinQueue dsq(nSessionDenom, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), GetAdjustedTime(), true);
505505
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s) " /* Continued */
506506
"with %d participants\n", dsq.ToString(), vecSessionCollaterals.size());
507507
dsq.Sign();
@@ -708,7 +708,7 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage&
708708

709709
if (!fUnitTest) {
710710
//broadcast that I'm accepting entries, only if it's the first entry through
711-
CCoinJoinQueue dsq(nSessionDenom, activeMasternodeInfo.outpoint, GetAdjustedTime(), false);
711+
CCoinJoinQueue dsq(nSessionDenom, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), GetAdjustedTime(), false);
712712
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString());
713713
dsq.Sign();
714714
dsq.Relay(connman);

src/coinjoin/coinjoin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ bool CCoinJoinQueue::Sign()
5050

5151

5252
uint256 hash = GetSignatureHash();
53-
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
53+
CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash));
5454
if (!sig.IsValid()) {
5555
return false;
5656
}
@@ -96,7 +96,7 @@ bool CCoinJoinBroadcastTx::Sign()
9696

9797
uint256 hash = GetSignatureHash();
9898

99-
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
99+
CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash));
100100
if (!sig.IsValid()) {
101101
return false;
102102
}

src/evo/mnauth.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
void CMNAuth::PushMNAUTH(CNode* pnode, CConnman& connman)
2020
{
21+
LOCK(activeMasternodeInfoCs);
2122
if (!fMasternodeMode || activeMasternodeInfo.proTxHash.IsNull()) {
2223
return;
2324
}
@@ -149,10 +150,10 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS
149150

150151
if (pnode2->verifiedProRegTxHash == mnauth.proRegTxHash) {
151152
if (fMasternodeMode) {
152-
auto deterministicOutbound = llmq::CLLMQUtils::DeterministicOutboundConnection(activeMasternodeInfo.proTxHash, mnauth.proRegTxHash);
153+
auto deterministicOutbound = WITH_LOCK(activeMasternodeInfoCs, return llmq::CLLMQUtils::DeterministicOutboundConnection(activeMasternodeInfo.proTxHash, mnauth.proRegTxHash));
153154
LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- Masternode %s has already verified as peer %d, deterministicOutbound=%s. peer=%d\n",
154155
mnauth.proRegTxHash.ToString(), pnode2->GetId(), deterministicOutbound.ToString(), pnode->GetId());
155-
if (deterministicOutbound == activeMasternodeInfo.proTxHash) {
156+
if (WITH_LOCK(activeMasternodeInfoCs, return deterministicOutbound == activeMasternodeInfo.proTxHash)) {
156157
if (pnode2->fInbound) {
157158
LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- dropping old inbound, peer=%d\n", pnode2->GetId());
158159
pnode2->fDisconnect = true;

src/init.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,12 @@ void PrepareShutdown()
363363
UnregisterValidationInterface(activeMasternodeManager);
364364
}
365365

366-
// make sure to clean up BLS keys before global destructors are called (they have allocated from the secure memory pool)
367-
activeMasternodeInfo.blsKeyOperator.reset();
368-
activeMasternodeInfo.blsPubKeyOperator.reset();
366+
{
367+
LOCK(activeMasternodeInfoCs);
368+
// make sure to clean up BLS keys before global destructors are called (they have allocated from the secure memory pool)
369+
activeMasternodeInfo.blsKeyOperator.reset();
370+
activeMasternodeInfo.blsPubKeyOperator.reset();
371+
}
369372

370373
#ifndef WIN32
371374
try {
@@ -2316,8 +2319,12 @@ bool AppInitMain()
23162319
return InitError(_("Invalid masternodeblsprivkey. Please see documentation."));
23172320
}
23182321
fMasternodeMode = true;
2319-
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>(keyOperator);
2320-
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>(activeMasternodeInfo.blsKeyOperator->GetPublicKey());
2322+
{
2323+
LOCK(activeMasternodeInfoCs);
2324+
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>(keyOperator);
2325+
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>(
2326+
activeMasternodeInfo.blsKeyOperator->GetPublicKey());
2327+
}
23212328
LogPrintf("MASTERNODE:\n");
23222329
LogPrintf(" blsPubKeyOperator: %s\n", keyOperator.GetPublicKey().ToString());
23232330
}
@@ -2328,11 +2335,14 @@ bool AppInitMain()
23282335
RegisterValidationInterface(activeMasternodeManager);
23292336
}
23302337

2331-
if (activeMasternodeInfo.blsKeyOperator == nullptr) {
2332-
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>();
2333-
}
2334-
if (activeMasternodeInfo.blsPubKeyOperator == nullptr) {
2335-
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>();
2338+
{
2339+
LOCK(activeMasternodeInfoCs);
2340+
if (activeMasternodeInfo.blsKeyOperator == nullptr) {
2341+
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>();
2342+
}
2343+
if (activeMasternodeInfo.blsPubKeyOperator == nullptr) {
2344+
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>();
2345+
}
23362346
}
23372347

23382348
// ********************************************************* Step 10b: setup CoinJoin

src/llmq/quorums.cpp

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ void CQuorum::Init(const CFinalCommitmentPtr& _qc, const CBlockIndex* _pindexQuo
6161

6262
bool CQuorum::SetVerificationVector(const BLSVerificationVector& quorumVecIn)
6363
{
64-
if (::SerializeHash(quorumVecIn) != qc->quorumVvecHash) {
64+
const auto quorumVecInSerialized = ::SerializeHash(quorumVecIn);
65+
66+
LOCK(cs);
67+
if (quorumVecInSerialized != qc->quorumVvecHash) {
6568
return false;
6669
}
6770
quorumVvec = std::make_shared<BLSVerificationVector>(quorumVecIn);
@@ -70,9 +73,10 @@ bool CQuorum::SetVerificationVector(const BLSVerificationVector& quorumVecIn)
7073

7174
bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare)
7275
{
73-
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(GetMemberIndex(activeMasternodeInfo.proTxHash)))) {
76+
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(WITH_LOCK(activeMasternodeInfoCs, return GetMemberIndex(activeMasternodeInfo.proTxHash))))) {
7477
return false;
7578
}
79+
LOCK(cs);
7680
skShare = secretKeyShare;
7781
return true;
7882
}
@@ -99,15 +103,22 @@ bool CQuorum::IsValidMember(const uint256& proTxHash) const
99103

100104
CBLSPublicKey CQuorum::GetPubKeyShare(size_t memberIdx) const
101105
{
102-
if (quorumVvec == nullptr || memberIdx >= members.size() || !qc->validMembers[memberIdx]) {
106+
LOCK(cs);
107+
if (!HasVerificationVector() || memberIdx >= members.size() || !qc->validMembers[memberIdx]) {
103108
return CBLSPublicKey();
104109
}
105110
auto& m = members[memberIdx];
106111
return blsCache.BuildPubKeyShare(m->proTxHash, quorumVvec, CBLSId(m->proTxHash));
107112
}
108113

109-
const CBLSSecretKey& CQuorum::GetSkShare() const
114+
bool CQuorum::HasVerificationVector() const {
115+
LOCK(cs);
116+
return quorumVvec != nullptr;
117+
}
118+
119+
CBLSSecretKey CQuorum::GetSkShare() const
110120
{
121+
LOCK(cs);
111122
return skShare;
112123
}
113124

@@ -125,7 +136,8 @@ void CQuorum::WriteContributions(CEvoDB& evoDb) const
125136
{
126137
uint256 dbKey = MakeQuorumKey(*this);
127138

128-
if (quorumVvec != nullptr) {
139+
LOCK(cs);
140+
if (HasVerificationVector()) {
129141
evoDb.GetRawDB().Write(std::make_pair(DB_QUORUM_QUORUM_VVEC, dbKey), *quorumVvec);
130142
}
131143
if (skShare.IsValid()) {
@@ -139,14 +151,14 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb)
139151

140152
BLSVerificationVector qv;
141153
if (evoDb.Read(std::make_pair(DB_QUORUM_QUORUM_VVEC, dbKey), qv)) {
142-
quorumVvec = std::make_shared<BLSVerificationVector>(std::move(qv));
154+
WITH_LOCK(cs, quorumVvec = std::make_shared<BLSVerificationVector>(std::move(qv)));
143155
} else {
144156
return false;
145157
}
146158

147159
// We ignore the return value here as it is ok if this fails. If it fails, it usually means that we are not a
148160
// member of the quorum but observed the whole DKG process to have the quorum verification vector.
149-
evoDb.Read(std::make_pair(DB_QUORUM_SK_SHARE, dbKey), skShare);
161+
WITH_LOCK(cs, evoDb.Read(std::make_pair(DB_QUORUM_SK_SHARE, dbKey), skShare));
150162

151163
return true;
152164
}
@@ -197,8 +209,10 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)
197209

198210
// First check if we are member of any quorum of this type
199211
bool fWeAreQuorumTypeMember{false};
200-
for (const auto& pQuorum : vecQuorums) {
201-
if (pQuorum->IsValidMember(activeMasternodeInfo.proTxHash)) {
212+
213+
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
214+
for (const auto &pQuorum : vecQuorums) {
215+
if (pQuorum->IsValidMember(proTxHash)) {
202216
fWeAreQuorumTypeMember = true;
203217
break;
204218
}
@@ -211,16 +225,16 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)
211225
}
212226

213227
uint16_t nDataMask{0};
214-
const bool fWeAreQuorumMember = pQuorum->IsValidMember(activeMasternodeInfo.proTxHash);
228+
const bool fWeAreQuorumMember = pQuorum->IsValidMember(proTxHash);
215229
const bool fSyncForTypeEnabled = mapQuorumVvecSync.count(pQuorum->qc->llmqType) > 0;
216230
const QvvecSyncMode syncMode = fSyncForTypeEnabled ? mapQuorumVvecSync.at(pQuorum->qc->llmqType) : QvvecSyncMode::Invalid;
217231
const bool fSyncCurrent = syncMode == QvvecSyncMode::Always || (syncMode == QvvecSyncMode::OnlyIfTypeMember && fWeAreQuorumTypeMember);
218232

219-
if ((fWeAreQuorumMember || (fSyncForTypeEnabled && fSyncCurrent)) && pQuorum->quorumVvec == nullptr) {
233+
if ((fWeAreQuorumMember || (fSyncForTypeEnabled && fSyncCurrent)) && !pQuorum->HasVerificationVector()) {
220234
nDataMask |= llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR;
221235
}
222236

223-
if (fWeAreQuorumMember && !pQuorum->skShare.IsValid()) {
237+
if (fWeAreQuorumMember && !pQuorum->GetSkShare().IsValid()) {
224238
nDataMask |= llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS;
225239
}
226240

@@ -266,7 +280,6 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const
266280
{
267281
const auto& llmq_params = GetLLMQParams(llmqType);
268282

269-
const auto& myProTxHash = activeMasternodeInfo.proTxHash;
270283
auto lastQuorums = ScanQuorums(llmqType, pindexNew, (size_t)llmq_params.keepOldConnections);
271284

272285
auto connmanQuorumsToDelete = g_connman->GetMasternodeQuorums(llmqType);
@@ -277,7 +290,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const
277290
connmanQuorumsToDelete.erase(curDkgBlock);
278291

279292
for (const auto& quorum : lastQuorums) {
280-
if (CLLMQUtils::EnsureQuorumConnections(llmqType, quorum->pindexQuorum, myProTxHash)) {
293+
if (CLLMQUtils::EnsureQuorumConnections(llmqType, quorum->pindexQuorum, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
281294
continue;
282295
}
283296
if (connmanQuorumsToDelete.count(quorum->qc->quorumHash) > 0) {
@@ -339,8 +352,9 @@ bool CQuorumManager::BuildQuorumContributions(const CFinalCommitmentPtr& fqc, co
339352
}
340353

341354
cxxtimer::Timer t2(true);
355+
LOCK(quorum->cs);
342356
quorum->quorumVvec = blsWorker.BuildQuorumVerificationVector(vvecs);
343-
if (quorum->quorumVvec == nullptr) {
357+
if (quorum->HasVerificationVector()) {
344358
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build quorumVvec\n", __func__);
345359
// without the quorum vvec, there can't be a skShare, so we fail here. Failure is not fatal here, as it still
346360
// allows to use the quorum as a non-member (verification through the quorum pub key)
@@ -517,10 +531,13 @@ size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, c
517531
});
518532
std::sort(vecProTxHashes.begin(), vecProTxHashes.end());
519533
size_t nIndex{0};
520-
for (size_t i = 0; i < vecProTxHashes.size(); ++i) {
521-
if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) {
522-
nIndex = i;
523-
break;
534+
{
535+
LOCK(activeMasternodeInfoCs);
536+
for (size_t i = 0; i < vecProTxHashes.size(); ++i) {
537+
if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) {
538+
nIndex = i;
539+
break;
540+
}
524541
}
525542
}
526543
return nIndex % pQuorum->qc->validMembers.size();
@@ -592,13 +609,12 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
592609

593610
// Check if request wants QUORUM_VERIFICATION_VECTOR data
594611
if (request.GetDataMask() & CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR) {
595-
596-
if (!pQuorum->quorumVvec) {
612+
if (!pQuorum->HasVerificationVector()) {
597613
sendQDATA(CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING);
598614
return;
599615
}
600616

601-
ssResponseData << *pQuorum->quorumVvec;
617+
WITH_LOCK(pQuorum->cs, ssResponseData << *pQuorum->quorumVvec);
602618
}
603619

604620
// Check if request wants ENCRYPTED_CONTRIBUTIONS data
@@ -682,7 +698,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
682698
// Check if request has ENCRYPTED_CONTRIBUTIONS data
683699
if (request.GetDataMask() & CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) {
684700

685-
if (pQuorum->quorumVvec->size() != pQuorum->params.threshold) {
701+
if (WITH_LOCK(pQuorum->cs, return pQuorum->quorumVvec->size() != pQuorum->params.threshold)) {
686702
errorHandler("No valid quorum verification vector available", 0); // Don't bump score because we asked for it
687703
return;
688704
}
@@ -698,8 +714,9 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
698714

699715
BLSSecretKeyVector vecSecretKeys;
700716
vecSecretKeys.resize(vecEncrypted.size());
717+
auto secret = WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator);
701718
for (size_t i = 0; i < vecEncrypted.size(); ++i) {
702-
if (!vecEncrypted[i].Decrypt(memberIdx, *activeMasternodeInfo.blsKeyOperator, vecSecretKeys[i], PROTOCOL_VERSION)) {
719+
if (!vecEncrypted[i].Decrypt(memberIdx, secret, vecSecretKeys[i], PROTOCOL_VERSION)) {
703720
errorHandler("Failed to decrypt");
704721
return;
705722
}
@@ -718,7 +735,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
718735

719736
void CQuorumManager::StartCachePopulatorThread(const CQuorumCPtr pQuorum) const
720737
{
721-
if (pQuorum->quorumVvec == nullptr) {
738+
if (!pQuorum->HasVerificationVector()) {
722739
return;
723740
}
724741

@@ -771,7 +788,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
771788

772789
vecMemberHashes.reserve(pQuorum->qc->validMembers.size());
773790
for (auto& member : pQuorum->members) {
774-
if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != activeMasternodeInfo.proTxHash) {
791+
if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash)) {
775792
vecMemberHashes.push_back(member->proTxHash);
776793
}
777794
}
@@ -781,12 +798,13 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
781798

782799
while (nDataMask > 0 && !quorumThreadInterrupt) {
783800

784-
if (nDataMask & llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR && pQuorum->quorumVvec != nullptr) {
801+
if (nDataMask & llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR &&
802+
pQuorum->HasVerificationVector()) {
785803
nDataMask &= ~llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR;
786804
printLog("Received quorumVvec");
787805
}
788806

789-
if (nDataMask & llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS && pQuorum->skShare.IsValid()) {
807+
if (nDataMask & llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS && pQuorum->GetSkShare().IsValid()) {
790808
nDataMask &= ~llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS;
791809
printLog("Received skShare");
792810
}
@@ -818,13 +836,14 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
818836
printLog("Connect");
819837
}
820838

839+
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
821840
g_connman->ForEachNode([&](CNode* pNode) {
822841

823842
if (pCurrentMemberHash == nullptr || pNode->verifiedProRegTxHash != *pCurrentMemberHash) {
824843
return;
825844
}
826845

827-
if (quorumManager->RequestQuorumData(pNode, pQuorum->qc->llmqType, pQuorum->pindexQuorum, nDataMask, activeMasternodeInfo.proTxHash)) {
846+
if (quorumManager->RequestQuorumData(pNode, pQuorum->qc->llmqType, pQuorum->pindexQuorum, nDataMask, proTxHash)) {
828847
nTimeLastSuccess = GetAdjustedTime();
829848
printLog("Requested");
830849
} else {

0 commit comments

Comments
 (0)