mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Fix data races triggered by functional tests. (#4247)
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. Guarded all mnauth fields of a CNode. Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
parent
edf0552c0c
commit
41190e9899
@ -56,7 +56,7 @@ void CCoinJoinServer::ProcessMessage(CNode* pfrom, const std::string& strCommand
|
||||
LogPrint(BCLog::COINJOIN, "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CCoinJoin::DenominationToString(dsa.nDenom), dsa.txCollateral.ToString()); /* Continued */
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint);
|
||||
auto dmn = WITH_LOCK(activeMasternodeInfoCs, return mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint));
|
||||
if (!dmn) {
|
||||
PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST, connman);
|
||||
return;
|
||||
@ -68,7 +68,7 @@ void CCoinJoinServer::ProcessMessage(CNode* pfrom, const std::string& strCommand
|
||||
if (!lockRecv) return;
|
||||
|
||||
for (const auto& q : vecCoinJoinQueue) {
|
||||
if (q.masternodeOutpoint == activeMasternodeInfo.outpoint) {
|
||||
if (WITH_LOCK(activeMasternodeInfoCs, return q.masternodeOutpoint == activeMasternodeInfo.outpoint)) {
|
||||
// refuse to create another queue this often
|
||||
LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq is still in queue, refuse to mix\n");
|
||||
PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman);
|
||||
@ -334,7 +334,7 @@ void CCoinJoinServer::CommitFinalTransaction(CConnman& connman)
|
||||
|
||||
// create and sign masternode dstx transaction
|
||||
if (!CCoinJoin::GetDSTX(hashTx)) {
|
||||
CCoinJoinBroadcastTx dstxNew(finalTransaction, activeMasternodeInfo.outpoint, GetAdjustedTime());
|
||||
CCoinJoinBroadcastTx dstxNew(finalTransaction, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), GetAdjustedTime());
|
||||
dstxNew.Sign();
|
||||
CCoinJoin::AddDSTX(dstxNew);
|
||||
}
|
||||
@ -501,7 +501,7 @@ void CCoinJoinServer::CheckForCompleteQueue(CConnman& connman)
|
||||
if (nState == POOL_STATE_QUEUE && IsSessionReady()) {
|
||||
SetState(POOL_STATE_ACCEPTING_ENTRIES);
|
||||
|
||||
CCoinJoinQueue dsq(nSessionDenom, activeMasternodeInfo.outpoint, GetAdjustedTime(), true);
|
||||
CCoinJoinQueue dsq(nSessionDenom, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), GetAdjustedTime(), true);
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s) " /* Continued */
|
||||
"with %d participants\n", dsq.ToString(), vecSessionCollaterals.size());
|
||||
dsq.Sign();
|
||||
@ -708,7 +708,7 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage&
|
||||
|
||||
if (!fUnitTest) {
|
||||
//broadcast that I'm accepting entries, only if it's the first entry through
|
||||
CCoinJoinQueue dsq(nSessionDenom, activeMasternodeInfo.outpoint, GetAdjustedTime(), false);
|
||||
CCoinJoinQueue dsq(nSessionDenom, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), GetAdjustedTime(), false);
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString());
|
||||
dsq.Sign();
|
||||
dsq.Relay(connman);
|
||||
|
@ -50,7 +50,7 @@ bool CCoinJoinQueue::Sign()
|
||||
|
||||
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash));
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@ -96,7 +96,7 @@ bool CCoinJoinBroadcastTx::Sign()
|
||||
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash));
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -18,31 +18,30 @@
|
||||
|
||||
void CMNAuth::PushMNAUTH(CNode* pnode, CConnman& connman)
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
if (!fMasternodeMode || activeMasternodeInfo.proTxHash.IsNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint256 signHash;
|
||||
{
|
||||
LOCK(pnode->cs_mnauth);
|
||||
if (pnode->receivedMNAuthChallenge.IsNull()) {
|
||||
return;
|
||||
}
|
||||
// We include fInbound in signHash to forbid interchanging of challenges by a man in the middle (MITM). This way
|
||||
// we protect ourselves against MITM in this form:
|
||||
// node1 <- Eve -> node2
|
||||
// It does not protect against:
|
||||
// node1 -> Eve -> node2
|
||||
// This is ok as we only use MNAUTH as a DoS protection and not for sensitive stuff
|
||||
int nOurNodeVersion{PROTOCOL_VERSION};
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) {
|
||||
nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION);
|
||||
}
|
||||
if (pnode->nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) {
|
||||
signHash = ::SerializeHash(std::make_tuple(*activeMasternodeInfo.blsPubKeyOperator, pnode->receivedMNAuthChallenge, pnode->fInbound));
|
||||
} else {
|
||||
signHash = ::SerializeHash(std::make_tuple(*activeMasternodeInfo.blsPubKeyOperator, pnode->receivedMNAuthChallenge, pnode->fInbound, nOurNodeVersion));
|
||||
}
|
||||
auto receivedMNAuthChallenge = pnode->GetReceivedMNAuthChallenge();
|
||||
if (receivedMNAuthChallenge.IsNull()) {
|
||||
return;
|
||||
}
|
||||
// We include fInbound in signHash to forbid interchanging of challenges by a man in the middle (MITM). This way
|
||||
// we protect ourselves against MITM in this form:
|
||||
// node1 <- Eve -> node2
|
||||
// It does not protect against:
|
||||
// node1 -> Eve -> node2
|
||||
// This is ok as we only use MNAUTH as a DoS protection and not for sensitive stuff
|
||||
int nOurNodeVersion{PROTOCOL_VERSION};
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) {
|
||||
nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION);
|
||||
}
|
||||
if (pnode->nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) {
|
||||
signHash = ::SerializeHash(std::make_tuple(*activeMasternodeInfo.blsPubKeyOperator, receivedMNAuthChallenge, pnode->fInbound));
|
||||
} else {
|
||||
signHash = ::SerializeHash(std::make_tuple(*activeMasternodeInfo.blsPubKeyOperator, receivedMNAuthChallenge, pnode->fInbound, nOurNodeVersion));
|
||||
}
|
||||
|
||||
CMNAuth mnauth;
|
||||
@ -66,11 +65,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS
|
||||
vRecv >> mnauth;
|
||||
|
||||
// only one MNAUTH allowed
|
||||
bool fAlreadyHaveMNAUTH = false;
|
||||
{
|
||||
LOCK(pnode->cs_mnauth);
|
||||
fAlreadyHaveMNAUTH = !pnode->verifiedProRegTxHash.IsNull();
|
||||
}
|
||||
bool fAlreadyHaveMNAUTH = !pnode->GetVerifiedProRegTxHash().IsNull();
|
||||
if (fAlreadyHaveMNAUTH) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pnode->GetId(), 100, "duplicate mnauth");
|
||||
@ -108,20 +103,17 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS
|
||||
}
|
||||
|
||||
uint256 signHash;
|
||||
{
|
||||
LOCK(pnode->cs_mnauth);
|
||||
int nOurNodeVersion{PROTOCOL_VERSION};
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) {
|
||||
nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION);
|
||||
}
|
||||
// See comment in PushMNAUTH (fInbound is negated here as we're on the other side of the connection)
|
||||
if (pnode->nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) {
|
||||
signHash = ::SerializeHash(std::make_tuple(dmn->pdmnState->pubKeyOperator, pnode->sentMNAuthChallenge, !pnode->fInbound));
|
||||
} else {
|
||||
signHash = ::SerializeHash(std::make_tuple(dmn->pdmnState->pubKeyOperator, pnode->sentMNAuthChallenge, !pnode->fInbound, pnode->nVersion.load()));
|
||||
}
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- constructed signHash for nVersion %d, peer=%d\n", __func__, pnode->nVersion, pnode->GetId());
|
||||
int nOurNodeVersion{PROTOCOL_VERSION};
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) {
|
||||
nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION);
|
||||
}
|
||||
// See comment in PushMNAUTH (fInbound is negated here as we're on the other side of the connection)
|
||||
if (pnode->nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) {
|
||||
signHash = ::SerializeHash(std::make_tuple(dmn->pdmnState->pubKeyOperator, pnode->GetSentMNAuthChallenge(), !pnode->fInbound));
|
||||
} else {
|
||||
signHash = ::SerializeHash(std::make_tuple(dmn->pdmnState->pubKeyOperator, pnode->GetSentMNAuthChallenge(), !pnode->fInbound, pnode->nVersion.load()));
|
||||
}
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- constructed signHash for nVersion %d, peer=%d\n", __func__, pnode->nVersion, pnode->GetId());
|
||||
|
||||
if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash)) {
|
||||
LOCK(cs_main);
|
||||
@ -147,12 +139,12 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS
|
||||
return;
|
||||
}
|
||||
|
||||
if (pnode2->verifiedProRegTxHash == mnauth.proRegTxHash) {
|
||||
if (pnode2->GetVerifiedProRegTxHash() == mnauth.proRegTxHash) {
|
||||
if (fMasternodeMode) {
|
||||
auto deterministicOutbound = llmq::CLLMQUtils::DeterministicOutboundConnection(activeMasternodeInfo.proTxHash, mnauth.proRegTxHash);
|
||||
auto deterministicOutbound = WITH_LOCK(activeMasternodeInfoCs, return llmq::CLLMQUtils::DeterministicOutboundConnection(activeMasternodeInfo.proTxHash, mnauth.proRegTxHash));
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- Masternode %s has already verified as peer %d, deterministicOutbound=%s. peer=%d\n",
|
||||
mnauth.proRegTxHash.ToString(), pnode2->GetId(), deterministicOutbound.ToString(), pnode->GetId());
|
||||
if (deterministicOutbound == activeMasternodeInfo.proTxHash) {
|
||||
if (WITH_LOCK(activeMasternodeInfoCs, return deterministicOutbound == activeMasternodeInfo.proTxHash)) {
|
||||
if (pnode2->fInbound) {
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- dropping old inbound, peer=%d\n", pnode2->GetId());
|
||||
pnode2->fDisconnect = true;
|
||||
@ -181,13 +173,10 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(pnode->cs_mnauth);
|
||||
pnode->verifiedProRegTxHash = mnauth.proRegTxHash;
|
||||
pnode->verifiedPubKeyHash = dmn->pdmnState->pubKeyOperator.GetHash();
|
||||
}
|
||||
pnode->SetVerifiedProRegTxHash(mnauth.proRegTxHash);
|
||||
pnode->SetVerifiedPubKeyHash(dmn->pdmnState->pubKeyOperator.GetHash());
|
||||
|
||||
if (!pnode->m_masternode_iqr_connection && connman.IsMasternodeQuorumRelayMember(pnode->verifiedProRegTxHash)) {
|
||||
if (!pnode->m_masternode_iqr_connection && connman.IsMasternodeQuorumRelayMember(pnode->GetVerifiedProRegTxHash())) {
|
||||
// Tell our peer that we're interested in plain LLMQ recovered signatures.
|
||||
// Otherwise the peer would only announce/send messages resulting from QRECSIG,
|
||||
// e.g. InstantSend locks or ChainLocks. SPV and regular full nodes should not send
|
||||
@ -209,11 +198,11 @@ void CMNAuth::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList&
|
||||
}
|
||||
|
||||
g_connman->ForEachNode([&](CNode* pnode) {
|
||||
LOCK(pnode->cs_mnauth);
|
||||
if (pnode->verifiedProRegTxHash.IsNull()) {
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (verifiedProRegTxHash.IsNull()) {
|
||||
return;
|
||||
}
|
||||
auto verifiedDmn = oldMNList.GetMN(pnode->verifiedProRegTxHash);
|
||||
auto verifiedDmn = oldMNList.GetMN(verifiedProRegTxHash);
|
||||
if (!verifiedDmn) {
|
||||
return;
|
||||
}
|
||||
@ -223,7 +212,7 @@ void CMNAuth::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList&
|
||||
} else {
|
||||
auto it = diff.updatedMNs.find(verifiedDmn->GetInternalId());
|
||||
if (it != diff.updatedMNs.end()) {
|
||||
if ((it->second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && it->second.state.pubKeyOperator.GetHash() != pnode->verifiedPubKeyHash) {
|
||||
if ((it->second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && it->second.state.pubKeyOperator.GetHash() != pnode->GetVerifiedPubKeyHash()) {
|
||||
doRemove = true;
|
||||
}
|
||||
}
|
||||
@ -231,7 +220,7 @@ void CMNAuth::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList&
|
||||
|
||||
if (doRemove) {
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::NotifyMasternodeListChanged -- Disconnecting MN %s due to key changed/removed, peer=%d\n",
|
||||
pnode->verifiedProRegTxHash.ToString(), pnode->GetId());
|
||||
verifiedProRegTxHash.ToString(), pnode->GetId());
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
});
|
||||
|
30
src/init.cpp
30
src/init.cpp
@ -369,9 +369,12 @@ void PrepareShutdown()
|
||||
UnregisterValidationInterface(activeMasternodeManager);
|
||||
}
|
||||
|
||||
// make sure to clean up BLS keys before global destructors are called (they have allocated from the secure memory pool)
|
||||
activeMasternodeInfo.blsKeyOperator.reset();
|
||||
activeMasternodeInfo.blsPubKeyOperator.reset();
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
// make sure to clean up BLS keys before global destructors are called (they have allocated from the secure memory pool)
|
||||
activeMasternodeInfo.blsKeyOperator.reset();
|
||||
activeMasternodeInfo.blsPubKeyOperator.reset();
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
try {
|
||||
@ -2329,8 +2332,12 @@ bool AppInitMain()
|
||||
return InitError(_("Invalid masternodeblsprivkey. Please see documentation."));
|
||||
}
|
||||
fMasternodeMode = true;
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>(keyOperator);
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>(activeMasternodeInfo.blsKeyOperator->GetPublicKey());
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>(keyOperator);
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>(
|
||||
activeMasternodeInfo.blsKeyOperator->GetPublicKey());
|
||||
}
|
||||
LogPrintf("MASTERNODE:\n");
|
||||
LogPrintf(" blsPubKeyOperator: %s\n", keyOperator.GetPublicKey().ToString());
|
||||
}
|
||||
@ -2341,11 +2348,14 @@ bool AppInitMain()
|
||||
RegisterValidationInterface(activeMasternodeManager);
|
||||
}
|
||||
|
||||
if (activeMasternodeInfo.blsKeyOperator == nullptr) {
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>();
|
||||
}
|
||||
if (activeMasternodeInfo.blsPubKeyOperator == nullptr) {
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>();
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
if (activeMasternodeInfo.blsKeyOperator == nullptr) {
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>();
|
||||
}
|
||||
if (activeMasternodeInfo.blsPubKeyOperator == nullptr) {
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>();
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************* Step 10b: setup CoinJoin
|
||||
|
@ -61,7 +61,10 @@ void CQuorum::Init(const CFinalCommitmentPtr& _qc, const CBlockIndex* _pindexQuo
|
||||
|
||||
bool CQuorum::SetVerificationVector(const BLSVerificationVector& quorumVecIn)
|
||||
{
|
||||
if (::SerializeHash(quorumVecIn) != qc->quorumVvecHash) {
|
||||
const auto quorumVecInSerialized = ::SerializeHash(quorumVecIn);
|
||||
|
||||
LOCK(cs);
|
||||
if (quorumVecInSerialized != qc->quorumVvecHash) {
|
||||
return false;
|
||||
}
|
||||
quorumVvec = std::make_shared<BLSVerificationVector>(quorumVecIn);
|
||||
@ -70,9 +73,10 @@ bool CQuorum::SetVerificationVector(const BLSVerificationVector& quorumVecIn)
|
||||
|
||||
bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare)
|
||||
{
|
||||
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(GetMemberIndex(activeMasternodeInfo.proTxHash)))) {
|
||||
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(WITH_LOCK(activeMasternodeInfoCs, return GetMemberIndex(activeMasternodeInfo.proTxHash))))) {
|
||||
return false;
|
||||
}
|
||||
LOCK(cs);
|
||||
skShare = secretKeyShare;
|
||||
return true;
|
||||
}
|
||||
@ -99,15 +103,22 @@ bool CQuorum::IsValidMember(const uint256& proTxHash) const
|
||||
|
||||
CBLSPublicKey CQuorum::GetPubKeyShare(size_t memberIdx) const
|
||||
{
|
||||
if (quorumVvec == nullptr || memberIdx >= members.size() || !qc->validMembers[memberIdx]) {
|
||||
LOCK(cs);
|
||||
if (!HasVerificationVector() || memberIdx >= members.size() || !qc->validMembers[memberIdx]) {
|
||||
return CBLSPublicKey();
|
||||
}
|
||||
auto& m = members[memberIdx];
|
||||
return blsCache.BuildPubKeyShare(m->proTxHash, quorumVvec, CBLSId(m->proTxHash));
|
||||
}
|
||||
|
||||
const CBLSSecretKey& CQuorum::GetSkShare() const
|
||||
bool CQuorum::HasVerificationVector() const {
|
||||
LOCK(cs);
|
||||
return quorumVvec != nullptr;
|
||||
}
|
||||
|
||||
CBLSSecretKey CQuorum::GetSkShare() const
|
||||
{
|
||||
LOCK(cs);
|
||||
return skShare;
|
||||
}
|
||||
|
||||
@ -125,7 +136,8 @@ void CQuorum::WriteContributions(CEvoDB& evoDb) const
|
||||
{
|
||||
uint256 dbKey = MakeQuorumKey(*this);
|
||||
|
||||
if (quorumVvec != nullptr) {
|
||||
LOCK(cs);
|
||||
if (HasVerificationVector()) {
|
||||
evoDb.GetRawDB().Write(std::make_pair(DB_QUORUM_QUORUM_VVEC, dbKey), *quorumVvec);
|
||||
}
|
||||
if (skShare.IsValid()) {
|
||||
@ -139,14 +151,14 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb)
|
||||
|
||||
BLSVerificationVector qv;
|
||||
if (evoDb.Read(std::make_pair(DB_QUORUM_QUORUM_VVEC, dbKey), qv)) {
|
||||
quorumVvec = std::make_shared<BLSVerificationVector>(std::move(qv));
|
||||
WITH_LOCK(cs, quorumVvec = std::make_shared<BLSVerificationVector>(std::move(qv)));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We ignore the return value here as it is ok if this fails. If it fails, it usually means that we are not a
|
||||
// member of the quorum but observed the whole DKG process to have the quorum verification vector.
|
||||
evoDb.Read(std::make_pair(DB_QUORUM_SK_SHARE, dbKey), skShare);
|
||||
WITH_LOCK(cs, evoDb.Read(std::make_pair(DB_QUORUM_SK_SHARE, dbKey), skShare));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -197,8 +209,10 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)
|
||||
|
||||
// First check if we are member of any quorum of this type
|
||||
bool fWeAreQuorumTypeMember{false};
|
||||
|
||||
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
for (const auto& pQuorum : vecQuorums) {
|
||||
if (pQuorum->IsValidMember(activeMasternodeInfo.proTxHash)) {
|
||||
if (pQuorum->IsValidMember(proTxHash)) {
|
||||
fWeAreQuorumTypeMember = true;
|
||||
break;
|
||||
}
|
||||
@ -211,16 +225,16 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)
|
||||
}
|
||||
|
||||
uint16_t nDataMask{0};
|
||||
const bool fWeAreQuorumMember = pQuorum->IsValidMember(activeMasternodeInfo.proTxHash);
|
||||
const bool fWeAreQuorumMember = pQuorum->IsValidMember(proTxHash);
|
||||
const bool fSyncForTypeEnabled = mapQuorumVvecSync.count(pQuorum->qc->llmqType) > 0;
|
||||
const QvvecSyncMode syncMode = fSyncForTypeEnabled ? mapQuorumVvecSync.at(pQuorum->qc->llmqType) : QvvecSyncMode::Invalid;
|
||||
const bool fSyncCurrent = syncMode == QvvecSyncMode::Always || (syncMode == QvvecSyncMode::OnlyIfTypeMember && fWeAreQuorumTypeMember);
|
||||
|
||||
if ((fWeAreQuorumMember || (fSyncForTypeEnabled && fSyncCurrent)) && pQuorum->quorumVvec == nullptr) {
|
||||
if ((fWeAreQuorumMember || (fSyncForTypeEnabled && fSyncCurrent)) && !pQuorum->HasVerificationVector()) {
|
||||
nDataMask |= llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR;
|
||||
}
|
||||
|
||||
if (fWeAreQuorumMember && !pQuorum->skShare.IsValid()) {
|
||||
if (fWeAreQuorumMember && !pQuorum->GetSkShare().IsValid()) {
|
||||
nDataMask |= llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS;
|
||||
}
|
||||
|
||||
@ -266,7 +280,6 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const
|
||||
{
|
||||
const auto& llmq_params = GetLLMQParams(llmqType);
|
||||
|
||||
const auto& myProTxHash = activeMasternodeInfo.proTxHash;
|
||||
auto lastQuorums = ScanQuorums(llmqType, pindexNew, (size_t)llmq_params.keepOldConnections);
|
||||
|
||||
auto connmanQuorumsToDelete = g_connman->GetMasternodeQuorums(llmqType);
|
||||
@ -277,7 +290,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const
|
||||
connmanQuorumsToDelete.erase(curDkgBlock);
|
||||
|
||||
for (const auto& quorum : lastQuorums) {
|
||||
if (CLLMQUtils::EnsureQuorumConnections(llmqType, quorum->pindexQuorum, myProTxHash)) {
|
||||
if (CLLMQUtils::EnsureQuorumConnections(llmqType, quorum->pindexQuorum, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
continue;
|
||||
}
|
||||
if (connmanQuorumsToDelete.count(quorum->qc->quorumHash) > 0) {
|
||||
@ -339,8 +352,9 @@ bool CQuorumManager::BuildQuorumContributions(const CFinalCommitmentPtr& fqc, co
|
||||
}
|
||||
|
||||
cxxtimer::Timer t2(true);
|
||||
LOCK(quorum->cs);
|
||||
quorum->quorumVvec = blsWorker.BuildQuorumVerificationVector(vvecs);
|
||||
if (quorum->quorumVvec == nullptr) {
|
||||
if (!quorum->HasVerificationVector()) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build quorumVvec\n", __func__);
|
||||
// without the quorum vvec, there can't be a skShare, so we fail here. Failure is not fatal here, as it still
|
||||
// allows to use the quorum as a non-member (verification through the quorum pub key)
|
||||
@ -371,7 +385,7 @@ bool CQuorumManager::RequestQuorumData(CNode* pFrom, Consensus::LLMQType llmqTyp
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Version must be %d or greater.\n", __func__, LLMQ_DATA_MESSAGES_VERSION);
|
||||
return false;
|
||||
}
|
||||
if (pFrom == nullptr || (pFrom->verifiedProRegTxHash.IsNull() && !pFrom->qwatch)) {
|
||||
if (pFrom == nullptr || (pFrom->GetVerifiedProRegTxHash().IsNull() && !pFrom->qwatch)) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- pFrom is neither a verified masternode nor a qwatch connection\n", __func__);
|
||||
return false;
|
||||
}
|
||||
@ -389,7 +403,7 @@ bool CQuorumManager::RequestQuorumData(CNode* pFrom, Consensus::LLMQType llmqTyp
|
||||
}
|
||||
|
||||
LOCK(cs_data_requests);
|
||||
auto key = std::make_pair(pFrom->verifiedProRegTxHash, true);
|
||||
auto key = std::make_pair(pFrom->GetVerifiedProRegTxHash(), true);
|
||||
auto it = mapQuorumDataRequests.emplace(key, CQuorumDataRequest(llmqType, pQuorumIndex->GetBlockHash(), nDataMask, proTxHash));
|
||||
if (!it.second && !it.first->second.IsExpired()) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already requested\n", __func__);
|
||||
@ -517,10 +531,13 @@ size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, c
|
||||
});
|
||||
std::sort(vecProTxHashes.begin(), vecProTxHashes.end());
|
||||
size_t nIndex{0};
|
||||
for (size_t i = 0; i < vecProTxHashes.size(); ++i) {
|
||||
if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) {
|
||||
nIndex = i;
|
||||
break;
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
for (size_t i = 0; i < vecProTxHashes.size(); ++i) {
|
||||
if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) {
|
||||
nIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nIndex % pQuorum->qc->validMembers.size();
|
||||
@ -539,7 +556,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
|
||||
if (strCommand == NetMsgType::QGETDATA) {
|
||||
|
||||
if (!fMasternodeMode || pFrom == nullptr || (pFrom->verifiedProRegTxHash.IsNull() && !pFrom->qwatch)) {
|
||||
if (!fMasternodeMode || pFrom == nullptr || (pFrom->GetVerifiedProRegTxHash().IsNull() && !pFrom->qwatch)) {
|
||||
errorHandler("Not a verified masternode or a qwatch connection");
|
||||
return;
|
||||
}
|
||||
@ -556,7 +573,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
|
||||
{
|
||||
LOCK2(cs_main, cs_data_requests);
|
||||
auto key = std::make_pair(pFrom->verifiedProRegTxHash, false);
|
||||
auto key = std::make_pair(pFrom->GetVerifiedProRegTxHash(), false);
|
||||
auto it = mapQuorumDataRequests.find(key);
|
||||
if (it == mapQuorumDataRequests.end()) {
|
||||
it = mapQuorumDataRequests.emplace(key, request).first;
|
||||
@ -592,13 +609,12 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
|
||||
// Check if request wants QUORUM_VERIFICATION_VECTOR data
|
||||
if (request.GetDataMask() & CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR) {
|
||||
|
||||
if (!pQuorum->quorumVvec) {
|
||||
if (!pQuorum->HasVerificationVector()) {
|
||||
sendQDATA(CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING);
|
||||
return;
|
||||
}
|
||||
|
||||
ssResponseData << *pQuorum->quorumVvec;
|
||||
WITH_LOCK(pQuorum->cs, ssResponseData << *pQuorum->quorumVvec);
|
||||
}
|
||||
|
||||
// Check if request wants ENCRYPTED_CONTRIBUTIONS data
|
||||
@ -624,8 +640,8 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
}
|
||||
|
||||
if (strCommand == NetMsgType::QDATA) {
|
||||
|
||||
if ((!fMasternodeMode && !CLLMQUtils::IsWatchQuorumsEnabled()) || pFrom == nullptr || (pFrom->verifiedProRegTxHash.IsNull() && !pFrom->qwatch)) {
|
||||
auto verifiedProRegTxHash = pFrom->GetVerifiedProRegTxHash();
|
||||
if ((!fMasternodeMode && !CLLMQUtils::IsWatchQuorumsEnabled()) || pFrom == nullptr || (verifiedProRegTxHash.IsNull() && !pFrom->qwatch)) {
|
||||
errorHandler("Not a verified masternode or a qwatch connection");
|
||||
return;
|
||||
}
|
||||
@ -635,7 +651,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
|
||||
{
|
||||
LOCK2(cs_main, cs_data_requests);
|
||||
auto it = mapQuorumDataRequests.find(std::make_pair(pFrom->verifiedProRegTxHash, true));
|
||||
auto it = mapQuorumDataRequests.find(std::make_pair(verifiedProRegTxHash, true));
|
||||
if (it == mapQuorumDataRequests.end()) {
|
||||
errorHandler("Not requested");
|
||||
return;
|
||||
@ -682,7 +698,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
// Check if request has ENCRYPTED_CONTRIBUTIONS data
|
||||
if (request.GetDataMask() & CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) {
|
||||
|
||||
if (pQuorum->quorumVvec->size() != pQuorum->params.threshold) {
|
||||
if (WITH_LOCK(pQuorum->cs, return pQuorum->quorumVvec->size() != pQuorum->params.threshold)) {
|
||||
errorHandler("No valid quorum verification vector available", 0); // Don't bump score because we asked for it
|
||||
return;
|
||||
}
|
||||
@ -698,8 +714,9 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
|
||||
BLSSecretKeyVector vecSecretKeys;
|
||||
vecSecretKeys.resize(vecEncrypted.size());
|
||||
auto secret = WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator);
|
||||
for (size_t i = 0; i < vecEncrypted.size(); ++i) {
|
||||
if (!vecEncrypted[i].Decrypt(memberIdx, *activeMasternodeInfo.blsKeyOperator, vecSecretKeys[i], PROTOCOL_VERSION)) {
|
||||
if (!vecEncrypted[i].Decrypt(memberIdx, secret, vecSecretKeys[i], PROTOCOL_VERSION)) {
|
||||
errorHandler("Failed to decrypt");
|
||||
return;
|
||||
}
|
||||
@ -718,7 +735,7 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
|
||||
|
||||
void CQuorumManager::StartCachePopulatorThread(const CQuorumCPtr pQuorum) const
|
||||
{
|
||||
if (pQuorum->quorumVvec == nullptr) {
|
||||
if (!pQuorum->HasVerificationVector()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -771,7 +788,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
|
||||
|
||||
vecMemberHashes.reserve(pQuorum->qc->validMembers.size());
|
||||
for (auto& member : pQuorum->members) {
|
||||
if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != activeMasternodeInfo.proTxHash) {
|
||||
if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash)) {
|
||||
vecMemberHashes.push_back(member->proTxHash);
|
||||
}
|
||||
}
|
||||
@ -781,12 +798,13 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
|
||||
|
||||
while (nDataMask > 0 && !quorumThreadInterrupt) {
|
||||
|
||||
if (nDataMask & llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR && pQuorum->quorumVvec != nullptr) {
|
||||
if (nDataMask & llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR &&
|
||||
pQuorum->HasVerificationVector()) {
|
||||
nDataMask &= ~llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR;
|
||||
printLog("Received quorumVvec");
|
||||
}
|
||||
|
||||
if (nDataMask & llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS && pQuorum->skShare.IsValid()) {
|
||||
if (nDataMask & llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS && pQuorum->GetSkShare().IsValid()) {
|
||||
nDataMask &= ~llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS;
|
||||
printLog("Received skShare");
|
||||
}
|
||||
@ -818,18 +836,19 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
|
||||
printLog("Connect");
|
||||
}
|
||||
|
||||
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
g_connman->ForEachNode([&](CNode* pNode) {
|
||||
|
||||
if (pCurrentMemberHash == nullptr || pNode->verifiedProRegTxHash != *pCurrentMemberHash) {
|
||||
auto verifiedProRegTxHash = pNode->GetVerifiedProRegTxHash();
|
||||
if (pCurrentMemberHash == nullptr || verifiedProRegTxHash != *pCurrentMemberHash) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (quorumManager->RequestQuorumData(pNode, pQuorum->qc->llmqType, pQuorum->pindexQuorum, nDataMask, activeMasternodeInfo.proTxHash)) {
|
||||
if (quorumManager->RequestQuorumData(pNode, pQuorum->qc->llmqType, pQuorum->pindexQuorum, nDataMask, proTxHash)) {
|
||||
nTimeLastSuccess = GetAdjustedTime();
|
||||
printLog("Requested");
|
||||
} else {
|
||||
LOCK(cs_data_requests);
|
||||
auto it = mapQuorumDataRequests.find(std::make_pair(pNode->verifiedProRegTxHash, true));
|
||||
auto it = mapQuorumDataRequests.find(std::make_pair(verifiedProRegTxHash, true));
|
||||
if (it == mapQuorumDataRequests.end()) {
|
||||
printLog("Failed");
|
||||
pNode->fDisconnect = true;
|
||||
|
@ -157,16 +157,17 @@ public:
|
||||
uint256 minedBlockHash;
|
||||
std::vector<CDeterministicMNCPtr> members;
|
||||
|
||||
// These are only valid when we either participated in the DKG or fully watched it
|
||||
BLSVerificationVectorPtr quorumVvec;
|
||||
CBLSSecretKey skShare;
|
||||
|
||||
private:
|
||||
// Recovery of public key shares is very slow, so we start a background thread that pre-populates a cache so that
|
||||
// the public key shares are ready when needed later
|
||||
mutable CBLSWorkerCache blsCache;
|
||||
mutable std::atomic<bool> fQuorumDataRecoveryThreadRunning{false};
|
||||
|
||||
mutable CCriticalSection cs;
|
||||
// These are only valid when we either participated in the DKG or fully watched it
|
||||
BLSVerificationVectorPtr quorumVvec GUARDED_BY(cs);
|
||||
CBLSSecretKey skShare GUARDED_BY(cs);
|
||||
|
||||
public:
|
||||
CQuorum(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker);
|
||||
~CQuorum();
|
||||
@ -175,12 +176,13 @@ public:
|
||||
bool SetVerificationVector(const BLSVerificationVector& quorumVecIn);
|
||||
bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare);
|
||||
|
||||
bool HasVerificationVector() const;
|
||||
bool IsMember(const uint256& proTxHash) const;
|
||||
bool IsValidMember(const uint256& proTxHash) const;
|
||||
int GetMemberIndex(const uint256& proTxHash) const;
|
||||
|
||||
CBLSPublicKey GetPubKeyShare(size_t memberIdx) const;
|
||||
const CBLSSecretKey& GetSkShare() const;
|
||||
CBLSSecretKey GetSkShare() const;
|
||||
|
||||
private:
|
||||
void WriteContributions(CEvoDB& evoDb) const;
|
||||
|
@ -199,7 +199,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages)
|
||||
|
||||
logger.Batch("encrypted contributions. time=%d", t1.count());
|
||||
|
||||
qc.sig = activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash());
|
||||
qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash()));
|
||||
|
||||
logger.Flush();
|
||||
|
||||
@ -324,7 +324,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
|
||||
|
||||
bool complain = false;
|
||||
CBLSSecretKey skContribution;
|
||||
if (!qc.contributions->Decrypt(myIdx, *activeMasternodeInfo.blsKeyOperator, skContribution, PROTOCOL_VERSION)) {
|
||||
if (!qc.contributions->Decrypt(myIdx, WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator), skContribution, PROTOCOL_VERSION)) {
|
||||
logger.Batch("contribution from %s could not be decrypted", member->dmn->proTxHash.ToString());
|
||||
complain = true;
|
||||
} else if (member->idx != myIdx && ShouldSimulateError("complain-lie")) {
|
||||
@ -466,10 +466,11 @@ void CDKGSession::VerifyConnectionAndMinProtoVersions() const
|
||||
|
||||
std::unordered_map<uint256, int, StaticSaltedHasher> protoMap;
|
||||
g_connman->ForEachNode([&](const CNode* pnode) {
|
||||
if (pnode->verifiedProRegTxHash.IsNull()) {
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (verifiedProRegTxHash.IsNull()) {
|
||||
return;
|
||||
}
|
||||
protoMap.emplace(pnode->verifiedProRegTxHash, pnode->nVersion);
|
||||
protoMap.emplace(verifiedProRegTxHash, pnode->nVersion);
|
||||
});
|
||||
|
||||
bool fShouldAllMembersBeConnected = CLLMQUtils::IsAllMembersConnectedEnabled(params.type);
|
||||
@ -525,7 +526,7 @@ void CDKGSession::SendComplaint(CDKGPendingMessages& pendingMessages)
|
||||
|
||||
logger.Batch("sending complaint. badCount=%d, complaintCount=%d", badCount, complaintCount);
|
||||
|
||||
qc.sig = activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash());
|
||||
qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash()));
|
||||
|
||||
logger.Flush();
|
||||
|
||||
@ -725,7 +726,7 @@ void CDKGSession::SendJustification(CDKGPendingMessages& pendingMessages, const
|
||||
return;
|
||||
}
|
||||
|
||||
qj.sig = activeMasternodeInfo.blsKeyOperator->Sign(qj.GetSignHash());
|
||||
qj.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qj.GetSignHash()));
|
||||
|
||||
logger.Flush();
|
||||
|
||||
@ -1027,7 +1028,7 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages)
|
||||
(*commitmentHash.begin())++;
|
||||
}
|
||||
|
||||
qc.sig = activeMasternodeInfo.blsKeyOperator->Sign(commitmentHash);
|
||||
qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(commitmentHash));
|
||||
qc.quorumSig = skShare.Sign(commitmentHash);
|
||||
|
||||
if (lieType == 3) {
|
||||
@ -1334,9 +1335,10 @@ void CDKGSession::RelayInvToParticipants(const CInv& inv) const
|
||||
LOCK(invCs);
|
||||
g_connman->ForEachNode([&](CNode* pnode) {
|
||||
bool relay = false;
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (pnode->qwatch) {
|
||||
relay = true;
|
||||
} else if (!pnode->verifiedProRegTxHash.IsNull() && relayMembers.count(pnode->verifiedProRegTxHash)) {
|
||||
} else if (!verifiedProRegTxHash.IsNull() && relayMembers.count(verifiedProRegTxHash)) {
|
||||
relay = true;
|
||||
}
|
||||
if (relay) {
|
||||
|
@ -166,7 +166,7 @@ bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pindexQuorum)
|
||||
|
||||
auto mns = CLLMQUtils::GetAllQuorumMembers(params.type, pindexQuorum);
|
||||
|
||||
if (!curSession->Init(pindexQuorum, mns, activeMasternodeInfo.proTxHash)) {
|
||||
if (!curSession->Init(pindexQuorum, mns, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
LogPrintf("CDKGSessionManager::%s -- quorum initialization failed for %s\n", __func__, curSession->params.name);
|
||||
return false;
|
||||
}
|
||||
|
@ -784,7 +784,7 @@ void CSigningManager::UnregisterRecoveredSigsListener(CRecoveredSigsListener* l)
|
||||
|
||||
bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash, const uint256& quorumHash, bool allowReSign)
|
||||
{
|
||||
if (!fMasternodeMode || activeMasternodeInfo.proTxHash.IsNull()) {
|
||||
if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -805,7 +805,7 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, const uint
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!quorum->IsValidMember(activeMasternodeInfo.proTxHash)) {
|
||||
if (!WITH_LOCK(activeMasternodeInfoCs, return quorum->IsValidMember(activeMasternodeInfo.proTxHash))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ void CSigSharesManager::InterruptWorkerThread()
|
||||
void CSigSharesManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv)
|
||||
{
|
||||
// non-masternodes are not interested in sigshares
|
||||
if (!fMasternodeMode || activeMasternodeInfo.proTxHash.IsNull()) {
|
||||
if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ bool CSigSharesManager::ProcessMessageSigSharesInv(CNode* pfrom, const CSigShare
|
||||
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__,
|
||||
sessionInfo.signHash.ToString(), inv.ToString(), pfrom->GetId());
|
||||
|
||||
if (sessionInfo.quorum->quorumVvec == nullptr) {
|
||||
if (!sessionInfo.quorum->HasVerificationVector()) {
|
||||
// TODO we should allow to ask other nodes for the quorum vvec if we missed it in the DKG
|
||||
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have the quorum vvec for %s, not requesting sig shares. node=%d\n", __func__,
|
||||
sessionInfo.quorumHash.ToString(), pfrom->GetId());
|
||||
@ -485,11 +485,11 @@ void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& s
|
||||
// quorum is too old
|
||||
return;
|
||||
}
|
||||
if (!quorum->IsMember(activeMasternodeInfo.proTxHash)) {
|
||||
if (!quorum->IsMember(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
// we're not a member so we can't verify it (we actually shouldn't have received it)
|
||||
return;
|
||||
}
|
||||
if (quorum->quorumVvec == nullptr) {
|
||||
if (!quorum->HasVerificationVector()) {
|
||||
// TODO we should allow to ask other nodes for the quorum vvec if we missed it in the DKG
|
||||
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have the quorum vvec for %s, no verification possible. node=%d\n", __func__,
|
||||
quorum->qc->quorumHash.ToString(), fromId);
|
||||
@ -534,11 +534,11 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(const CSigSharesNodeState::Ses
|
||||
// quorum is too old
|
||||
return false;
|
||||
}
|
||||
if (!session.quorum->IsMember(activeMasternodeInfo.proTxHash)) {
|
||||
if (!session.quorum->IsMember(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
// we're not a member so we can't verify it (we actually shouldn't have received it)
|
||||
return false;
|
||||
}
|
||||
if (session.quorum->quorumVvec == nullptr) {
|
||||
if (!session.quorum->HasVerificationVector()) {
|
||||
// TODO we should allow to ask other nodes for the quorum vvec if we missed it in the DKG
|
||||
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have the quorum vvec for %s, no verification possible.\n", __func__,
|
||||
session.quorumHash.ToString());
|
||||
@ -730,7 +730,7 @@ void CSigSharesManager::ProcessSigShare(const CSigShare& sigShare, CConnman& con
|
||||
|
||||
// prepare node set for direct-push in case this is our sig share
|
||||
std::set<NodeId> quorumNodes;
|
||||
if (!CLLMQUtils::IsAllMembersConnectedEnabled(llmqType) && sigShare.quorumMember == quorum->GetMemberIndex(activeMasternodeInfo.proTxHash)) {
|
||||
if (!CLLMQUtils::IsAllMembersConnectedEnabled(llmqType) && sigShare.quorumMember == quorum->GetMemberIndex(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
quorumNodes = connman.GetMasternodeQuorumNodes(sigShare.llmqType, sigShare.quorumHash);
|
||||
}
|
||||
|
||||
@ -1018,10 +1018,11 @@ void CSigSharesManager::CollectSigSharesToSendConcentrated(std::unordered_map<No
|
||||
|
||||
std::unordered_map<uint256, CNode*> proTxToNode;
|
||||
for (const auto& pnode : vNodes) {
|
||||
if (pnode->verifiedProRegTxHash.IsNull()) {
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (verifiedProRegTxHash.IsNull()) {
|
||||
continue;
|
||||
}
|
||||
proTxToNode.emplace(pnode->verifiedProRegTxHash, pnode);
|
||||
proTxToNode.emplace(verifiedProRegTxHash, pnode);
|
||||
}
|
||||
|
||||
auto curTime = GetTime<std::chrono::milliseconds>().count();
|
||||
@ -1567,8 +1568,9 @@ void CSigSharesManager::SignPendingSigShares()
|
||||
CSigShare CSigSharesManager::CreateSigShare(const CQuorumCPtr& quorum, const uint256& id, const uint256& msgHash) const
|
||||
{
|
||||
cxxtimer::Timer t(true);
|
||||
auto activeMasterNodeProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
|
||||
if (!quorum->IsValidMember(activeMasternodeInfo.proTxHash)) {
|
||||
if (!quorum->IsValidMember(activeMasterNodeProTxHash)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -1578,7 +1580,7 @@ CSigShare CSigSharesManager::CreateSigShare(const CQuorumCPtr& quorum, const uin
|
||||
return {};
|
||||
}
|
||||
|
||||
int memberIdx = quorum->GetMemberIndex(activeMasternodeInfo.proTxHash);
|
||||
int memberIdx = quorum->GetMemberIndex(activeMasterNodeProTxHash);
|
||||
if (memberIdx == -1) {
|
||||
// this should really not happen (IsValidMember gave true)
|
||||
return {};
|
||||
|
@ -15,7 +15,8 @@
|
||||
#include <bls/bls.h>
|
||||
|
||||
// Keep track of the active Masternode
|
||||
CActiveMasternodeInfo activeMasternodeInfo;
|
||||
CCriticalSection activeMasternodeInfoCs;
|
||||
CActiveMasternodeInfo activeMasternodeInfo GUARDED_BY(activeMasternodeInfoCs);
|
||||
CActiveMasternodeManager* activeMasternodeManager;
|
||||
|
||||
std::string CActiveMasternodeManager::GetStateString() const
|
||||
@ -64,7 +65,7 @@ std::string CActiveMasternodeManager::GetStatus() const
|
||||
|
||||
void CActiveMasternodeManager::Init(const CBlockIndex* pindex)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
LOCK2(cs_main, activeMasternodeInfoCs);
|
||||
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
@ -136,7 +137,7 @@ void CActiveMasternodeManager::Init(const CBlockIndex* pindex)
|
||||
|
||||
void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
LOCK2(cs_main, activeMasternodeInfoCs);
|
||||
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
@ -201,10 +202,11 @@ bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet)
|
||||
if (!fFoundLocal) {
|
||||
bool empty = true;
|
||||
// If we have some peers, let's try to find our local address from one of them
|
||||
g_connman->ForEachNodeContinueIf(CConnman::AllNodes, [&fFoundLocal, &empty](CNode* pnode) {
|
||||
auto service = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.service);
|
||||
g_connman->ForEachNodeContinueIf(CConnman::AllNodes, [&](CNode* pnode) {
|
||||
empty = false;
|
||||
if (pnode->addr.IsIPv4())
|
||||
fFoundLocal = GetLocal(activeMasternodeInfo.service, &pnode->addr) && IsValidNetAddr(activeMasternodeInfo.service);
|
||||
fFoundLocal = GetLocal(service, &pnode->addr) && IsValidNetAddr(service);
|
||||
return !fFoundLocal;
|
||||
});
|
||||
// nothing and no live connections, can't do anything for now
|
||||
|
@ -16,6 +16,7 @@ struct CActiveMasternodeInfo;
|
||||
class CActiveMasternodeManager;
|
||||
|
||||
extern CActiveMasternodeInfo activeMasternodeInfo;
|
||||
extern CCriticalSection activeMasternodeInfoCs;
|
||||
extern CActiveMasternodeManager* activeMasternodeManager;
|
||||
|
||||
struct CActiveMasternodeInfo {
|
||||
|
26
src/net.cpp
26
src/net.cpp
@ -925,7 +925,7 @@ bool CConnman::AttemptToEvictConnection()
|
||||
}
|
||||
// if MNAUTH was valid, the node is always protected (and at the same time not accounted when
|
||||
// checking incoming connection limits)
|
||||
if (!node->verifiedProRegTxHash.IsNull()) {
|
||||
if (!node->GetVerifiedProRegTxHash().IsNull()) {
|
||||
isProtected = true;
|
||||
}
|
||||
if (isProtected) {
|
||||
@ -1036,7 +1036,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
for (const CNode* pnode : vNodes) {
|
||||
if (pnode->fInbound) {
|
||||
nInbound++;
|
||||
if (!pnode->verifiedProRegTxHash.IsNull()) {
|
||||
if (!pnode->GetVerifiedProRegTxHash().IsNull()) {
|
||||
nVerifiedInboundMasternodes++;
|
||||
}
|
||||
}
|
||||
@ -2251,8 +2251,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes) {
|
||||
if (!pnode->verifiedProRegTxHash.IsNull()) {
|
||||
setConnectedMasternodes.emplace(pnode->verifiedProRegTxHash);
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (!verifiedProRegTxHash.IsNull()) {
|
||||
setConnectedMasternodes.emplace(verifiedProRegTxHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2475,9 +2476,10 @@ void CConnman::ThreadOpenMasternodeConnections()
|
||||
std::set<CService> connectedNodes;
|
||||
std::map<uint256, bool> connectedProRegTxHashes;
|
||||
ForEachNode([&](const CNode* pnode) {
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
connectedNodes.emplace(pnode->addr);
|
||||
if (!pnode->verifiedProRegTxHash.IsNull()) {
|
||||
connectedProRegTxHashes.emplace(pnode->verifiedProRegTxHash, pnode->fInbound);
|
||||
if (!verifiedProRegTxHash.IsNull()) {
|
||||
connectedProRegTxHashes.emplace(verifiedProRegTxHash, pnode->fInbound);
|
||||
}
|
||||
});
|
||||
|
||||
@ -3344,7 +3346,8 @@ void CConnman::SetMasternodeQuorumRelayMembers(Consensus::LLMQType llmqType, con
|
||||
|
||||
// Update existing connections
|
||||
ForEachNode([&](CNode* pnode) {
|
||||
if (!pnode->verifiedProRegTxHash.IsNull() && !pnode->m_masternode_iqr_connection && IsMasternodeQuorumRelayMember(pnode->verifiedProRegTxHash)) {
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (!verifiedProRegTxHash.IsNull() && !pnode->m_masternode_iqr_connection && IsMasternodeQuorumRelayMember(verifiedProRegTxHash)) {
|
||||
// Tell our peer that we're interested in plain LLMQ recovered signatures.
|
||||
// Otherwise the peer would only announce/send messages resulting from QRECSIG,
|
||||
// e.g. InstantSend locks or ChainLocks. SPV and regular full nodes should not send
|
||||
@ -3389,7 +3392,8 @@ std::set<NodeId> CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType
|
||||
if (pnode->fDisconnect) {
|
||||
continue;
|
||||
}
|
||||
if (!pnode->qwatch && (pnode->verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(pnode->verifiedProRegTxHash))) {
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (!pnode->qwatch && (verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(verifiedProRegTxHash))) {
|
||||
continue;
|
||||
}
|
||||
nodes.emplace(pnode->GetId());
|
||||
@ -3409,7 +3413,7 @@ bool CConnman::IsMasternodeQuorumNode(const CNode* pnode)
|
||||
// Let's see if this is an outgoing connection to an address that is known to be a masternode
|
||||
// We however only need to know this if the node did not authenticate itself as a MN yet
|
||||
uint256 assumedProTxHash;
|
||||
if (pnode->verifiedProRegTxHash.IsNull() && !pnode->fInbound) {
|
||||
if (pnode->GetVerifiedProRegTxHash().IsNull() && !pnode->fInbound) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetMNByService(pnode->addr);
|
||||
if (dmn == nullptr) {
|
||||
@ -3421,8 +3425,8 @@ bool CConnman::IsMasternodeQuorumNode(const CNode* pnode)
|
||||
|
||||
LOCK(cs_vPendingMasternodes);
|
||||
for (const auto& p : masternodeQuorumNodes) {
|
||||
if (!pnode->verifiedProRegTxHash.IsNull()) {
|
||||
if (p.second.count(pnode->verifiedProRegTxHash)) {
|
||||
if (!pnode->GetVerifiedProRegTxHash().IsNull()) {
|
||||
if (p.second.count(pnode->GetVerifiedProRegTxHash())) {
|
||||
return true;
|
||||
}
|
||||
} else if (!assumedProTxHash.IsNull()) {
|
||||
|
61
src/net.h
61
src/net.h
@ -905,11 +905,11 @@ public:
|
||||
bool fRelayTxes; //protected by cs_filter
|
||||
bool fSentAddr;
|
||||
// If 'true' this node will be disconnected on CMasternodeMan::ProcessMasternodeConnections()
|
||||
bool m_masternode_connection;
|
||||
std::atomic<bool> m_masternode_connection;
|
||||
// If 'true' this node will be disconnected after MNAUTH
|
||||
bool m_masternode_probe_connection;
|
||||
std::atomic<bool> m_masternode_probe_connection;
|
||||
// If 'true', we identified it as an intra-quorum relay connection
|
||||
bool m_masternode_iqr_connection{false};
|
||||
std::atomic<bool> m_masternode_iqr_connection{false};
|
||||
CSemaphoreGrant grantOutbound;
|
||||
CCriticalSection cs_filter;
|
||||
std::unique_ptr<CBloomFilter> pfilter PT_GUARDED_BY(cs_filter){nullptr};
|
||||
@ -980,13 +980,6 @@ public:
|
||||
// If true, we will send him CoinJoin queue messages
|
||||
std::atomic<bool> fSendDSQueue{false};
|
||||
|
||||
// Challenge sent in VERSION to be answered with MNAUTH (only happens between MNs)
|
||||
mutable CCriticalSection cs_mnauth;
|
||||
uint256 sentMNAuthChallenge;
|
||||
uint256 receivedMNAuthChallenge;
|
||||
uint256 verifiedProRegTxHash;
|
||||
uint256 verifiedPubKeyHash;
|
||||
|
||||
// If true, we will announce/send him plain recovered sigs (usually true for full nodes)
|
||||
std::atomic<bool> fSendRecSigs{false};
|
||||
// If true, we will send him all quorum related messages, even if he is not a member of our quorums
|
||||
@ -1015,6 +1008,14 @@ private:
|
||||
// Our address, as reported by the peer
|
||||
CService addrLocal GUARDED_BY(cs_addrLocal);
|
||||
mutable CCriticalSection cs_addrLocal;
|
||||
|
||||
// Challenge sent in VERSION to be answered with MNAUTH (only happens between MNs)
|
||||
mutable CCriticalSection cs_mnauth;
|
||||
uint256 sentMNAuthChallenge GUARDED_BY(cs_mnauth);
|
||||
uint256 receivedMNAuthChallenge GUARDED_BY(cs_mnauth);
|
||||
uint256 verifiedProRegTxHash GUARDED_BY(cs_mnauth);
|
||||
uint256 verifiedPubKeyHash GUARDED_BY(cs_mnauth);
|
||||
|
||||
public:
|
||||
|
||||
NodeId GetId() const {
|
||||
@ -1148,6 +1149,46 @@ public:
|
||||
std::string GetLogString() const;
|
||||
|
||||
bool CanRelay() const { return !m_masternode_connection || m_masternode_iqr_connection; }
|
||||
|
||||
uint256 GetSentMNAuthChallenge() const {
|
||||
LOCK(cs_mnauth);
|
||||
return sentMNAuthChallenge;
|
||||
}
|
||||
|
||||
uint256 GetReceivedMNAuthChallenge() const {
|
||||
LOCK(cs_mnauth);
|
||||
return receivedMNAuthChallenge;
|
||||
}
|
||||
|
||||
uint256 GetVerifiedProRegTxHash() const {
|
||||
LOCK(cs_mnauth);
|
||||
return verifiedProRegTxHash;
|
||||
}
|
||||
|
||||
uint256 GetVerifiedPubKeyHash() const {
|
||||
LOCK(cs_mnauth);
|
||||
return verifiedPubKeyHash;
|
||||
}
|
||||
|
||||
void SetSentMNAuthChallenge(const uint256& newSentMNAuthChallenge) {
|
||||
LOCK(cs_mnauth);
|
||||
sentMNAuthChallenge = newSentMNAuthChallenge;
|
||||
}
|
||||
|
||||
void SetReceivedMNAuthChallenge(const uint256& newReceivedMNAuthChallenge) {
|
||||
LOCK(cs_mnauth);
|
||||
receivedMNAuthChallenge = newReceivedMNAuthChallenge;
|
||||
}
|
||||
|
||||
void SetVerifiedProRegTxHash(const uint256& newVerifiedProRegTxHash) {
|
||||
LOCK(cs_mnauth);
|
||||
verifiedProRegTxHash = newVerifiedProRegTxHash;
|
||||
}
|
||||
|
||||
void SetVerifiedPubKeyHash(const uint256& newVerifiedPubKeyHash) {
|
||||
LOCK(cs_mnauth);
|
||||
verifiedPubKeyHash = newVerifiedPubKeyHash;
|
||||
}
|
||||
};
|
||||
|
||||
class CExplicitNetCleanup
|
||||
|
@ -438,10 +438,7 @@ static void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
|
||||
|
||||
uint256 mnauthChallenge;
|
||||
GetRandBytes(mnauthChallenge.begin(), mnauthChallenge.size());
|
||||
{
|
||||
LOCK(pnode->cs_mnauth);
|
||||
pnode->sentMNAuthChallenge = mnauthChallenge;
|
||||
}
|
||||
pnode->SetSentMNAuthChallenge(mnauthChallenge);
|
||||
|
||||
int nProtocolVersion = PROTOCOL_VERSION;
|
||||
if (params.NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) {
|
||||
@ -449,7 +446,7 @@ static void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
|
||||
}
|
||||
|
||||
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, nProtocolVersion, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
|
||||
nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes, mnauthChallenge, pnode->m_masternode_connection));
|
||||
nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes, mnauthChallenge, pnode->m_masternode_connection.load()));
|
||||
|
||||
if (fLogIPs) {
|
||||
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
|
||||
@ -2222,8 +2219,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
if (!vRecv.empty())
|
||||
vRecv >> fRelay;
|
||||
if (!vRecv.empty()) {
|
||||
LOCK(pfrom->cs_mnauth);
|
||||
vRecv >> pfrom->receivedMNAuthChallenge;
|
||||
uint256 receivedMNAuthChallenge;
|
||||
vRecv >> receivedMNAuthChallenge;
|
||||
pfrom->SetReceivedMNAuthChallenge(receivedMNAuthChallenge);
|
||||
}
|
||||
if (!vRecv.empty()) {
|
||||
bool fOtherMasternode = false;
|
||||
@ -4283,7 +4281,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
||||
} else {
|
||||
// Use half the delay for regular outbound peers, as there is less privacy concern for them.
|
||||
// and quarter the delay for Masternode outbound peers, as there is even less privacy concern in this case.
|
||||
pto->nNextInvSend = PoissonNextSend(current_time, std::chrono::seconds{INVENTORY_BROADCAST_INTERVAL >> 1 >> !pto->verifiedProRegTxHash.IsNull()});
|
||||
pto->nNextInvSend = PoissonNextSend(current_time, std::chrono::seconds{INVENTORY_BROADCAST_INTERVAL >> 1 >> !pto->GetVerifiedProRegTxHash().IsNull()});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,11 +310,11 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
bool fMnFound = mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint);
|
||||
bool fMnFound = WITH_LOCK(activeMasternodeInfoCs, return mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint));
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "gobject_submit -- pubKeyOperator = %s, outpoint = %s, params.size() = %lld, fMnFound = %d\n",
|
||||
(activeMasternodeInfo.blsPubKeyOperator ? activeMasternodeInfo.blsPubKeyOperator->ToString() : "N/A"),
|
||||
activeMasternodeInfo.outpoint.ToStringShort(), request.params.size(), fMnFound);
|
||||
(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsPubKeyOperator ? activeMasternodeInfo.blsPubKeyOperator->ToString() : "N/A")),
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint.ToStringShort()), request.params.size(), fMnFound);
|
||||
|
||||
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
|
||||
|
||||
@ -351,6 +351,7 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
// Attempt to sign triggers if we are a MN
|
||||
if (govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) {
|
||||
if (fMnFound) {
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
govobj.SetMasternodeOutpoint(activeMasternodeInfo.outpoint);
|
||||
govobj.Sign(*activeMasternodeInfo.blsKeyOperator);
|
||||
} else {
|
||||
@ -450,7 +451,7 @@ static UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
UniValue statusObj(UniValue::VOBJ);
|
||||
UniValue returnObj(UniValue::VOBJ);
|
||||
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(activeMasternodeInfo.outpoint);
|
||||
auto dmn = WITH_LOCK(activeMasternodeInfoCs, return deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(activeMasternodeInfo.outpoint));
|
||||
|
||||
if (!dmn) {
|
||||
nFailed++;
|
||||
@ -468,8 +469,12 @@ static UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals");
|
||||
}
|
||||
if (activeMasternodeInfo.blsKeyOperator) {
|
||||
signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
|
||||
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
if (activeMasternodeInfo.blsKeyOperator) {
|
||||
signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
|
||||
}
|
||||
}
|
||||
|
||||
if (!signSuccess) {
|
||||
|
@ -233,11 +233,15 @@ static UniValue masternode_status(const JSONRPCRequest& request)
|
||||
|
||||
UniValue mnObj(UniValue::VOBJ);
|
||||
|
||||
// keep compatibility with legacy status for now (might get deprecated/removed later)
|
||||
mnObj.pushKV("outpoint", activeMasternodeInfo.outpoint.ToStringShort());
|
||||
mnObj.pushKV("service", activeMasternodeInfo.service.ToString());
|
||||
CDeterministicMNCPtr dmn;
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(activeMasternodeInfo.proTxHash);
|
||||
// keep compatibility with legacy status for now (might get deprecated/removed later)
|
||||
mnObj.pushKV("outpoint", activeMasternodeInfo.outpoint.ToStringShort());
|
||||
mnObj.pushKV("service", activeMasternodeInfo.service.ToString());
|
||||
dmn = deterministicMNManager->GetListAtChainTip().GetMN(activeMasternodeInfo.proTxHash);
|
||||
}
|
||||
if (dmn) {
|
||||
mnObj.pushKV("proTxHash", dmn->proTxHash.ToString());
|
||||
mnObj.pushKV("collateralHash", dmn->collateralOutpoint.hash.ToString());
|
||||
|
@ -447,9 +447,8 @@ static UniValue mnauth(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
bool fSuccess = g_connman->ForNode(nodeId, CConnman::AllNodes, [&](CNode* pNode){
|
||||
LOCK(pNode->cs_mnauth);
|
||||
pNode->verifiedProRegTxHash = proTxHash;
|
||||
pNode->verifiedPubKeyHash = publicKey.GetHash();
|
||||
pNode->SetVerifiedProRegTxHash(proTxHash);
|
||||
pNode->SetVerifiedPubKeyHash(publicKey.GetHash());
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -191,6 +191,7 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request)
|
||||
}
|
||||
int tipHeight = pindexTip->nHeight;
|
||||
|
||||
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
UniValue minableCommitments(UniValue::VOBJ);
|
||||
UniValue quorumConnections(UniValue::VOBJ);
|
||||
for (const auto& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexTip)) {
|
||||
@ -202,12 +203,13 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request)
|
||||
LOCK(cs_main);
|
||||
pindexQuorum = chainActive[tipHeight - (tipHeight % llmq_params.dkgInterval)];
|
||||
}
|
||||
auto allConnections = llmq::CLLMQUtils::GetQuorumConnections(llmq_params.type, pindexQuorum, activeMasternodeInfo.proTxHash, false);
|
||||
auto outboundConnections = llmq::CLLMQUtils::GetQuorumConnections(llmq_params.type, pindexQuorum, activeMasternodeInfo.proTxHash, true);
|
||||
auto allConnections = llmq::CLLMQUtils::GetQuorumConnections(llmq_params.type, pindexQuorum, proTxHash, false);
|
||||
auto outboundConnections = llmq::CLLMQUtils::GetQuorumConnections(llmq_params.type, pindexQuorum, proTxHash, true);
|
||||
std::map<uint256, CAddress> foundConnections;
|
||||
g_connman->ForEachNode([&](const CNode* pnode) {
|
||||
if (!pnode->verifiedProRegTxHash.IsNull() && allConnections.count(pnode->verifiedProRegTxHash)) {
|
||||
foundConnections.emplace(pnode->verifiedProRegTxHash, pnode->addr);
|
||||
auto verifiedProRegTxHash = pnode->GetVerifiedProRegTxHash();
|
||||
if (!verifiedProRegTxHash.IsNull() && allConnections.count(verifiedProRegTxHash)) {
|
||||
foundConnections.emplace(verifiedProRegTxHash, pnode->addr);
|
||||
}
|
||||
});
|
||||
UniValue arr(UniValue::VARR);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
static CCriticalSection cs_rpcWarmup;
|
||||
static bool fRPCRunning = false;
|
||||
static std::atomic<bool> fRPCRunning{false};
|
||||
static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup) = true;
|
||||
static std::string rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server started";
|
||||
/* Timer-creating functions */
|
||||
|
@ -4377,11 +4377,14 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
|
||||
void CWallet::KeepKey(int64_t nIndex)
|
||||
{
|
||||
// Remove from key pool
|
||||
WalletBatch batch(*database);
|
||||
if (batch.ErasePool(nIndex))
|
||||
--nKeysLeftSinceAutoBackup;
|
||||
if (!nWalletBackups)
|
||||
nKeysLeftSinceAutoBackup = 0;
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
WalletBatch batch(*database);
|
||||
if (batch.ErasePool(nIndex))
|
||||
--nKeysLeftSinceAutoBackup;
|
||||
if (!nWalletBackups)
|
||||
nKeysLeftSinceAutoBackup = 0;
|
||||
}
|
||||
WalletLogPrintf("keypool keep %d\n", nIndex);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user