You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

validationinterface.cpp 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (c) 2009-2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2017 The Bitcoin Core developers
  3. // Distributed under the MIT software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include <validationinterface.h>
  6. #include <init.h>
  7. #include <primitives/block.h>
  8. #include <scheduler.h>
  9. #include <sync.h>
  10. #include <txmempool.h>
  11. #include <util.h>
  12. #include <validation.h>
  13. #include <list>
  14. #include <atomic>
  15. #include <future>
  16. #include <boost/signals2/signal.hpp>
  17. struct MainSignalsInstance {
  18. boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
  19. boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
  20. boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
  21. boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
  22. boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
  23. boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
  24. boost::signals2::signal<void (const uint256 &)> Inventory;
  25. boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
  26. boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
  27. boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
  28. // We are not allowed to assume the scheduler only runs in one thread,
  29. // but must ensure all callbacks happen in-order, so we end up creating
  30. // our own queue here :(
  31. SingleThreadedSchedulerClient m_schedulerClient;
  32. explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
  33. };
  34. static CMainSignals g_signals;
  35. void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
  36. assert(!m_internals);
  37. m_internals.reset(new MainSignalsInstance(&scheduler));
  38. }
  39. void CMainSignals::UnregisterBackgroundSignalScheduler() {
  40. m_internals.reset(nullptr);
  41. }
  42. void CMainSignals::FlushBackgroundCallbacks() {
  43. if (m_internals) {
  44. m_internals->m_schedulerClient.EmptyQueue();
  45. }
  46. }
  47. size_t CMainSignals::CallbacksPending() {
  48. if (!m_internals) return 0;
  49. return m_internals->m_schedulerClient.CallbacksPending();
  50. }
  51. void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) {
  52. pool.NotifyEntryRemoved.connect(boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2));
  53. }
  54. void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) {
  55. pool.NotifyEntryRemoved.disconnect(boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2));
  56. }
  57. CMainSignals& GetMainSignals()
  58. {
  59. return g_signals;
  60. }
  61. void RegisterValidationInterface(CValidationInterface* pwalletIn) {
  62. g_signals.m_internals->UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
  63. g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
  64. g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
  65. g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
  66. g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
  67. g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
  68. g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
  69. g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
  70. g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
  71. g_signals.m_internals->NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
  72. }
  73. void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
  74. g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
  75. g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
  76. g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
  77. g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
  78. g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
  79. g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
  80. g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
  81. g_signals.m_internals->TransactionRemovedFromMempool.disconnect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
  82. g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
  83. g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
  84. }
  85. void UnregisterAllValidationInterfaces() {
  86. if (!g_signals.m_internals) {
  87. return;
  88. }
  89. g_signals.m_internals->BlockChecked.disconnect_all_slots();
  90. g_signals.m_internals->Broadcast.disconnect_all_slots();
  91. g_signals.m_internals->Inventory.disconnect_all_slots();
  92. g_signals.m_internals->SetBestChain.disconnect_all_slots();
  93. g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots();
  94. g_signals.m_internals->BlockConnected.disconnect_all_slots();
  95. g_signals.m_internals->BlockDisconnected.disconnect_all_slots();
  96. g_signals.m_internals->TransactionRemovedFromMempool.disconnect_all_slots();
  97. g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots();
  98. g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots();
  99. }
  100. void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
  101. g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func));
  102. }
  103. void SyncWithValidationInterfaceQueue() {
  104. AssertLockNotHeld(cs_main);
  105. // Block until the validation queue drains
  106. std::promise<void> promise;
  107. CallFunctionInValidationInterfaceQueue([&promise] {
  108. promise.set_value();
  109. });
  110. promise.get_future().wait();
  111. }
  112. void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason reason) {
  113. if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) {
  114. m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] {
  115. m_internals->TransactionRemovedFromMempool(ptx);
  116. });
  117. }
  118. }
  119. void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
  120. // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
  121. // the chain actually updates. One way to ensure this is for the caller to invoke this signal
  122. // in the same critical section where the chain is updated
  123. m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, fInitialDownload, this] {
  124. m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
  125. });
  126. }
  127. void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
  128. m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] {
  129. m_internals->TransactionAddedToMempool(ptx);
  130. });
  131. }
  132. void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) {
  133. m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, pvtxConflicted, this] {
  134. m_internals->BlockConnected(pblock, pindex, *pvtxConflicted);
  135. });
  136. }
  137. void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) {
  138. m_internals->m_schedulerClient.AddToProcessQueue([pblock, this] {
  139. m_internals->BlockDisconnected(pblock);
  140. });
  141. }
  142. void CMainSignals::SetBestChain(const CBlockLocator &locator) {
  143. m_internals->m_schedulerClient.AddToProcessQueue([locator, this] {
  144. m_internals->SetBestChain(locator);
  145. });
  146. }
  147. void CMainSignals::Inventory(const uint256 &hash) {
  148. m_internals->m_schedulerClient.AddToProcessQueue([hash, this] {
  149. m_internals->Inventory(hash);
  150. });
  151. }
  152. void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) {
  153. m_internals->Broadcast(nBestBlockTime, connman);
  154. }
  155. void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
  156. m_internals->BlockChecked(block, state);
  157. }
  158. void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &block) {
  159. m_internals->NewPoWValidBlock(pindex, block);
  160. }