Line data Source code
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 : #include <validationinterface.h>
7 :
8 : #include <attributes.h>
9 : #include <chain.h>
10 : #include <consensus/validation.h>
11 : #include <logging.h>
12 : #include <primitives/block.h>
13 : #include <primitives/transaction.h>
14 : #include <scheduler.h>
15 :
16 : #include <future>
17 : #include <unordered_map>
18 : #include <utility>
19 :
20 : std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept;
21 :
22 : /**
23 : * MainSignalsImpl manages a list of shared_ptr<CValidationInterface> callbacks.
24 : *
25 : * A std::unordered_map is used to track what callbacks are currently
26 : * registered, and a std::list is used to store the callbacks that are
27 : * currently registered as well as any callbacks that are just unregistered
28 : * and about to be deleted when they are done executing.
29 : */
30 : class MainSignalsImpl
31 : {
32 : private:
33 : Mutex m_mutex;
34 : //! List entries consist of a callback pointer and reference count. The
35 : //! count is equal to the number of current executions of that entry, plus 1
36 : //! if it's registered. It cannot be 0 because that would imply it is
37 : //! unregistered and also not being executed (so shouldn't exist).
38 : struct ListEntry { std::shared_ptr<CValidationInterface> callbacks; int count = 1; };
39 : std::list<ListEntry> m_list GUARDED_BY(m_mutex);
40 : std::unordered_map<CValidationInterface*, std::list<ListEntry>::iterator> m_map GUARDED_BY(m_mutex);
41 :
42 : public:
43 : // We are not allowed to assume the scheduler only runs in one thread,
44 : // but must ensure all callbacks happen in-order, so we end up creating
45 : // our own queue here :(
46 : SingleThreadedSchedulerClient m_schedulerClient;
47 :
48 6414 : explicit MainSignalsImpl(CScheduler& scheduler LIFETIMEBOUND) : m_schedulerClient(scheduler) {}
49 :
50 277148 : void Register(std::shared_ptr<CValidationInterface> callbacks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
51 : {
52 277148 : LOCK(m_mutex);
53 277148 : auto inserted = m_map.emplace(callbacks.get(), m_list.end());
54 277148 : if (inserted.second) inserted.first->second = m_list.emplace(m_list.end());
55 277148 : inserted.first->second->callbacks = std::move(callbacks);
56 277148 : }
57 :
58 289344 : void Unregister(CValidationInterface* callbacks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
59 : {
60 289344 : LOCK(m_mutex);
61 289344 : auto it = m_map.find(callbacks);
62 289344 : if (it != m_map.end()) {
63 277147 : if (!--it->second->count) m_list.erase(it->second);
64 277147 : m_map.erase(it);
65 277147 : }
66 289344 : }
67 :
68 : //! Clear unregisters every previously registered callback, erasing every
69 : //! map entry. After this call, the list may still contain callbacks that
70 : //! are currently executing, but it will be cleared when they are done
71 : //! executing.
72 3025 : void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
73 : {
74 3025 : LOCK(m_mutex);
75 3026 : for (const auto& entry : m_map) {
76 1 : if (!--entry.second->count) m_list.erase(entry.second);
77 : }
78 3025 : m_map.clear();
79 3025 : }
80 :
81 1922679 : template<typename F> void Iterate(F&& f) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
82 : {
83 1922679 : WAIT_LOCK(m_mutex, lock);
84 18183620 : for (auto it = m_list.begin(); it != m_list.end();) {
85 16260941 : ++it->count;
86 : {
87 16260941 : REVERSE_LOCK(lock);
88 16260941 : f(*it->callbacks);
89 16260941 : }
90 16260941 : it = --it->count ? std::next(it) : m_list.erase(it);
91 : }
92 1922679 : }
93 : };
94 :
95 : static CMainSignals g_signals;
96 :
97 3207 : void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler)
98 : {
99 3207 : assert(!m_internals);
100 3207 : m_internals = std::make_unique<MainSignalsImpl>(scheduler);
101 3207 : }
102 :
103 3214 : void CMainSignals::UnregisterBackgroundSignalScheduler()
104 : {
105 3214 : m_internals.reset(nullptr);
106 3214 : }
107 :
108 6244 : void CMainSignals::FlushBackgroundCallbacks()
109 : {
110 6244 : if (m_internals) {
111 6230 : m_internals->m_schedulerClient.EmptyQueue();
112 6230 : }
113 6244 : }
114 :
115 280157 : size_t CMainSignals::CallbacksPending()
116 : {
117 280157 : if (!m_internals) return 0;
118 280157 : return m_internals->m_schedulerClient.CallbacksPending();
119 280157 : }
120 :
121 2218372 : CMainSignals& GetMainSignals()
122 : {
123 2218372 : return g_signals;
124 : }
125 :
126 277148 : void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
127 : {
128 : // Each connection captures the shared_ptr to ensure that each callback is
129 : // executed before the subscriber is destroyed. For more details see #18338.
130 277148 : g_signals.m_internals->Register(std::move(callbacks));
131 277148 : }
132 :
133 24291 : void RegisterValidationInterface(CValidationInterface* callbacks)
134 : {
135 : // Create a shared_ptr with a no-op deleter - CValidationInterface lifecycle
136 : // is managed by the caller.
137 48582 : RegisterSharedValidationInterface({callbacks, [](CValidationInterface*){}});
138 24291 : }
139 :
140 252856 : void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
141 : {
142 252856 : UnregisterValidationInterface(callbacks.get());
143 252856 : }
144 :
145 289347 : void UnregisterValidationInterface(CValidationInterface* callbacks)
146 : {
147 289347 : if (g_signals.m_internals) {
148 289344 : g_signals.m_internals->Unregister(callbacks);
149 289344 : }
150 289347 : }
151 :
152 3032 : void UnregisterAllValidationInterfaces()
153 : {
154 3032 : if (!g_signals.m_internals) {
155 7 : return;
156 : }
157 3025 : g_signals.m_internals->Clear();
158 3032 : }
159 :
160 38780 : void CallFunctionInValidationInterfaceQueue(std::function<void()> func)
161 : {
162 38780 : g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func));
163 38780 : }
164 :
165 27756 : void SyncWithValidationInterfaceQueue()
166 : {
167 27756 : AssertLockNotHeld(cs_main);
168 : // Block until the validation queue drains
169 27756 : std::promise<void> promise;
170 55512 : CallFunctionInValidationInterfaceQueue([&promise] {
171 27756 : promise.set_value();
172 27756 : });
173 27756 : promise.get_future().wait();
174 27756 : }
175 :
176 : // Use a macro instead of a function for conditional logging to prevent
177 : // evaluating arguments when logging is not enabled.
178 : //
179 : // NOTE: The lambda captures all local variables by value.
180 : #define ENQUEUE_AND_LOG_EVENT(event, fmt, name, ...) \
181 : do { \
182 : auto local_name = (name); \
183 : LOG_EVENT("Enqueuing " fmt, local_name, __VA_ARGS__); \
184 : m_internals->m_schedulerClient.AddToProcessQueue([=] { \
185 : LOG_EVENT(fmt, local_name, __VA_ARGS__); \
186 : event(); \
187 : }); \
188 : } while (0)
189 :
190 : #define LOG_EVENT(fmt, ...) \
191 : LogPrint(BCLog::VALIDATION, fmt "\n", __VA_ARGS__)
192 :
193 245027 : void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
194 : // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
195 : // the chain actually updates. One way to ensure this is for the caller to invoke this signal
196 : // in the same critical section where the chain is updated
197 :
198 490054 : auto event = [pindexNew, pindexFork, fInitialDownload, this] {
199 2308764 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); });
200 245027 : };
201 490054 : ENQUEUE_AND_LOG_EVENT(event, "%s: new block hash=%s fork block hash=%s (in IBD=%s)", __func__,
202 : pindexNew->GetBlockHash().ToString(),
203 : pindexFork ? pindexFork->GetBlockHash().ToString() : "null",
204 : fInitialDownload);
205 245027 : }
206 :
207 2831 : void CMainSignals::InitializeCurrentBlockTip(const CBlockIndex* tip, bool ibd) {
208 27349 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.InitializeCurrentBlockTip(tip, ibd); });
209 2831 : }
210 :
211 245027 : void CMainSignals::SynchronousUpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
212 2309275 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.SynchronousUpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); });
213 245027 : }
214 :
215 36886 : void CMainSignals::TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime, uint64_t mempool_sequence) {
216 73772 : auto event = [tx, nAcceptTime, mempool_sequence, this] {
217 346214 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionAddedToMempool(tx, nAcceptTime, mempool_sequence); });
218 36886 : };
219 73772 : ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s", __func__,
220 : tx->GetHash().ToString());
221 36886 : }
222 :
223 416 : void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {
224 832 : auto event = [tx, reason, mempool_sequence, this] {
225 3232 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionRemovedFromMempool(tx, reason, mempool_sequence); });
226 416 : };
227 832 : ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s reason=%s", __func__,
228 : tx->GetHash().ToString(),
229 : RemovalReasonToString(reason));
230 416 : }
231 :
232 253165 : void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex) {
233 506330 : auto event = [pblock, pindex, this] {
234 2378044 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockConnected(pblock, pindex); });
235 253165 : };
236 506330 : ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s block height=%d", __func__,
237 : pblock->GetHash().ToString(),
238 : pindex->nHeight);
239 253165 : }
240 :
241 14623 : void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex* pindex) {
242 29246 : auto event = [pblock, pindex, this] {
243 136692 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockDisconnected(pblock, pindex); });
244 14623 : };
245 29246 : ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s block height=%d", __func__,
246 : pblock->GetHash().ToString(),
247 : pindex->nHeight);
248 14623 : }
249 :
250 7520 : void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
251 12169 : auto event = [locator, this] {
252 29874 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.ChainStateFlushed(locator); });
253 4649 : };
254 19689 : ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s", __func__,
255 : locator.IsNull() ? "null" : locator.vHave.front().ToString());
256 7520 : }
257 :
258 261260 : void CMainSignals::BlockChecked(const CBlock& block, const BlockValidationState& state) {
259 261260 : LOG_EVENT("%s: block hash=%s state=%s", __func__,
260 : block.GetHash().ToString(), state.ToString());
261 2418833 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockChecked(block, state); });
262 261260 : }
263 :
264 224672 : void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &block) {
265 224672 : LOG_EVENT("%s: block hash=%s", __func__, block->GetHash().ToString());
266 2113593 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NewPoWValidBlock(pindex, block); });
267 224672 : }
268 :
269 269010 : void CMainSignals::AcceptedBlockHeader(const CBlockIndex *pindexNew) {
270 269010 : LOG_EVENT("%s: accepted block header hash=%s", __func__, pindexNew->GetBlockHash().ToString());
271 2523990 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.AcceptedBlockHeader(pindexNew); });
272 269010 : }
273 :
274 216239 : void CMainSignals::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) {
275 216239 : LOG_EVENT("%s: accepted block header hash=%s initial=%d", __func__, pindexNew->GetBlockHash().ToString(), fInitialDownload);
276 2029650 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyHeaderTip(pindexNew, fInitialDownload); });
277 216239 : }
278 :
279 820 : void CMainSignals::NotifyTransactionLock(const CTransactionRef &tx, const std::shared_ptr<const instantsend::InstantSendLock>& islock) {
280 1640 : auto event = [tx, islock, this] {
281 8776 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyTransactionLock(tx, islock); });
282 820 : };
283 1640 : ENQUEUE_AND_LOG_EVENT(event, "%s: transaction lock txid=%s", __func__,
284 : tx->GetHash().ToString());
285 820 : }
286 :
287 13549 : void CMainSignals::NotifyChainLock(const CBlockIndex* pindex, const std::shared_ptr<const chainlock::ChainLockSig>& clsig, const std::string& id) {
288 27098 : auto event = [pindex, clsig, this] {
289 147266 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyChainLock(pindex, clsig); });
290 13549 : };
291 27098 : ENQUEUE_AND_LOG_EVENT(event, "%s: notify chainlock at block=%s cl=%s", __func__,
292 : pindex->GetBlockHash().ToString(),
293 : id);
294 13549 : }
295 :
296 1480 : void CMainSignals::NotifyGovernanceVote(const std::shared_ptr<CDeterministicMNList>& tip_mn_list, const std::shared_ptr<const CGovernanceVote>& vote, const std::string& id) {
297 2960 : auto event = [vote, tip_mn_list, this] {
298 16024 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyGovernanceVote(tip_mn_list, vote); });
299 1480 : };
300 2960 : ENQUEUE_AND_LOG_EVENT(event, "%s: notify governance vote: %s", __func__, id);
301 1480 : }
302 :
303 300 : void CMainSignals::NotifyGovernanceObject(const std::shared_ptr<const Governance::Object>& object, const std::string& id) {
304 600 : auto event = [object, this] {
305 3248 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyGovernanceObject(object); });
306 300 : };
307 600 : ENQUEUE_AND_LOG_EVENT(event, "%s: notify governance object: %s", __func__, id);
308 300 : }
309 :
310 2 : void CMainSignals::NotifyInstantSendDoubleSpendAttempt(const CTransactionRef& currentTx, const CTransactionRef& previousTx) {
311 4 : auto event = [currentTx, previousTx, this] {
312 20 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyInstantSendDoubleSpendAttempt(currentTx, previousTx); });
313 2 : };
314 4 : ENQUEUE_AND_LOG_EVENT(event, "%s: notify instant doublespendattempt currenttxid=%s previoustxid=%s", __func__,
315 : currentTx->GetHash().ToString(),
316 : previousTx->GetHash().ToString());
317 2 : }
318 :
319 27218 : void CMainSignals::NotifyRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& sig, const std::string& id, bool proactive_relay) {
320 54436 : auto event = [sig, proactive_relay, this] {
321 299110 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyRecoveredSig(sig, proactive_relay); });
322 27218 : };
323 54436 : ENQUEUE_AND_LOG_EVENT(event, "%s: notify recoveredsig=%s", __func__,
324 : id);
325 27218 : }
326 :
327 105505 : void CMainSignals::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {
328 105505 : LOG_EVENT("%s: notify mn list changed undo=%d", __func__, undo);
329 1083666 : m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NotifyMasternodeListChanged(undo, oldMNList, diff); });
330 105505 : }
|