PIVX Core  5.6.99
P2P Digital Currency
quorums_dkgsessionhandler.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2021 The Dash Core developers
2 // Copyright (c) 2022 The PIVX Core developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
7 
8 #include "activemasternode.h"
9 #include "chainparams.h"
12 #include "llmq/quorums_debug.h"
13 #include "net_processing.h"
14 #include "shutdown.h"
15 #include "util/threadnames.h"
16 #include "validation.h"
17 
18 namespace llmq
19 {
20 
21 CDKGPendingMessages::CDKGPendingMessages(size_t _maxMessagesPerNode) :
22  maxMessagesPerNode(_maxMessagesPerNode)
23 {
24 }
25 
27 {
28  // this will also consume the data, even if we bail out early
29  auto pm = std::make_shared<CDataStream>(std::move(vRecv));
30 
31  {
32  LOCK(cs);
33 
34  if (messagesPerNode[from] >= maxMessagesPerNode) {
35  // TODO ban?
36  LogPrint(BCLog::NET, "CDKGPendingMessages::%s -- too many messages, peer=%d\n", __func__, from);
37  return;
38  }
39  messagesPerNode[from]++;
40  }
41 
42  CHashWriter hw(SER_GETHASH, 0);
43  hw.write(pm->data(), pm->size());
44  uint256 hash = hw.GetHash();
45 
46  LOCK2(cs_main, cs);
47 
48  g_connman->RemoveAskFor(hash, invType);
49 
50  if (!seenMessages.emplace(hash).second) {
51  LogPrint(BCLog::NET, "CDKGPendingMessages::%s -- already seen %s, peer=%d\n", __func__, hash.ToString(), from);
52  return;
53  }
54 
55  pendingMessages.emplace_back(std::make_pair(from, std::move(pm)));
56 }
57 
58 std::list<CDKGPendingMessages::BinaryMessage> CDKGPendingMessages::PopPendingMessages(size_t maxCount)
59 {
60  LOCK(cs);
61 
62  std::list<BinaryMessage> ret;
63  while (!pendingMessages.empty() && ret.size() < maxCount) {
64  ret.emplace_back(std::move(pendingMessages.front()));
65  pendingMessages.pop_front();
66  }
67 
68  return ret;
69 }
70 
71 bool CDKGPendingMessages::HasSeen(const uint256& hash) const
72 {
73  LOCK(cs);
74  return seenMessages.count(hash) != 0;
75 }
76 
78 {
79  LOCK(cs);
80  pendingMessages.clear();
81  messagesPerNode.clear();
82  seenMessages.clear();
83 }
84 
86 
88  params(_params),
89  blsWorker(_blsWorker),
90  dkgManager(_dkgManager),
91  curSession(std::make_shared<CDKGSession>(_params, _blsWorker, _dkgManager)),
92  pendingContributions((size_t)_params.size * 2), // we allow size*2 messages as we need to make sure we see bad behavior (double messages)
93  pendingComplaints((size_t)_params.size * 2),
94  pendingJustifications((size_t)_params.size * 2),
95  pendingPrematureCommitments((size_t)_params.size * 2)
96 {
98  throw std::runtime_error("Can't initialize CDKGSessionHandler with LLMQ_NONE type.");
99  }
100 }
101 
103 {
104 }
105 
107 {
109  LOCK(cs);
110 
111  int quorumStageInt = pindexNew->nHeight % params.dkgInterval;
112  const CBlockIndex* pindexQuorum = chainActive[pindexNew->nHeight - quorumStageInt];
113 
114  currentHeight = pindexNew->nHeight;
115  quorumHeight = pindexQuorum->nHeight;
116  quorumHash = pindexQuorum->GetBlockHash();
117 
118  bool fNewPhase = (quorumStageInt % params.dkgPhaseBlocks) == 0;
119  int phaseInt = quorumStageInt / params.dkgPhaseBlocks + 1;
120  QuorumPhase oldPhase = phase;
121 
122  if (fNewPhase && phaseInt >= QuorumPhase_Initialized && phaseInt <= QuorumPhase_Idle) {
123  phase = static_cast<QuorumPhase>(phaseInt);
124  }
125 
126  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - currentHeight=%d, quorumHeight=%d, oldPhase=%d, newPhase=%d\n", __func__,
128 }
129 
130 void CDKGSessionHandler::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv)
131 {
132  // We don't handle messages in the calling thread as deserialization/processing of these would block everything
133  if (strCommand == NetMsgType::QCONTRIB) {
135  } else if (strCommand == NetMsgType::QCOMPLAINT) {
137  } else if (strCommand == NetMsgType::QJUSTIFICATION) {
139  } else if (strCommand == NetMsgType::QPCOMMITMENT) {
141  }
142 }
143 
145 {
146  if (phaseHandlerThread.joinable()) {
147  throw std::runtime_error("Tried to start an already started CDKGSessionHandler thread.");
148  }
149 
150  std::string threadName = strprintf("llmq-%d", (uint8_t)params.type);
151  phaseHandlerThread = std::thread(&TraceThread<std::function<void()> >, threadName, std::function<void()>(std::bind(&CDKGSessionHandler::PhaseHandlerThread, this)));
152 }
153 
155 {
156  stopRequested = true;
157  if (phaseHandlerThread.joinable()) {
158  phaseHandlerThread.join();
159  }
160 }
161 
163 {
164  curSession = std::make_shared<CDKGSession>(params, blsWorker, dkgManager);
165 
166  if (!deterministicMNManager->IsDIP3Enforced(pindexQuorum->nHeight) ||
168  return false;
169  }
170 
171  auto mns = deterministicMNManager->GetAllQuorumMembers(params.type, pindexQuorum);
172 
173  if (!curSession->Init(pindexQuorum, mns, activeMasternodeManager->GetProTx())) {
174  LogPrintf("CDKGSessionHandler::%s -- quorum initialization failed for %s\n", __func__, curSession->params.name);
175  return false;
176  }
177 
178  return true;
179 }
180 
182 {
183  LOCK(cs);
184  return {phase, quorumHash};
185 }
186 
187 class AbortPhaseException : public std::exception {
188 };
189 
191  QuorumPhase nextPhase,
192  const uint256& expectedQuorumHash,
193  const WhileWaitFunc& runWhileWaiting)
194 {
195  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase, nextPhase);
196 
197  while (true) {
198  if (stopRequested || ShutdownRequested()) {
199  throw AbortPhaseException();
200  }
201  auto currState = GetPhaseAndQuorumHash();
202  if (!expectedQuorumHash.IsNull() && currState.quorumHash != expectedQuorumHash) {
203  throw AbortPhaseException();
204  }
205  if (currState.phase == nextPhase) {
206  break;
207  }
208  if (curPhase != QuorumPhase_None && currState.phase != curPhase) {
209  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - aborting due unexpected phase change\n", __func__, params.name);
210  throw AbortPhaseException();
211  }
212  if (!runWhileWaiting()) {
213  MilliSleep(100);
214  }
215  }
216 
217  if (nextPhase == QuorumPhase_Initialized) {
218  quorumDKGDebugManager->ResetLocalSessionStatus(params.type);
219  } else {
220  quorumDKGDebugManager->UpdateLocalSessionStatus(params.type, [&](CDKGDebugSessionStatus& status) {
221  bool changed = status.phase != (uint8_t) nextPhase;
222  status.phase = (uint8_t) nextPhase;
223  return changed;
224  });
225  }
226 
227  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase, nextPhase);
228 
229 }
230 
232 {
233  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - starting\n", __func__, params.name);
234 
235  while (true) {
236  if (stopRequested || ShutdownRequested()) {
237  throw AbortPhaseException();
238  }
239  auto currState = GetPhaseAndQuorumHash();
240  if (currState.quorumHash != oldQuorumHash) {
241  break;
242  }
243  MilliSleep(100);
244  }
245 
246  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - done\n", __func__, params.name);
247 }
248 
249 // Sleep some time to not fully overload the whole network
251  const uint256& expectedQuorumHash,
252  double randomSleepFactor,
253  const WhileWaitFunc& runWhileWaiting)
254 {
255  if (Params().IsRegTestNet()) {
256  // On regtest, blocks can be mined on demand without any significant time passing between these.
257  // We shouldn't wait before phases in this case.
258  return;
259  }
260 
261  if (!curSession->AreWeMember()) {
262  // Non-members do not participate and do not create any network load, no need to sleep.
263  return;
264  }
265 
266  // Two blocks can come very close to each other, this happens pretty regularly. We don't want to be
267  // left behind and marked as a bad member. This means that we should not count the last block of the
268  // phase as a safe one to keep sleeping, that's why we calculate the phase sleep time as a time of
269  // the full phase minus one block here.
270  const int nTargetSpacing = Params().GetConsensus().nTargetSpacing;
271  double phaseSleepTime = (params.dkgPhaseBlocks - 1) * nTargetSpacing * 1000;
272  // Expected phase sleep time per member
273  double phaseSleepTimePerMember = phaseSleepTime / params.size;
274  // Don't expect perfect block times and thus reduce the phase time to be on the secure side (caller chooses factor)
275  double adjustedPhaseSleepTimePerMember = phaseSleepTimePerMember * randomSleepFactor;
276 
277  int64_t sleepTime = (int64_t)(adjustedPhaseSleepTimePerMember * curSession->GetMyMemberIndex());
278  int64_t endTime = GetTimeMillis() + sleepTime;
279  int heightTmp{-1};
280  int heightStart{-1};
281  {
282  LOCK(cs);
283  heightTmp = heightStart = currentHeight;
284  }
285 
286  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, sleepTime, curPhase);
287 
288  while (GetTimeMillis() < endTime) {
289  if (stopRequested) {
290  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name);
291  throw AbortPhaseException();
292  }
293  {
294  LOCK(cs);
295  if (currentHeight > heightTmp) {
296  // New block(s) just came in
297  int64_t expectedBlockTime = (currentHeight - heightStart) * nTargetSpacing * 1000;
298  if (expectedBlockTime > sleepTime) {
299  // Blocks came faster than we expected, jump into the phase func asap
300  break;
301  }
302  heightTmp = currentHeight;
303  }
304  if (phase != curPhase || quorumHash != expectedQuorumHash) {
305  // Something went wrong and/or we missed quite a few blocks and it's just too late now
306  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name);
307  throw AbortPhaseException();
308  }
309  }
310  if (!runWhileWaiting()) {
311  MilliSleep(100);
312  }
313  }
314 
315  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - done, curPhase=%d\n", __func__, params.name, curPhase);
316 }
317 
319  QuorumPhase nextPhase,
320  const uint256& expectedQuorumHash,
321  double randomSleepFactor,
322  const StartPhaseFunc& startPhaseFunc,
323  const WhileWaitFunc& runWhileWaiting)
324 {
325  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase, nextPhase);
326 
327  SleepBeforePhase(curPhase, expectedQuorumHash, randomSleepFactor, runWhileWaiting);
328  startPhaseFunc();
329  WaitForNextPhase(curPhase, nextPhase, expectedQuorumHash, runWhileWaiting);
330 
331  LogPrint(BCLog::DKG, "CDKGSessionHandler::%s -- %s - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase, nextPhase);
332 }
333 
334 // returns a set of NodeIds which sent invalid messages
335 template<typename Message>
336 std::set<NodeId> BatchVerifyMessageSigs(CDKGSession& session, const std::vector<std::pair<NodeId, std::shared_ptr<Message>>>& messages)
337 {
338  if (messages.empty()) {
339  return {};
340  }
341 
342  std::set<NodeId> ret;
343  bool revertToSingleVerification = false;
344 
345  CBLSSignature aggSig;
346  std::vector<CBLSPublicKey> pubKeys;
347  std::vector<uint256> messageHashes;
348  std::set<uint256> messageHashesSet;
349  pubKeys.reserve(messages.size());
350  messageHashes.reserve(messages.size());
351  bool first = true;
352  for (const auto& p : messages ) {
353  const auto& msg = *p.second;
354 
355  auto member = session.GetMember(msg.proTxHash);
356  if (!member) {
357  // should not happen as it was verified before
358  ret.emplace(p.first);
359  continue;
360  }
361 
362  if (first) {
363  aggSig = msg.sig;
364  } else {
365  aggSig.AggregateInsecure(msg.sig);
366  }
367  first = false;
368 
369  auto msgHash = msg.GetSignHash();
370  if (!messageHashesSet.emplace(msgHash).second) {
371  // can only happen in 2 cases:
372  // 1. Someone sent us the same message twice but with differing signature, meaning that at least one of them
373  // must be invalid. In this case, we'd have to revert to single message verification nevertheless
374  // 2. Someone managed to find a way to create two different binary representations of a message that deserializes
375  // to the same object representation. This would be some form of malleability. However, this shouldn't be
376  // possible as only deterministic/unique BLS signatures and very simple data types are involved
377  revertToSingleVerification = true;
378  break;
379  }
380 
381  pubKeys.emplace_back(member->dmn->pdmnState->pubKeyOperator.Get());
382  messageHashes.emplace_back(msgHash);
383  }
384  if (!revertToSingleVerification) {
385  bool valid = aggSig.VerifyInsecureAggregated(pubKeys, messageHashes);
386  if (valid) {
387  // all good
388  return ret;
389  }
390 
391  // are all messages from the same node?
392  NodeId firstNodeId;
393  first = true;
394  bool nodeIdsAllSame = true;
395  for (auto it = messages.begin(); it != messages.end(); ++it) {
396  if (first) {
397  firstNodeId = it->first;
398  } else {
399  first = false;
400  if (it->first != firstNodeId) {
401  nodeIdsAllSame = false;
402  break;
403  }
404  }
405  }
406  // if yes, take a short path and return a set with only him
407  if (nodeIdsAllSame) {
408  ret.emplace(firstNodeId);
409  return ret;
410  }
411  // different nodes, let's figure out who are the bad ones
412  }
413 
414  for (const auto& p : messages) {
415  if (ret.count(p.first)) {
416  continue;
417  }
418 
419  const auto& msg = *p.second;
420  auto member = session.GetMember(msg.proTxHash);
421  bool valid = msg.sig.VerifyInsecure(member->dmn->pdmnState->pubKeyOperator.Get(), msg.GetSignHash());
422  if (!valid) {
423  ret.emplace(p.first);
424  }
425  }
426  return ret;
427 }
428 
429 template<typename Message>
430 static bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendingMessages, size_t maxCount)
431 {
432  auto msgs = pendingMessages.PopAndDeserializeMessages<Message>(maxCount);
433  if (msgs.empty()) {
434  return false;
435  }
436 
437  std::vector<uint256> hashes;
438  std::vector<std::pair<NodeId, std::shared_ptr<Message>>> preverifiedMessages;
439  hashes.reserve(msgs.size());
440  preverifiedMessages.reserve(msgs.size());
441 
442  for (const auto& p : msgs) {
443  if (!p.second) {
444  LogPrint(BCLog::NET, "%s -- failed to deserialize message, peer=%d\n", __func__, p.first);
445  {
446  LOCK(cs_main);
447  Misbehaving(p.first, 100);
448  }
449  continue;
450  }
451  const auto& msg = *p.second;
452 
453  bool ban = false;
454  if (!session.PreVerifyMessage(msg, ban)) {
455  if (ban) {
456  LogPrint(BCLog::NET, "%s -- banning node due to failed preverification, peer=%d\n", __func__, p.first);
457  {
458  LOCK(cs_main);
459  Misbehaving(p.first, 100);
460  }
461  }
462  LogPrint(BCLog::NET, "%s -- skipping message due to failed preverification, peer=%d\n", __func__, p.first);
463  continue;
464  }
465  hashes.emplace_back(::SerializeHash(msg));
466  preverifiedMessages.emplace_back(p);
467  }
468  if (preverifiedMessages.empty()) {
469  return true;
470  }
471 
472  auto badNodes = BatchVerifyMessageSigs(session, preverifiedMessages);
473  if (!badNodes.empty()) {
474  LOCK(cs_main);
475  for (auto nodeId : badNodes) {
476  LogPrint(BCLog::NET, "%s -- failed to verify signature, peer=%d\n", __func__, nodeId);
477  Misbehaving(nodeId, 100);
478  }
479  }
480 
481  for (size_t i = 0; i < preverifiedMessages.size(); i++) {
482  NodeId nodeId = preverifiedMessages[i].first;
483  if (badNodes.count(nodeId)) {
484  continue;
485  }
486  const auto& msg = *preverifiedMessages[i].second;
487  bool ban = false;
488  session.ReceiveMessage(hashes[i], msg, ban);
489  if (ban) {
490  LogPrint(BCLog::NET, "%s -- banning node after ReceiveMessage failed, peer=%d\n", __func__, nodeId);
491  LOCK(cs_main);
492  Misbehaving(nodeId, 100);
493  badNodes.emplace(nodeId);
494  }
495  }
496 
497  return true;
498 }
499 
501 {
502  uint256 curQuorumHash;
503 
505 
506  {
507  LOCK(cs);
512  curQuorumHash = quorumHash;
513  }
514 
515  const CBlockIndex* pindexQuorum = WITH_LOCK(cs_main, return LookupBlockIndex(curQuorumHash));
516  if (!pindexQuorum) {
517  // should never happen
518  LogPrintf("%s: ERROR: Unable to find block %s\n", __func__, curQuorumHash.ToString());
519  return;
520  }
521 
522  if (!InitNewQuorum(pindexQuorum)) {
523  // should actually never happen
524  WaitForNewQuorum(curQuorumHash);
525  throw AbortPhaseException();
526  }
527 
528  quorumDKGDebugManager->UpdateLocalSessionStatus(params.type, [&](CDKGDebugSessionStatus& status) {
529  bool changed = status.phase != (uint8_t) QuorumPhase_Initialized;
530  status.phase = (uint8_t) QuorumPhase_Initialized;
531  return changed;
532  });
533 
534  EnsureQuorumConnections(params.type, pindexQuorum, curSession->myProTxHash);
535  if (curSession->AreWeMember()) {
536  AddQuorumProbeConnections(params.type, pindexQuorum, curSession->myProTxHash);
537  }
538 
539  WaitForNextPhase(QuorumPhase_Initialized, QuorumPhase_Contribute, curQuorumHash, []{return false;});
540 
541  // Contribute
542  auto fContributeStart = [this]() {
543  curSession->Contribute(pendingContributions);
544  };
545  auto fContributeWait = [this] {
546  return ProcessPendingMessageBatch<CDKGContribution>(*curSession, pendingContributions, 8);
547  };
548  HandlePhase(QuorumPhase_Contribute, QuorumPhase_Complain, curQuorumHash, 0.05, fContributeStart, fContributeWait);
549 
550  // Complain
551  auto fComplainStart = [this]() {
552  curSession->VerifyAndComplain(pendingComplaints);
553  };
554  auto fComplainWait = [this] {
555  return ProcessPendingMessageBatch<CDKGComplaint>(*curSession, pendingComplaints, 8);
556  };
557  HandlePhase(QuorumPhase_Complain, QuorumPhase_Justify, curQuorumHash, 0.05, fComplainStart, fComplainWait);
558 
559  // Justify
560  auto fJustifyStart = [this]() {
561  curSession->VerifyAndJustify(pendingJustifications);
562  };
563  auto fJustifyWait = [this] {
564  return ProcessPendingMessageBatch<CDKGJustification>(*curSession, pendingJustifications, 8);
565  };
566  HandlePhase(QuorumPhase_Justify, QuorumPhase_Commit, curQuorumHash, 0.05, fJustifyStart, fJustifyWait);
567 
568  // Commit
569  auto fCommitStart = [this]() {
570  curSession->VerifyAndCommit(pendingPrematureCommitments);
571  };
572  auto fCommitWait = [this] {
573  return ProcessPendingMessageBatch<CDKGPrematureCommitment>(*curSession, pendingPrematureCommitments, 8);
574  };
575  HandlePhase(QuorumPhase_Commit, QuorumPhase_Finalize, curQuorumHash, 0.1, fCommitStart, fCommitWait);
576 
577  auto finalCommitments = curSession->FinalizeCommitments();
578  for (const auto& fqc : finalCommitments) {
579  quorumBlockProcessor->AddAndRelayMinableCommitment(fqc);
580  }
581 }
582 
584 {
585  while (!stopRequested && !ShutdownRequested()) {
586  try {
587  HandleDKGRound();
588  } catch (AbortPhaseException& e) {
589  quorumDKGDebugManager->UpdateLocalSessionStatus(params.type, [&](CDKGDebugSessionStatus& status) {
590  status.aborted = true;
591  return true;
592  });
593  LogPrintf("CDKGSessionHandler::%s -- aborted current DKG session for llmq=%s\n", __func__, params.name);
594  }
595  }
596 }
597 
598 }
CActiveDeterministicMasternodeManager * activeMasternodeManager
const CChainParams & Params()
Return the currently selected parameters.
void AggregateInsecure(const CBLSSignature &o)
bool VerifyInsecureAggregated(const std::vector< CBLSPublicKey > &pubKeys, const std::vector< uint256 > &hashes) const
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
uint256 GetBlockHash() const
Definition: chain.h:215
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:216
void write(const char *pch, size_t size)
Definition: hash.h:230
uint256 GetHash()
Definition: hash.h:236
Information about a peer.
Definition: net.h:669
NodeId GetId() const
Definition: net.h:825
std::string ToString() const
Definition: uint256.cpp:65
bool IsNull() const
Definition: uint256.h:36
bool HasSeen(const uint256 &hash) const
void PushPendingMessage(NodeId from, CDataStream &vRecv, int invType)
std::list< BinaryMessage > PopPendingMessages(size_t maxCount)
std::list< BinaryMessage > pendingMessages
std::map< NodeId, size_t > messagesPerNode
CDKGPendingMessages(size_t _maxMessagesPerNode)
QuorumPhaseAndHash GetPhaseAndQuorumHash() const
std::function< bool()> WhileWaitFunc
bool InitNewQuorum(const CBlockIndex *pindexQuorum)
void ProcessMessage(CNode *pfrom, const std::string &strCommand, CDataStream &vRecv)
void HandlePhase(QuorumPhase curPhase, QuorumPhase nextPhase, const uint256 &expectedQuorumHash, double randomSleepFactor, const StartPhaseFunc &startPhaseFunc, const WhileWaitFunc &runWhileWaiting)
void SleepBeforePhase(QuorumPhase curPhase, const uint256 &expectedQuorumHash, double randomSleepFactor, const WhileWaitFunc &runWhileWaiting)
std::shared_ptr< CDKGSession > curSession
CDKGPendingMessages pendingPrematureCommitments
CDKGPendingMessages pendingContributions
void UpdatedBlockTip(const CBlockIndex *pindexNew)
const Consensus::LLMQParams & params
void WaitForNewQuorum(const uint256 &oldQuorumHash)
CDKGSessionHandler(const Consensus::LLMQParams &_params, CBLSWorker &blsWorker, CDKGSessionManager &_dkgManager)
void WaitForNextPhase(QuorumPhase curPhase, QuorumPhase nextPhase, const uint256 &expectedQuorumHash, const WhileWaitFunc &runWhileWaiting)
CDKGPendingMessages pendingJustifications
std::function< void()> StartPhaseFunc
The DKG session is a single instance of the DKG process.
CDKGMember * GetMember(const uint256 &proTxHash) const
256-bit opaque blob.
Definition: uint256.h:138
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object's serialization.
Definition: hash.h:289
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:90
@ LOCK
Definition: lockunlock.h:16
#define LogPrint(category,...)
Definition: logging.h:163
@ DKG
Definition: logging.h:68
@ NET
Definition: logging.h:41
@ LLMQ_NONE
Definition: params.h:91
const char * QCONTRIB
Definition: protocol.cpp:59
const char * QPCOMMITMENT
Definition: protocol.cpp:62
const char * QCOMPLAINT
Definition: protocol.cpp:60
const char * QJUSTIFICATION
Definition: protocol.cpp:61
Definition: quorums.cpp:26
std::set< NodeId > BatchVerifyMessageSigs(CDKGSession &session, const std::vector< std::pair< NodeId, std::shared_ptr< Message >>> &messages)
std::unique_ptr< CQuorumBlockProcessor > quorumBlockProcessor
void EnsureQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const uint256 &myProTxHash)
std::unique_ptr< CDKGDebugManager > quorumDKGDebugManager
CBLSWorker * blsWorker
void AddQuorumProbeConnections(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const uint256 &myProTxHash)
Definition: uint256.h:212
int NodeId
Definition: net.h:109
void Misbehaving(NodeId pnode, int howmuch, const std::string &message) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Increase a node's misbehavior score.
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
@ MSG_QUORUM_JUSTIFICATION
Definition: protocol.h:457
@ MSG_QUORUM_COMPLAINT
Definition: protocol.h:456
@ MSG_QUORUM_CONTRIB
Definition: protocol.h:455
@ MSG_QUORUM_PREMATURE_COMMITMENT
Definition: protocol.h:458
@ SER_GETHASH
Definition: serialize.h:176
bool ShutdownRequested()
Definition: shutdown.cpp:22
std::string name
Definition: params.h:107
int64_t nTargetSpacing
Definition: params.h:193
#define LOCK2(cs1, cs2)
Definition: sync.h:221
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
#define AssertLockHeld(cs)
Definition: sync.h:75
void TraceThread(const std::string name, Callable func)
Definition: system.h:271
#define strprintf
Definition: tinyformat.h:1056
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:175
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: utiltime.cpp:61
void MilliSleep(int64_t n)
Definition: utiltime.cpp:82
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: validation.h:345