1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-2020 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 6 #ifndef BITCOIN_VALIDATIONINTERFACE_H 7 #define BITCOIN_VALIDATIONINTERFACE_H 8 9 #include <primitives/transaction.h> // CTransaction(Ref) 10 #include <sync.h> 11 12 #include <functional> 13 #include <memory> 14 15 extern RecursiveMutex cs_main; 16 class BlockValidationState; 17 class CBlock; 18 class CBlockIndex; 19 struct CBlockLocator; 20 class CConnman; 21 class CValidationInterface; 22 class uint256; 23 class CScheduler; 24 enum class MemPoolRemovalReason; 25 26 // These functions dispatch to one or all registered wallets 27 28 /** Register a wallet to receive updates from core */ 29 void RegisterValidationInterface(CValidationInterface* pwalletIn); 30 /** Unregister a wallet from core */ 31 void UnregisterValidationInterface(CValidationInterface* pwalletIn); 32 /** Unregister all wallets from core */ 33 void UnregisterAllValidationInterfaces(); 34 35 // Alternate registration functions that release a shared_ptr after the last 36 // notification is sent. These are useful for race-free cleanup, since 37 // unregistration is nonblocking and can return before the last notification is 38 // processed. 39 void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks); 40 void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks); 41 42 /** 43 * Pushes a function to callback onto the notification queue, guaranteeing any 44 * callbacks generated prior to now are finished when the function is called. 45 * 46 * Be very careful blocking on func to be called if any locks are held - 47 * validation interface clients may not be able to make progress as they often 48 * wait for things like cs_main, so blocking until func is called with cs_main 49 * will result in a deadlock (that DEBUG_LOCKORDER will miss). 50 */ 51 void CallFunctionInValidationInterfaceQueue(std::function<void ()> func); 52 /** 53 * This is a synonym for the following, which asserts certain locks are not 54 * held: 55 * std::promise<void> promise; 56 * CallFunctionInValidationInterfaceQueue([&promise] { 57 * promise.set_value(); 58 * }); 59 * promise.get_future().wait(); 60 */ 61 void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main); 62 63 /** 64 * Implement this to subscribe to events generated in validation 65 * 66 * Each CValidationInterface() subscriber will receive event callbacks 67 * in the order in which the events were generated by validation. 68 * Furthermore, each ValidationInterface() subscriber may assume that 69 * callbacks effectively run in a single thread with single-threaded 70 * memory consistency. That is, for a given ValidationInterface() 71 * instantiation, each callback will complete before the next one is 72 * invoked. This means, for example when a block is connected that the 73 * UpdatedBlockTip() callback may depend on an operation performed in 74 * the BlockConnected() callback without worrying about explicit 75 * synchronization. No ordering should be assumed across 76 * ValidationInterface() subscribers. 77 */ 78 class CValidationInterface { 79 protected: 80 /** 81 * Protected destructor so that instances can only be deleted by derived classes. 82 * If that restriction is no longer desired, this should be made public and virtual. 83 */ 84 ~CValidationInterface() = default; 85 /** 86 * Notifies listeners when the block chain tip advances. 87 * 88 * When multiple blocks are connected at once, UpdatedBlockTip will be called on the final tip 89 * but may not be called on every intermediate tip. If the latter behavior is desired, 90 * subscribe to BlockConnected() instead. 91 * 92 * Called on a background thread. 93 */ UpdatedBlockTip(const CBlockIndex * pindexNew,const CBlockIndex * pindexFork,bool fInitialDownload)94 virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} 95 /** 96 * Notifies listeners of a transaction having been added to mempool. 97 * 98 * Called on a background thread. 99 */ TransactionAddedToMempool(const CTransactionRef & tx)100 virtual void TransactionAddedToMempool(const CTransactionRef& tx) {} 101 /** 102 * Notifies listeners of a transaction leaving mempool. 103 * 104 * This notification fires for transactions that are removed from the 105 * mempool for the following reasons: 106 * 107 * - EXPIRY (expired from mempool after -mempoolexpiry hours) 108 * - SIZELIMIT (removed in size limiting if the mempool exceeds -maxmempool megabytes) 109 * - REORG (removed during a reorg) 110 * - CONFLICT (removed because it conflicts with in-block transaction) 111 * - REPLACED (removed due to RBF replacement) 112 * 113 * This does not fire for transactions that are removed from the mempool 114 * because they have been included in a block. Any client that is interested 115 * in transactions removed from the mempool for inclusion in a block can learn 116 * about those transactions from the BlockConnected notification. 117 * 118 * Transactions that are removed from the mempool because they conflict 119 * with a transaction in the new block will have 120 * TransactionRemovedFromMempool events fired *before* the BlockConnected 121 * event is fired. If multiple blocks are connected in one step, then the 122 * ordering could be: 123 * 124 * - TransactionRemovedFromMempool(tx1 from block A) 125 * - TransactionRemovedFromMempool(tx2 from block A) 126 * - TransactionRemovedFromMempool(tx1 from block B) 127 * - TransactionRemovedFromMempool(tx2 from block B) 128 * - BlockConnected(A) 129 * - BlockConnected(B) 130 * 131 * Called on a background thread. 132 */ TransactionRemovedFromMempool(const CTransactionRef & tx,MemPoolRemovalReason reason)133 virtual void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) {} 134 /** 135 * Notifies listeners of a block being connected. 136 * Provides a vector of transactions evicted from the mempool as a result. 137 * 138 * Called on a background thread. 139 */ BlockConnected(const std::shared_ptr<const CBlock> & block,const CBlockIndex * pindex)140 virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex) {} 141 /** 142 * Notifies listeners of a block being disconnected 143 * 144 * Called on a background thread. 145 */ BlockDisconnected(const std::shared_ptr<const CBlock> & block,const CBlockIndex * pindex)146 virtual void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) {} 147 /** 148 * Notifies listeners of the new active block chain on-disk. 149 * 150 * Prior to this callback, any updates are not guaranteed to persist on disk 151 * (ie clients need to handle shutdown/restart safety by being able to 152 * understand when some updates were lost due to unclean shutdown). 153 * 154 * When this callback is invoked, the validation changes done by any prior 155 * callback are guaranteed to exist on disk and survive a restart, including 156 * an unclean shutdown. 157 * 158 * Provides a locator describing the best chain, which is likely useful for 159 * storing current state on disk in client DBs. 160 * 161 * Called on a background thread. 162 */ ChainStateFlushed(const CBlockLocator & locator)163 virtual void ChainStateFlushed(const CBlockLocator &locator) {} 164 /** 165 * Notifies listeners of a block validation result. 166 * If the provided BlockValidationState IsValid, the provided block 167 * is guaranteed to be the current best block at the time the 168 * callback was generated (not necessarily now) 169 */ BlockChecked(const CBlock &,const BlockValidationState &)170 virtual void BlockChecked(const CBlock&, const BlockValidationState&) {} 171 /** 172 * Notifies listeners that a block which builds directly on our current tip 173 * has been received and connected to the headers tree, though not validated yet */ NewPoWValidBlock(const CBlockIndex * pindex,const std::shared_ptr<const CBlock> & block)174 virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {}; 175 friend class CMainSignals; 176 }; 177 178 struct MainSignalsInstance; 179 class CMainSignals { 180 private: 181 std::unique_ptr<MainSignalsInstance> m_internals; 182 183 friend void ::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface>); 184 friend void ::UnregisterValidationInterface(CValidationInterface*); 185 friend void ::UnregisterAllValidationInterfaces(); 186 friend void ::CallFunctionInValidationInterfaceQueue(std::function<void ()> func); 187 188 public: 189 /** Register a CScheduler to give callbacks which should run in the background (may only be called once) */ 190 void RegisterBackgroundSignalScheduler(CScheduler& scheduler); 191 /** Unregister a CScheduler to give callbacks which should run in the background - these callbacks will now be dropped! */ 192 void UnregisterBackgroundSignalScheduler(); 193 /** Call any remaining callbacks on the calling thread */ 194 void FlushBackgroundCallbacks(); 195 196 size_t CallbacksPending(); 197 198 199 void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); 200 void TransactionAddedToMempool(const CTransactionRef&); 201 void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason); 202 void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex); 203 void BlockDisconnected(const std::shared_ptr<const CBlock> &, const CBlockIndex* pindex); 204 void ChainStateFlushed(const CBlockLocator &); 205 void BlockChecked(const CBlock&, const BlockValidationState&); 206 void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&); 207 }; 208 209 CMainSignals& GetMainSignals(); 210 211 #endif // BITCOIN_VALIDATIONINTERFACE_H 212