Coverage Report

Created: 2025-06-10 13:21

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