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