mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
refactor: significant Mutex refactoring
Includes: RecursiveMutex -> Mutex, renaming of `cs` to something more meaningful, usage of atomics where trivially possible, introduce a method CQuorum::SetVerificationVector to avoid needing to lock an internal mutex externally fix: avoid cs_vvec_shShare double-lock Co-authored-by: UdjinM6 <udjinm6@users.noreply.github.com>
This commit is contained in:
parent
c3f34dcd98
commit
acd0f49d7b
@ -138,13 +138,13 @@ UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, const Chainsta
|
|||||||
|
|
||||||
void CDKGDebugManager::GetLocalDebugStatus(llmq::CDKGDebugStatus& ret) const
|
void CDKGDebugManager::GetLocalDebugStatus(llmq::CDKGDebugStatus& ret) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_lockStatus);
|
||||||
ret = localStatus;
|
ret = localStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDKGDebugManager::ResetLocalSessionStatus(Consensus::LLMQType llmqType, int quorumIndex)
|
void CDKGDebugManager::ResetLocalSessionStatus(Consensus::LLMQType llmqType, int quorumIndex)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_lockStatus);
|
||||||
|
|
||||||
auto it = localStatus.sessions.find(std::make_pair(llmqType, quorumIndex));
|
auto it = localStatus.sessions.find(std::make_pair(llmqType, quorumIndex));
|
||||||
if (it == localStatus.sessions.end()) {
|
if (it == localStatus.sessions.end()) {
|
||||||
@ -157,7 +157,7 @@ void CDKGDebugManager::ResetLocalSessionStatus(Consensus::LLMQType llmqType, int
|
|||||||
|
|
||||||
void CDKGDebugManager::InitLocalSessionStatus(const Consensus::LLMQParams& llmqParams, int quorumIndex, const uint256& quorumHash, int quorumHeight)
|
void CDKGDebugManager::InitLocalSessionStatus(const Consensus::LLMQParams& llmqParams, int quorumIndex, const uint256& quorumHash, int quorumHeight)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_lockStatus);
|
||||||
|
|
||||||
auto it = localStatus.sessions.find(std::make_pair(llmqParams.type, quorumIndex));
|
auto it = localStatus.sessions.find(std::make_pair(llmqParams.type, quorumIndex));
|
||||||
if (it == localStatus.sessions.end()) {
|
if (it == localStatus.sessions.end()) {
|
||||||
@ -176,7 +176,7 @@ void CDKGDebugManager::InitLocalSessionStatus(const Consensus::LLMQParams& llmqP
|
|||||||
|
|
||||||
void CDKGDebugManager::UpdateLocalSessionStatus(Consensus::LLMQType llmqType, int quorumIndex, std::function<bool(CDKGDebugSessionStatus& status)>&& func)
|
void CDKGDebugManager::UpdateLocalSessionStatus(Consensus::LLMQType llmqType, int quorumIndex, std::function<bool(CDKGDebugSessionStatus& status)>&& func)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_lockStatus);
|
||||||
|
|
||||||
auto it = localStatus.sessions.find(std::make_pair(llmqType, quorumIndex));
|
auto it = localStatus.sessions.find(std::make_pair(llmqType, quorumIndex));
|
||||||
if (it == localStatus.sessions.end()) {
|
if (it == localStatus.sessions.end()) {
|
||||||
@ -190,7 +190,7 @@ void CDKGDebugManager::UpdateLocalSessionStatus(Consensus::LLMQType llmqType, in
|
|||||||
|
|
||||||
void CDKGDebugManager::UpdateLocalMemberStatus(Consensus::LLMQType llmqType, int quorumIndex, size_t memberIdx, std::function<bool(CDKGDebugMemberStatus& status)>&& func)
|
void CDKGDebugManager::UpdateLocalMemberStatus(Consensus::LLMQType llmqType, int quorumIndex, size_t memberIdx, std::function<bool(CDKGDebugMemberStatus& status)>&& func)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_lockStatus);
|
||||||
|
|
||||||
auto it = localStatus.sessions.find(std::make_pair(llmqType, quorumIndex));
|
auto it = localStatus.sessions.find(std::make_pair(llmqType, quorumIndex));
|
||||||
if (it == localStatus.sessions.end()) {
|
if (it == localStatus.sessions.end()) {
|
||||||
|
@ -96,8 +96,8 @@ public:
|
|||||||
class CDKGDebugManager
|
class CDKGDebugManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
mutable RecursiveMutex cs;
|
mutable Mutex cs_lockStatus;
|
||||||
CDKGDebugStatus localStatus GUARDED_BY(cs);
|
CDKGDebugStatus localStatus GUARDED_BY(cs_lockStatus);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDKGDebugManager();
|
CDKGDebugManager();
|
||||||
|
@ -261,8 +261,6 @@ bool CDKGSession::PreVerifyMessage(const CDKGContribution& qc, bool& retBan) con
|
|||||||
|
|
||||||
void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
|
void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
|
||||||
{
|
{
|
||||||
LOCK(cs_pending);
|
|
||||||
|
|
||||||
CDKGLogger logger(*this, __func__, __LINE__);
|
CDKGLogger logger(*this, __func__, __LINE__);
|
||||||
|
|
||||||
retBan = false;
|
retBan = false;
|
||||||
@ -336,15 +334,11 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
|
|||||||
|
|
||||||
logger.Batch("decrypted our contribution share. time=%d", t2.count());
|
logger.Batch("decrypted our contribution share. time=%d", t2.count());
|
||||||
|
|
||||||
bool verifyPending = false;
|
|
||||||
receivedSkContributions[member->idx] = skContribution;
|
receivedSkContributions[member->idx] = skContribution;
|
||||||
vecEncryptedContributions[member->idx] = qc.contributions;
|
vecEncryptedContributions[member->idx] = qc.contributions;
|
||||||
|
LOCK(cs_pending);
|
||||||
pendingContributionVerifications.emplace_back(member->idx);
|
pendingContributionVerifications.emplace_back(member->idx);
|
||||||
if (pendingContributionVerifications.size() >= 32) {
|
if (pendingContributionVerifications.size() >= 32) {
|
||||||
verifyPending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verifyPending) {
|
|
||||||
VerifyPendingContributions();
|
VerifyPendingContributions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,13 +308,13 @@ private:
|
|||||||
// we expect to only receive a single vvec and contribution per member, but we must also be able to relay
|
// we expect to only receive a single vvec and contribution per member, but we must also be able to relay
|
||||||
// conflicting messages as otherwise an attacker might be able to broadcast conflicting (valid+invalid) messages
|
// conflicting messages as otherwise an attacker might be able to broadcast conflicting (valid+invalid) messages
|
||||||
// and thus split the quorum. Such members are later removed from the quorum.
|
// and thus split the quorum. Such members are later removed from the quorum.
|
||||||
mutable RecursiveMutex invCs;
|
mutable Mutex invCs;
|
||||||
std::map<uint256, CDKGContribution> contributions GUARDED_BY(invCs);
|
std::map<uint256, CDKGContribution> contributions GUARDED_BY(invCs);
|
||||||
std::map<uint256, CDKGComplaint> complaints GUARDED_BY(invCs);
|
std::map<uint256, CDKGComplaint> complaints GUARDED_BY(invCs);
|
||||||
std::map<uint256, CDKGJustification> justifications GUARDED_BY(invCs);
|
std::map<uint256, CDKGJustification> justifications GUARDED_BY(invCs);
|
||||||
std::map<uint256, CDKGPrematureCommitment> prematureCommitments GUARDED_BY(invCs);
|
std::map<uint256, CDKGPrematureCommitment> prematureCommitments GUARDED_BY(invCs);
|
||||||
|
|
||||||
mutable RecursiveMutex cs_pending;
|
mutable Mutex cs_pending;
|
||||||
std::vector<size_t> pendingContributionVerifications GUARDED_BY(cs_pending);
|
std::vector<size_t> pendingContributionVerifications GUARDED_BY(cs_pending);
|
||||||
|
|
||||||
// filled by ReceivePrematureCommitment and used by FinalizeCommitments
|
// filled by ReceivePrematureCommitment and used by FinalizeCommitments
|
||||||
|
@ -76,7 +76,7 @@ void CDKGPendingMessages::PushPendingMessage(NodeId from, PeerManager* peerman,
|
|||||||
EraseObjectRequest(from, CInv(invType, hash));
|
EraseObjectRequest(from, CInv(invType, hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_messages);
|
||||||
|
|
||||||
if (messagesPerNode[from] >= maxMessagesPerNode) {
|
if (messagesPerNode[from] >= maxMessagesPerNode) {
|
||||||
// TODO ban?
|
// TODO ban?
|
||||||
@ -95,7 +95,7 @@ void CDKGPendingMessages::PushPendingMessage(NodeId from, PeerManager* peerman,
|
|||||||
|
|
||||||
std::list<CDKGPendingMessages::BinaryMessage> CDKGPendingMessages::PopPendingMessages(size_t maxCount)
|
std::list<CDKGPendingMessages::BinaryMessage> CDKGPendingMessages::PopPendingMessages(size_t maxCount)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_messages);
|
||||||
|
|
||||||
std::list<BinaryMessage> ret;
|
std::list<BinaryMessage> ret;
|
||||||
while (!pendingMessages.empty() && ret.size() < maxCount) {
|
while (!pendingMessages.empty() && ret.size() < maxCount) {
|
||||||
@ -108,7 +108,7 @@ std::list<CDKGPendingMessages::BinaryMessage> CDKGPendingMessages::PopPendingMes
|
|||||||
|
|
||||||
bool CDKGPendingMessages::HasSeen(const uint256& hash) const
|
bool CDKGPendingMessages::HasSeen(const uint256& hash) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_messages);
|
||||||
return seenMessages.count(hash) != 0;
|
return seenMessages.count(hash) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ void CDKGPendingMessages::Misbehaving(const NodeId from, const int score)
|
|||||||
|
|
||||||
void CDKGPendingMessages::Clear()
|
void CDKGPendingMessages::Clear()
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_messages);
|
||||||
pendingMessages.clear();
|
pendingMessages.clear();
|
||||||
messagesPerNode.clear();
|
messagesPerNode.clear();
|
||||||
seenMessages.clear();
|
seenMessages.clear();
|
||||||
@ -135,7 +135,7 @@ void CDKGSessionHandler::UpdatedBlockTip(const CBlockIndex* pindexNew)
|
|||||||
if (quorumIndex > 0 && !IsQuorumRotationEnabled(params, pindexNew)) {
|
if (quorumIndex > 0 && !IsQuorumRotationEnabled(params, pindexNew)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOCK(cs);
|
LOCK(cs_phase_qhash);
|
||||||
|
|
||||||
int quorumStageInt = (pindexNew->nHeight - quorumIndex) % params.dkgInterval;
|
int quorumStageInt = (pindexNew->nHeight - quorumIndex) % params.dkgInterval;
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex)
|
|||||||
|
|
||||||
std::pair<QuorumPhase, uint256> CDKGSessionHandler::GetPhaseAndQuorumHash() const
|
std::pair<QuorumPhase, uint256> CDKGSessionHandler::GetPhaseAndQuorumHash() const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_phase_qhash);
|
||||||
return std::make_pair(phase, quorumHash);
|
return std::make_pair(phase, quorumHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,9 +304,8 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase,
|
|||||||
|
|
||||||
int64_t sleepTime = (int64_t)(adjustedPhaseSleepTimePerMember * curSession->GetMyMemberIndex().value_or(0));
|
int64_t sleepTime = (int64_t)(adjustedPhaseSleepTimePerMember * curSession->GetMyMemberIndex().value_or(0));
|
||||||
int64_t endTime = GetTimeMillis() + sleepTime;
|
int64_t endTime = GetTimeMillis() + sleepTime;
|
||||||
int heightTmp{-1};
|
int heightTmp{currentHeight.load()};
|
||||||
int heightStart{-1};
|
int heightStart{heightTmp};
|
||||||
heightTmp = heightStart = WITH_LOCK(cs, return currentHeight);
|
|
||||||
|
|
||||||
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, quorumIndex, sleepTime, ToUnderlying(curPhase));
|
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, quorumIndex, sleepTime, ToUnderlying(curPhase));
|
||||||
|
|
||||||
@ -315,22 +314,20 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase,
|
|||||||
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex);
|
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex);
|
||||||
throw AbortPhaseException();
|
throw AbortPhaseException();
|
||||||
}
|
}
|
||||||
{
|
auto cur_height = currentHeight.load();
|
||||||
LOCK(cs);
|
if (cur_height > heightTmp) {
|
||||||
if (currentHeight > heightTmp) {
|
// New block(s) just came in
|
||||||
// New block(s) just came in
|
int64_t expectedBlockTime = (cur_height - heightStart) * Params().GetConsensus().nPowTargetSpacing * 1000;
|
||||||
int64_t expectedBlockTime = (currentHeight - heightStart) * Params().GetConsensus().nPowTargetSpacing * 1000;
|
if (expectedBlockTime > sleepTime) {
|
||||||
if (expectedBlockTime > sleepTime) {
|
// Blocks came faster than we expected, jump into the phase func asap
|
||||||
// Blocks came faster than we expected, jump into the phase func asap
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
heightTmp = currentHeight;
|
|
||||||
}
|
|
||||||
if (phase != curPhase || quorumHash != expectedQuorumHash) {
|
|
||||||
// Something went wrong and/or we missed quite a few blocks and it's just too late now
|
|
||||||
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name, quorumIndex);
|
|
||||||
throw AbortPhaseException();
|
|
||||||
}
|
}
|
||||||
|
heightTmp = cur_height;
|
||||||
|
}
|
||||||
|
if (WITH_LOCK(cs_phase_qhash, return phase != curPhase || quorumHash != expectedQuorumHash)) {
|
||||||
|
// Something went wrong and/or we missed quite a few blocks and it's just too late now
|
||||||
|
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name, quorumIndex);
|
||||||
|
throw AbortPhaseException();
|
||||||
}
|
}
|
||||||
if (!runWhileWaiting()) {
|
if (!runWhileWaiting()) {
|
||||||
UninterruptibleSleep(std::chrono::milliseconds{100});
|
UninterruptibleSleep(std::chrono::milliseconds{100});
|
||||||
@ -505,18 +502,13 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
|
|||||||
|
|
||||||
void CDKGSessionHandler::HandleDKGRound()
|
void CDKGSessionHandler::HandleDKGRound()
|
||||||
{
|
{
|
||||||
uint256 curQuorumHash;
|
|
||||||
|
|
||||||
WaitForNextPhase(std::nullopt, QuorumPhase::Initialized);
|
WaitForNextPhase(std::nullopt, QuorumPhase::Initialized);
|
||||||
|
|
||||||
{
|
pendingContributions.Clear();
|
||||||
LOCK(cs);
|
pendingComplaints.Clear();
|
||||||
pendingContributions.Clear();
|
pendingJustifications.Clear();
|
||||||
pendingComplaints.Clear();
|
pendingPrematureCommitments.Clear();
|
||||||
pendingJustifications.Clear();
|
uint256 curQuorumHash = WITH_LOCK(cs_phase_qhash, return quorumHash);
|
||||||
pendingPrematureCommitments.Clear();
|
|
||||||
curQuorumHash = quorumHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return m_chainstate.m_blockman.LookupBlockIndex(curQuorumHash));
|
const CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return m_chainstate.m_blockman.LookupBlockIndex(curQuorumHash));
|
||||||
|
|
||||||
|
@ -54,13 +54,13 @@ public:
|
|||||||
using BinaryMessage = std::pair<NodeId, std::shared_ptr<CDataStream>>;
|
using BinaryMessage = std::pair<NodeId, std::shared_ptr<CDataStream>>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable RecursiveMutex cs;
|
|
||||||
std::atomic<PeerManager*> m_peerman{nullptr};
|
std::atomic<PeerManager*> m_peerman{nullptr};
|
||||||
const int invType;
|
const int invType;
|
||||||
size_t maxMessagesPerNode GUARDED_BY(cs);
|
const size_t maxMessagesPerNode;
|
||||||
std::list<BinaryMessage> pendingMessages GUARDED_BY(cs);
|
mutable Mutex cs_messages;
|
||||||
std::map<NodeId, size_t> messagesPerNode GUARDED_BY(cs);
|
std::list<BinaryMessage> pendingMessages GUARDED_BY(cs_messages);
|
||||||
std::set<uint256> seenMessages GUARDED_BY(cs);
|
std::map<NodeId, size_t> messagesPerNode GUARDED_BY(cs_messages);
|
||||||
|
std::set<uint256> seenMessages GUARDED_BY(cs_messages);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CDKGPendingMessages(size_t _maxMessagesPerNode, int _invType) :
|
explicit CDKGPendingMessages(size_t _maxMessagesPerNode, int _invType) :
|
||||||
@ -117,7 +117,6 @@ private:
|
|||||||
friend class CDKGSessionManager;
|
friend class CDKGSessionManager;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable RecursiveMutex cs;
|
|
||||||
std::atomic<bool> stopRequested{false};
|
std::atomic<bool> stopRequested{false};
|
||||||
|
|
||||||
CBLSWorker& blsWorker;
|
CBLSWorker& blsWorker;
|
||||||
@ -134,9 +133,10 @@ private:
|
|||||||
const Consensus::LLMQParams params;
|
const Consensus::LLMQParams params;
|
||||||
const int quorumIndex;
|
const int quorumIndex;
|
||||||
|
|
||||||
QuorumPhase phase GUARDED_BY(cs) {QuorumPhase::Idle};
|
std::atomic<int> currentHeight {-1};
|
||||||
int currentHeight GUARDED_BY(cs) {-1};
|
mutable Mutex cs_phase_qhash;
|
||||||
uint256 quorumHash GUARDED_BY(cs);
|
QuorumPhase phase GUARDED_BY(cs_phase_qhash) {QuorumPhase::Idle};
|
||||||
|
uint256 quorumHash GUARDED_BY(cs_phase_qhash);
|
||||||
|
|
||||||
std::unique_ptr<CDKGSession> curSession;
|
std::unique_ptr<CDKGSession> curSession;
|
||||||
std::thread phaseHandlerThread;
|
std::thread phaseHandlerThread;
|
||||||
|
@ -293,7 +293,7 @@ bool CDKGSessionManager::GetContribution(const uint256& hash, CDKGContribution&
|
|||||||
|
|
||||||
for (const auto& p : dkgSessionHandlers) {
|
for (const auto& p : dkgSessionHandlers) {
|
||||||
const auto& dkgType = p.second;
|
const auto& dkgType = p.second;
|
||||||
LOCK(dkgType.cs);
|
LOCK(dkgType.cs_phase_qhash);
|
||||||
if (dkgType.phase < QuorumPhase::Initialized || dkgType.phase > QuorumPhase::Contribute) {
|
if (dkgType.phase < QuorumPhase::Initialized || dkgType.phase > QuorumPhase::Contribute) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -314,7 +314,7 @@ bool CDKGSessionManager::GetComplaint(const uint256& hash, CDKGComplaint& ret) c
|
|||||||
|
|
||||||
for (const auto& p : dkgSessionHandlers) {
|
for (const auto& p : dkgSessionHandlers) {
|
||||||
const auto& dkgType = p.second;
|
const auto& dkgType = p.second;
|
||||||
LOCK(dkgType.cs);
|
LOCK(dkgType.cs_phase_qhash);
|
||||||
if (dkgType.phase < QuorumPhase::Contribute || dkgType.phase > QuorumPhase::Complain) {
|
if (dkgType.phase < QuorumPhase::Contribute || dkgType.phase > QuorumPhase::Complain) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -335,7 +335,7 @@ bool CDKGSessionManager::GetJustification(const uint256& hash, CDKGJustification
|
|||||||
|
|
||||||
for (const auto& p : dkgSessionHandlers) {
|
for (const auto& p : dkgSessionHandlers) {
|
||||||
const auto& dkgType = p.second;
|
const auto& dkgType = p.second;
|
||||||
LOCK(dkgType.cs);
|
LOCK(dkgType.cs_phase_qhash);
|
||||||
if (dkgType.phase < QuorumPhase::Complain || dkgType.phase > QuorumPhase::Justify) {
|
if (dkgType.phase < QuorumPhase::Complain || dkgType.phase > QuorumPhase::Justify) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -356,7 +356,7 @@ bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematu
|
|||||||
|
|
||||||
for (const auto& p : dkgSessionHandlers) {
|
for (const auto& p : dkgSessionHandlers) {
|
||||||
const auto& dkgType = p.second;
|
const auto& dkgType = p.second;
|
||||||
LOCK(dkgType.cs);
|
LOCK(dkgType.cs_phase_qhash);
|
||||||
if (dkgType.phase < QuorumPhase::Justify || dkgType.phase > QuorumPhase::Commit) {
|
if (dkgType.phase < QuorumPhase::Justify || dkgType.phase > QuorumPhase::Commit) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ bool CQuorum::SetVerificationVector(const std::vector<CBLSPublicKey>& quorumVecI
|
|||||||
{
|
{
|
||||||
const auto quorumVecInSerialized = ::SerializeHash(quorumVecIn);
|
const auto quorumVecInSerialized = ::SerializeHash(quorumVecIn);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
if (quorumVecInSerialized != qc->quorumVvecHash) {
|
if (quorumVecInSerialized != qc->quorumVvecHash) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActi
|
|||||||
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(GetMemberIndex(mn_activeman.GetProTxHash())))) {
|
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(GetMemberIndex(mn_activeman.GetProTxHash())))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
skShare = secretKeyShare;
|
skShare = secretKeyShare;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -131,8 +131,8 @@ bool CQuorum::IsValidMember(const uint256& proTxHash) const
|
|||||||
|
|
||||||
CBLSPublicKey CQuorum::GetPubKeyShare(size_t memberIdx) const
|
CBLSPublicKey CQuorum::GetPubKeyShare(size_t memberIdx) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
if (!HasVerificationVector() || memberIdx >= members.size() || !qc->validMembers[memberIdx]) {
|
if (!HasVerificationVectorInternal() || memberIdx >= members.size() || !qc->validMembers[memberIdx]) {
|
||||||
return CBLSPublicKey();
|
return CBLSPublicKey();
|
||||||
}
|
}
|
||||||
const auto& m = members[memberIdx];
|
const auto& m = members[memberIdx];
|
||||||
@ -140,13 +140,18 @@ CBLSPublicKey CQuorum::GetPubKeyShare(size_t memberIdx) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CQuorum::HasVerificationVector() const {
|
bool CQuorum::HasVerificationVector() const {
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
|
return HasVerificationVectorInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CQuorum::HasVerificationVectorInternal() const {
|
||||||
|
AssertLockHeld(cs_vvec_shShare);
|
||||||
return quorumVvec != nullptr;
|
return quorumVvec != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBLSSecretKey CQuorum::GetSkShare() const
|
CBLSSecretKey CQuorum::GetSkShare() const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
return skShare;
|
return skShare;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +170,8 @@ void CQuorum::WriteContributions(CEvoDB& evoDb) const
|
|||||||
{
|
{
|
||||||
uint256 dbKey = MakeQuorumKey(*this);
|
uint256 dbKey = MakeQuorumKey(*this);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
if (HasVerificationVector()) {
|
if (HasVerificationVectorInternal()) {
|
||||||
CDataStream s(SER_DISK, CLIENT_VERSION);
|
CDataStream s(SER_DISK, CLIENT_VERSION);
|
||||||
WriteCompactSize(s, quorumVvec->size());
|
WriteCompactSize(s, quorumVvec->size());
|
||||||
for (auto& pubkey : *quorumVvec) {
|
for (auto& pubkey : *quorumVvec) {
|
||||||
@ -196,7 +201,7 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb)
|
|||||||
qv.emplace_back(pubkey);
|
qv.emplace_back(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_vvec_shShare);
|
||||||
quorumVvec = std::make_shared<std::vector<CBLSPublicKey>>(std::move(qv));
|
quorumVvec = std::make_shared<std::vector<CBLSPublicKey>>(std::move(qv));
|
||||||
// We ignore the return value here as it is ok if this fails. If it fails, it usually means that we are not a
|
// 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.
|
// member of the quorum but observed the whole DKG process to have the quorum verification vector.
|
||||||
@ -434,17 +439,14 @@ bool CQuorumManager::BuildQuorumContributions(const CFinalCommitmentPtr& fqc, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
cxxtimer::Timer t2(true);
|
cxxtimer::Timer t2(true);
|
||||||
LOCK(quorum->cs);
|
quorum->SetVerificationVector(blsWorker.BuildQuorumVerificationVector(vvecs));
|
||||||
quorum->quorumVvec = blsWorker.BuildQuorumVerificationVector(vvecs);
|
|
||||||
if (!quorum->HasVerificationVector()) {
|
if (!quorum->HasVerificationVector()) {
|
||||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build quorumVvec\n", __func__);
|
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
|
// 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)
|
// allows to use the quorum as a non-member (verification through the quorum pub key)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
quorum->skShare = blsWorker.AggregateSecretKeys(skContributions);
|
if (!quorum->SetSecretKeyShare(blsWorker.AggregateSecretKeys(skContributions), *m_mn_activeman)) {
|
||||||
if (!quorum->skShare.IsValid()) {
|
|
||||||
quorum->skShare.Reset();
|
|
||||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build skShare\n", __func__);
|
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build skShare\n", __func__);
|
||||||
// We don't bail out here as this is not a fatal error and still allows us to recover public key shares (as we
|
// We don't bail out here as this is not a fatal error and still allows us to recover public key shares (as we
|
||||||
// have a valid quorum vvec at this point)
|
// have a valid quorum vvec at this point)
|
||||||
@ -747,7 +749,7 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t
|
|||||||
return sendQDATA(CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING, request_limit_exceeded);
|
return sendQDATA(CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING, request_limit_exceeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
WITH_LOCK(pQuorum->cs, ssResponseData << *pQuorum->quorumVvec);
|
WITH_LOCK(pQuorum->cs_vvec_shShare, ssResponseData << *pQuorum->quorumVvec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if request wants ENCRYPTED_CONTRIBUTIONS data
|
// Check if request wants ENCRYPTED_CONTRIBUTIONS data
|
||||||
@ -821,7 +823,7 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t
|
|||||||
if (request.GetDataMask() & CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) {
|
if (request.GetDataMask() & CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) {
|
||||||
assert(m_mn_activeman);
|
assert(m_mn_activeman);
|
||||||
|
|
||||||
if (WITH_LOCK(pQuorum->cs, return pQuorum->quorumVvec->size() != size_t(pQuorum->params.threshold))) {
|
if (WITH_LOCK(pQuorum->cs_vvec_shShare, return pQuorum->quorumVvec->size() != size_t(pQuorum->params.threshold))) {
|
||||||
return errorHandler("No valid quorum verification vector available", 0); // Don't bump score because we asked for it
|
return errorHandler("No valid quorum verification vector available", 0); // Don't bump score because we asked for it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
class CActiveMasternodeManager;
|
class CActiveMasternodeManager;
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
@ -182,10 +183,10 @@ private:
|
|||||||
mutable CBLSWorkerCache blsCache;
|
mutable CBLSWorkerCache blsCache;
|
||||||
mutable std::atomic<bool> fQuorumDataRecoveryThreadRunning{false};
|
mutable std::atomic<bool> fQuorumDataRecoveryThreadRunning{false};
|
||||||
|
|
||||||
mutable RecursiveMutex cs;
|
mutable Mutex cs_vvec_shShare;
|
||||||
// These are only valid when we either participated in the DKG or fully watched it
|
// These are only valid when we either participated in the DKG or fully watched it
|
||||||
BLSVerificationVectorPtr quorumVvec GUARDED_BY(cs);
|
BLSVerificationVectorPtr quorumVvec GUARDED_BY(cs_vvec_shShare);
|
||||||
CBLSSecretKey skShare GUARDED_BY(cs);
|
CBLSSecretKey skShare GUARDED_BY(cs_vvec_shShare);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CQuorum(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker);
|
CQuorum(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker);
|
||||||
@ -193,9 +194,13 @@ public:
|
|||||||
void Init(CFinalCommitmentPtr _qc, const CBlockIndex* _pQuorumBaseBlockIndex, const uint256& _minedBlockHash, Span<CDeterministicMNCPtr> _members);
|
void Init(CFinalCommitmentPtr _qc, const CBlockIndex* _pQuorumBaseBlockIndex, const uint256& _minedBlockHash, Span<CDeterministicMNCPtr> _members);
|
||||||
|
|
||||||
bool SetVerificationVector(const std::vector<CBLSPublicKey>& quorumVecIn);
|
bool SetVerificationVector(const std::vector<CBLSPublicKey>& quorumVecIn);
|
||||||
|
void SetVerificationVector(BLSVerificationVectorPtr vvec_in) {
|
||||||
|
LOCK(cs_vvec_shShare);
|
||||||
|
quorumVvec = std::move(vvec_in);
|
||||||
|
}
|
||||||
bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActiveMasternodeManager& mn_activeman);
|
bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActiveMasternodeManager& mn_activeman);
|
||||||
|
|
||||||
bool HasVerificationVector() const;
|
bool HasVerificationVector() const LOCKS_EXCLUDED(cs_vvec_shShare);
|
||||||
bool IsMember(const uint256& proTxHash) const;
|
bool IsMember(const uint256& proTxHash) const;
|
||||||
bool IsValidMember(const uint256& proTxHash) const;
|
bool IsValidMember(const uint256& proTxHash) const;
|
||||||
int GetMemberIndex(const uint256& proTxHash) const;
|
int GetMemberIndex(const uint256& proTxHash) const;
|
||||||
@ -204,6 +209,7 @@ public:
|
|||||||
CBLSSecretKey GetSkShare() const;
|
CBLSSecretKey GetSkShare() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool HasVerificationVectorInternal() const EXCLUSIVE_LOCKS_REQUIRED(cs_vvec_shShare);
|
||||||
void WriteContributions(CEvoDB& evoDb) const;
|
void WriteContributions(CEvoDB& evoDb) const;
|
||||||
bool ReadContributions(CEvoDB& evoDb);
|
bool ReadContributions(CEvoDB& evoDb);
|
||||||
};
|
};
|
||||||
|
@ -247,7 +247,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForId(Consensus::LLMQType llmqType, const
|
|||||||
auto cacheKey = std::make_pair(llmqType, id);
|
auto cacheKey = std::make_pair(llmqType, id);
|
||||||
bool ret;
|
bool ret;
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
if (hasSigForIdCache.get(cacheKey, ret)) {
|
if (hasSigForIdCache.get(cacheKey, ret)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForId(Consensus::LLMQType llmqType, const
|
|||||||
auto k = std::make_tuple(std::string("rs_r"), llmqType, id);
|
auto k = std::make_tuple(std::string("rs_r"), llmqType, id);
|
||||||
ret = db->Exists(k);
|
ret = db->Exists(k);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
hasSigForIdCache.insert(cacheKey, ret);
|
hasSigForIdCache.insert(cacheKey, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForSession(const uint256& signHash) const
|
|||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
if (hasSigForSessionCache.get(signHash, ret)) {
|
if (hasSigForSessionCache.get(signHash, ret)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -275,7 +275,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForSession(const uint256& signHash) const
|
|||||||
auto k = std::make_tuple(std::string("rs_s"), signHash);
|
auto k = std::make_tuple(std::string("rs_s"), signHash);
|
||||||
ret = db->Exists(k);
|
ret = db->Exists(k);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
hasSigForSessionCache.insert(signHash, ret);
|
hasSigForSessionCache.insert(signHash, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -284,7 +284,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForHash(const uint256& hash) const
|
|||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
if (hasSigForHashCache.get(hash, ret)) {
|
if (hasSigForHashCache.get(hash, ret)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForHash(const uint256& hash) const
|
|||||||
auto k = std::make_tuple(std::string("rs_h"), hash);
|
auto k = std::make_tuple(std::string("rs_h"), hash);
|
||||||
ret = db->Exists(k);
|
ret = db->Exists(k);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
hasSigForHashCache.insert(hash, ret);
|
hasSigForHashCache.insert(hash, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig)
|
|||||||
db->WriteBatch(batch);
|
db->WriteBatch(batch);
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_cache);
|
||||||
hasSigForIdCache.insert(std::make_pair(recSig.getLlmqType(), recSig.getId()), true);
|
hasSigForIdCache.insert(std::make_pair(recSig.getLlmqType(), recSig.getId()), true);
|
||||||
hasSigForSessionCache.insert(signHash, true);
|
hasSigForSessionCache.insert(signHash, true);
|
||||||
hasSigForHashCache.insert(recSig.GetHash(), true);
|
hasSigForHashCache.insert(recSig.GetHash(), true);
|
||||||
@ -370,8 +370,6 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig)
|
|||||||
|
|
||||||
void CRecoveredSigsDb::RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType llmqType, const uint256& id, bool deleteHashKey, bool deleteTimeKey)
|
void CRecoveredSigsDb::RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType llmqType, const uint256& id, bool deleteHashKey, bool deleteTimeKey)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
|
||||||
|
|
||||||
CRecoveredSig recSig;
|
CRecoveredSig recSig;
|
||||||
if (!ReadRecoveredSig(llmqType, id, recSig)) {
|
if (!ReadRecoveredSig(llmqType, id, recSig)) {
|
||||||
return;
|
return;
|
||||||
@ -401,6 +399,7 @@ void CRecoveredSigsDb::RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOCK(cs_cache);
|
||||||
hasSigForIdCache.erase(std::make_pair(recSig.getLlmqType(), recSig.getId()));
|
hasSigForIdCache.erase(std::make_pair(recSig.getLlmqType(), recSig.getId()));
|
||||||
hasSigForSessionCache.erase(signHash);
|
hasSigForSessionCache.erase(signHash);
|
||||||
if (deleteHashKey) {
|
if (deleteHashKey) {
|
||||||
@ -412,7 +411,6 @@ void CRecoveredSigsDb::RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType l
|
|||||||
// This will leave the byHash key in-place so that HasRecoveredSigForHash still returns true
|
// This will leave the byHash key in-place so that HasRecoveredSigForHash still returns true
|
||||||
void CRecoveredSigsDb::TruncateRecoveredSig(Consensus::LLMQType llmqType, const uint256& id)
|
void CRecoveredSigsDb::TruncateRecoveredSig(Consensus::LLMQType llmqType, const uint256& id)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
|
||||||
CDBBatch batch(*db);
|
CDBBatch batch(*db);
|
||||||
RemoveRecoveredSig(batch, llmqType, id, false, false);
|
RemoveRecoveredSig(batch, llmqType, id, false, false);
|
||||||
db->WriteBatch(batch);
|
db->WriteBatch(batch);
|
||||||
@ -451,15 +449,12 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CDBBatch batch(*db);
|
CDBBatch batch(*db);
|
||||||
{
|
for (const auto& e : toDelete) {
|
||||||
LOCK(cs);
|
RemoveRecoveredSig(batch, e.first, e.second, true, false);
|
||||||
for (const auto& e : toDelete) {
|
|
||||||
RemoveRecoveredSig(batch, e.first, e.second, true, false);
|
|
||||||
|
|
||||||
if (batch.SizeEstimate() >= (1 << 24)) {
|
if (batch.SizeEstimate() >= (1 << 24)) {
|
||||||
db->WriteBatch(batch);
|
db->WriteBatch(batch);
|
||||||
batch.Clear();
|
batch.Clear();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,7 +546,7 @@ bool CSigningManager::AlreadyHave(const CInv& inv) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_pending);
|
||||||
if (pendingReconstructedRecoveredSigs.count(inv.hash)) {
|
if (pendingReconstructedRecoveredSigs.count(inv.hash)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -607,7 +602,7 @@ PeerMsgRet CSigningManager::ProcessMessageRecoveredSig(const CNode& pfrom, const
|
|||||||
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- signHash=%s, id=%s, msgHash=%s, node=%d\n", __func__,
|
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- signHash=%s, id=%s, msgHash=%s, node=%d\n", __func__,
|
||||||
recoveredSig->buildSignHash().ToString(), recoveredSig->getId().ToString(), recoveredSig->getMsgHash().ToString(), pfrom.GetId());
|
recoveredSig->buildSignHash().ToString(), recoveredSig->getId().ToString(), recoveredSig->getMsgHash().ToString(), pfrom.GetId());
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs_pending);
|
||||||
if (pendingReconstructedRecoveredSigs.count(recoveredSig->GetHash())) {
|
if (pendingReconstructedRecoveredSigs.count(recoveredSig->GetHash())) {
|
||||||
// no need to perform full verification
|
// no need to perform full verification
|
||||||
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- already pending reconstructed sig, signHash=%s, id=%s, msgHash=%s, node=%d\n", __func__,
|
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- already pending reconstructed sig, signHash=%s, id=%s, msgHash=%s, node=%d\n", __func__,
|
||||||
@ -649,7 +644,7 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify(
|
|||||||
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr, StaticSaltedHasher>& retQuorums)
|
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr, StaticSaltedHasher>& retQuorums)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_pending);
|
||||||
if (pendingRecoveredSigs.empty()) {
|
if (pendingRecoveredSigs.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -714,7 +709,7 @@ void CSigningManager::ProcessPendingReconstructedRecoveredSigs()
|
|||||||
{
|
{
|
||||||
decltype(pendingReconstructedRecoveredSigs) m;
|
decltype(pendingReconstructedRecoveredSigs) m;
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_pending);
|
||||||
m = std::move(pendingReconstructedRecoveredSigs);
|
m = std::move(pendingReconstructedRecoveredSigs);
|
||||||
}
|
}
|
||||||
for (const auto& p : m) {
|
for (const auto& p : m) {
|
||||||
@ -795,43 +790,36 @@ void CSigningManager::ProcessRecoveredSig(const std::shared_ptr<const CRecovered
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CRecoveredSigsListener*> listeners;
|
auto signHash = recoveredSig->buildSignHash();
|
||||||
{
|
|
||||||
LOCK(cs);
|
|
||||||
listeners = recoveredSigsListeners;
|
|
||||||
|
|
||||||
auto signHash = recoveredSig->buildSignHash();
|
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- valid recSig. signHash=%s, id=%s, msgHash=%s\n", __func__,
|
||||||
|
signHash.ToString(), recoveredSig->getId().ToString(), recoveredSig->getMsgHash().ToString());
|
||||||
|
|
||||||
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- valid recSig. signHash=%s, id=%s, msgHash=%s\n", __func__,
|
if (db.HasRecoveredSigForId(llmqType, recoveredSig->getId())) {
|
||||||
signHash.ToString(), recoveredSig->getId().ToString(), recoveredSig->getMsgHash().ToString());
|
CRecoveredSig otherRecoveredSig;
|
||||||
|
if (db.GetRecoveredSigById(llmqType, recoveredSig->getId(), otherRecoveredSig)) {
|
||||||
if (db.HasRecoveredSigForId(llmqType, recoveredSig->getId())) {
|
auto otherSignHash = otherRecoveredSig.buildSignHash();
|
||||||
CRecoveredSig otherRecoveredSig;
|
if (signHash != otherSignHash) {
|
||||||
if (db.GetRecoveredSigById(llmqType, recoveredSig->getId(), otherRecoveredSig)) {
|
// this should really not happen, as each masternode is participating in only one vote,
|
||||||
auto otherSignHash = otherRecoveredSig.buildSignHash();
|
// even if it's a member of multiple quorums. so a majority is only possible on one quorum and one msgHash per id
|
||||||
if (signHash != otherSignHash) {
|
LogPrintf("CSigningManager::%s -- conflicting recoveredSig for signHash=%s, id=%s, msgHash=%s, otherSignHash=%s\n", __func__,
|
||||||
// this should really not happen, as each masternode is participating in only one vote,
|
signHash.ToString(), recoveredSig->getId().ToString(), recoveredSig->getMsgHash().ToString(), otherSignHash.ToString());
|
||||||
// even if it's a member of multiple quorums. so a majority is only possible on one quorum and one msgHash per id
|
|
||||||
LogPrintf("CSigningManager::%s -- conflicting recoveredSig for signHash=%s, id=%s, msgHash=%s, otherSignHash=%s\n", __func__,
|
|
||||||
signHash.ToString(), recoveredSig->getId().ToString(), recoveredSig->getMsgHash().ToString(), otherSignHash.ToString());
|
|
||||||
} else {
|
|
||||||
// Looks like we're trying to process a recSig that is already known. This might happen if the same
|
|
||||||
// recSig comes in through regular QRECSIG messages and at the same time through some other message
|
|
||||||
// which allowed to reconstruct a recSig (e.g. ISLOCK). In this case, just bail out.
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
// This case is very unlikely. It can only happen when cleanup caused this specific recSig to vanish
|
// Looks like we're trying to process a recSig that is already known. This might happen if the same
|
||||||
// between the HasRecoveredSigForId and GetRecoveredSigById call. If that happens, treat it as if we
|
// recSig comes in through regular QRECSIG messages and at the same time through some other message
|
||||||
// never had that recSig
|
// which allowed to reconstruct a recSig (e.g. ISLOCK). In this case, just bail out.
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// This case is very unlikely. It can only happen when cleanup caused this specific recSig to vanish
|
||||||
|
// between the HasRecoveredSigForId and GetRecoveredSigById call. If that happens, treat it as if we
|
||||||
|
// never had that recSig
|
||||||
}
|
}
|
||||||
|
|
||||||
db.WriteRecoveredSig(*recoveredSig);
|
|
||||||
|
|
||||||
pendingReconstructedRecoveredSigs.erase(recoveredSig->GetHash());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.WriteRecoveredSig(*recoveredSig);
|
||||||
|
WITH_LOCK(cs_pending, pendingReconstructedRecoveredSigs.erase(recoveredSig->GetHash()));
|
||||||
|
|
||||||
if (m_mn_activeman != nullptr) {
|
if (m_mn_activeman != nullptr) {
|
||||||
CInv inv(MSG_QUORUM_RECOVERED_SIG, recoveredSig->GetHash());
|
CInv inv(MSG_QUORUM_RECOVERED_SIG, recoveredSig->GetHash());
|
||||||
connman.ForEachNode([&](const CNode* pnode) {
|
connman.ForEachNode([&](const CNode* pnode) {
|
||||||
@ -841,6 +829,7 @@ void CSigningManager::ProcessRecoveredSig(const std::shared_ptr<const CRecovered
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto listeners = WITH_LOCK(cs_listeners, return recoveredSigsListeners);
|
||||||
for (auto& l : listeners) {
|
for (auto& l : listeners) {
|
||||||
l->HandleNewRecoveredSig(*recoveredSig);
|
l->HandleNewRecoveredSig(*recoveredSig);
|
||||||
}
|
}
|
||||||
@ -850,7 +839,7 @@ void CSigningManager::ProcessRecoveredSig(const std::shared_ptr<const CRecovered
|
|||||||
|
|
||||||
void CSigningManager::PushReconstructedRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& recoveredSig)
|
void CSigningManager::PushReconstructedRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& recoveredSig)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_pending);
|
||||||
pendingReconstructedRecoveredSigs.emplace(std::piecewise_construct, std::forward_as_tuple(recoveredSig->GetHash()), std::forward_as_tuple(recoveredSig));
|
pendingReconstructedRecoveredSigs.emplace(std::piecewise_construct, std::forward_as_tuple(recoveredSig->GetHash()), std::forward_as_tuple(recoveredSig));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -876,13 +865,13 @@ void CSigningManager::Cleanup()
|
|||||||
|
|
||||||
void CSigningManager::RegisterRecoveredSigsListener(CRecoveredSigsListener* l)
|
void CSigningManager::RegisterRecoveredSigsListener(CRecoveredSigsListener* l)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_listeners);
|
||||||
recoveredSigsListeners.emplace_back(l);
|
recoveredSigsListeners.emplace_back(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSigningManager::UnregisterRecoveredSigsListener(CRecoveredSigsListener* l)
|
void CSigningManager::UnregisterRecoveredSigsListener(CRecoveredSigsListener* l)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs_listeners);
|
||||||
auto itRem = std::remove(recoveredSigsListeners.begin(), recoveredSigsListeners.end(), l);
|
auto itRem = std::remove(recoveredSigsListeners.begin(), recoveredSigsListeners.end(), l);
|
||||||
recoveredSigsListeners.erase(itRem, recoveredSigsListeners.end());
|
recoveredSigsListeners.erase(itRem, recoveredSigsListeners.end());
|
||||||
}
|
}
|
||||||
@ -917,8 +906,6 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigShares
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
|
||||||
|
|
||||||
bool hasVoted = db.HasVotedOnId(llmqType, id);
|
bool hasVoted = db.HasVotedOnId(llmqType, id);
|
||||||
if (hasVoted) {
|
if (hasVoted) {
|
||||||
uint256 prevMsgHash;
|
uint256 prevMsgHash;
|
||||||
|
@ -114,10 +114,10 @@ class CRecoveredSigsDb
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<CDBWrapper> db{nullptr};
|
std::unique_ptr<CDBWrapper> db{nullptr};
|
||||||
|
|
||||||
mutable RecursiveMutex cs;
|
mutable Mutex cs_cache;
|
||||||
mutable unordered_lru_cache<std::pair<Consensus::LLMQType, uint256>, bool, StaticSaltedHasher, 30000> hasSigForIdCache GUARDED_BY(cs);
|
mutable unordered_lru_cache<std::pair<Consensus::LLMQType, uint256>, bool, StaticSaltedHasher, 30000> hasSigForIdCache GUARDED_BY(cs_cache);
|
||||||
mutable unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForSessionCache GUARDED_BY(cs);
|
mutable unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForSessionCache GUARDED_BY(cs_cache);
|
||||||
mutable unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForHashCache GUARDED_BY(cs);
|
mutable unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForHashCache GUARDED_BY(cs_cache);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CRecoveredSigsDb(bool fMemory, bool fWipe);
|
explicit CRecoveredSigsDb(bool fMemory, bool fWipe);
|
||||||
@ -145,7 +145,7 @@ private:
|
|||||||
void MigrateRecoveredSigs();
|
void MigrateRecoveredSigs();
|
||||||
|
|
||||||
bool ReadRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret) const;
|
bool ReadRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret) const;
|
||||||
void RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType llmqType, const uint256& id, bool deleteHashKey, bool deleteTimeKey) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
void RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType llmqType, const uint256& id, bool deleteHashKey, bool deleteTimeKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CRecoveredSigsListener
|
class CRecoveredSigsListener
|
||||||
@ -159,7 +159,6 @@ public:
|
|||||||
class CSigningManager
|
class CSigningManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
mutable RecursiveMutex cs;
|
|
||||||
|
|
||||||
CRecoveredSigsDb db;
|
CRecoveredSigsDb db;
|
||||||
CConnman& connman;
|
CConnman& connman;
|
||||||
@ -167,15 +166,17 @@ private:
|
|||||||
const CQuorumManager& qman;
|
const CQuorumManager& qman;
|
||||||
const std::unique_ptr<PeerManager>& m_peerman;
|
const std::unique_ptr<PeerManager>& m_peerman;
|
||||||
|
|
||||||
|
mutable Mutex cs_pending;
|
||||||
// Incoming and not verified yet
|
// Incoming and not verified yet
|
||||||
std::unordered_map<NodeId, std::list<std::shared_ptr<const CRecoveredSig>>> pendingRecoveredSigs GUARDED_BY(cs);
|
std::unordered_map<NodeId, std::list<std::shared_ptr<const CRecoveredSig>>> pendingRecoveredSigs GUARDED_BY(cs_pending);
|
||||||
std::unordered_map<uint256, std::shared_ptr<const CRecoveredSig>, StaticSaltedHasher> pendingReconstructedRecoveredSigs GUARDED_BY(cs);
|
std::unordered_map<uint256, std::shared_ptr<const CRecoveredSig>, StaticSaltedHasher> pendingReconstructedRecoveredSigs GUARDED_BY(cs_pending);
|
||||||
|
|
||||||
FastRandomContext rnd GUARDED_BY(cs);
|
FastRandomContext rnd GUARDED_BY(cs_pending);
|
||||||
|
|
||||||
int64_t lastCleanupTime{0};
|
int64_t lastCleanupTime{0};
|
||||||
|
|
||||||
std::vector<CRecoveredSigsListener*> recoveredSigsListeners GUARDED_BY(cs);
|
mutable Mutex cs_listeners;
|
||||||
|
std::vector<CRecoveredSigsListener*> recoveredSigsListeners GUARDED_BY(cs_listeners);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSigningManager(CConnman& _connman, const CActiveMasternodeManager* const mn_activeman, const CQuorumManager& _qman,
|
CSigningManager(CConnman& _connman, const CActiveMasternodeManager* const mn_activeman, const CQuorumManager& _qman,
|
||||||
|
Loading…
Reference in New Issue
Block a user