1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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.
6 #include <validationinterface.h>
9 #include <primitives/block.h>
10 #include <scheduler.h>
12 #include <txmempool.h>
14 #include <validation.h>
20 #include <boost/signals2/signal.hpp>
22 struct MainSignalsInstance
{
23 boost::signals2::signal
<void (const CBlockIndex
*, const CBlockIndex
*, bool fInitialDownload
)> UpdatedBlockTip
;
24 boost::signals2::signal
<void (const CTransactionRef
&)> TransactionAddedToMempool
;
25 boost::signals2::signal
<void (const std::shared_ptr
<const CBlock
> &, const CBlockIndex
*pindex
, const std::vector
<CTransactionRef
>&)> BlockConnected
;
26 boost::signals2::signal
<void (const std::shared_ptr
<const CBlock
> &)> BlockDisconnected
;
27 boost::signals2::signal
<void (const CTransactionRef
&)> TransactionRemovedFromMempool
;
28 boost::signals2::signal
<void (const CBlockLocator
&)> SetBestChain
;
29 boost::signals2::signal
<void (const uint256
&)> Inventory
;
30 boost::signals2::signal
<void (int64_t nBestBlockTime
, CConnman
* connman
)> Broadcast
;
31 boost::signals2::signal
<void (const CBlock
&, const CValidationState
&)> BlockChecked
;
32 boost::signals2::signal
<void (const CBlockIndex
*, const std::shared_ptr
<const CBlock
>&)> NewPoWValidBlock
;
34 // We are not allowed to assume the scheduler only runs in one thread,
35 // but must ensure all callbacks happen in-order, so we end up creating
36 // our own queue here :(
37 SingleThreadedSchedulerClient m_schedulerClient
;
39 explicit MainSignalsInstance(CScheduler
*pscheduler
) : m_schedulerClient(pscheduler
) {}
42 static CMainSignals g_signals
;
44 void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler
& scheduler
) {
46 m_internals
.reset(new MainSignalsInstance(&scheduler
));
49 void CMainSignals::UnregisterBackgroundSignalScheduler() {
50 m_internals
.reset(nullptr);
53 void CMainSignals::FlushBackgroundCallbacks() {
55 m_internals
->m_schedulerClient
.EmptyQueue();
59 size_t CMainSignals::CallbacksPending() {
60 if (!m_internals
) return 0;
61 return m_internals
->m_schedulerClient
.CallbacksPending();
64 void CMainSignals::RegisterWithMempoolSignals(CTxMemPool
& pool
) {
65 pool
.NotifyEntryRemoved
.connect(boost::bind(&CMainSignals::MempoolEntryRemoved
, this, _1
, _2
));
68 void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool
& pool
) {
69 pool
.NotifyEntryRemoved
.disconnect(boost::bind(&CMainSignals::MempoolEntryRemoved
, this, _1
, _2
));
72 CMainSignals
& GetMainSignals()
77 void RegisterValidationInterface(CValidationInterface
* pwalletIn
) {
78 g_signals
.m_internals
->UpdatedBlockTip
.connect(boost::bind(&CValidationInterface::UpdatedBlockTip
, pwalletIn
, _1
, _2
, _3
));
79 g_signals
.m_internals
->TransactionAddedToMempool
.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool
, pwalletIn
, _1
));
80 g_signals
.m_internals
->BlockConnected
.connect(boost::bind(&CValidationInterface::BlockConnected
, pwalletIn
, _1
, _2
, _3
));
81 g_signals
.m_internals
->BlockDisconnected
.connect(boost::bind(&CValidationInterface::BlockDisconnected
, pwalletIn
, _1
));
82 g_signals
.m_internals
->TransactionRemovedFromMempool
.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool
, pwalletIn
, _1
));
83 g_signals
.m_internals
->SetBestChain
.connect(boost::bind(&CValidationInterface::SetBestChain
, pwalletIn
, _1
));
84 g_signals
.m_internals
->Inventory
.connect(boost::bind(&CValidationInterface::Inventory
, pwalletIn
, _1
));
85 g_signals
.m_internals
->Broadcast
.connect(boost::bind(&CValidationInterface::ResendWalletTransactions
, pwalletIn
, _1
, _2
));
86 g_signals
.m_internals
->BlockChecked
.connect(boost::bind(&CValidationInterface::BlockChecked
, pwalletIn
, _1
, _2
));
87 g_signals
.m_internals
->NewPoWValidBlock
.connect(boost::bind(&CValidationInterface::NewPoWValidBlock
, pwalletIn
, _1
, _2
));
90 void UnregisterValidationInterface(CValidationInterface
* pwalletIn
) {
91 g_signals
.m_internals
->BlockChecked
.disconnect(boost::bind(&CValidationInterface::BlockChecked
, pwalletIn
, _1
, _2
));
92 g_signals
.m_internals
->Broadcast
.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions
, pwalletIn
, _1
, _2
));
93 g_signals
.m_internals
->Inventory
.disconnect(boost::bind(&CValidationInterface::Inventory
, pwalletIn
, _1
));
94 g_signals
.m_internals
->SetBestChain
.disconnect(boost::bind(&CValidationInterface::SetBestChain
, pwalletIn
, _1
));
95 g_signals
.m_internals
->TransactionAddedToMempool
.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool
, pwalletIn
, _1
));
96 g_signals
.m_internals
->BlockConnected
.disconnect(boost::bind(&CValidationInterface::BlockConnected
, pwalletIn
, _1
, _2
, _3
));
97 g_signals
.m_internals
->BlockDisconnected
.disconnect(boost::bind(&CValidationInterface::BlockDisconnected
, pwalletIn
, _1
));
98 g_signals
.m_internals
->TransactionRemovedFromMempool
.disconnect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool
, pwalletIn
, _1
));
99 g_signals
.m_internals
->UpdatedBlockTip
.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip
, pwalletIn
, _1
, _2
, _3
));
100 g_signals
.m_internals
->NewPoWValidBlock
.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock
, pwalletIn
, _1
, _2
));
103 void UnregisterAllValidationInterfaces() {
104 if (!g_signals
.m_internals
) {
107 g_signals
.m_internals
->BlockChecked
.disconnect_all_slots();
108 g_signals
.m_internals
->Broadcast
.disconnect_all_slots();
109 g_signals
.m_internals
->Inventory
.disconnect_all_slots();
110 g_signals
.m_internals
->SetBestChain
.disconnect_all_slots();
111 g_signals
.m_internals
->TransactionAddedToMempool
.disconnect_all_slots();
112 g_signals
.m_internals
->BlockConnected
.disconnect_all_slots();
113 g_signals
.m_internals
->BlockDisconnected
.disconnect_all_slots();
114 g_signals
.m_internals
->TransactionRemovedFromMempool
.disconnect_all_slots();
115 g_signals
.m_internals
->UpdatedBlockTip
.disconnect_all_slots();
116 g_signals
.m_internals
->NewPoWValidBlock
.disconnect_all_slots();
119 void CallFunctionInValidationInterfaceQueue(std::function
<void ()> func
) {
120 g_signals
.m_internals
->m_schedulerClient
.AddToProcessQueue(std::move(func
));
123 void SyncWithValidationInterfaceQueue() {
124 AssertLockNotHeld(cs_main
);
125 // Block until the validation queue drains
126 std::promise
<void> promise
;
127 CallFunctionInValidationInterfaceQueue([&promise
] {
130 promise
.get_future().wait();
133 void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx
, MemPoolRemovalReason reason
) {
134 if (reason
!= MemPoolRemovalReason::BLOCK
&& reason
!= MemPoolRemovalReason::CONFLICT
) {
135 m_internals
->m_schedulerClient
.AddToProcessQueue([ptx
, this] {
136 m_internals
->TransactionRemovedFromMempool(ptx
);
141 void CMainSignals::UpdatedBlockTip(const CBlockIndex
*pindexNew
, const CBlockIndex
*pindexFork
, bool fInitialDownload
) {
142 m_internals
->m_schedulerClient
.AddToProcessQueue([pindexNew
, pindexFork
, fInitialDownload
, this] {
143 m_internals
->UpdatedBlockTip(pindexNew
, pindexFork
, fInitialDownload
);
147 void CMainSignals::TransactionAddedToMempool(const CTransactionRef
&ptx
) {
148 m_internals
->m_schedulerClient
.AddToProcessQueue([ptx
, this] {
149 m_internals
->TransactionAddedToMempool(ptx
);
153 void CMainSignals::BlockConnected(const std::shared_ptr
<const CBlock
> &pblock
, const CBlockIndex
*pindex
, const std::shared_ptr
<const std::vector
<CTransactionRef
>>& pvtxConflicted
) {
154 m_internals
->m_schedulerClient
.AddToProcessQueue([pblock
, pindex
, pvtxConflicted
, this] {
155 m_internals
->BlockConnected(pblock
, pindex
, *pvtxConflicted
);
159 void CMainSignals::BlockDisconnected(const std::shared_ptr
<const CBlock
> &pblock
) {
160 m_internals
->m_schedulerClient
.AddToProcessQueue([pblock
, this] {
161 m_internals
->BlockDisconnected(pblock
);
165 void CMainSignals::SetBestChain(const CBlockLocator
&locator
) {
166 m_internals
->m_schedulerClient
.AddToProcessQueue([locator
, this] {
167 m_internals
->SetBestChain(locator
);
171 void CMainSignals::Inventory(const uint256
&hash
) {
172 m_internals
->m_schedulerClient
.AddToProcessQueue([hash
, this] {
173 m_internals
->Inventory(hash
);
177 void CMainSignals::Broadcast(int64_t nBestBlockTime
, CConnman
* connman
) {
178 m_internals
->Broadcast(nBestBlockTime
, connman
);
181 void CMainSignals::BlockChecked(const CBlock
& block
, const CValidationState
& state
) {
182 m_internals
->BlockChecked(block
, state
);
185 void CMainSignals::NewPoWValidBlock(const CBlockIndex
*pindex
, const std::shared_ptr
<const CBlock
> &block
) {
186 m_internals
->NewPoWValidBlock(pindex
, block
);