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