Coverage Report

Created: 2026-10-07 13:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/validationinterface.cpp
Line
Count
Source
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-present 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 <chain.h>
9
#include <consensus/validation.h>
10
#include <kernel/mempool_entry.h>
11
#include <kernel/mempool_removal_reason.h>
12
#include <kernel/types.h>
13
#include <primitives/block.h>
14
#include <primitives/transaction.h>
15
#include <util/check.h>
16
#include <util/log.h>
17
#include <util/task_runner.h>
18
19
#include <future>
20
#include <memory>
21
#include <unordered_map>
22
#include <utility>
23
24
using kernel::ChainstateRole;
25
26
/**
27
 * ValidationSignalsImpl manages a list of shared_ptr<CValidationInterface> callbacks.
28
 *
29
 * A std::unordered_map is used to track what callbacks are currently
30
 * registered, and a std::list is used to store the callbacks that are
31
 * currently registered as well as any callbacks that are just unregistered
32
 * and about to be deleted when they are done executing.
33
 */
34
class ValidationSignalsImpl
35
{
36
private:
37
    Mutex m_mutex;
38
    //! List entries consist of a callback pointer and reference count. The
39
    //! count is equal to the number of current executions of that entry, plus 1
40
    //! if it's registered. It cannot be 0 because that would imply it is
41
    //! unregistered and also not being executed (so shouldn't exist).
42
    struct ListEntry { std::shared_ptr<CValidationInterface> callbacks; int count = 1; };
43
    std::list<ListEntry> m_list GUARDED_BY(m_mutex);
44
    std::unordered_map<CValidationInterface*, std::list<ListEntry>::iterator> m_map GUARDED_BY(m_mutex);
45
46
public:
47
    std::unique_ptr<util::TaskRunnerInterface> m_task_runner;
48
49
    explicit ValidationSignalsImpl(std::unique_ptr<util::TaskRunnerInterface> task_runner)
50
1.41k
        : m_task_runner{std::move(Assert(task_runner))} {}
51
52
    void Register(std::shared_ptr<CValidationInterface> callbacks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
53
260k
    {
54
260k
        LOCK(m_mutex);
55
260k
        auto inserted = m_map.emplace(callbacks.get(), m_list.end());
56
260k
        if (inserted.second) inserted.first->second = m_list.emplace(m_list.end());
57
260k
        inserted.first->second->callbacks = std::move(callbacks);
58
260k
    }
59
60
    void Unregister(CValidationInterface* callbacks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
61
261k
    {
62
261k
        LOCK(m_mutex);
63
261k
        auto it = m_map.find(callbacks);
64
261k
        if (it != m_map.end()) {
65
260k
            if (!--it->second->count) m_list.erase(it->second);
66
260k
            m_map.erase(it);
67
260k
        }
68
261k
    }
69
70
    //! Clear unregisters every previously registered callback, erasing every
71
    //! map entry. After this call, the list may still contain callbacks that
72
    //! are currently executing, but it will be cleared when they are done
73
    //! executing.
74
    void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
75
1.22k
    {
76
1.22k
        LOCK(m_mutex);
77
1.22k
        for (const auto& entry : m_map) {
78
1
            if (!--entry.second->count) m_list.erase(entry.second);
79
1
        }
80
1.22k
        m_map.clear();
81
1.22k
    }
82
83
    template<typename F> void Iterate(F&& f) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
84
649k
    {
85
649k
        WAIT_LOCK(m_mutex, lock);
86
2.30M
        for (auto it = m_list.begin(); it != m_list.end();) {
87
1.65M
            ++it->count;
88
1.65M
            {
89
1.65M
                REVERSE_LOCK(lock, m_mutex);
90
1.65M
                f(*it->callbacks);
91
1.65M
            }
92
1.65M
            it = --it->count ? std::next(it) : m_list.erase(it);
93
1.65M
        }
94
649k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::UpdatedBlockTip(CBlockIndex const*, CBlockIndex const*, bool)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::UpdatedBlockTip(CBlockIndex const*, CBlockIndex const*, bool)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
97.5k
    {
85
97.5k
        WAIT_LOCK(m_mutex, lock);
86
355k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
257k
            ++it->count;
88
257k
            {
89
257k
                REVERSE_LOCK(lock, m_mutex);
90
257k
                f(*it->callbacks);
91
257k
            }
92
257k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
257k
        }
94
97.5k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::ActiveTipChange(CBlockIndex const&, bool)::$_0>(ValidationSignals::ActiveTipChange(CBlockIndex const&, bool)::$_0&&)
Line
Count
Source
84
100k
    {
85
100k
        WAIT_LOCK(m_mutex, lock);
86
369k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
268k
            ++it->count;
88
268k
            {
89
268k
                REVERSE_LOCK(lock, m_mutex);
90
268k
                f(*it->callbacks);
91
268k
            }
92
268k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
268k
        }
94
100k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::TransactionAddedToMempool(NewMempoolTransactionInfo const&, unsigned long)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::TransactionAddedToMempool(NewMempoolTransactionInfo const&, unsigned long)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
27.7k
    {
85
27.7k
        WAIT_LOCK(m_mutex, lock);
86
91.8k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
64.0k
            ++it->count;
88
64.0k
            {
89
64.0k
                REVERSE_LOCK(lock, m_mutex);
90
64.0k
                f(*it->callbacks);
91
64.0k
            }
92
64.0k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
64.0k
        }
94
27.7k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::TransactionRemovedFromMempool(std::shared_ptr<CTransaction const> const&, MemPoolRemovalReason, unsigned long)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::TransactionRemovedFromMempool(std::shared_ptr<CTransaction const> const&, MemPoolRemovalReason, unsigned long)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
2.17k
    {
85
2.17k
        WAIT_LOCK(m_mutex, lock);
86
6.68k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
4.51k
            ++it->count;
88
4.51k
            {
89
4.51k
                REVERSE_LOCK(lock, m_mutex);
90
4.51k
                f(*it->callbacks);
91
4.51k
            }
92
4.51k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
4.51k
        }
94
2.17k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::BlockConnected(kernel::ChainstateRole const&, std::shared_ptr<CBlock const>, CBlockIndex const*)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::BlockConnected(kernel::ChainstateRole const&, std::shared_ptr<CBlock const>, CBlockIndex const*)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
106k
    {
85
106k
        WAIT_LOCK(m_mutex, lock);
86
384k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
278k
            ++it->count;
88
278k
            {
89
278k
                REVERSE_LOCK(lock, m_mutex);
90
278k
                f(*it->callbacks);
91
278k
            }
92
278k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
278k
        }
94
106k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::MempoolTransactionsRemovedForBlock(std::shared_ptr<CBlock const>, std::vector<RemovedMempoolTransactionInfo, std::allocator<RemovedMempoolTransactionInfo>>, unsigned int)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::MempoolTransactionsRemovedForBlock(std::shared_ptr<CBlock const>, std::vector<RemovedMempoolTransactionInfo, std::allocator<RemovedMempoolTransactionInfo>>, unsigned int)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
87.7k
    {
85
87.7k
        WAIT_LOCK(m_mutex, lock);
86
322k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
234k
            ++it->count;
88
234k
            {
89
234k
                REVERSE_LOCK(lock, m_mutex);
90
234k
                f(*it->callbacks);
91
234k
            }
92
234k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
234k
        }
94
87.7k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::BlockDisconnected(std::shared_ptr<CBlock const>, CBlockIndex const*)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::BlockDisconnected(std::shared_ptr<CBlock const>, CBlockIndex const*)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
9.69k
    {
85
9.69k
        WAIT_LOCK(m_mutex, lock);
86
29.6k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
19.9k
            ++it->count;
88
19.9k
            {
89
19.9k
                REVERSE_LOCK(lock, m_mutex);
90
19.9k
                f(*it->callbacks);
91
19.9k
            }
92
19.9k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
19.9k
        }
94
9.69k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::ChainStateFlushed(kernel::ChainstateRole const&, CBlockLocator const&)::$_0::operator()() const::'lambda'(CValidationInterface&)>(ValidationSignals::ChainStateFlushed(kernel::ChainstateRole const&, CBlockLocator const&)::$_0::operator()() const::'lambda'(CValidationInterface&)&&)
Line
Count
Source
84
2.50k
    {
85
2.50k
        WAIT_LOCK(m_mutex, lock);
86
6.57k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
4.07k
            ++it->count;
88
4.07k
            {
89
4.07k
                REVERSE_LOCK(lock, m_mutex);
90
4.07k
                f(*it->callbacks);
91
4.07k
            }
92
4.07k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
4.07k
        }
94
2.50k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::BlockChecked(std::shared_ptr<CBlock const> const&, BlockValidationState const&)::$_0>(ValidationSignals::BlockChecked(std::shared_ptr<CBlock const> const&, BlockValidationState const&)::$_0&&)
Line
Count
Source
84
135k
    {
85
135k
        WAIT_LOCK(m_mutex, lock);
86
435k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
299k
            ++it->count;
88
299k
            {
89
299k
                REVERSE_LOCK(lock, m_mutex);
90
299k
                f(*it->callbacks);
91
299k
            }
92
299k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
299k
        }
94
135k
    }
validationinterface.cpp:void ValidationSignalsImpl::Iterate<ValidationSignals::NewPoWValidBlock(CBlockIndex const*, std::shared_ptr<CBlock const> const&)::$_0>(ValidationSignals::NewPoWValidBlock(CBlockIndex const*, std::shared_ptr<CBlock const> const&)::$_0&&)
Line
Count
Source
84
80.7k
    {
85
80.7k
        WAIT_LOCK(m_mutex, lock);
86
302k
        for (auto it = m_list.begin(); it != m_list.end();) {
87
222k
            ++it->count;
88
222k
            {
89
222k
                REVERSE_LOCK(lock, m_mutex);
90
222k
                f(*it->callbacks);
91
222k
            }
92
222k
            it = --it->count ? std::next(it) : m_list.erase(it);
93
222k
        }
94
80.7k
    }
95
};
96
97
ValidationSignals::ValidationSignals(std::unique_ptr<util::TaskRunnerInterface> task_runner)
98
1.41k
    : m_internals{std::make_unique<ValidationSignalsImpl>(std::move(task_runner))} {}
99
100
1.41k
ValidationSignals::~ValidationSignals() = default;
101
102
void ValidationSignals::FlushBackgroundCallbacks()
103
1.41k
{
104
1.41k
    m_internals->m_task_runner->flush();
105
1.41k
}
106
107
size_t ValidationSignals::CallbacksPending()
108
130k
{
109
130k
    return m_internals->m_task_runner->size();
110
130k
}
111
112
void ValidationSignals::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
113
260k
{
114
    // Each connection captures the shared_ptr to ensure that each callback is
115
    // executed before the subscriber is destroyed. For more details see #18338.
116
260k
    m_internals->Register(std::move(callbacks));
117
260k
}
118
119
void ValidationSignals::RegisterValidationInterface(CValidationInterface* callbacks)
120
2.40k
{
121
    // Create a shared_ptr with a no-op deleter - CValidationInterface lifecycle
122
    // is managed by the caller.
123
2.40k
    RegisterSharedValidationInterface({callbacks, [](CValidationInterface*){}});
124
2.40k
}
125
126
void ValidationSignals::UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
127
258k
{
128
258k
    UnregisterValidationInterface(callbacks.get());
129
258k
}
130
131
void ValidationSignals::UnregisterValidationInterface(CValidationInterface* callbacks)
132
261k
{
133
261k
    m_internals->Unregister(callbacks);
134
261k
}
135
136
void ValidationSignals::UnregisterAllValidationInterfaces()
137
1.22k
{
138
1.22k
    m_internals->Clear();
139
1.22k
}
140
141
void ValidationSignals::CallFunctionInValidationInterfaceQueue(std::function<void()> func)
142
28.8k
{
143
28.8k
    m_internals->m_task_runner->insert(std::move(func));
144
28.8k
}
145
146
void ValidationSignals::SyncWithValidationInterfaceQueue()
147
28.8k
{
148
28.8k
    AssertLockNotHeld(cs_main);
149
    // Block until the validation queue drains
150
28.8k
    std::promise<void> promise;
151
28.8k
    CallFunctionInValidationInterfaceQueue([&promise] {
152
28.8k
        promise.set_value();
153
28.8k
    });
154
28.8k
    promise.get_future().wait();
155
28.8k
}
156
157
// Use a macro instead of a function for conditional logging to prevent
158
// evaluating arguments when logging is not enabled.
159
#define ENQUEUE_AND_LOG_EVENT(event, log_msg)                                                                    \
160
334k
    do {                                                                                                         \
161
334k
        static_assert(std::is_rvalue_reference_v<decltype((event))>,                                             \
162
334k
                      "event must be passed as an rvalue");                                                      \
163
334k
        static_assert(std::is_rvalue_reference_v<decltype((log_msg))>,                                           \
164
334k
                      "log_msg must be passed as an rvalue");                                                    \
165
334k
        auto enqueue_log_msg = (log_msg);                                                                        \
166
334k
        LOG_EVENT("Enqueuing %s", enqueue_log_msg);                                                              \
167
334k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
333k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
333k
            local_event();                                                                                       \
170
333k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::UpdatedBlockTip(CBlockIndex const*, CBlockIndex const*, bool)::$_1::operator()() const
Line
Count
Source
167
97.5k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
97.5k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
97.5k
            local_event();                                                                                       \
170
97.5k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::TransactionAddedToMempool(NewMempoolTransactionInfo const&, unsigned long)::$_1::operator()() const
Line
Count
Source
167
27.7k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
27.7k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
27.7k
            local_event();                                                                                       \
170
27.7k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::TransactionRemovedFromMempool(std::shared_ptr<CTransaction const> const&, MemPoolRemovalReason, unsigned long)::$_1::operator()() const
Line
Count
Source
167
2.17k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
2.17k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
2.17k
            local_event();                                                                                       \
170
2.17k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::BlockConnected(kernel::ChainstateRole const&, std::shared_ptr<CBlock const>, CBlockIndex const*)::$_1::operator()() const
Line
Count
Source
167
106k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
106k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
106k
            local_event();                                                                                       \
170
106k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::MempoolTransactionsRemovedForBlock(std::shared_ptr<CBlock const>, std::vector<RemovedMempoolTransactionInfo, std::allocator<RemovedMempoolTransactionInfo>>, unsigned int)::$_1::operator()() const
Line
Count
Source
167
87.7k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
87.7k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
87.7k
            local_event();                                                                                       \
170
87.7k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::BlockDisconnected(std::shared_ptr<CBlock const>, CBlockIndex const*)::$_1::operator()() const
Line
Count
Source
167
9.69k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
9.69k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
9.69k
            local_event();                                                                                       \
170
9.69k
        });                                                                                                      \
validationinterface.cpp:ValidationSignals::ChainStateFlushed(kernel::ChainstateRole const&, CBlockLocator const&)::$_1::operator()() const
Line
Count
Source
167
2.50k
        m_internals->m_task_runner->insert([local_log_msg = std::move(enqueue_log_msg), local_event = (event)] { \
168
2.50k
            LOG_EVENT("%s", local_log_msg);                                                                      \
169
2.50k
            local_event();                                                                                       \
170
2.50k
        });                                                                                                      \
171
334k
    } while (0)
172
173
#define LOG_MSG(fmt, ...) \
174
334k
    (util::log::ShouldDebugLog(BCLog::VALIDATION) ? tfm::format((fmt), __VA_ARGS__) : std::string{})
175
176
#define LOG_EVENT(fmt, ...) \
177
984k
    LogDebug(BCLog::VALIDATION, fmt, __VA_ARGS__)
178
179
97.5k
void ValidationSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
180
    // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
181
    // the chain actually updates. One way to ensure this is for the caller to invoke this signal
182
    // in the same critical section where the chain is updated
183
184
97.5k
    auto log_msg = LOG_MSG("%s: new block hash=%s fork block hash=%s (in IBD=%s)", __func__,
185
97.5k
                          pindexNew->GetBlockHash().ToString(),
186
97.5k
                          pindexFork ? pindexFork->GetBlockHash().ToString() : "null",
187
97.5k
                          fInitialDownload);
188
97.5k
    auto event = [pindexNew, pindexFork, fInitialDownload, this] {
189
257k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); });
190
97.5k
    };
191
97.5k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
192
97.5k
}
193
194
void ValidationSignals::ActiveTipChange(const CBlockIndex& new_tip, bool is_ibd)
195
100k
{
196
100k
    LOG_EVENT("%s: new block hash=%s block height=%d", __func__, new_tip.GetBlockHash().ToString(), new_tip.nHeight);
197
268k
    m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.ActiveTipChange(new_tip, is_ibd); });
198
100k
}
199
200
void ValidationSignals::TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t mempool_sequence)
201
27.7k
{
202
27.7k
    auto log_msg = LOG_MSG("%s: txid=%s wtxid=%s", __func__,
203
27.7k
                          tx.info.m_tx->GetHash().ToString(),
204
27.7k
                          tx.info.m_tx->GetWitnessHash().ToString());
205
27.7k
    auto event = [tx, mempool_sequence, this] {
206
64.0k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionAddedToMempool(tx, mempool_sequence); });
207
27.7k
    };
208
27.7k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
209
27.7k
}
210
211
2.17k
void ValidationSignals::TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {
212
2.17k
    auto log_msg = LOG_MSG("%s: txid=%s wtxid=%s reason=%s", __func__,
213
2.17k
                          tx->GetHash().ToString(),
214
2.17k
                          tx->GetWitnessHash().ToString(),
215
2.17k
                          RemovalReasonToString(reason));
216
2.17k
    auto event = [tx, reason, mempool_sequence, this] {
217
4.51k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionRemovedFromMempool(tx, reason, mempool_sequence); });
218
2.17k
    };
219
2.17k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
220
2.17k
}
221
222
void ValidationSignals::BlockConnected(const ChainstateRole& role, std::shared_ptr<const CBlock> pblock, const CBlockIndex* pindex)
223
106k
{
224
106k
    auto log_msg = LOG_MSG("%s: block hash=%s block height=%d", __func__,
225
106k
                          pblock->GetHash().ToString(),
226
106k
                          pindex->nHeight);
227
106k
    auto event = [role, pblock = std::move(pblock), pindex, this] {
228
278k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockConnected(role, pblock, pindex); });
229
106k
    };
230
106k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
231
106k
}
232
233
void ValidationSignals::MempoolTransactionsRemovedForBlock(std::shared_ptr<const CBlock> block, std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block, unsigned int block_height)
234
87.7k
{
235
87.7k
    Assume(block);
236
87.7k
    auto log_msg = LOG_MSG("%s: block hash=%s block height=%s txs removed=%s block txs=%s", __func__,
237
87.7k
                           block->GetHash().ToString(),
238
87.7k
                           block_height,
239
87.7k
                           txs_removed_for_block.size(),
240
87.7k
                           block->vtx.size());
241
87.7k
    auto event = [block = std::move(block), txs_removed_for_block = std::move(txs_removed_for_block), block_height, this] {
242
234k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.MempoolTransactionsRemovedForBlock(block, txs_removed_for_block, block_height); });
243
87.7k
    };
244
87.7k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
245
87.7k
}
246
247
void ValidationSignals::BlockDisconnected(std::shared_ptr<const CBlock> pblock, const CBlockIndex* pindex)
248
9.69k
{
249
9.69k
    auto log_msg = LOG_MSG("%s: block hash=%s block height=%d", __func__,
250
9.69k
                          pblock->GetHash().ToString(),
251
9.69k
                          pindex->nHeight);
252
9.69k
    auto event = [pblock = std::move(pblock), pindex, this] {
253
19.9k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockDisconnected(pblock, pindex); });
254
9.69k
    };
255
9.69k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
256
9.69k
}
257
258
void ValidationSignals::ChainStateFlushed(const ChainstateRole& role, const CBlockLocator& locator)
259
3.63k
{
260
3.63k
    auto log_msg = LOG_MSG("%s: block hash=%s", __func__,
261
3.63k
                          locator.IsNull() ? "null" : locator.vHave.front().ToString());
262
3.63k
    auto event = [role, locator, this] {
263
4.07k
        m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.ChainStateFlushed(role, locator); });
264
2.50k
    };
265
3.63k
    ENQUEUE_AND_LOG_EVENT(std::move(event), std::move(log_msg));
266
3.63k
}
267
268
void ValidationSignals::BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& state)
269
135k
{
270
135k
    LOG_EVENT("%s: block hash=%s state=%s", __func__,
271
135k
              block->GetHash().ToString(), state.ToString());
272
299k
    m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockChecked(block, state); });
273
135k
}
274
275
80.7k
void ValidationSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &block) {
276
80.7k
    LOG_EVENT("%s: block hash=%s", __func__, block->GetHash().ToString());
277
222k
    m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NewPoWValidBlock(pindex, block); });
278
80.7k
}