Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

quorums_chainlocks.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <llmq/quorums.h>
8 #include <llmq/quorums_signing.h>
9 #include <llmq/quorums_utils.h>
10 
11 #include <chain.h>
13 #include <net_processing.h>
14 #include <scheduler.h>
15 #include <spork.h>
16 #include <txmempool.h>
17 #include <validation.h>
18 
19 namespace llmq
20 {
21 
22 static const std::string CLSIG_REQUESTID_PREFIX = "clsig";
23 
25 
27 {
28  return nHeight == -1 && blockHash == uint256();
29 }
30 
31 std::string CChainLockSig::ToString() const
32 {
33  return strprintf("CChainLockSig(nHeight=%d, blockHash=%s)", nHeight, blockHash.ToString());
34 }
35 
37 {
38  scheduler = new CScheduler();
39  CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, scheduler);
40  scheduler_thread = new boost::thread(boost::bind(&TraceThread<CScheduler::Function>, "cl-scheduler", serviceLoop));
41 }
42 
44 {
45  scheduler_thread->interrupt();
46  scheduler_thread->join();
47  delete scheduler_thread;
48  delete scheduler;
49 }
50 
52 {
54  scheduler->scheduleEvery([&]() {
57  // regularly retry signing the current chaintip as it might have failed before due to missing ixlocks
59  }, 5000);
60 }
61 
63 {
64  scheduler->stop();
66 }
67 
69 {
70  LOCK(cs);
71  return seenChainLocks.count(inv.hash) != 0;
72 }
73 
75 {
76  LOCK(cs);
77 
78  if (hash != bestChainLockHash) {
79  // we only propagate the best one and ditch all the old ones
80  return false;
81  }
82 
83  ret = bestChainLock;
84  return true;
85 }
86 
88 {
89  LOCK(cs);
90  return bestChainLock;
91 }
92 
93 void CChainLocksHandler::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
94 {
96  return;
97  }
98 
99  if (strCommand == NetMsgType::CLSIG) {
100  CChainLockSig clsig;
101  vRecv >> clsig;
102 
103  auto hash = ::SerializeHash(clsig);
104 
105  ProcessNewChainLock(pfrom->GetId(), clsig, hash);
106  }
107 }
108 
110 {
111  {
112  LOCK(cs_main);
113  EraseObjectRequest(from, CInv(MSG_CLSIG, hash));
114  }
115 
116  {
117  LOCK(cs);
118  if (!seenChainLocks.emplace(hash, GetTimeMillis()).second) {
119  return;
120  }
121 
122  if (!bestChainLock.IsNull() && clsig.nHeight <= bestChainLock.nHeight) {
123  // no need to process/relay older CLSIGs
124  return;
125  }
126  }
127 
128  uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, clsig.nHeight));
129  uint256 msgHash = clsig.blockHash;
130  if (!quorumSigningManager->VerifyRecoveredSig(Params().GetConsensus().llmqTypeChainLocks, clsig.nHeight, requestId, msgHash, clsig.sig)) {
131  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- invalid CLSIG (%s), peer=%d\n", __func__, clsig.ToString(), from);
132  if (from != -1) {
133  LOCK(cs_main);
134  Misbehaving(from, 10);
135  }
136  return;
137  }
138 
139  {
140  LOCK2(cs_main, cs);
141 
143  // This should not happen. If it happens, it means that a malicious entity controls a large part of the MN
144  // network. In this case, we don't allow him to reorg older chainlocks.
145  LogPrintf("CChainLocksHandler::%s -- new CLSIG (%s) tries to reorg previous CLSIG (%s), peer=%d\n",
146  __func__, clsig.ToString(), bestChainLock.ToString(), from);
147  return;
148  }
149 
150  bestChainLockHash = hash;
151  bestChainLock = clsig;
152 
153  CInv inv(MSG_CLSIG, hash);
154  g_connman->RelayInv(inv, LLMQS_PROTO_VERSION);
155 
156  auto blockIt = mapBlockIndex.find(clsig.blockHash);
157  if (blockIt == mapBlockIndex.end()) {
158  // we don't know the block/header for this CLSIG yet, so bail out for now
159  // when the block or the header later comes in, we will enforce the correct chain
160  return;
161  }
162 
163  if (blockIt->second->nHeight != clsig.nHeight) {
164  // Should not happen, same as the conflict check from above.
165  LogPrintf("CChainLocksHandler::%s -- height of CLSIG (%s) does not match the specified block's height (%d)\n",
166  __func__, clsig.ToString(), blockIt->second->nHeight);
167  return;
168  }
169 
170  const CBlockIndex* pindex = blockIt->second;
172  bestChainLockBlockIndex = pindex;
173  }
174 
175  scheduler->scheduleFromNow([&]() {
178  }, 0);
179 
180  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- processed new CLSIG (%s), peer=%d\n",
181  __func__, clsig.ToString(), from);
182 }
183 
185 {
186  LOCK2(cs_main, cs);
187 
188  if (pindexNew->GetBlockHash() == bestChainLock.blockHash) {
189  LogPrintf("CChainLocksHandler::%s -- block header %s came in late, updating and enforcing\n", __func__, pindexNew->GetBlockHash().ToString());
190 
191  if (bestChainLock.nHeight != pindexNew->nHeight) {
192  // Should not happen, same as the conflict check from ProcessNewChainLock.
193  LogPrintf("CChainLocksHandler::%s -- height of CLSIG (%s) does not match the specified block's height (%d)\n",
194  __func__, bestChainLock.ToString(), pindexNew->nHeight);
195  return;
196  }
197 
198  // when EnforceBestChainLock is called later, it might end up invalidating other chains but not activating the
199  // CLSIG locked chain. This happens when only the header is known but the block is still missing yet. The usual
200  // block processing logic will handle this when the block arrives
202  bestChainLockBlockIndex = pindexNew;
203  }
204 }
205 
207 {
208  // don't call TrySignChainTip directly but instead let the scheduler call it. This way we ensure that cs_main is
209  // never locked and TrySignChainTip is not called twice in parallel. Also avoids recursive calls due to
210  // EnforceBestChainLock switching chains.
211  LOCK(cs);
213  return;
214  }
216  scheduler->scheduleFromNow([&]() {
219  TrySignChainTip();
220  LOCK(cs);
221  tryLockChainTipScheduled = false;
222  }, 0);
223 }
224 
226 {
227  bool fDIP0008Active;
228  {
229  LOCK(cs_main);
231  }
232 
233  LOCK(cs);
234  bool oldIsEnforced = isEnforced;
236  isEnforced = (fDIP0008Active && isSporkActive);
237 
238  if (!oldIsEnforced && isEnforced) {
239  // ChainLocks got activated just recently, but it's possible that it was already running before, leaving
240  // us with some stale values which we should not try to enforce anymore (there probably was a good reason
241  // to disable spork19)
245  }
246 }
247 
249 {
250  Cleanup();
251 
252  if (!fMasternodeMode) {
253  return;
254  }
255 
257  return;
258  }
259 
260  const CBlockIndex* pindex;
261  {
262  LOCK(cs_main);
263  pindex = chainActive.Tip();
264  }
265 
266  if (!pindex->pprev) {
267  return;
268  }
269 
270  // DIP8 defines a process called "Signing attempts" which should run before the CLSIG is finalized
271  // To simplify the initial implementation, we skip this process and directly try to create a CLSIG
272  // This will fail when multiple blocks compete, but we accept this for the initial implementation.
273  // Later, we'll add the multiple attempts process.
274 
275  {
276  LOCK(cs);
277 
278  if (!isSporkActive) {
279  return;
280  }
281 
282  if (pindex->nHeight == lastSignedHeight) {
283  // already signed this one
284  return;
285  }
286 
287  if (bestChainLock.nHeight >= pindex->nHeight) {
288  // already got the same CLSIG or a better one
289  return;
290  }
291 
292  if (InternalHasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
293  // don't sign if another conflicting CLSIG is already present. EnforceBestChainLock will later enforce
294  // the correct chain.
295  return;
296  }
297  }
298 
299  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- trying to sign %s, height=%d\n", __func__, pindex->GetBlockHash().ToString(), pindex->nHeight);
300 
301  // When the new IX system is activated, we only try to ChainLock blocks which include safe transactions. A TX is
302  // considered safe when it is ixlocked or at least known since 10 minutes (from mempool or block). These checks are
303  // performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the
304  // way down, we consider all TXs to be safe.
306  auto pindexWalk = pindex;
307  while (pindexWalk) {
308  if (pindex->nHeight - pindexWalk->nHeight > 5) {
309  // no need to check further down, 6 confs is safe to assume that TXs below this height won't be
310  // ixlocked anymore if they aren't already
311  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- tip and previous 5 blocks all safe\n", __func__);
312  break;
313  }
314  if (HasChainLock(pindexWalk->nHeight, pindexWalk->GetBlockHash())) {
315  // we don't care about ixlocks for TXs that are ChainLocked already
316  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- chainlock at height %d \n", __func__, pindexWalk->nHeight);
317  break;
318  }
319 
320  auto txids = GetBlockTxs(pindexWalk->GetBlockHash());
321  if (!txids) {
322  pindexWalk = pindexWalk->pprev;
323  continue;
324  }
325 
326  for (auto& txid : *txids) {
327  int64_t txAge = 0;
328  {
329  LOCK(cs);
330  auto it = txFirstSeenTime.find(txid);
331  if (it != txFirstSeenTime.end()) {
332  txAge = GetAdjustedTime() - it->second;
333  }
334  }
335 
336  if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) {
337  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- not signing block %s due to TX %s not being ixlocked and not old enough. age=%d\n", __func__,
338  pindexWalk->GetBlockHash().ToString(), txid.ToString(), txAge);
339  return;
340  }
341  }
342 
343  pindexWalk = pindexWalk->pprev;
344  }
345  }
346 
347  uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindex->nHeight));
348  uint256 msgHash = pindex->GetBlockHash();
349 
350  {
351  LOCK(cs);
352  if (bestChainLock.nHeight >= pindex->nHeight) {
353  // might have happened while we didn't hold cs
354  return;
355  }
356  lastSignedHeight = pindex->nHeight;
357  lastSignedRequestId = requestId;
358  lastSignedMsgHash = msgHash;
359  }
360 
361  quorumSigningManager->AsyncSignIfMember(Params().GetConsensus().llmqTypeChainLocks, requestId, msgHash);
362 }
363 
365 {
366  if (tx->IsCoinBase() || tx->vin.empty()) {
367  return;
368  }
369 
370  LOCK(cs);
371  txFirstSeenTime.emplace(tx->GetHash(), nAcceptTime);
372 }
373 
374 void CChainLocksHandler::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted)
375 {
377  return;
378  }
379 
380  // We listen for BlockConnected so that we can collect all TX ids of all included TXs of newly received blocks
381  // We need this information later when we try to sign a new tip, so that we can determine if all included TXs are
382  // safe.
383 
384  LOCK(cs);
385 
386  auto it = blockTxs.find(pindex->GetBlockHash());
387  if (it == blockTxs.end()) {
388  // we must create this entry even if there are no lockable transactions in the block, so that TrySignChainTip
389  // later knows about this block
390  it = blockTxs.emplace(pindex->GetBlockHash(), std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>()).first;
391  }
392  auto& txids = *it->second;
393 
394  int64_t curTime = GetAdjustedTime();
395 
396  for (const auto& tx : pblock->vtx) {
397  if (tx->IsCoinBase() || tx->vin.empty()) {
398  continue;
399  }
400 
401  txids.emplace(tx->GetHash());
402  txFirstSeenTime.emplace(tx->GetHash(), curTime);
403  }
404 
405 }
406 
407 void CChainLocksHandler::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected)
408 {
409  LOCK(cs);
410  blockTxs.erase(pindexDisconnected->GetBlockHash());
411 }
412 
413 CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const uint256& blockHash)
414 {
417 
418  CChainLocksHandler::BlockTxs::mapped_type ret;
419 
420  {
421  LOCK(cs);
422  auto it = blockTxs.find(blockHash);
423  if (it != blockTxs.end()) {
424  ret = it->second;
425  }
426  }
427  if (!ret) {
428  // This should only happen when freshly started.
429  // If running for some time, SyncTransaction should have been called before which fills blockTxs.
430  LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__,
431  blockHash.ToString());
432 
433  uint32_t blockTime;
434  {
435  LOCK(cs_main);
436  auto pindex = mapBlockIndex.at(blockHash);
437  CBlock block;
438  if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
439  return nullptr;
440  }
441 
442  ret = std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>();
443  for (auto& tx : block.vtx) {
444  if (tx->IsCoinBase() || tx->vin.empty()) {
445  continue;
446  }
447  ret->emplace(tx->GetHash());
448  }
449 
450  blockTime = block.nTime;
451  }
452 
453  LOCK(cs);
454  blockTxs.emplace(blockHash, ret);
455  for (auto& txid : *ret) {
456  txFirstSeenTime.emplace(txid, blockTime);
457  }
458  }
459  return ret;
460 }
461 
463 {
465  return true;
466  }
467  if (!IsInstantSendEnabled()) {
468  return true;
469  }
470 
471  int64_t txAge = 0;
472  {
473  LOCK(cs);
474  if (!isSporkActive) {
475  return true;
476  }
477  auto it = txFirstSeenTime.find(txid);
478  if (it != txFirstSeenTime.end()) {
479  txAge = GetAdjustedTime() - it->second;
480  }
481  }
482 
483  if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) {
484  return false;
485  }
486  return true;
487 }
488 
489 // WARNING: cs_main and cs should not be held!
490 // This should also not be called from validation signals, as this might result in recursive calls
492 {
493  CChainLockSig clsig;
494  const CBlockIndex* pindex;
495  const CBlockIndex* currentBestChainLockBlockIndex;
496  {
497  LOCK(cs);
498 
499  if (!isEnforced) {
500  return;
501  }
502 
504  pindex = currentBestChainLockBlockIndex = this->bestChainLockBlockIndex;
505 
506  if (!currentBestChainLockBlockIndex) {
507  // we don't have the header/block, so we can't do anything right now
508  return;
509  }
510  }
511 
512  bool activateNeeded;
513  {
514  LOCK(cs_main);
515 
516  // Go backwards through the chain referenced by clsig until we find a block that is part of the main chain.
517  // For each of these blocks, check if there are children that are NOT part of the chain referenced by clsig
518  // and invalidate each of them.
519  while (pindex && !chainActive.Contains(pindex)) {
520  // Invalidate all blocks that have the same prevBlockHash but are not equal to blockHash
521  auto itp = mapPrevBlockIndex.equal_range(pindex->pprev->GetBlockHash());
522  for (auto jt = itp.first; jt != itp.second; ++jt) {
523  if (jt->second == pindex) {
524  continue;
525  }
526  LogPrintf("CChainLocksHandler::%s -- CLSIG (%s) invalidates block %s\n",
527  __func__, clsig.ToString(), jt->second->GetBlockHash().ToString());
528  DoInvalidateBlock(jt->second);
529  }
530 
531  pindex = pindex->pprev;
532  }
533  // In case blocks from the correct chain are invalid at the moment, reconsider them. The only case where this
534  // can happen right now is when missing superblock triggers caused the main chain to be dismissed first. When
535  // the trigger later appears, this should bring us to the correct chain eventually. Please note that this does
536  // NOT enforce invalid blocks in any way, it just causes re-validation.
537  if (!currentBestChainLockBlockIndex->IsValid()) {
538  ResetBlockFailureFlags(mapBlockIndex.at(currentBestChainLockBlockIndex->GetBlockHash()));
539  }
540 
541  activateNeeded = chainActive.Tip()->GetAncestor(currentBestChainLockBlockIndex->nHeight) != currentBestChainLockBlockIndex;
542  }
543 
544  CValidationState state;
545  if (activateNeeded && !ActivateBestChain(state, Params())) {
546  LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(state));
547  }
548 
549  const CBlockIndex* pindexNotify = nullptr;
550  {
551  LOCK(cs_main);
552  if (lastNotifyChainLockBlockIndex != currentBestChainLockBlockIndex &&
553  chainActive.Tip()->GetAncestor(currentBestChainLockBlockIndex->nHeight) == currentBestChainLockBlockIndex) {
554  lastNotifyChainLockBlockIndex = currentBestChainLockBlockIndex;
555  pindexNotify = currentBestChainLockBlockIndex;
556  }
557  }
558 
559  if (pindexNotify) {
560  GetMainSignals().NotifyChainLock(pindexNotify, clsig);
561  }
562 }
563 
565 {
566  CChainLockSig clsig;
567  {
568  LOCK(cs);
569 
570  if (!isSporkActive) {
571  return;
572  }
573 
574  if (recoveredSig.id != lastSignedRequestId || recoveredSig.msgHash != lastSignedMsgHash) {
575  // this is not what we signed, so lets not create a CLSIG for it
576  return;
577  }
579  // already got the same or a better CLSIG through the CLSIG message
580  return;
581  }
582 
583  clsig.nHeight = lastSignedHeight;
585  clsig.sig = recoveredSig.sig.Get();
586  }
587  ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig));
588 }
589 
590 // WARNING, do not hold cs while calling this method as we'll otherwise run into a deadlock
592 {
593  LOCK(cs_main);
594 
595  auto& params = Params();
596 
597  // get the non-const pointer
598  CBlockIndex* pindex2 = mapBlockIndex[pindex->GetBlockHash()];
599 
600  CValidationState state;
601  if (!InvalidateBlock(state, params, pindex2)) {
602  LogPrintf("CChainLocksHandler::%s -- InvalidateBlock failed: %s\n", __func__, FormatStateMessage(state));
603  // This should not have happened and we are in a state were it's not safe to continue anymore
604  assert(false);
605  }
606 }
607 
608 bool CChainLocksHandler::HasChainLock(int nHeight, const uint256& blockHash)
609 {
610  LOCK(cs);
611  return InternalHasChainLock(nHeight, blockHash);
612 }
613 
614 bool CChainLocksHandler::InternalHasChainLock(int nHeight, const uint256& blockHash)
615 {
617 
618  if (!isEnforced) {
619  return false;
620  }
621 
623  return false;
624  }
625 
626  if (nHeight > bestChainLockBlockIndex->nHeight) {
627  return false;
628  }
629 
630  if (nHeight == bestChainLockBlockIndex->nHeight) {
631  return blockHash == bestChainLockBlockIndex->GetBlockHash();
632  }
633 
634  auto pAncestor = bestChainLockBlockIndex->GetAncestor(nHeight);
635  return pAncestor && pAncestor->GetBlockHash() == blockHash;
636 }
637 
638 bool CChainLocksHandler::HasConflictingChainLock(int nHeight, const uint256& blockHash)
639 {
640  LOCK(cs);
641  return InternalHasConflictingChainLock(nHeight, blockHash);
642 }
643 
645 {
647 
648  if (!isEnforced) {
649  return false;
650  }
651 
653  return false;
654  }
655 
656  if (nHeight > bestChainLockBlockIndex->nHeight) {
657  return false;
658  }
659 
660  if (nHeight == bestChainLockBlockIndex->nHeight) {
661  return blockHash != bestChainLockBlockIndex->GetBlockHash();
662  }
663 
664  auto pAncestor = bestChainLockBlockIndex->GetAncestor(nHeight);
665  assert(pAncestor);
666  return pAncestor->GetBlockHash() != blockHash;
667 }
668 
670 {
672  return;
673  }
674 
675  {
676  LOCK(cs);
678  return;
679  }
680  }
681 
682  // need mempool.cs due to GetTransaction calls
684  LOCK(cs);
685 
686  for (auto it = seenChainLocks.begin(); it != seenChainLocks.end(); ) {
687  if (GetTimeMillis() - it->second >= CLEANUP_SEEN_TIMEOUT) {
688  it = seenChainLocks.erase(it);
689  } else {
690  ++it;
691  }
692  }
693 
694  for (auto it = blockTxs.begin(); it != blockTxs.end(); ) {
695  auto pindex = mapBlockIndex.at(it->first);
696  if (InternalHasChainLock(pindex->nHeight, pindex->GetBlockHash())) {
697  for (auto& txid : *it->second) {
698  txFirstSeenTime.erase(txid);
699  }
700  it = blockTxs.erase(it);
701  } else if (InternalHasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
702  it = blockTxs.erase(it);
703  } else {
704  ++it;
705  }
706  }
707  for (auto it = txFirstSeenTime.begin(); it != txFirstSeenTime.end(); ) {
708  CTransactionRef tx;
709  uint256 hashBlock;
710  if (!GetTransaction(it->first, tx, Params().GetConsensus(), hashBlock)) {
711  // tx has vanished, probably due to conflicts
712  it = txFirstSeenTime.erase(it);
713  } else if (!hashBlock.IsNull()) {
714  auto pindex = mapBlockIndex.at(hashBlock);
715  if (chainActive.Tip()->GetAncestor(pindex->nHeight) == pindex && chainActive.Height() - pindex->nHeight >= 6) {
716  // tx got confirmed >= 6 times, so we can stop keeping track of it
717  it = txFirstSeenTime.erase(it);
718  } else {
719  ++it;
720  }
721  } else {
722  ++it;
723  }
724  }
725 
727 }
728 
729 } // namespace llmq
void UpdatedBlockTip(const CBlockIndex *pindexNew)
CTxMemPool mempool
void TransactionAddedToMempool(const CTransactionRef &tx, int64_t nAcceptTime)
CMasternodeSync masternodeSync
bool IsInstantSendEnabled()
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params &consensusParams, uint256 &hashBlock, bool fAllowSlow, CBlockIndex *blockIndex)
Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock...
Definition: validation.cpp:950
void ProcessNewChainLock(NodeId from, const CChainLockSig &clsig, const uint256 &hash)
CChainLockSig bestChainLockWithKnownBlock
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:177
bool VerifyRecoveredSig(Consensus::LLMQType llmqType, int signedAtHeight, const uint256 &id, const uint256 &msgHash, const CBLSSignature &sig)
Definition: block.h:72
#define strprintf
Definition: tinyformat.h:1066
bool InvalidateBlock(CValidationState &state, const CChainParams &chainparams, CBlockIndex *pindex)
Mark a block as invalid.
bool HasChainLock(int nHeight, const uint256 &blockHash)
inv message data
Definition: protocol.h:429
BlockMap & mapBlockIndex
Definition: validation.cpp:215
BlockTxs::mapped_type GetBlockTxs(const uint256 &blockHash)
void RegisterRecoveredSigsListener(CRecoveredSigsListener *l)
int Height() const
Return the maximal height in the chain.
Definition: chain.h:484
CCriticalSection cs_main
Definition: validation.cpp:213
void NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig &clsig)
void ProcessMessage(CNode *pfrom, const std::string &strCommand, CDataStream &vRecv, CConnman &connman)
void scheduleEvery(Function f, int64_t deltaMilliSeconds)
Definition: scheduler.cpp:126
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:103
CBLSLazySignature sig
bool AsyncSignIfMember(Consensus::LLMQType llmqType, const uint256 &id, const uint256 &msgHash, bool allowReSign=false)
bool IsBlockchainSynced()
void scheduleFromNow(Function f, int64_t deltaMilliSeconds)
Definition: scheduler.cpp:115
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:345
bool IsNull() const
Definition: uint256.h:33
uint32_t nTime
Definition: block.h:27
bool ActivateBestChain(CValidationState &state, const CChainParams &chainparams, std::shared_ptr< const CBlock > pblock)
Find the best known block, and make it the tip of the block chain.
void UnregisterRecoveredSigsListener(CRecoveredSigsListener *l)
std::map< uint256, int64_t > seenChainLocks
uint256 GetBlockHash() const
Definition: chain.h:292
static const int LLMQS_PROTO_VERSION
introduction of LLMQs
Definition: version.h:51
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
Definition: chain.h:332
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object&#39;s serialization.
Definition: hash.h:254
void Misbehaving(NodeId pnode, int howmuch, const std::string &message)
Increase a node&#39;s misbehavior score.
bool fMasternodeMode
Definition: util.cpp:93
std::unordered_map< uint256, int64_t > txFirstSeenTime
#define LOCK2(cs1, cs2)
Definition: sync.h:179
PrevBlockMap & mapPrevBlockIndex
Definition: validation.cpp:216
CChainLocksHandler * chainLocksHandler
#define LogPrintf(...)
Definition: util.h:203
static const std::string CLSIG_REQUESTID_PREFIX
bool IsTxSafeForMining(const uint256 &txid)
void stop(bool drain=false)
Definition: scheduler.cpp:94
virtual void HandleNewRecoveredSig(const CRecoveredSig &recoveredSig)
#define LOCK(cs)
Definition: sync.h:178
boost::thread * scheduler_thread
bool InternalHasConflictingChainLock(int nHeight, const uint256 &blockHash)
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:471
void BlockDisconnected(const std::shared_ptr< const CBlock > &pblock, const CBlockIndex *pindexDisconnected)
const BLSObject & Get() const
Definition: bls.h:402
std::function< void(void)> Function
Definition: scheduler.h:43
uint256 hash
Definition: protocol.h:456
CMainSignals & GetMainSignals()
void serviceQueue()
Definition: scheduler.cpp:33
static const int64_t CLEANUP_SEEN_TIMEOUT
int64_t NodeId
Definition: net.h:109
Definition: net.h:136
std::string ToString() const
Definition: uint256.cpp:62
NodeId GetId() const
Definition: net.h:973
CCriticalSection cs
Definition: txmempool.h:488
VersionBitsCache versionbitscache
std::string ToString() const
static const int64_t CLEANUP_INTERVAL
CSporkManager sporkManager
Definition: spork.cpp:29
#define LogPrint(category,...)
Definition: util.h:214
Capture information about block/transaction validation.
Definition: validation.h:22
256-bit opaque blob.
Definition: uint256.h:123
const CBlockIndex * lastNotifyChainLockBlockIndex
std::vector< CTransactionRef > vtx
Definition: block.h:76
std::string FormatStateMessage(const CValidationState &state)
Convert CValidationState to a human-readable message for logging.
Definition: validation.cpp:513
bool ResetBlockFailureFlags(CBlockIndex *pindex)
Remove invalidity status from a block and its descendants.
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
const CChainParams & Params()
Return the currently selected parameters.
void BlockConnected(const std::shared_ptr< const CBlock > &pblock, const CBlockIndex *pindex, const std::vector< CTransactionRef > &vtxConflicted)
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: utiltime.cpp:56
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
bool AlreadyHave(const CInv &inv)
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:453
bool HasConflictingChainLock(int nHeight, const uint256 &blockHash)
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:97
bool InternalHasChainLock(int nHeight, const uint256 &blockHash)
#define AssertLockNotHeld(cs)
Definition: sync.h:88
void EraseObjectRequest(CNodeState *nodestate, const CInv &inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
CSigningManager * quorumSigningManager
const char * CLSIG
Definition: protocol.cpp:75
bool IsSporkActive(SporkId nSporkID)
IsSporkActive returns a bool for time-based sporks, and should be used to determine whether the spork...
Definition: spork.cpp:211
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:183
Information about a peer.
Definition: net.h:800
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:54
bool ReadBlockFromDisk(CBlock &block, const CDiskBlockPos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:110
bool GetChainLockByHash(const uint256 &hash, CChainLockSig &ret)
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
AssertLockHeld(g_cs_orphans)
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
const CBlockIndex * bestChainLockBlockIndex
void DoInvalidateBlock(const CBlockIndex *pindex)
void AcceptedBlockHeader(const CBlockIndex *pindexNew)
Released under the MIT license