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