Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

quorums_instantsend.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2020 The Dash Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
7 #include <llmq/quorums_utils.h>
8 
10 #include <chainparams.h>
11 #include <coins.h>
12 #include <txmempool.h>
14 #include <net_processing.h>
15 #include <spork.h>
16 #include <validation.h>
17 
18 #ifdef ENABLE_WALLET
19 #include <wallet/wallet.h>
20 #endif
21 
22 #include <cxxtimer.hpp>
23 
24 #include <boost/algorithm/string/replace.hpp>
25 #include <boost/thread.hpp>
26 
27 namespace llmq
28 {
29 
30 static const std::string INPUTLOCK_REQUESTID_PREFIX = "inlock";
31 static const std::string ISLOCK_REQUESTID_PREFIX = "islock";
32 
33 static const std::string DB_ISLOCK_BY_HASH = "is_i";
34 static const std::string DB_HASH_BY_TXID = "is_tx";
35 static const std::string DB_HASH_BY_OUTPOINT = "is_in";
36 static const std::string DB_MINED_BY_HEIGHT_AND_HASH = "is_m";
37 static const std::string DB_ARCHIVED_BY_HEIGHT_AND_HASH = "is_a1";
38 static const std::string DB_ARCHIVED_BY_HASH = "is_a2";
39 
41 
43 {
44  CHashWriter hw(SER_GETHASH, 0);
46  hw << inputs;
47  return hw.GetHash();
48 }
49 
51 
53 {
54  CDBBatch batch(db);
55  batch.Write(std::make_tuple(std::string(DB_ISLOCK_BY_HASH), hash), islock);
56  batch.Write(std::make_tuple(std::string(DB_HASH_BY_TXID), islock.txid), hash);
57  for (auto& in : islock.inputs) {
58  batch.Write(std::make_tuple(std::string(DB_HASH_BY_OUTPOINT), in), hash);
59  }
60  db.WriteBatch(batch);
61 
62  auto p = std::make_shared<CInstantSendLock>(islock);
63  islockCache.insert(hash, p);
64  txidCache.insert(islock.txid, hash);
65  for (auto& in : islock.inputs) {
66  outpointCache.insert(in, hash);
67  }
68 }
69 
71 {
72  if (!islock) {
73  islock = GetInstantSendLockByHash(hash);
74  if (!islock) {
75  return;
76  }
77  }
78 
79  batch.Erase(std::make_tuple(std::string(DB_ISLOCK_BY_HASH), hash));
80  batch.Erase(std::make_tuple(std::string(DB_HASH_BY_TXID), islock->txid));
81  for (auto& in : islock->inputs) {
82  batch.Erase(std::make_tuple(std::string(DB_HASH_BY_OUTPOINT), in));
83  }
84 
85  islockCache.erase(hash);
86  txidCache.erase(islock->txid);
87  for (auto& in : islock->inputs) {
88  outpointCache.erase(in);
89  }
90 }
91 
92 static std::tuple<std::string, uint32_t, uint256> BuildInversedISLockKey(const std::string& k, int nHeight, const uint256& islockHash)
93 {
94  return std::make_tuple(k, htobe32(std::numeric_limits<uint32_t>::max() - nHeight), islockHash);
95 }
96 
97 void CInstantSendDb::WriteInstantSendLockMined(const uint256& hash, int nHeight)
98 {
100 }
101 
103 {
105 }
106 
107 void CInstantSendDb::WriteInstantSendLockArchived(CDBBatch& batch, const uint256& hash, int nHeight)
108 {
109  batch.Write(BuildInversedISLockKey(DB_ARCHIVED_BY_HEIGHT_AND_HASH, nHeight, hash), true);
110  batch.Write(std::make_tuple(std::string(DB_ARCHIVED_BY_HASH), hash), true);
111 }
112 
113 std::unordered_map<uint256, CInstantSendLockPtr> CInstantSendDb::RemoveConfirmedInstantSendLocks(int nUntilHeight)
114 {
115  auto it = std::unique_ptr<CDBIterator>(db.NewIterator());
116 
117  auto firstKey = BuildInversedISLockKey(DB_MINED_BY_HEIGHT_AND_HASH, nUntilHeight, uint256());
118 
119  it->Seek(firstKey);
120 
121  CDBBatch batch(db);
122  std::unordered_map<uint256, CInstantSendLockPtr> ret;
123  while (it->Valid()) {
124  decltype(firstKey) curKey;
125  if (!it->GetKey(curKey) || std::get<0>(curKey) != DB_MINED_BY_HEIGHT_AND_HASH) {
126  break;
127  }
128  uint32_t nHeight = std::numeric_limits<uint32_t>::max() - be32toh(std::get<1>(curKey));
129  if (nHeight > nUntilHeight) {
130  break;
131  }
132 
133  auto& islockHash = std::get<2>(curKey);
134  auto islock = GetInstantSendLockByHash(islockHash);
135  if (islock) {
136  RemoveInstantSendLock(batch, islockHash, islock);
137  ret.emplace(islockHash, islock);
138  }
139 
140  // archive the islock hash, so that we're still able to check if we've seen the islock in the past
141  WriteInstantSendLockArchived(batch, islockHash, nHeight);
142 
143  batch.Erase(curKey);
144 
145  it->Next();
146  }
147 
148  db.WriteBatch(batch);
149 
150  return ret;
151 }
152 
154 {
155  auto it = std::unique_ptr<CDBIterator>(db.NewIterator());
156 
157  auto firstKey = BuildInversedISLockKey(DB_ARCHIVED_BY_HEIGHT_AND_HASH, nUntilHeight, uint256());
158 
159  it->Seek(firstKey);
160 
161  CDBBatch batch(db);
162  while (it->Valid()) {
163  decltype(firstKey) curKey;
164  if (!it->GetKey(curKey) || std::get<0>(curKey) != DB_ARCHIVED_BY_HEIGHT_AND_HASH) {
165  break;
166  }
167  uint32_t nHeight = std::numeric_limits<uint32_t>::max() - be32toh(std::get<1>(curKey));
168  if (nHeight > nUntilHeight) {
169  break;
170  }
171 
172  auto& islockHash = std::get<2>(curKey);
173  batch.Erase(std::make_tuple(std::string(DB_ARCHIVED_BY_HASH), islockHash));
174  batch.Erase(curKey);
175 
176  it->Next();
177  }
178 
179  db.WriteBatch(batch);
180 }
181 
183 {
184  return db.Exists(std::make_tuple(std::string(DB_ARCHIVED_BY_HASH), islockHash));
185 }
186 
188 {
189  auto it = std::unique_ptr<CDBIterator>(db.NewIterator());
190  auto firstKey = std::make_tuple(std::string(DB_ISLOCK_BY_HASH), uint256());
191 
192  it->Seek(firstKey);
193 
194  size_t cnt = 0;
195  while (it->Valid()) {
196  decltype(firstKey) curKey;
197  if (!it->GetKey(curKey) || std::get<0>(curKey) != DB_ISLOCK_BY_HASH) {
198  break;
199  }
200 
201  cnt++;
202 
203  it->Next();
204  }
205 
206  return cnt;
207 }
208 
210 {
212  if (islockCache.get(hash, ret)) {
213  return ret;
214  }
215 
216  ret = std::make_shared<CInstantSendLock>();
217  bool exists = db.Read(std::make_tuple(std::string(DB_ISLOCK_BY_HASH), hash), *ret);
218  if (!exists) {
219  ret = nullptr;
220  }
221  islockCache.insert(hash, ret);
222  return ret;
223 }
224 
226 {
227  uint256 islockHash;
228 
229  bool found = txidCache.get(txid, islockHash);
230  if (found && islockHash.IsNull()) {
231  return uint256();
232  }
233 
234  if (!found) {
235  found = db.Read(std::make_tuple(std::string(DB_HASH_BY_TXID), txid), islockHash);
236  txidCache.insert(txid, islockHash);
237  }
238 
239  if (!found) {
240  return uint256();
241  }
242  return islockHash;
243 }
244 
246 {
247  uint256 islockHash = GetInstantSendLockHashByTxid(txid);
248  if (islockHash.IsNull()) {
249  return nullptr;
250  }
251  return GetInstantSendLockByHash(islockHash);
252 }
253 
255 {
256  uint256 islockHash;
257  bool found = outpointCache.get(outpoint, islockHash);
258  if (found && islockHash.IsNull()) {
259  return nullptr;
260  }
261 
262  if (!found) {
263  found = db.Read(std::make_tuple(std::string(DB_HASH_BY_OUTPOINT), outpoint), islockHash);
264  outpointCache.insert(outpoint, islockHash);
265  }
266 
267  if (!found) {
268  return nullptr;
269  }
270  return GetInstantSendLockByHash(islockHash);
271 }
272 
273 std::vector<uint256> CInstantSendDb::GetInstantSendLocksByParent(const uint256& parent)
274 {
275  auto it = std::unique_ptr<CDBIterator>(db.NewIterator());
276  auto firstKey = std::make_tuple(std::string(DB_HASH_BY_OUTPOINT), COutPoint(parent, 0));
277  it->Seek(firstKey);
278 
279  std::vector<uint256> result;
280 
281  while (it->Valid()) {
282  decltype(firstKey) curKey;
283  if (!it->GetKey(curKey) || std::get<0>(curKey) != DB_HASH_BY_OUTPOINT) {
284  break;
285  }
286  auto& outpoint = std::get<1>(curKey);
287  if (outpoint.hash != parent) {
288  break;
289  }
290 
291  uint256 islockHash;
292  if (!it->GetValue(islockHash)) {
293  break;
294  }
295  result.emplace_back(islockHash);
296  it->Next();
297  }
298 
299  return result;
300 }
301 
302 std::vector<uint256> CInstantSendDb::RemoveChainedInstantSendLocks(const uint256& islockHash, const uint256& txid, int nHeight)
303 {
304  std::vector<uint256> result;
305 
306  std::vector<uint256> stack;
307  std::unordered_set<uint256, StaticSaltedHasher> added;
308  stack.emplace_back(txid);
309 
310  CDBBatch batch(db);
311  while (!stack.empty()) {
312  auto children = GetInstantSendLocksByParent(stack.back());
313  stack.pop_back();
314 
315  for (auto& childIslockHash : children) {
316  auto childIsLock = GetInstantSendLockByHash(childIslockHash);
317  if (!childIsLock) {
318  continue;
319  }
320 
321  RemoveInstantSendLock(batch, childIslockHash, childIsLock);
322  WriteInstantSendLockArchived(batch, childIslockHash, nHeight);
323  result.emplace_back(childIslockHash);
324 
325  if (added.emplace(childIsLock->txid).second) {
326  stack.emplace_back(childIsLock->txid);
327  }
328  }
329  }
330 
331  RemoveInstantSendLock(batch, islockHash, nullptr);
332  WriteInstantSendLockArchived(batch, islockHash, nHeight);
333  result.emplace_back(islockHash);
334 
335  db.WriteBatch(batch);
336 
337  return result;
338 }
339 
341 
343  db(_llmqDb)
344 {
346 }
347 
349 {
350 }
351 
353 {
354  // can't start new thread if we have one running already
355  if (workThread.joinable()) {
356  assert(false);
357  }
358 
359  workThread = std::thread(&TraceThread<std::function<void()> >, "instantsend", std::function<void()>(std::bind(&CInstantSendManager::WorkThreadMain, this)));
360 
362 }
363 
365 {
367 
368  // make sure to call InterruptWorkerThread() first
369  if (!workInterrupt) {
370  assert(false);
371  }
372 
373  if (workThread.joinable()) {
374  workThread.join();
375  }
376 }
377 
379 {
380  workInterrupt();
381 }
382 
383 bool CInstantSendManager::ProcessTx(const CTransaction& tx, bool allowReSigning, const Consensus::Params& params)
384 {
385  if (!IsInstantSendEnabled()) {
386  return true;
387  }
388 
389  auto llmqType = params.llmqTypeInstantSend;
390  if (llmqType == Consensus::LLMQ_NONE) {
391  return true;
392  }
393  if (!fMasternodeMode) {
394  return true;
395  }
396 
397  // Ignore any InstantSend messages until blockchain is synced
399  return true;
400  }
401 
402  // In case the islock was received before the TX, filtered announcement might have missed this islock because
403  // we were unable to check for filter matches deep inside the TX. Now we have the TX, so we should retry.
404  uint256 islockHash;
405  {
406  LOCK(cs);
407  islockHash = db.GetInstantSendLockHashByTxid(tx.GetHash());
408  }
409  if (!islockHash.IsNull()) {
410  CInv inv(MSG_ISLOCK, islockHash);
411  g_connman->RelayInvFiltered(inv, tx, LLMQS_PROTO_VERSION);
412  }
413 
414  if (!CheckCanLock(tx, true, params)) {
415  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: CheckCanLock returned false\n", __func__,
416  tx.GetHash().ToString());
417  return false;
418  }
419 
420  auto conflictingLock = GetConflictingLock(tx);
421  if (conflictingLock) {
422  auto islockHash = ::SerializeHash(*conflictingLock);
423  LogPrintf("CInstantSendManager::%s -- txid=%s: conflicts with islock %s, txid=%s\n", __func__,
424  tx.GetHash().ToString(), islockHash.ToString(), conflictingLock->txid.ToString());
425  return false;
426  }
427 
428  std::vector<uint256> ids;
429  ids.reserve(tx.vin.size());
430 
431  size_t alreadyVotedCount = 0;
432  for (const auto& in : tx.vin) {
433  auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout));
434  ids.emplace_back(id);
435 
436  uint256 otherTxHash;
437  if (quorumSigningManager->GetVoteForId(llmqType, id, otherTxHash)) {
438  if (otherTxHash != tx.GetHash()) {
439  LogPrintf("CInstantSendManager::%s -- txid=%s: input %s is conflicting with previous vote for tx %s\n", __func__,
440  tx.GetHash().ToString(), in.prevout.ToStringShort(), otherTxHash.ToString());
441  return false;
442  }
443  alreadyVotedCount++;
444  }
445 
446  // don't even try the actual signing if any input is conflicting
447  if (quorumSigningManager->IsConflicting(llmqType, id, tx.GetHash())) {
448  LogPrintf("CInstantSendManager::%s -- txid=%s: quorumSigningManager->IsConflicting returned true. id=%s\n", __func__,
449  tx.GetHash().ToString(), id.ToString());
450  return false;
451  }
452  }
453  if (!allowReSigning && alreadyVotedCount == ids.size()) {
454  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: already voted on all inputs, bailing out\n", __func__,
455  tx.GetHash().ToString());
456  return true;
457  }
458 
459  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: trying to vote on %d inputs\n", __func__,
460  tx.GetHash().ToString(), tx.vin.size());
461 
462  for (size_t i = 0; i < tx.vin.size(); i++) {
463  auto& in = tx.vin[i];
464  auto& id = ids[i];
465  inputRequestIds.emplace(id);
466  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: trying to vote on input %s with id %s. allowReSigning=%d\n", __func__,
467  tx.GetHash().ToString(), in.prevout.ToStringShort(), id.ToString(), allowReSigning);
468  if (quorumSigningManager->AsyncSignIfMember(llmqType, id, tx.GetHash(), allowReSigning)) {
469  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: voted on input %s with id %s\n", __func__,
470  tx.GetHash().ToString(), in.prevout.ToStringShort(), id.ToString());
471  }
472  }
473 
474  // We might have received all input locks before we got the corresponding TX. In this case, we have to sign the
475  // islock now instead of waiting for the input locks.
477 
478  return true;
479 }
480 
481 bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug, const Consensus::Params& params)
482 {
483  if (tx.vin.empty()) {
484  // can't lock TXs without inputs (e.g. quorum commitments)
485  return false;
486  }
487 
488  for (const auto& in : tx.vin) {
489  CAmount v = 0;
490  if (!CheckCanLock(in.prevout, printDebug, tx.GetHash(), &v, params)) {
491  return false;
492  }
493  }
494 
495  return true;
496 }
497 
498 bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebug, const uint256& txHash, CAmount* retValue, const Consensus::Params& params)
499 {
500  int nInstantSendConfirmationsRequired = params.nInstantSendConfirmationsRequired;
501 
502  if (IsLocked(outpoint.hash)) {
503  // if prevout was ix locked, allow locking of descendants (no matter if prevout is in mempool or already mined)
504  return true;
505  }
506 
507  auto mempoolTx = mempool.get(outpoint.hash);
508  if (mempoolTx) {
509  if (printDebug) {
510  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: parent mempool TX %s is not locked\n", __func__,
511  txHash.ToString(), outpoint.hash.ToString());
512  }
513  return false;
514  }
515 
516  CTransactionRef tx;
517  uint256 hashBlock;
518  // this relies on enabled txindex and won't work if we ever try to remove the requirement for txindex for masternodes
519  if (!GetTransaction(outpoint.hash, tx, params, hashBlock, false)) {
520  if (printDebug) {
521  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: failed to find parent TX %s\n", __func__,
522  txHash.ToString(), outpoint.hash.ToString());
523  }
524  return false;
525  }
526 
527  const CBlockIndex* pindexMined;
528  int nTxAge;
529  {
530  LOCK(cs_main);
531  pindexMined = mapBlockIndex.at(hashBlock);
532  nTxAge = chainActive.Height() - pindexMined->nHeight + 1;
533  }
534 
535  if (nTxAge < nInstantSendConfirmationsRequired) {
536  if (!llmq::chainLocksHandler->HasChainLock(pindexMined->nHeight, pindexMined->GetBlockHash())) {
537  if (printDebug) {
538  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: outpoint %s too new and not ChainLocked. nTxAge=%d, nInstantSendConfirmationsRequired=%d\n", __func__,
539  txHash.ToString(), outpoint.ToStringShort(), nTxAge, nInstantSendConfirmationsRequired);
540  }
541  return false;
542  }
543  }
544 
545  if (retValue) {
546  *retValue = tx->vout[outpoint.n].nValue;
547  }
548 
549  return true;
550 }
551 
553 {
554  if (!IsInstantSendEnabled()) {
555  return;
556  }
557 
558  auto llmqType = Params().GetConsensus().llmqTypeInstantSend;
559  if (llmqType == Consensus::LLMQ_NONE) {
560  return;
561  }
562  auto& params = Params().GetConsensus().llmqs.at(llmqType);
563 
564  uint256 txid;
565  bool isInstantSendLock = false;
566  {
567  LOCK(cs);
568  if (inputRequestIds.count(recoveredSig.id)) {
569  txid = recoveredSig.msgHash;
570  }
571  if (creatingInstantSendLocks.count(recoveredSig.id)) {
572  isInstantSendLock = true;
573  }
574  }
575  if (!txid.IsNull()) {
576  HandleNewInputLockRecoveredSig(recoveredSig, txid);
577  } else if (isInstantSendLock) {
579  }
580 }
581 
583 {
584  CTransactionRef tx;
585  uint256 hashBlock;
586  if (!GetTransaction(txid, tx, Params().GetConsensus(), hashBlock, true)) {
587  return;
588  }
589 
591  for (auto& in : tx->vin) {
592  auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout));
593  if (id == recoveredSig.id) {
594  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got recovered sig for input %s\n", __func__,
595  txid.ToString(), in.prevout.ToStringShort());
596  break;
597  }
598  }
599  }
600 
602 }
603 
605 {
606  auto llmqType = Params().GetConsensus().llmqTypeInstantSend;
607 
608  for (auto& in : tx.vin) {
609  auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout));
610  if (!quorumSigningManager->HasRecoveredSig(llmqType, id, tx.GetHash())) {
611  return;
612  }
613  }
614 
615  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got all recovered sigs, creating CInstantSendLock\n", __func__,
616  tx.GetHash().ToString());
617 
618  CInstantSendLock islock;
619  islock.txid = tx.GetHash();
620  for (auto& in : tx.vin) {
621  islock.inputs.emplace_back(in.prevout);
622  }
623 
624  auto id = islock.GetRequestId();
625 
626  if (quorumSigningManager->HasRecoveredSigForId(llmqType, id)) {
627  return;
628  }
629 
630  {
631  LOCK(cs);
632  auto e = creatingInstantSendLocks.emplace(id, std::move(islock));
633  if (!e.second) {
634  return;
635  }
636  txToCreatingInstantSendLocks.emplace(tx.GetHash(), &e.first->second);
637  }
638 
639  quorumSigningManager->AsyncSignIfMember(llmqType, id, tx.GetHash());
640 }
641 
643 {
644  CInstantSendLock islock;
645 
646  {
647  LOCK(cs);
648  auto it = creatingInstantSendLocks.find(recoveredSig.id);
649  if (it == creatingInstantSendLocks.end()) {
650  return;
651  }
652 
653  islock = std::move(it->second);
654  creatingInstantSendLocks.erase(it);
655  txToCreatingInstantSendLocks.erase(islock.txid);
656  }
657 
658  if (islock.txid != recoveredSig.msgHash) {
659  LogPrintf("CInstantSendManager::%s -- txid=%s: islock conflicts with %s, dropping own version\n", __func__,
660  islock.txid.ToString(), recoveredSig.msgHash.ToString());
661  return;
662  }
663 
664  islock.sig = recoveredSig.sig;
665  ProcessInstantSendLock(-1, ::SerializeHash(islock), islock);
666 }
667 
668 void CInstantSendManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
669 {
670  if (!IsInstantSendEnabled()) {
671  return;
672  }
673 
674  if (strCommand == NetMsgType::ISLOCK) {
675  CInstantSendLock islock;
676  vRecv >> islock;
677  ProcessMessageInstantSendLock(pfrom, islock, connman);
678  }
679 }
680 
682 {
683  bool ban = false;
684  if (!PreVerifyInstantSendLock(pfrom->GetId(), islock, ban)) {
685  if (ban) {
686  LOCK(cs_main);
687  Misbehaving(pfrom->GetId(), 100);
688  }
689  return;
690  }
691 
692  auto hash = ::SerializeHash(islock);
693 
694  LOCK(cs);
695  if (db.GetInstantSendLockByHash(hash) != nullptr) {
696  return;
697  }
698  if (pendingInstantSendLocks.count(hash)) {
699  return;
700  }
701 
702  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: received islock, peer=%d\n", __func__,
703  islock.txid.ToString(), hash.ToString(), pfrom->GetId());
704 
705  pendingInstantSendLocks.emplace(hash, std::make_pair(pfrom->GetId(), std::move(islock)));
706 }
707 
709 {
710  retBan = false;
711 
712  if (islock.txid.IsNull() || islock.inputs.empty()) {
713  retBan = true;
714  return false;
715  }
716 
717  std::set<COutPoint> dups;
718  for (auto& o : islock.inputs) {
719  if (!dups.emplace(o).second) {
720  retBan = true;
721  return false;
722  }
723  }
724 
725  return true;
726 }
727 
729 {
730  decltype(pendingInstantSendLocks) pend;
731 
732  {
733  LOCK(cs);
734  // only process a max 32 locks at a time to avoid duplicate verification of recovered signatures which have been
735  // verified by CSigningManager in parallel
736  const size_t maxCount = 32;
737  if (pendingInstantSendLocks.size() <= maxCount) {
738  pend = std::move(pendingInstantSendLocks);
739  } else {
740  while (pend.size() < maxCount) {
741  auto it = pendingInstantSendLocks.begin();
742  pend.emplace(it->first, std::move(it->second));
743  pendingInstantSendLocks.erase(it);
744  }
745  }
746  }
747 
748  if (pend.empty()) {
749  return false;
750  }
751 
752  if (!IsInstantSendEnabled()) {
753  return false;
754  }
755 
756  auto llmqType = Params().GetConsensus().llmqTypeInstantSend;
757  auto dkgInterval = Params().GetConsensus().llmqs.at(llmqType).dkgInterval;
758 
759  // First check against the current active set and don't ban
760  auto badISLocks = ProcessPendingInstantSendLocks(0, pend, false);
761  if (!badISLocks.empty()) {
762  LogPrintf("CInstantSendManager::%s -- doing verification on old active set\n", __func__);
763 
764  // filter out valid IS locks from "pend"
765  for (auto it = pend.begin(); it != pend.end(); ) {
766  if (!badISLocks.count(it->first)) {
767  it = pend.erase(it);
768  } else {
769  ++it;
770  }
771  }
772  // Now check against the previous active set and perform banning if this fails
773  ProcessPendingInstantSendLocks(dkgInterval, pend, true);
774  }
775 
776  return true;
777 }
778 
779 std::unordered_set<uint256> CInstantSendManager::ProcessPendingInstantSendLocks(int signOffset, const std::unordered_map<uint256, std::pair<NodeId, CInstantSendLock>, StaticSaltedHasher>& pend, bool ban)
780 {
781  auto llmqType = Params().GetConsensus().llmqTypeInstantSend;
782 
783  CBLSBatchVerifier<NodeId, uint256> batchVerifier(false, true, 8);
784  std::unordered_map<uint256, std::pair<CQuorumCPtr, CRecoveredSig>> recSigs;
785 
786  size_t verifyCount = 0;
787  size_t alreadyVerified = 0;
788  for (const auto& p : pend) {
789  auto& hash = p.first;
790  auto nodeId = p.second.first;
791  auto& islock = p.second.second;
792 
793  if (batchVerifier.badSources.count(nodeId)) {
794  continue;
795  }
796 
797  if (!islock.sig.Get().IsValid()) {
798  batchVerifier.badSources.emplace(nodeId);
799  continue;
800  }
801 
802  auto id = islock.GetRequestId();
803 
804  // no need to verify an ISLOCK if we already have verified the recovered sig that belongs to it
805  if (quorumSigningManager->HasRecoveredSig(llmqType, id, islock.txid)) {
806  alreadyVerified++;
807  continue;
808  }
809 
810  auto quorum = quorumSigningManager->SelectQuorumForSigning(llmqType, id, -1, signOffset);
811  if (!quorum) {
812  // should not happen, but if one fails to select, all others will also fail to select
813  return {};
814  }
815  uint256 signHash = CLLMQUtils::BuildSignHash(llmqType, quorum->qc.quorumHash, id, islock.txid);
816  batchVerifier.PushMessage(nodeId, hash, signHash, islock.sig.Get(), quorum->qc.quorumPublicKey);
817  verifyCount++;
818 
819  // We can reconstruct the CRecoveredSig objects from the islock and pass it to the signing manager, which
820  // avoids unnecessary double-verification of the signature. We however only do this when verification here
821  // turns out to be good (which is checked further down)
822  if (!quorumSigningManager->HasRecoveredSigForId(llmqType, id)) {
823  CRecoveredSig recSig;
824  recSig.llmqType = llmqType;
825  recSig.quorumHash = quorum->qc.quorumHash;
826  recSig.id = id;
827  recSig.msgHash = islock.txid;
828  recSig.sig = islock.sig;
829  recSigs.emplace(std::piecewise_construct,
830  std::forward_as_tuple(hash),
831  std::forward_as_tuple(std::move(quorum), std::move(recSig)));
832  }
833  }
834 
835  cxxtimer::Timer verifyTimer(true);
836  batchVerifier.Verify();
837  verifyTimer.stop();
838 
839  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- verified locks. count=%d, alreadyVerified=%d, vt=%d, nodes=%d\n", __func__,
840  verifyCount, alreadyVerified, verifyTimer.count(), batchVerifier.GetUniqueSourceCount());
841 
842  std::unordered_set<uint256> badISLocks;
843 
844  if (ban && !batchVerifier.badSources.empty()) {
845  LOCK(cs_main);
846  for (auto& nodeId : batchVerifier.badSources) {
847  // Let's not be too harsh, as the peer might simply be unlucky and might have sent us an old lock which
848  // does not validate anymore due to changed quorums
849  Misbehaving(nodeId, 20);
850  }
851  }
852  for (const auto& p : pend) {
853  auto& hash = p.first;
854  auto nodeId = p.second.first;
855  auto& islock = p.second.second;
856 
857  if (batchVerifier.badMessages.count(hash)) {
858  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: invalid sig in islock, peer=%d\n", __func__,
859  islock.txid.ToString(), hash.ToString(), nodeId);
860  badISLocks.emplace(hash);
861  continue;
862  }
863 
864  ProcessInstantSendLock(nodeId, hash, islock);
865 
866  // See comment further on top. We pass a reconstructed recovered sig to the signing manager to avoid
867  // double-verification of the sig.
868  auto it = recSigs.find(hash);
869  if (it != recSigs.end()) {
870  auto& quorum = it->second.first;
871  auto& recSig = it->second.second;
872  if (!quorumSigningManager->HasRecoveredSigForId(llmqType, recSig.id)) {
873  recSig.UpdateHash();
874  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: passing reconstructed recSig to signing mgr, peer=%d\n", __func__,
875  islock.txid.ToString(), hash.ToString(), nodeId);
877  }
878  }
879  }
880 
881  return badISLocks;
882 }
883 
885 {
886  {
887  LOCK(cs_main);
888  EraseObjectRequest(from, CInv(MSG_ISLOCK, hash));
889  }
890 
891  CTransactionRef tx;
892  uint256 hashBlock;
893  const CBlockIndex* pindexMined = nullptr;
894  // we ignore failure here as we must be able to propagate the lock even if we don't have the TX locally
895  if (GetTransaction(islock.txid, tx, Params().GetConsensus(), hashBlock)) {
896  if (!hashBlock.IsNull()) {
897  {
898  LOCK(cs_main);
899  pindexMined = mapBlockIndex.at(hashBlock);
900  }
901 
902  // Let's see if the TX that was locked by this islock is already mined in a ChainLocked block. If yes,
903  // we can simply ignore the islock, as the ChainLock implies locking of all TXs in that chain
904  if (llmq::chainLocksHandler->HasChainLock(pindexMined->nHeight, pindexMined->GetBlockHash())) {
905  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txlock=%s, islock=%s: dropping islock as it already got a ChainLock in block %s, peer=%d\n", __func__,
906  islock.txid.ToString(), hash.ToString(), hashBlock.ToString(), from);
907  return;
908  }
909  }
910  }
911 
912  {
913  LOCK(cs);
914 
915  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: processsing islock, peer=%d\n", __func__,
916  islock.txid.ToString(), hash.ToString(), from);
917 
918  creatingInstantSendLocks.erase(islock.GetRequestId());
919  txToCreatingInstantSendLocks.erase(islock.txid);
920 
921  CInstantSendLockPtr otherIsLock;
922  if (db.GetInstantSendLockByHash(hash)) {
923  return;
924  }
925  otherIsLock = db.GetInstantSendLockByTxid(islock.txid);
926  if (otherIsLock != nullptr) {
927  LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: duplicate islock, other islock=%s, peer=%d\n", __func__,
928  islock.txid.ToString(), hash.ToString(), ::SerializeHash(*otherIsLock).ToString(), from);
929  }
930  for (auto& in : islock.inputs) {
931  otherIsLock = db.GetInstantSendLockByInput(in);
932  if (otherIsLock != nullptr) {
933  LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: conflicting input in islock. input=%s, other islock=%s, peer=%d\n", __func__,
934  islock.txid.ToString(), hash.ToString(), in.ToStringShort(), ::SerializeHash(*otherIsLock).ToString(), from);
935  }
936  }
937 
938  db.WriteNewInstantSendLock(hash, islock);
939  if (pindexMined) {
940  db.WriteInstantSendLockMined(hash, pindexMined->nHeight);
941  }
942 
943  // This will also add children TXs to pendingRetryTxs
944  RemoveNonLockedTx(islock.txid, true);
945 
946  // We don't need the recovered sigs for the inputs anymore. This prevents unnecessary propagation of these sigs.
947  // We only need the ISLOCK from now on to detect conflicts
949  }
950 
951  CInv inv(MSG_ISLOCK, hash);
952  if (tx != nullptr) {
953  g_connman->RelayInvFiltered(inv, *tx, LLMQS_PROTO_VERSION);
954  } else {
955  // we don't have the TX yet, so we only filter based on txid. Later when that TX arrives, we will re-announce
956  // with the TX taken into account.
957  g_connman->RelayInvFiltered(inv, islock.txid, LLMQS_PROTO_VERSION);
958  }
959 
960  RemoveMempoolConflictsForLock(hash, islock);
961  ResolveBlockConflicts(hash, islock);
962  UpdateWalletTransaction(tx, islock);
963 }
964 
966 {
967  if (tx == nullptr) {
968  return;
969  }
970 
971  GetMainSignals().NotifyTransactionLock(*tx, islock);
972  // bump mempool counter to make sure newly mined txes are picked up by getblocktemplate
974 }
975 
976 void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, bool allowReSigning)
977 {
978  if (!IsInstantSendEnabled()) {
979  return;
980  }
981 
982  if (tx->IsCoinBase() || tx->vin.empty()) {
983  // coinbase and TXs with no inputs can't be locked
984  return;
985  }
986 
987  uint256 islockHash;
988  {
989  LOCK(cs);
990  islockHash = db.GetInstantSendLockHashByTxid(tx->GetHash());
991 
992  // update DB about when an IS lock was mined
993  if (!islockHash.IsNull() && pindex) {
994  db.WriteInstantSendLockMined(islockHash, pindex->nHeight);
995  }
996  }
997 
999  return;
1000  }
1001 
1002  bool chainlocked = pindex && chainLocksHandler->HasChainLock(pindex->nHeight, pindex->GetBlockHash());
1003  if (islockHash.IsNull() && !chainlocked) {
1004  ProcessTx(*tx, allowReSigning, Params().GetConsensus());
1005  }
1006 
1007  LOCK(cs);
1008  if (!chainlocked && islockHash.IsNull()) {
1009  // TX is not locked, so make sure it is tracked
1010  AddNonLockedTx(tx, pindex);
1011  } else {
1012  // TX is locked, so make sure we don't track it anymore
1013  RemoveNonLockedTx(tx->GetHash(), true);
1014  }
1015 }
1016 
1018 {
1019  ProcessNewTransaction(tx, nullptr, false);
1020 }
1021 
1022 void CInstantSendManager::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted)
1023 {
1024  if (!IsInstantSendEnabled()) {
1025  return;
1026  }
1027 
1028  if (!vtxConflicted.empty()) {
1029  LOCK(cs);
1030  for (const auto& tx : vtxConflicted) {
1031  RemoveConflictedTx(*tx);
1032  }
1033  }
1034 
1035  for (const auto& tx : pblock->vtx) {
1036  ProcessNewTransaction(tx, pindex, true);
1037  }
1038 }
1039 
1040 void CInstantSendManager::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected)
1041 {
1042  LOCK(cs);
1043  for (auto& tx : pblock->vtx) {
1044  auto islockHash = db.GetInstantSendLockHashByTxid(tx->GetHash());
1045  if (!islockHash.IsNull()) {
1046  db.RemoveInstantSendLockMined(islockHash, pindexDisconnected->nHeight);
1047  }
1048  }
1049 }
1050 
1052 {
1053  AssertLockHeld(cs);
1054  auto res = nonLockedTxs.emplace(tx->GetHash(), NonLockedTxInfo());
1055  auto& info = res.first->second;
1056  info.pindexMined = pindexMined;
1057 
1058  if (!info.tx) {
1059  info.tx = tx;
1060  for (const auto& in : tx->vin) {
1061  nonLockedTxs[in.prevout.hash].children.emplace(tx->GetHash());
1062  }
1063  }
1064 
1065  if (res.second) {
1066  for (auto& in : tx->vin) {
1067  nonLockedTxsByOutpoints.emplace(in.prevout, tx->GetHash());
1068  }
1069  }
1070 
1071  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, pindexMined=%s\n", __func__,
1072  tx->GetHash().ToString(), pindexMined ? pindexMined->GetBlockHash().ToString() : "");
1073 }
1074 
1075 void CInstantSendManager::RemoveNonLockedTx(const uint256& txid, bool retryChildren)
1076 {
1077  AssertLockHeld(cs);
1078 
1079  auto it = nonLockedTxs.find(txid);
1080  if (it == nonLockedTxs.end()) {
1081  return;
1082  }
1083  auto& info = it->second;
1084 
1085  size_t retryChildrenCount = 0;
1086  if (retryChildren) {
1087  // TX got locked, so we can retry locking children
1088  for (auto& childTxid : info.children) {
1089  pendingRetryTxs.emplace(childTxid);
1090  retryChildrenCount++;
1091  }
1092  }
1093 
1094  if (info.tx) {
1095  for (const auto& in : info.tx->vin) {
1096  auto jt = nonLockedTxs.find(in.prevout.hash);
1097  if (jt != nonLockedTxs.end()) {
1098  jt->second.children.erase(txid);
1099  if (!jt->second.tx && jt->second.children.empty()) {
1100  nonLockedTxs.erase(jt);
1101  }
1102  }
1103  nonLockedTxsByOutpoints.erase(in.prevout);
1104  }
1105  }
1106 
1107  nonLockedTxs.erase(it);
1108 
1109  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, retryChildren=%d, retryChildrenCount=%d\n", __func__,
1110  txid.ToString(), retryChildren, retryChildrenCount);
1111 }
1112 
1114 {
1115  AssertLockHeld(cs);
1116  RemoveNonLockedTx(tx.GetHash(), false);
1117 
1118  for (const auto& in : tx.vin) {
1119  auto inputRequestId = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in));
1120  inputRequestIds.erase(inputRequestId);
1121  }
1122 }
1123 
1125 {
1126  auto& consensusParams = Params().GetConsensus();
1127 
1128  for (auto& in : islock.inputs) {
1129  auto inputRequestId = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in));
1130  inputRequestIds.erase(inputRequestId);
1131  quorumSigningManager->TruncateRecoveredSig(consensusParams.llmqTypeInstantSend, inputRequestId);
1132  }
1133 }
1134 
1136 {
1137  HandleFullyConfirmedBlock(pindexChainLock);
1138 }
1139 
1141 {
1142  // TODO remove this after DIP8 has activated
1143  bool fDIP0008Active = VersionBitsState(pindexNew->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0008, versionbitscache) == THRESHOLD_ACTIVE;
1144 
1145  if (sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED) && fDIP0008Active) {
1146  // Nothing to do here. We should keep all islocks and let chainlocks handle them.
1147  return;
1148  }
1149 
1150  int nConfirmedHeight = pindexNew->nHeight - Params().GetConsensus().nInstantSendKeepLock;
1151  const CBlockIndex* pindex = pindexNew->GetAncestor(nConfirmedHeight);
1152 
1153  if (pindex) {
1154  HandleFullyConfirmedBlock(pindex);
1155  }
1156 }
1157 
1159 {
1160  LOCK(cs);
1161 
1162  auto& consensusParams = Params().GetConsensus();
1163 
1164  auto removeISLocks = db.RemoveConfirmedInstantSendLocks(pindex->nHeight);
1165 
1166  if (pindex->nHeight > 100) {
1167  db.RemoveArchivedInstantSendLocks(pindex->nHeight - 100);
1168  }
1169  for (auto& p : removeISLocks) {
1170  auto& islockHash = p.first;
1171  auto& islock = p.second;
1172  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: removed islock as it got fully confirmed\n", __func__,
1173  islock->txid.ToString(), islockHash.ToString());
1174 
1175  // No need to keep recovered sigs for fully confirmed IS locks, as there is no chance for conflicts
1176  // from now on. All inputs are spent now and can't be spend in any other TX.
1178 
1179  // And we don't need the recovered sig for the ISLOCK anymore, as the block in which it got mined is considered
1180  // fully confirmed now
1181  quorumSigningManager->TruncateRecoveredSig(consensusParams.llmqTypeInstantSend, islock->GetRequestId());
1182  }
1183 
1184  // Find all previously unlocked TXs that got locked by this fully confirmed (ChainLock) block and remove them
1185  // from the nonLockedTxs map. Also collect all children of these TXs and mark them for retrying of IS locking.
1186  std::vector<uint256> toRemove;
1187  for (auto& p : nonLockedTxs) {
1188  auto pindexMined = p.second.pindexMined;
1189 
1190  if (pindexMined && pindex->GetAncestor(pindexMined->nHeight) == pindexMined) {
1191  toRemove.emplace_back(p.first);
1192  }
1193  }
1194  for (auto& txid : toRemove) {
1195  // This will also add children to pendingRetryTxs
1196  RemoveNonLockedTx(txid, true);
1197  }
1198 }
1199 
1201 {
1202  std::unordered_map<uint256, CTransactionRef> toDelete;
1203 
1204  {
1205  LOCK(mempool.cs);
1206 
1207  for (auto& in : islock.inputs) {
1208  auto it = mempool.mapNextTx.find(in);
1209  if (it == mempool.mapNextTx.end()) {
1210  continue;
1211  }
1212  if (it->second->GetHash() != islock.txid) {
1213  toDelete.emplace(it->second->GetHash(), mempool.get(it->second->GetHash()));
1214 
1215  LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: mempool TX %s with input %s conflicts with islock\n", __func__,
1216  islock.txid.ToString(), hash.ToString(), it->second->GetHash().ToString(), in.ToStringShort());
1217  }
1218  }
1219 
1220  for (auto& p : toDelete) {
1222  }
1223  }
1224 
1225  if (!toDelete.empty()) {
1226  {
1227  LOCK(cs);
1228  for (auto& p : toDelete) {
1229  RemoveConflictedTx(*p.second);
1230  }
1231  }
1232  AskNodesForLockedTx(islock.txid);
1233  }
1234 }
1235 
1237 {
1238  // Lets first collect all non-locked TXs which conflict with the given ISLOCK
1239  std::unordered_map<const CBlockIndex*, std::unordered_map<uint256, CTransactionRef, StaticSaltedHasher>> conflicts;
1240  {
1241  LOCK(cs);
1242  for (auto& in : islock.inputs) {
1243  auto it = nonLockedTxsByOutpoints.find(in);
1244  if (it != nonLockedTxsByOutpoints.end()) {
1245  auto& conflictTxid = it->second;
1246  if (conflictTxid == islock.txid) {
1247  continue;
1248  }
1249  auto jt = nonLockedTxs.find(conflictTxid);
1250  if (jt == nonLockedTxs.end()) {
1251  continue;
1252  }
1253  auto& info = jt->second;
1254  if (!info.pindexMined || !info.tx) {
1255  continue;
1256  }
1257  LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: mined TX %s with input %s and mined in block %s conflicts with islock\n", __func__,
1258  islock.txid.ToString(), islockHash.ToString(), conflictTxid.ToString(), in.ToStringShort(), info.pindexMined->GetBlockHash().ToString());
1259  conflicts[info.pindexMined].emplace(conflictTxid, info.tx);
1260  }
1261  }
1262  }
1263 
1264  // Lets see if any of the conflicts was already mined into a ChainLocked block
1265  bool hasChainLockedConflict = false;
1266  for (const auto& p : conflicts) {
1267  auto pindex = p.first;
1268  if (chainLocksHandler->HasChainLock(pindex->nHeight, pindex->GetBlockHash())) {
1269  hasChainLockedConflict = true;
1270  break;
1271  }
1272  }
1273 
1274  // If a conflict was mined into a ChainLocked block, then we have no other choice and must prune the ISLOCK and all
1275  // chained ISLOCKs that build on top of this one. The probability of this is practically zero and can only happen
1276  // when large parts of the masternode network are controlled by an attacker. In this case we must still find consensus
1277  // and its better to sacrifice individual ISLOCKs then to sacrifice whole ChainLocks.
1278  if (hasChainLockedConflict) {
1279  RemoveChainLockConflictingLock(islockHash, islock);
1280  return;
1281  }
1282 
1283  bool activateBestChain = false;
1284  for (const auto& p : conflicts) {
1285  auto pindex = p.first;
1286  {
1287  LOCK(cs);
1288  for (auto& p2 : p.second) {
1289  const auto& tx = *p2.second;
1290  RemoveConflictedTx(tx);
1291  }
1292  }
1293 
1294  LogPrintf("CInstantSendManager::%s -- invalidating block %s\n", __func__, pindex->GetBlockHash().ToString());
1295 
1296  LOCK(cs_main);
1297  CValidationState state;
1298  // need non-const pointer
1299  auto pindex2 = mapBlockIndex.at(pindex->GetBlockHash());
1300  if (!InvalidateBlock(state, Params(), pindex2)) {
1301  LogPrintf("CInstantSendManager::%s -- InvalidateBlock failed: %s\n", __func__, FormatStateMessage(state));
1302  // This should not have happened and we are in a state were it's not safe to continue anymore
1303  assert(false);
1304  }
1305  activateBestChain = true;
1306  }
1307 
1308  if (activateBestChain) {
1309  CValidationState state;
1310  if (!ActivateBestChain(state, Params())) {
1311  LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(state));
1312  // This should not have happened and we are in a state were it's not safe to continue anymore
1313  assert(false);
1314  }
1315  }
1316 }
1317 
1319 {
1320  LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: at least one conflicted TX already got a ChainLock. Removing ISLOCK and its chained children.\n", __func__,
1321  islock.txid.ToString(), islockHash.ToString());
1322  int tipHeight;
1323  {
1324  LOCK(cs_main);
1325  tipHeight = chainActive.Height();
1326  }
1327 
1328  LOCK(cs);
1329  auto removedIslocks = db.RemoveChainedInstantSendLocks(islockHash, islock.txid, tipHeight);
1330  for (auto& h : removedIslocks) {
1331  LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: removed (child) ISLOCK %s\n", __func__,
1332  islock.txid.ToString(), islockHash.ToString(), h.ToString());
1333  }
1334 }
1335 
1337 {
1338  std::vector<CNode*> nodesToAskFor;
1339  g_connman->ForEachNode([&](CNode* pnode) {
1340  LOCK(pnode->cs_filter);
1341  if (pnode->filterInventoryKnown.contains(txid)) {
1342  pnode->AddRef();
1343  nodesToAskFor.emplace_back(pnode);
1344  }
1345  });
1346  {
1347  LOCK(cs_main);
1348  for (CNode* pnode : nodesToAskFor) {
1349  LogPrintf("CInstantSendManager::%s -- txid=%s: asking other peer %d for correct TX\n", __func__,
1350  txid.ToString(), pnode->GetId());
1351 
1352  CInv inv(MSG_TX, txid);
1353  RequestObject(pnode->GetId(), inv, GetTime<std::chrono::microseconds>(), true);
1354  }
1355  }
1356  for (CNode* pnode : nodesToAskFor) {
1357  pnode->Release();
1358  }
1359 }
1360 
1362 {
1363  decltype(pendingRetryTxs) retryTxs;
1364  {
1365  LOCK(cs);
1366  retryTxs = std::move(pendingRetryTxs);
1367  }
1368 
1369  if (retryTxs.empty()) {
1370  return false;
1371  }
1372 
1373  if (!IsInstantSendEnabled()) {
1374  return false;
1375  }
1376 
1377  int retryCount = 0;
1378  for (const auto& txid : retryTxs) {
1379  CTransactionRef tx;
1380  {
1381  LOCK(cs);
1382  auto it = nonLockedTxs.find(txid);
1383  if (it == nonLockedTxs.end()) {
1384  continue;
1385  }
1386  tx = it->second.tx;
1387 
1388  if (!tx) {
1389  continue;
1390  }
1391 
1392  if (txToCreatingInstantSendLocks.count(tx->GetHash())) {
1393  // we're already in the middle of locking this one
1394  continue;
1395  }
1396  if (IsLocked(tx->GetHash())) {
1397  continue;
1398  }
1399  if (IsConflicted(*tx)) {
1400  // should not really happen as we have already filtered these out
1401  continue;
1402  }
1403  }
1404 
1405  // CheckCanLock is already called by ProcessTx, so we should avoid calling it twice. But we also shouldn't spam
1406  // the logs when retrying TXs that are not ready yet.
1408  if (!CheckCanLock(*tx, false, Params().GetConsensus())) {
1409  continue;
1410  }
1411  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: retrying to lock\n", __func__,
1412  tx->GetHash().ToString());
1413  }
1414 
1415  ProcessTx(*tx, false, Params().GetConsensus());
1416  retryCount++;
1417  }
1418 
1419  if (retryCount != 0) {
1420  LOCK(cs);
1421  LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- retried %d TXs. nonLockedTxs.size=%d\n", __func__,
1422  retryCount, nonLockedTxs.size());
1423  }
1424 
1425  return retryCount != 0;
1426 }
1427 
1429 {
1430  if (!IsInstantSendEnabled()) {
1431  return true;
1432  }
1433 
1434  LOCK(cs);
1435  return db.GetInstantSendLockByHash(inv.hash) != nullptr || pendingInstantSendLocks.count(inv.hash) != 0 || db.HasArchivedInstantSendLock(inv.hash);
1436 }
1437 
1439 {
1440  if (!IsInstantSendEnabled()) {
1441  return false;
1442  }
1443 
1444  LOCK(cs);
1445  auto islock = db.GetInstantSendLockByHash(hash);
1446  if (!islock) {
1447  return false;
1448  }
1449  ret = *islock;
1450  return true;
1451 }
1452 
1454 {
1455  if (!IsInstantSendEnabled()) {
1456  return false;
1457  }
1458 
1459  LOCK(cs);
1460  ret = db.GetInstantSendLockHashByTxid(txid);
1461  return !ret.IsNull();
1462 }
1463 
1465 {
1466  if (!IsInstantSendEnabled()) {
1467  return false;
1468  }
1469 
1470  LOCK(cs);
1471  return db.GetInstantSendLockByTxid(txHash) != nullptr;
1472 }
1473 
1475 {
1476  return GetConflictingLock(tx) != nullptr;
1477 }
1478 
1480 {
1481  if (!IsInstantSendEnabled()) {
1482  return nullptr;
1483  }
1484 
1485  LOCK(cs);
1486  for (const auto& in : tx.vin) {
1487  auto otherIsLock = db.GetInstantSendLockByInput(in.prevout);
1488  if (!otherIsLock) {
1489  continue;
1490  }
1491 
1492  if (otherIsLock->txid != tx.GetHash()) {
1493  return otherIsLock;
1494  }
1495  }
1496  return nullptr;
1497 }
1498 
1500 {
1501  return db.GetInstantSendLockCount();
1502 }
1503 
1505 {
1506  while (!workInterrupt) {
1507  bool didWork = false;
1508 
1509  didWork |= ProcessPendingInstantSendLocks();
1510  didWork |= ProcessPendingRetryLockTxs();
1511 
1512  if (!didWork) {
1513  if (!workInterrupt.sleep_for(std::chrono::milliseconds(100))) {
1514  return;
1515  }
1516  }
1517  }
1518 }
1519 
1521 {
1523 }
1524 
1525 } // namespace llmq
bool Exists(const K &key) const
Definition: dbwrapper.h:306
void AddNonLockedTx(const CTransactionRef &tx, const CBlockIndex *pindexMined)
void RequestObject(CNodeState *state, const CInv &inv, std::chrono::microseconds current_time, bool fForce=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void PushMessage(const SourceId &sourceId, const MessageId &msgId, const uint256 &msgHash, const CBLSSignature &sig, const CBLSPublicKey &pubKey)
void UpdateWalletTransaction(const CTransactionRef &tx, const CInstantSendLock &islock)
CTxMemPool mempool
std::set< MessageId > badMessages
void RemoveInstantSendLockMined(const uint256 &hash, int nHeight)
void TruncateRecoveredSigsForInputs(const CInstantSendLock &islock)
bool sleep_for(std::chrono::milliseconds rel_time)
CMasternodeSync masternodeSync
bool IsInstantSendEnabled()
UniValue quorum(const JSONRPCRequest &request)
Definition: rpcquorums.cpp:492
void ResolveBlockConflicts(const uint256 &islockHash, const CInstantSendLock &islock)
static const std::string DB_ARCHIVED_BY_HEIGHT_AND_HASH
static uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256 &quorumHash, const uint256 &id, const uint256 &msgHash)
CCriticalSection cs_filter
Definition: net.h:868
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 TraceThread(const std::string name, Callable func)
Definition: util.h:436
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:177
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:49
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason=MemPoolRemovalReason::UNKNOWN)
Definition: txmempool.cpp:725
void PushReconstructedRecoveredSig(const CRecoveredSig &recoveredSig, const CQuorumCPtr &quorum)
void BlockDisconnected(const std::shared_ptr< const CBlock > &pblock, const CBlockIndex *pindexDisconnected)
CInstantSendLockPtr GetInstantSendLockByInput(const COutPoint &outpoint)
void TransactionAddedToMempool(const CTransactionRef &tx)
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
unordered_lru_cache< uint256, uint256, StaticSaltedHasher, 10000 > txidCache
bool AlreadyHave(const CInv &inv)
void ProcessNewTransaction(const CTransactionRef &tx, const CBlockIndex *pindex, bool allowReSigning)
static const std::string DB_ARCHIVED_BY_HASH
void Erase(const K &key)
Definition: dbwrapper.h:104
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 HandleNewInputLockRecoveredSig(const CRecoveredSig &recoveredSig, const uint256 &txid)
static const std::string DB_MINED_BY_HEIGHT_AND_HASH
void TrySignInstantSendLock(const CTransaction &tx)
void ProcessMessageInstantSendLock(CNode *pfrom, const CInstantSendLock &islock, CConnman &connman)
uint32_t be32toh(uint32_t big_endian_32bits)
Definition: endian.h:198
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)
void erase(const Key &key)
bool IsBlockchainSynced()
std::unordered_map< uint256, std::pair< NodeId, CInstantSendLock >, StaticSaltedHasher > pendingInstantSendLocks
void RemoveConflictedTx(const CTransaction &tx)
void AskNodesForLockedTx(const uint256 &txid)
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:345
bool IsNull() const
Definition: uint256.h:33
static bool LogAcceptCategory(uint64_t category)
Definition: util.h:152
CDBIterator * NewIterator()
Definition: dbwrapper.h:351
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.
indirectmap< COutPoint, const CTransaction * > mapNextTx
Definition: txmempool.h:538
const std::vector< CTxIn > vin
Definition: transaction.h:215
void UnregisterRecoveredSigsListener(CRecoveredSigsListener *l)
bool HasRecoveredSig(Consensus::LLMQType llmqType, const uint256 &id, const uint256 &msgHash)
uint32_t htobe32(uint32_t host_32bits)
Definition: endian.h:184
CInstantSendManager * quorumInstantSendManager
bool GetInstantSendLockHashByTxid(const uint256 &txid, uint256 &ret)
int nInstantSendKeepLock
Definition: params.h:138
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
bool HasArchivedInstantSendLock(const uint256 &islockHash)
void insert(const Key &key, const Value &v)
uint256 GetBlockHash() const
Definition: chain.h:292
static const int LLMQS_PROTO_VERSION
introduction of LLMQs
Definition: version.h:51
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_set< uint256, StaticSaltedHasher > inputRequestIds
Request ids of inputs that we signed.
iterator end()
Definition: indirectmap.h:49
const char * ISLOCK
Definition: protocol.cpp:76
CChainLocksHandler * chainLocksHandler
This class works as a stopwatch.
Definition: cxxtimer.hpp:38
#define LogPrintf(...)
Definition: util.h:203
int nInstantSendConfirmationsRequired
Definition: params.h:137
void Release()
Definition: net.h:1014
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:330
bool get(const Key &key, Value &value)
CQuorumCPtr SelectQuorumForSigning(Consensus::LLMQType llmqType, const uint256 &selectionHash, int signHeight=-1, int signOffset=SIGN_HEIGHT_OFFSET)
void RemoveChainLockConflictingLock(const uint256 &islockHash, const CInstantSendLock &islock)
#define LOCK(cs)
Definition: sync.h:178
const uint256 & GetHash() const
Definition: transaction.h:256
static const std::string DB_ISLOCK_BY_HASH
std::shared_ptr< CInstantSendLock > CInstantSendLockPtr
uint32_t n
Definition: transaction.h:30
bool IsLocked(const uint256 &txHash)
void ProcessInstantSendLock(NodeId from, const uint256 &hash, const CInstantSendLock &islock)
void HandleFullyConfirmedBlock(const CBlockIndex *pindex)
std::unordered_map< uint256, NonLockedTxInfo, StaticSaltedHasher > nonLockedTxs
uint256 hash
Definition: protocol.h:456
void Write(const K &key, const V &value)
Definition: dbwrapper.h:75
CMainSignals & GetMainSignals()
CInstantSendLockPtr GetConflictingLock(const CTransaction &tx)
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
size_t GetUniqueSourceCount() const
Parameters that influence chain consensus.
Definition: params.h:130
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
void AddTransactionsUpdated(unsigned int n)
Definition: txmempool.cpp:356
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:273
void WriteNewInstantSendLock(const uint256 &hash, const CInstantSendLock &islock)
std::map< LLMQType, LLMQParams > llmqs
Definition: params.h:189
CCriticalSection cs
Definition: txmempool.h:488
VersionBitsCache versionbitscache
std::set< SourceId > badSources
bool GetInstantSendLockByHash(const uint256 &hash, CInstantSendLock &ret)
void UpdatedBlockTip(const CBlockIndex *pindexNew)
static std::tuple< std::string, uint32_t, uint256 > BuildInversedISLockKey(const std::string &k, int nHeight, const uint256 &islockHash)
CInstantSendManager(CDBWrapper &_llmqDb)
void NotifyChainLock(const CBlockIndex *pindexChainLock)
bool PreVerifyInstantSendLock(NodeId nodeId, const CInstantSendLock &islock, bool &retBan)
CSporkManager sporkManager
Definition: spork.cpp:29
#define LogPrint(category,...)
Definition: util.h:214
uint256 GetHash()
Definition: hash.h:203
void WriteInstantSendLockMined(const uint256 &hash, int nHeight)
Capture information about block/transaction validation.
Definition: validation.h:22
256-bit opaque blob.
Definition: uint256.h:123
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:298
CInstantSendLockPtr GetInstantSendLockByHash(const uint256 &hash)
std::string FormatStateMessage(const CValidationState &state)
Convert CValidationState to a human-readable message for logging.
Definition: validation.cpp:513
std::vector< uint256 > GetInstantSendLocksByParent(const uint256 &parent)
bool IsConflicting(Consensus::LLMQType llmqType, const uint256 &id, const uint256 &msgHash)
bool HasRecoveredSigForId(Consensus::LLMQType llmqType, const uint256 &id)
Consensus::LLMQType llmqType
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 RemoveNonLockedTx(const uint256 &txid, bool retryChildren)
std::unordered_map< uint256, CInstantSendLockPtr > RemoveConfirmedInstantSendLocks(int nUntilHeight)
CInstantSendLockPtr GetInstantSendLockByTxid(const uint256 &txid)
uint256 GetInstantSendLockHashByTxid(const uint256 &txid)
void RemoveArchivedInstantSendLocks(int nUntilHeight)
void RemoveInstantSendLock(CDBBatch &batch, const uint256 &hash, CInstantSendLockPtr islock)
bool ProcessTx(const CTransaction &tx, bool allowReSigning, const Consensus::Params &params)
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:97
void HandleNewInstantSendLockRecoveredSig(const CRecoveredSig &recoveredSig)
duration_t::rep count() const
Return the elapsed time.
Definition: cxxtimer.hpp:170
static const std::string INPUTLOCK_REQUESTID_PREFIX
void EraseObjectRequest(CNodeState *nodestate, const CInv &inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
CSigningManager * quorumSigningManager
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:184
void WriteInstantSendLockArchived(CDBBatch &batch, const uint256 &hash, int nHeight)
void RemoveMempoolConflictsForLock(const uint256 &hash, const CInstantSendLock &islock)
std::vector< COutPoint > inputs
void stop()
Stop/pause the timer.
Definition: cxxtimer.hpp:152
static const std::string ISLOCK_REQUESTID_PREFIX
CTransactionRef get(const uint256 &hash) const
Definition: txmempool.cpp:1211
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:157
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:198
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
std::unordered_map< uint256, CInstantSendLock, StaticSaltedHasher > creatingInstantSendLocks
These are the islocks that are currently in the middle of being created.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:110
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
AssertLockHeld(g_cs_orphans)
bool CheckCanLock(const CTransaction &tx, bool printDebug, const Consensus::Params &params)
CNode * AddRef()
Definition: net.h:1008
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
std::unordered_set< uint256, StaticSaltedHasher > pendingRetryTxs
LLMQType llmqTypeInstantSend
Definition: params.h:191
void BlockConnected(const std::shared_ptr< const CBlock > &pblock, const CBlockIndex *pindex, const std::vector< CTransactionRef > &vtxConflicted)
void ProcessMessage(CNode *pfrom, const std::string &strCommand, CDataStream &vRecv, CConnman &connman)
iterator find(const K &key)
Definition: indirectmap.h:36
static const std::string DB_HASH_BY_TXID
std::unordered_map< uint256, CInstantSendLock *, StaticSaltedHasher > txToCreatingInstantSendLocks
std::vector< uint256 > RemoveChainedInstantSendLocks(const uint256 &islockHash, const uint256 &txid, int nHeight)
virtual void HandleNewRecoveredSig(const CRecoveredSig &recoveredSig)
bool IsConflicted(const CTransaction &tx)
static const std::string DB_HASH_BY_OUTPOINT
void TruncateRecoveredSig(Consensus::LLMQType llmqType, const uint256 &id)
void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock &islock)
bool GetVoteForId(Consensus::LLMQType llmqType, const uint256 &id, uint256 &msgHashRet)
unordered_lru_cache< uint256, CInstantSendLockPtr, StaticSaltedHasher, 10000 > islockCache
unordered_lru_cache< COutPoint, uint256, SaltedOutpointHasher, 10000 > outpointCache
std::unordered_map< COutPoint, uint256, SaltedOutpointHasher > nonLockedTxsByOutpoints
uint256 hash
Definition: transaction.h:29
std::string ToStringShort() const
Definition: transaction.cpp:17
Released under the MIT license