Merge #6282: refactor: drop some of circular dependencies over dkgsession

74a5a9f984 style: apply clang-format (Konstantin Akimov)
db9798f5e4 refactor: move call GetQuorumMembers inside Init() (Konstantin Akimov)
9593566802 refactor: move pQuorumBaseBlockIndex from Init() to constructor in CDKGSession (Konstantin Akimov)
9f3eb6bbb8 perf: check DIP0003 before CDKGSession initialization (Konstantin Akimov)
7f815cb501 refactor: remove unused constructor of CDKGLogger (Konstantin Akimov)
c82672af94 refactor: remove dependency of CDKGSession on PeerManager (Konstantin Akimov)
fb78b0cc94 refactor: remove retBan flag from ReceiveMessage (Konstantin Akimov)
d26d4ab0bc refactor: remove dependency of dkgsessionmgr on dkgsession (Konstantin Akimov)
d361b11e5b refactor: moved including llmq/dkgsession.h from dkgsessionmgr.h to cpp file (Konstantin Akimov)
e77aeb321b refactor: removed including quorums.h from chainlocks.h (Konstantin Akimov)
6f7068ef42 refactor: remove exceeding evodb.h from headers (Konstantin Akimov)

Pull request description:

  ## Issue being fixed or feature implemented
  We have 72 circular dependencies of dash specific code. This PR removes 2 of them, over dkgsession.

  ## What was done?
  Refactor dkgsession initialization, message processing, dropped unused arguments, re-distributed code between functions and modules... See each commit.
  Also optimized headers: excluded evo/evodb.h and llmq/quorums.h from the headers where they are not needed.

  ## How Has This Been Tested?
  Run `test/lint/lint-circular-dependencies.sh`
  Run unit/functional tests

  ## Breaking Changes
  N/A

  ## Checklist:
  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone

ACKs for top commit:
  UdjinM6:
    utACK 74a5a9f984
  PastaPastaPasta:
    utACK 74a5a9f984

Tree-SHA512: f3adabe6a7bc6c4dcae6430be6857b31a0722d7f605d6651f3ff93c6fcb350a7312a9a0ecbda8ac131ffef6fbf2499700112de3990c7512ddb057bde7cc42665
This commit is contained in:
pasta 2024-09-25 09:07:48 -05:00
commit 0a9a83fa4f
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
20 changed files with 249 additions and 169 deletions

View File

@ -2,16 +2,17 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/validation.h>
#include <evo/cbtx.h>
#include <evo/deterministicmns.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>
#include <llmq/blockprocessor.h>
#include <llmq/chainlocks.h>
#include <llmq/commitment.h>
#include <llmq/options.h>
#include <llmq/quorums.h>
#include <node/blockstorage.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>
#include <consensus/validation.h>
#include <chain.h>
#include <chainparams.h>

View File

@ -6,6 +6,7 @@
#include <evo/assetlocktx.h>
#include <evo/cbtx.h>
#include <evo/evodb.h>
#include <evo/specialtx.h>
#include <chain.h>

View File

@ -8,7 +8,6 @@
#include <coins.h>
#include <evo/assetlocktx.h>
#include <evo/evodb.h>
#include <saltedhasher.h>
#include <serialize.h>
@ -23,6 +22,7 @@
class BlockManager;
class CBlockIndex;
class BlockValidationState;
class CEvoDB;
class TxValidationState;
namespace Consensus {
struct Params;

View File

@ -5,6 +5,7 @@
#include <evo/deterministicmns.h>
#include <evo/dmn_types.h>
#include <evo/dmnstate.h>
#include <evo/evodb.h>
#include <evo/providertx.h>
#include <evo/specialtx.h>
#include <llmq/commitment.h>

View File

@ -8,15 +8,15 @@
#include <evo/dmnstate.h>
#include <arith_uint256.h>
#include <clientversion.h>
#include <consensus/params.h>
#include <crypto/common.h>
#include <evo/dmn_types.h>
#include <evo/evodb.h>
#include <evo/providertx.h>
#include <gsl/pointers.h>
#include <saltedhasher.h>
#include <scheduler.h>
#include <sync.h>
#include <gsl/pointers.h>
#include <immer/map.hpp>
@ -30,6 +30,7 @@ class CBlock;
class CBlockIndex;
class CChainState;
class CConnman;
class CEvoDB;
class TxValidationState;
extern RecursiveMutex cs_main;

View File

@ -4,11 +4,12 @@
#include <consensus/validation.h>
#include <deploymentstatus.h>
#include <evo/evodb.h>
#include <evo/mnhftx.h>
#include <evo/specialtx.h>
#include <llmq/commitment.h>
#include <llmq/signing.h>
#include <llmq/quorums.h>
#include <llmq/signing.h>
#include <node/blockstorage.h>
#include <chain.h>

View File

@ -90,6 +90,7 @@
#include <spork.h>
#include <walletinitinterface.h>
#include <evo/evodb.h>
#include <evo/chainhelper.h>
#include <evo/creditpool.h>
#include <evo/deterministicmns.h>

View File

@ -9,7 +9,6 @@
#include <crypto/common.h>
#include <llmq/signing.h>
#include <llmq/quorums.h>
#include <net.h>
#include <net_types.h>
#include <primitives/block.h>
@ -36,6 +35,7 @@ namespace llmq
{
class CSigningManager;
class CSigSharesManager;
enum class VerifyRecSigStatus;
class CChainLocksHandler : public CRecoveredSigsListener
{

View File

@ -20,7 +20,6 @@
#include <logging.h>
#include <masternode/meta.h>
#include <masternode/node.h>
#include <net_processing.h>
#include <netmessagemaker.h>
#include <validation.h>
#include <util/irange.h>
@ -33,14 +32,13 @@
namespace llmq
{
class CDKGLogger : public CBatchedLogger
CDKGLogger::CDKGLogger(const CDKGSession& _quorumDkg, std::string_view _func, int source_line) :
CBatchedLogger(BCLog::LLMQ_DKG,
strprintf("QuorumDKG(type=%s, qIndex=%d, h=%d, member=%d)", _quorumDkg.params.name, _quorumDkg.quorumIndex,
_quorumDkg.m_quorum_base_block_index->nHeight, _quorumDkg.AreWeMember()),
__FILE__, source_line)
{
public:
CDKGLogger(const CDKGSession& _quorumDkg, std::string_view _func, int source_line) :
CDKGLogger(_quorumDkg.params.name, _quorumDkg.quorumIndex, _quorumDkg.m_quorum_base_block_index->GetBlockHash(), _quorumDkg.m_quorum_base_block_index->nHeight, _quorumDkg.AreWeMember(), _func, source_line){};
CDKGLogger(std::string_view _llmqTypeName, int _quorumIndex, const uint256& _quorumHash, int _height, bool _areWeMember, std::string_view _func, int source_line) :
CBatchedLogger(BCLog::LLMQ_DKG, strprintf("QuorumDKG(type=%s, qIndex=%d, h=%d, member=%d)", _llmqTypeName, _quorumIndex, _height, _areWeMember), __FILE__, source_line){};
};
}
static std::array<std::atomic<double>, ToUnderlying(DKGError::type::_COUNT)> simDkgErrorMap{};
@ -73,9 +71,28 @@ CDKGMember::CDKGMember(const CDeterministicMNCPtr& _dmn, size_t _idx) :
}
bool CDKGSession::Init(gsl::not_null<const CBlockIndex*> _pQuorumBaseBlockIndex, Span<CDeterministicMNCPtr> mns, const uint256& _myProTxHash, int _quorumIndex)
CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params,
CBLSWorker& _blsWorker, CConnman& _connman, CDeterministicMNManager& dmnman,
CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager,
CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman,
const CSporkManager& sporkman) :
params(_params),
blsWorker(_blsWorker),
cache(_blsWorker),
connman(_connman),
m_dmnman(dmnman),
dkgManager(_dkgManager),
dkgDebugManager(_dkgDebugManager),
m_mn_metaman(mn_metaman),
m_mn_activeman(mn_activeman),
m_sporkman(sporkman),
m_quorum_base_block_index{pQuorumBaseBlockIndex}
{
m_quorum_base_block_index = _pQuorumBaseBlockIndex;
}
bool CDKGSession::Init(const uint256& _myProTxHash, int _quorumIndex)
{
const auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, m_quorum_base_block_index);
quorumIndex = _quorumIndex;
members.resize(mns.size());
memberIds.resize(members.size());
@ -259,12 +276,10 @@ bool CDKGSession::PreVerifyMessage(const CDKGContribution& qc, bool& retBan) con
return true;
}
void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
std::optional<CInv> CDKGSession::ReceiveMessage(const CDKGContribution& qc)
{
CDKGLogger logger(*this, __func__, __LINE__);
retBan = false;
auto* member = GetMember(qc.proTxHash);
cxxtimer::Timer t1(true);
@ -275,7 +290,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
if (member->contributions.size() >= 2) {
// only relay up to 2 contributions, that's enough to let the other members know about his bad behavior
return;
return std::nullopt;
}
const uint256 hash = ::SerializeHash(qc);
@ -283,7 +298,6 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
member->contributions.emplace(hash);
CInv inv(MSG_QUORUM_CONTRIB, hash);
RelayInvToParticipants(inv);
dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) {
status.statusBits.receivedContribution = true;
@ -295,7 +309,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
// so others know about his bad behavior
MarkBadMember(member->idx);
logger.Batch("%s did send multiple contributions", member->dmn->proTxHash.ToString());
return;
return inv;
}
receivedVvecs[member->idx] = qc.vvec;
@ -308,7 +322,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
if (!AreWeMember()) {
// can't further validate
return;
return inv;
}
dkgManager.WriteVerifiedVvecContribution(params.type, m_quorum_base_block_index, qc.proTxHash, qc.vvec);
@ -329,7 +343,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
status.statusBits.weComplain = true;
return true;
});
return;
return inv;
}
logger.Batch("decrypted our contribution share. time=%d", t2.count());
@ -341,6 +355,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
if (pendingContributionVerifications.size() >= 32) {
VerifyPendingContributions();
}
return inv;
}
// Verifies all pending secret key contributions in one batch
@ -569,19 +584,17 @@ bool CDKGSession::PreVerifyMessage(const CDKGComplaint& qc, bool& retBan) const
return true;
}
void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan)
std::optional<CInv> CDKGSession::ReceiveMessage(const CDKGComplaint& qc)
{
CDKGLogger logger(*this, __func__, __LINE__);
retBan = false;
logger.Batch("received complaint from %s", qc.proTxHash.ToString());
auto* member = GetMember(qc.proTxHash);
if (member->complaints.size() >= 2) {
// only relay up to 2 complaints, that's enough to let the other members know about his bad behavior
return;
return std::nullopt;
}
const uint256 hash = ::SerializeHash(qc);
@ -589,7 +602,6 @@ void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan)
member->complaints.emplace(hash);
CInv inv(MSG_QUORUM_COMPLAINT, hash);
RelayInvToParticipants(inv);
dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) {
status.statusBits.receivedComplaint = true;
@ -601,7 +613,7 @@ void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan)
// so others know about his bad behavior
MarkBadMember(member->idx);
logger.Batch("%s did send multiple complaints", member->dmn->proTxHash.ToString());
return;
return inv;
}
int receivedCount = 0;
@ -630,6 +642,7 @@ void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan)
}
logger.Batch("received and relayed complaint. received=%d", receivedCount);
return inv;
}
void CDKGSession::VerifyAndJustify(CDKGPendingMessages& pendingMessages)
@ -780,19 +793,17 @@ bool CDKGSession::PreVerifyMessage(const CDKGJustification& qj, bool& retBan) co
return true;
}
void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan)
std::optional<CInv> CDKGSession::ReceiveMessage(const CDKGJustification& qj)
{
CDKGLogger logger(*this, __func__, __LINE__);
retBan = false;
logger.Batch("received justification from %s", qj.proTxHash.ToString());
auto* member = GetMember(qj.proTxHash);
if (member->justifications.size() >= 2) {
// only relay up to 2 justifications, that's enough to let the other members know about his bad behavior
return;
return std::nullopt;
}
const uint256 hash = ::SerializeHash(qj);
@ -801,7 +812,6 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan)
// we always relay, even if further verification fails
CInv inv(MSG_QUORUM_JUSTIFICATION, hash);
RelayInvToParticipants(inv);
dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) {
status.statusBits.receivedJustification = true;
@ -813,13 +823,13 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan)
// so others know about his bad behavior
logger.Batch("%s did send multiple justifications", member->dmn->proTxHash.ToString());
MarkBadMember(member->idx);
return;
return inv;
}
if (member->bad) {
// we locally determined him to be bad (sent none or more then one contributions)
// don't give him a second chance (but we relay the justification in case other members disagree)
return;
return inv;
}
for (const auto& p : qj.contributions) {
@ -832,7 +842,7 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan)
}
}
if (member->bad) {
return;
return inv;
}
cxxtimer::Timer t1(true);
@ -872,6 +882,7 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan)
});
logger.Batch("verified justification: received=%d/%d time=%d", receivedCount, expectedCount, t1.count());
return inv;
}
void CDKGSession::VerifyAndCommit(CDKGPendingMessages& pendingMessages)
@ -1095,12 +1106,10 @@ bool CDKGSession::PreVerifyMessage(const CDKGPrematureCommitment& qc, bool& retB
return true;
}
void CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan)
std::optional<CInv> CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc)
{
CDKGLogger logger(*this, __func__, __LINE__);
retBan = false;
cxxtimer::Timer t1(true);
logger.Batch("received premature commitment from %s. validMembers=%d", qc.proTxHash.ToString(), qc.CountValidMembers());
@ -1137,30 +1146,29 @@ void CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan
if ((*quorumVvec)[0] != qc.quorumPublicKey) {
logger.Batch("calculated quorum public key does not match");
return;
return std::nullopt;
}
uint256 vvecHash = ::SerializeHash(*quorumVvec);
if (qc.quorumVvecHash != vvecHash) {
logger.Batch("calculated quorum vvec hash does not match");
return;
return std::nullopt;
}
CBLSPublicKey pubKeyShare = cache.BuildPubKeyShare(::SerializeHash(std::make_pair(memberIndexes, member->id)), quorumVvec, member->id);
if (!pubKeyShare.IsValid()) {
logger.Batch("failed to calculate public key share");
return;
return std::nullopt;
}
if (!qc.quorumSig.VerifyInsecure(pubKeyShare, qc.GetSignHash())) {
logger.Batch("failed to verify quorumSig");
return;
return std::nullopt;
}
}
WITH_LOCK(invCs, validCommitments.emplace(hash));
CInv inv(MSG_QUORUM_PREMATURE_COMMITMENT, hash);
RelayInvToParticipants(inv);
dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) {
status.statusBits.receivedPrematureCommitment = true;
@ -1172,6 +1180,7 @@ void CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan
t1.stop();
logger.Batch("verified premature commitment. received=%d/%d, time=%d", receivedCount, members.size(), t1.count());
return inv;
}
std::vector<CFinalCommitment> CDKGSession::FinalizeCommitments()
@ -1304,41 +1313,5 @@ void CDKGSession::MarkBadMember(size_t idx)
member->bad = true;
}
void CDKGSession::RelayInvToParticipants(const CInv& inv) const
{
CDKGLogger logger(*this, __func__, __LINE__);
std::stringstream ss;
for (const auto& r : relayMembers) {
ss << r.ToString().substr(0, 4) << " | ";
}
logger.Batch("RelayInvToParticipants inv[%s] relayMembers[%d] GetNodeCount[%d] GetNetworkActive[%d] HasMasternodeQuorumNodes[%d] for quorumHash[%s] forMember[%s] relayMembers[%s]",
inv.ToString(),
relayMembers.size(),
connman.GetNodeCount(ConnectionDirection::Both),
connman.GetNetworkActive(),
connman.HasMasternodeQuorumNodes(params.type, m_quorum_base_block_index->GetBlockHash()),
m_quorum_base_block_index->GetBlockHash().ToString(),
myProTxHash.ToString().substr(0, 4), ss.str());
std::stringstream ss2;
connman.ForEachNode([&](const CNode* pnode) {
if (pnode->qwatch ||
(!pnode->GetVerifiedProRegTxHash().IsNull() && (relayMembers.count(pnode->GetVerifiedProRegTxHash()) != 0))) {
Assert(m_peerman)->PushInventory(pnode->GetId(), inv);
}
if (pnode->GetVerifiedProRegTxHash().IsNull()) {
logger.Batch("node[%d:%s] not mn",
pnode->GetId(),
pnode->m_addr_name);
} else if (relayMembers.count(pnode->GetVerifiedProRegTxHash()) == 0) {
ss2 << pnode->GetVerifiedProRegTxHash().ToString().substr(0, 4) << " | ";
}
});
logger.Batch("forMember[%s] NOTrelayMembers[%s]",
myProTxHash.ToString().substr(0, 4),
ss2.str());
logger.Flush();
}
} // namespace llmq

View File

@ -5,13 +5,14 @@
#ifndef BITCOIN_LLMQ_DKGSESSION_H
#define BITCOIN_LLMQ_DKGSESSION_H
#include <llmq/commitment.h>
#include <batchedlogger.h>
#include <bls/bls.h>
#include <bls/bls_ies.h>
#include <bls/bls_worker.h>
#include <llmq/commitment.h>
#include <util/underlying.h>
#include <sync.h>
#include <util/underlying.h>
#include <optional>
@ -22,7 +23,6 @@ class CDeterministicMN;
class CMasternodeMetaMan;
class CSporkManager;
class UniValue;
class PeerManager;
using CDeterministicMNCPtr = std::shared_ptr<const CDeterministicMN>;
@ -249,6 +249,12 @@ public:
}
};
class CDKGLogger : public CBatchedLogger
{
public:
CDKGLogger(const CDKGSession& _quorumDkg, std::string_view _func, int source_line);
};
/**
* The DKG session is a single instance of the DKG process. It is owned and called by CDKGSessionHandler, which passes
* received DKG messages to the session. The session is not persistent and will loose it's state (the whole object is
@ -281,9 +287,8 @@ private:
CMasternodeMetaMan& m_mn_metaman;
const CActiveMasternodeManager* const m_mn_activeman;
const CSporkManager& m_sporkman;
const std::unique_ptr<PeerManager>& m_peerman;
const CBlockIndex* m_quorum_base_block_index{nullptr};
const CBlockIndex* const m_quorum_base_block_index;
int quorumIndex{0};
private:
@ -321,15 +326,13 @@ private:
std::set<uint256> validCommitments GUARDED_BY(invCs);
public:
CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CConnman& _connman,
CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager,
CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman,
const CSporkManager& sporkman, const std::unique_ptr<PeerManager>& peerman) :
params(_params), blsWorker(_blsWorker), cache(_blsWorker), connman(_connman), m_dmnman(dmnman), dkgManager(_dkgManager),
dkgDebugManager(_dkgDebugManager), m_mn_metaman(mn_metaman), m_mn_activeman(mn_activeman), m_sporkman(sporkman),
m_peerman(peerman) {}
CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker,
CConnman& _connman, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager,
CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman,
const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman);
bool Init(gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, Span<CDeterministicMNCPtr> mns, const uint256& _myProTxHash, int _quorumIndex);
// TODO: remove Init completely
bool Init(const uint256& _myProTxHash, int _quorumIndex);
[[nodiscard]] std::optional<size_t> GetMyMemberIndex() const { return myIdx; }
@ -350,7 +353,7 @@ public:
void Contribute(CDKGPendingMessages& pendingMessages);
void SendContributions(CDKGPendingMessages& pendingMessages);
bool PreVerifyMessage(const CDKGContribution& qc, bool& retBan) const;
void ReceiveMessage(const CDKGContribution& qc, bool& retBan);
std::optional<CInv> ReceiveMessage(const CDKGContribution& qc);
void VerifyPendingContributions() EXCLUSIVE_LOCKS_REQUIRED(cs_pending);
// Phase 2: complaint
@ -358,19 +361,19 @@ public:
void VerifyConnectionAndMinProtoVersions() const;
void SendComplaint(CDKGPendingMessages& pendingMessages);
bool PreVerifyMessage(const CDKGComplaint& qc, bool& retBan) const;
void ReceiveMessage(const CDKGComplaint& qc, bool& retBan);
std::optional<CInv> ReceiveMessage(const CDKGComplaint& qc);
// Phase 3: justification
void VerifyAndJustify(CDKGPendingMessages& pendingMessages);
void SendJustification(CDKGPendingMessages& pendingMessages, const std::set<uint256>& forMembers);
bool PreVerifyMessage(const CDKGJustification& qj, bool& retBan) const;
void ReceiveMessage(const CDKGJustification& qj, bool& retBan);
std::optional<CInv> ReceiveMessage(const CDKGJustification& qj);
// Phase 4: commit
void VerifyAndCommit(CDKGPendingMessages& pendingMessages);
void SendCommitment(CDKGPendingMessages& pendingMessages);
bool PreVerifyMessage(const CDKGPrematureCommitment& qc, bool& retBan) const;
void ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan);
std::optional<CInv> ReceiveMessage(const CDKGPrematureCommitment& qc);
// Phase 5: aggregate/finalize
std::vector<CFinalCommitment> FinalizeCommitments();
@ -378,10 +381,12 @@ public:
[[nodiscard]] bool AreWeMember() const { return !myProTxHash.IsNull(); }
void MarkBadMember(size_t idx);
void RelayInvToParticipants(const CInv& inv) const;
public:
[[nodiscard]] CDKGMember* GetMember(const uint256& proTxHash) const;
[[nodiscard]] const std::set<uint256>& RelayMembers() const { return relayMembers; }
[[nodiscard]] const CBlockIndex* BlockIndex() const { return m_quorum_base_block_index; }
[[nodiscard]] const uint256& ProTx() const { return myProTxHash; }
[[nodiscard]] const Consensus::LLMQParams GetParams() const { return params; }
private:
[[nodiscard]] bool ShouldSimulateError(DKGError::type type) const;

View File

@ -24,10 +24,13 @@
namespace llmq
{
CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman,
CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman,
const CSporkManager& sporkman, const std::unique_ptr<PeerManager>& peerman, const Consensus::LLMQParams& _params, int _quorumIndex) :
CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman,
CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager,
CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman,
CQuorumBlockProcessor& _quorumBlockProcessor,
const CActiveMasternodeManager* const mn_activeman,
const CSporkManager& sporkman, const std::unique_ptr<PeerManager>& peerman,
const Consensus::LLMQParams& _params, int _quorumIndex) :
blsWorker(_blsWorker),
m_chainstate(chainstate),
connman(_connman),
@ -41,8 +44,11 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chai
m_peerman(peerman),
params(_params),
quorumIndex(_quorumIndex),
curSession(std::make_unique<CDKGSession>(_params, _blsWorker, _connman, dmnman, _dkgManager, _dkgDebugManager, m_mn_metaman, m_mn_activeman, sporkman, peerman)),
pendingContributions((size_t)_params.size * 2, MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages)
curSession(std::make_unique<CDKGSession>(nullptr, _params, _blsWorker, _connman, dmnman, _dkgManager,
_dkgDebugManager, m_mn_metaman, m_mn_activeman, sporkman)),
pendingContributions(
(size_t)_params.size * 2,
MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages)
pendingComplaints((size_t)_params.size * 2, MSG_QUORUM_COMPLAINT),
pendingJustifications((size_t)_params.size * 2, MSG_QUORUM_JUSTIFICATION),
pendingPrematureCommitments((size_t)_params.size * 2, MSG_QUORUM_PREMATURE_COMMITMENT)
@ -52,6 +58,8 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chai
}
}
CDKGSessionHandler::~CDKGSessionHandler() = default;
void CDKGPendingMessages::PushPendingMessage(NodeId from, PeerManager* peerman, CDataStream& vRecv)
{
// if peer is not -1 we should always pass valid peerman
@ -188,15 +196,16 @@ void CDKGSessionHandler::StopThread()
bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex)
{
curSession = std::make_unique<CDKGSession>(params, blsWorker, connman, m_dmnman, dkgManager, dkgDebugManager, m_mn_metaman, m_mn_activeman, m_sporkman, m_peerman);
if (!DeploymentDIP0003Enforced(pQuorumBaseBlockIndex->nHeight, Params().GetConsensus())) {
return false;
}
auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, pQuorumBaseBlockIndex);
if (!curSession->Init(pQuorumBaseBlockIndex, mns, m_mn_activeman->GetProTxHash(), quorumIndex)) {
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d] mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex, mns.size());
curSession = std::make_unique<CDKGSession>(pQuorumBaseBlockIndex, params, blsWorker, connman, m_dmnman, dkgManager,
dkgDebugManager, m_mn_metaman, m_mn_activeman, m_sporkman);
if (!curSession->Init(m_mn_activeman->GetProTxHash(), quorumIndex)) {
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d]\n", __func__,
pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex);
return false;
}
@ -436,8 +445,40 @@ std::set<NodeId> BatchVerifyMessageSigs(CDKGSession& session, const std::vector<
return ret;
}
template<typename Message, int MessageType>
bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendingMessages, size_t maxCount)
static void RelayInvToParticipants(const CDKGSession& session, CConnman& connman, PeerManager& peerman, const CInv& inv)
{
CDKGLogger logger(session, __func__, __LINE__);
std::stringstream ss;
const auto& relayMembers = session.RelayMembers();
for (const auto& r : relayMembers) {
ss << r.ToString().substr(0, 4) << " | ";
}
logger.Batch("RelayInvToParticipants inv[%s] relayMembers[%d] GetNodeCount[%d] GetNetworkActive[%d] "
"HasMasternodeQuorumNodes[%d] for quorumHash[%s] forMember[%s] relayMembers[%s]",
inv.ToString(), relayMembers.size(), connman.GetNodeCount(ConnectionDirection::Both),
connman.GetNetworkActive(),
connman.HasMasternodeQuorumNodes(session.GetParams().type, session.BlockIndex()->GetBlockHash()),
session.BlockIndex()->GetBlockHash().ToString(), session.ProTx().ToString().substr(0, 4), ss.str());
std::stringstream ss2;
connman.ForEachNode([&](const CNode* pnode) {
if (pnode->qwatch ||
(!pnode->GetVerifiedProRegTxHash().IsNull() && (relayMembers.count(pnode->GetVerifiedProRegTxHash()) != 0))) {
peerman.PushInventory(pnode->GetId(), inv);
}
if (pnode->GetVerifiedProRegTxHash().IsNull()) {
logger.Batch("node[%d:%s] not mn", pnode->GetId(), pnode->m_addr_name);
} else if (relayMembers.count(pnode->GetVerifiedProRegTxHash()) == 0) {
ss2 << pnode->GetVerifiedProRegTxHash().ToString().substr(0, 4) << " | ";
}
});
logger.Batch("forMember[%s] NOTrelayMembers[%s]", session.ProTx().ToString().substr(0, 4), ss2.str());
logger.Flush();
}
template <typename Message, int MessageType>
bool ProcessPendingMessageBatch(CConnman& connman, PeerManager* peerman, CDKGSession& session,
CDKGPendingMessages& pendingMessages, size_t maxCount)
{
auto msgs = pendingMessages.PopAndDeserializeMessages<Message>(maxCount);
if (msgs.empty()) {
@ -487,12 +528,9 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
if (badNodes.count(nodeId)) {
continue;
}
bool ban = false;
session.ReceiveMessage(*p.second, ban);
if (ban) {
LogPrint(BCLog::LLMQ_DKG, "%s -- banning node after ReceiveMessage failed, peer=%d\n", __func__, nodeId);
pendingMessages.Misbehaving(nodeId, 100);
badNodes.emplace(nodeId);
const std::optional<CInv> inv = session.ReceiveMessage(*p.second);
if (inv && peerman) {
RelayInvToParticipants(session, connman, *peerman, *inv);
}
}
@ -536,7 +574,8 @@ void CDKGSessionHandler::HandleDKGRound()
curSession->Contribute(pendingContributions);
};
auto fContributeWait = [this] {
return ProcessPendingMessageBatch<CDKGContribution, MSG_QUORUM_CONTRIB>(*curSession, pendingContributions, 8);
return ProcessPendingMessageBatch<CDKGContribution, MSG_QUORUM_CONTRIB>(connman, m_peerman.get(), *curSession,
pendingContributions, 8);
};
HandlePhase(QuorumPhase::Contribute, QuorumPhase::Complain, curQuorumHash, 0.05, fContributeStart, fContributeWait);
@ -545,7 +584,8 @@ void CDKGSessionHandler::HandleDKGRound()
curSession->VerifyAndComplain(pendingComplaints);
};
auto fComplainWait = [this] {
return ProcessPendingMessageBatch<CDKGComplaint, MSG_QUORUM_COMPLAINT>(*curSession, pendingComplaints, 8);
return ProcessPendingMessageBatch<CDKGComplaint, MSG_QUORUM_COMPLAINT>(connman, m_peerman.get(), *curSession,
pendingComplaints, 8);
};
HandlePhase(QuorumPhase::Complain, QuorumPhase::Justify, curQuorumHash, 0.05, fComplainStart, fComplainWait);
@ -554,7 +594,9 @@ void CDKGSessionHandler::HandleDKGRound()
curSession->VerifyAndJustify(pendingJustifications);
};
auto fJustifyWait = [this] {
return ProcessPendingMessageBatch<CDKGJustification, MSG_QUORUM_JUSTIFICATION>(*curSession, pendingJustifications, 8);
return ProcessPendingMessageBatch<CDKGJustification, MSG_QUORUM_JUSTIFICATION>(connman, m_peerman.get(),
*curSession,
pendingJustifications, 8);
};
HandlePhase(QuorumPhase::Justify, QuorumPhase::Commit, curQuorumHash, 0.05, fJustifyStart, fJustifyWait);
@ -563,7 +605,8 @@ void CDKGSessionHandler::HandleDKGRound()
curSession->VerifyAndCommit(pendingPrematureCommitments);
};
auto fCommitWait = [this] {
return ProcessPendingMessageBatch<CDKGPrematureCommitment, MSG_QUORUM_PREMATURE_COMMITMENT>(*curSession, pendingPrematureCommitments, 8);
return ProcessPendingMessageBatch<CDKGPrematureCommitment, MSG_QUORUM_PREMATURE_COMMITMENT>(
connman, m_peerman.get(), *curSession, pendingPrematureCommitments, 8);
};
HandlePhase(QuorumPhase::Commit, QuorumPhase::Finalize, curQuorumHash, 0.1, fCommitStart, fCommitWait);
@ -589,4 +632,48 @@ void CDKGSessionHandler::PhaseHandlerThread()
}
}
bool CDKGSessionHandler::GetContribution(const uint256& hash, CDKGContribution& ret) const
{
LOCK(curSession->invCs);
auto it = curSession->contributions.find(hash);
if (it != curSession->contributions.end()) {
ret = it->second;
return true;
}
return false;
}
bool CDKGSessionHandler::GetComplaint(const uint256& hash, CDKGComplaint& ret) const
{
LOCK(curSession->invCs);
auto it = curSession->complaints.find(hash);
if (it != curSession->complaints.end()) {
ret = it->second;
return true;
}
return false;
}
bool CDKGSessionHandler::GetJustification(const uint256& hash, CDKGJustification& ret) const
{
LOCK(curSession->invCs);
auto it = curSession->justifications.find(hash);
if (it != curSession->justifications.end()) {
ret = it->second;
return true;
}
return false;
}
bool CDKGSessionHandler::GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const
{
LOCK(curSession->invCs);
auto it = curSession->prematureCommitments.find(hash);
if (it != curSession->prematureCommitments.end() && curSession->validCommitments.count(hash)) {
ret = it->second;
return true;
}
return false;
}
} // namespace llmq

View File

@ -25,6 +25,10 @@ class PeerManager;
namespace llmq
{
class CDKGContribution;
class CDKGComplaint;
class CDKGJustification;
class CDKGPrematureCommitment;
class CDKGDebugManager;
class CDKGSession;
class CDKGSessionManager;
@ -153,7 +157,7 @@ public:
CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman,
CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman,
const CSporkManager& sporkman, const std::unique_ptr<PeerManager>& peerman, const Consensus::LLMQParams& _params, int _quorumIndex);
~CDKGSessionHandler() = default;
~CDKGSessionHandler();
void UpdatedBlockTip(const CBlockIndex *pindexNew);
void ProcessMessage(const CNode& pfrom, gsl::not_null<PeerManager*> peerman, const std::string& msg_type, CDataStream& vRecv);
@ -161,6 +165,11 @@ public:
void StartThread();
void StopThread();
bool GetContribution(const uint256& hash, CDKGContribution& ret) const;
bool GetComplaint(const uint256& hash, CDKGComplaint& ret) const;
bool GetJustification(const uint256& hash, CDKGJustification& ret) const;
bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const;
private:
bool InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex);

View File

@ -56,6 +56,8 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai
}
}
CDKGSessionManager::~CDKGSessionManager() = default;
void CDKGSessionManager::MigrateDKG()
{
if (!db->IsEmpty()) return;
@ -297,10 +299,7 @@ bool CDKGSessionManager::GetContribution(const uint256& hash, CDKGContribution&
if (dkgType.phase < QuorumPhase::Initialized || dkgType.phase > QuorumPhase::Contribute) {
continue;
}
LOCK(dkgType.curSession->invCs);
auto it = dkgType.curSession->contributions.find(hash);
if (it != dkgType.curSession->contributions.end()) {
ret = it->second;
if (dkgType.GetContribution(hash, ret)) {
return true;
}
}
@ -318,10 +317,7 @@ bool CDKGSessionManager::GetComplaint(const uint256& hash, CDKGComplaint& ret) c
if (dkgType.phase < QuorumPhase::Contribute || dkgType.phase > QuorumPhase::Complain) {
continue;
}
LOCK(dkgType.curSession->invCs);
auto it = dkgType.curSession->complaints.find(hash);
if (it != dkgType.curSession->complaints.end()) {
ret = it->second;
if (dkgType.GetComplaint(hash, ret)) {
return true;
}
}
@ -339,10 +335,7 @@ bool CDKGSessionManager::GetJustification(const uint256& hash, CDKGJustification
if (dkgType.phase < QuorumPhase::Complain || dkgType.phase > QuorumPhase::Justify) {
continue;
}
LOCK(dkgType.curSession->invCs);
auto it = dkgType.curSession->justifications.find(hash);
if (it != dkgType.curSession->justifications.end()) {
ret = it->second;
if (dkgType.GetJustification(hash, ret)) {
return true;
}
}
@ -360,10 +353,7 @@ bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematu
if (dkgType.phase < QuorumPhase::Justify || dkgType.phase > QuorumPhase::Commit) {
continue;
}
LOCK(dkgType.curSession->invCs);
auto it = dkgType.curSession->prematureCommitments.find(hash);
if (it != dkgType.curSession->prematureCommitments.end() && dkgType.curSession->validCommitments.count(hash)) {
ret = it->second;
if (dkgType.GetPrematureCommitment(hash, ret)) {
return true;
}
}

View File

@ -5,10 +5,10 @@
#ifndef BITCOIN_LLMQ_DKGSESSIONMGR_H
#define BITCOIN_LLMQ_DKGSESSIONMGR_H
#include <llmq/dkgsessionhandler.h>
#include <llmq/dkgsession.h>
#include <bls/bls.h>
#include <bls/bls_ies.h>
#include <bls/bls_worker.h>
#include <llmq/dkgsessionhandler.h>
#include <net_types.h>
#include <map>
@ -23,6 +23,10 @@ class CDKGDebugManager;
class CMasternodeMetaMan;
class CSporkManager;
class PeerManager;
class CDKGContribution;
class CDKGComplaint;
class CDKGJustification;
class CDKGPrematureCommitment;
class UniValue;
@ -71,7 +75,7 @@ public:
CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor,
const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman,
const std::unique_ptr<PeerManager>& peerman, bool unitTests, bool fWipe);
~CDKGSessionManager() = default;
~CDKGSessionManager();
void StartThreads();
void StopThreads();

View File

@ -11,10 +11,12 @@
#include <llmq/params.h>
#include <llmq/utils.h>
#include <evo/specialtx.h>
#include <evo/deterministicmns.h>
#include <evo/evodb.h>
#include <evo/specialtx.h>
#include <chainparams.h>
#include <dbwrapper.h>
#include <masternode/node.h>
#include <masternode/sync.h>
#include <net.h>
@ -230,6 +232,8 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate,
MigrateOldQuorumDB(_evoDb);
}
CQuorumManager::~CQuorumManager() { Stop(); }
void CQuorumManager::Start()
{
int workerCount = std::thread::hardware_concurrency() / 2;

View File

@ -14,7 +14,6 @@
#include <bls/bls.h>
#include <bls/bls_worker.h>
#include <evo/evodb.h>
#include <net_types.h>
#include <gsl/pointers.h>
@ -26,8 +25,11 @@ class CActiveMasternodeManager;
class CBlockIndex;
class CChainState;
class CConnman;
class CDataStream;
class CDeterministicMN;
class CDeterministicMNManager;
class CDBWrapper;
class CEvoDB;
class CMasternodeSync;
class CNode;
class CSporkManager;
@ -258,7 +260,7 @@ public:
CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor,
const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync,
const CSporkManager& sporkman, bool unit_tests, bool wipe);
~CQuorumManager() { Stop(); };
~CQuorumManager();
void Start();
void Stop();

View File

@ -4,6 +4,7 @@
#include <llmq/snapshot.h>
#include <evo/evodb.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>

View File

@ -5,7 +5,6 @@
#ifndef BITCOIN_LLMQ_SNAPSHOT_H
#define BITCOIN_LLMQ_SNAPSHOT_H
#include <evo/evodb.h>
#include <evo/simplifiedmns.h>
#include <llmq/commitment.h>
#include <llmq/params.h>
@ -20,6 +19,7 @@
class CBlockIndex;
class CDeterministicMN;
class CDeterministicMNList;
class CEvoDb;
namespace llmq {
class CQuorumBlockProcessor;

View File

@ -61,6 +61,7 @@
#include <llmq/chainlocks.h>
#include <llmq/commitment.h>
#include <llmq/context.h>
#include <llmq/dkgsession.h>
#include <llmq/dkgsessionmgr.h>
#include <llmq/instantsend.h>
#include <llmq/options.h>

View File

@ -62,7 +62,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
"banman -> bloom -> evo/assetlocktx -> llmq/quorums -> net -> banman"
"banman -> bloom -> evo/assetlocktx -> llmq/signing -> net_processing -> banman"
"llmq/dkgsession -> llmq/dkgsessionmgr -> llmq/dkgsession"
"llmq/chainlocks -> validation -> llmq/chainlocks"
"coinjoin/coinjoin -> llmq/chainlocks -> net -> coinjoin/coinjoin"
"evo/deterministicmns -> llmq/utils -> llmq/snapshot -> evo/simplifiedmns -> evo/deterministicmns"
@ -94,7 +93,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
"llmq/context -> llmq/ehf_signals -> net_processing -> llmq/context"
"llmq/blockprocessor -> net_processing -> llmq/blockprocessor"
"llmq/chainlocks -> net_processing -> llmq/chainlocks"
"llmq/dkgsession -> net_processing -> llmq/quorums -> llmq/dkgsession"
"net_processing -> spork -> net_processing"
"evo/simplifiedmns -> llmq/blockprocessor -> net_processing -> evo/simplifiedmns"
"governance/governance -> net_processing -> governance/governance"