0diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
1index 85827115a3..1cbbd43d35 100644
2--- a/src/validationinterface.cpp
3+++ b/src/validationinterface.cpp
4@@ -157,15 +157,17 @@ void ValidationSignals::SyncWithValidationInterfaceQueue()
5 // Use a macro instead of a function for conditional logging to prevent
6 // evaluating arguments when logging is not enabled.
7 //
8-// NOTE: The lambda captures the event by move and all other variables by value.
9-#define ENQUEUE_AND_LOG_EVENT(event, fmt, name, ...) \
10- do { \
11- auto local_name = (name); \
12- LOG_EVENT("Enqueuing " fmt, local_name, __VA_ARGS__); \
13- m_internals->m_task_runner->insert([=, event = std::move(event)] { \
14- LOG_EVENT(fmt, local_name, __VA_ARGS__); \
15- event(); \
16- }); \
17+// NOTE: The lambda captures all local variables by value.
18+#define ENQUEUE_AND_LOG_EVENT(event, fmt, name, ...) \
19+ do { \
20+ static_assert(std::is_rvalue_reference_v<decltype((event))>, \
21+ "event must be passed as an rvalue"); \
22+ auto local_name = (name); \
23+ LOG_EVENT("Enqueuing " fmt, local_name, __VA_ARGS__); \
24+ m_internals->m_task_runner->insert([=, local_event = (event)] { \
25+ LOG_EVENT(fmt, local_name, __VA_ARGS__); \
26+ local_event(); \
27+ }); \
28 } while (0)
29
30 #define LOG_EVENT(fmt, ...) \
31@@ -179,7 +181,7 @@ void ValidationSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlo
32 auto event = [pindexNew, pindexFork, fInitialDownload, this] {
33 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); });
34 };
35- ENQUEUE_AND_LOG_EVENT(event, "%s: new block hash=%s fork block hash=%s (in IBD=%s)", __func__,
36+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: new block hash=%s fork block hash=%s (in IBD=%s)", __func__,
37 pindexNew->GetBlockHash().ToString(),
38 pindexFork ? pindexFork->GetBlockHash().ToString() : "null",
39 fInitialDownload);
40@@ -196,7 +198,7 @@ void ValidationSignals::TransactionAddedToMempool(const NewMempoolTransactionInf
41 auto event = [tx, mempool_sequence, this] {
42 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionAddedToMempool(tx, mempool_sequence); });
43 };
44- ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s wtxid=%s", __func__,
45+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: txid=%s wtxid=%s", __func__,
46 tx.info.m_tx->GetHash().ToString(),
47 tx.info.m_tx->GetWitnessHash().ToString());
48 }
49@@ -205,7 +207,7 @@ void ValidationSignals::TransactionRemovedFromMempool(const CTransactionRef& tx,
50 auto event = [tx, reason, mempool_sequence, this] {
51 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.TransactionRemovedFromMempool(tx, reason, mempool_sequence); });
52 };
53- ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s wtxid=%s reason=%s", __func__,
54+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: txid=%s wtxid=%s reason=%s", __func__,
55 tx->GetHash().ToString(),
56 tx->GetWitnessHash().ToString(),
57 RemovalReasonToString(reason));
58@@ -217,7 +219,7 @@ void ValidationSignals::BlockConnected(const ChainstateRole& role, std::shared_p
59 auto event = [role, pblock = std::move(pblock), pindex, this] {
60 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockConnected(role, pblock, pindex); });
61 };
62- ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s block height=%d", __func__,
63+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: block hash=%s block height=%d", __func__,
64 block_hash,
65 pindex->nHeight);
66 }
67@@ -227,7 +229,7 @@ void ValidationSignals::MempoolTransactionsRemovedForBlock(const std::vector<Rem
68 auto event = [txs_removed_for_block, nBlockHeight, this] {
69 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight); });
70 };
71- ENQUEUE_AND_LOG_EVENT(event, "%s: block height=%s txs removed=%s", __func__,
72+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: block height=%s txs removed=%s", __func__,
73 nBlockHeight,
74 txs_removed_for_block.size());
75 }
76@@ -238,7 +240,7 @@ void ValidationSignals::BlockDisconnected(std::shared_ptr<const CBlock> pblock,
77 auto event = [pblock = std::move(pblock), pindex, this] {
78 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.BlockDisconnected(pblock, pindex); });
79 };
80- ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s block height=%d", __func__,
81+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: block hash=%s block height=%d", __func__,
82 block_hash,
83 pindex->nHeight);
84 }
85@@ -248,7 +250,7 @@ void ValidationSignals::ChainStateFlushed(const ChainstateRole& role, const CBlo
86 auto event = [role, locator, this] {
87 m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.ChainStateFlushed(role, locator); });
88 };
89- ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s", __func__,
90+ ENQUEUE_AND_LOG_EVENT(std::move(event), "%s: block hash=%s", __func__,
91 locator.IsNull() ? "null" : locator.vHave.front().ToString());
92 }
93