1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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>
18 #include <boost/signals2/signal.hpp>
20 struct MainSignalsInstance
{
21 boost::signals2::signal
<void (const CBlockIndex
*, const CBlockIndex
*, bool fInitialDownload
)> UpdatedBlockTip
;
22 boost::signals2::signal
<void (const CTransactionRef
&)> TransactionAddedToMempool
;
23 boost::signals2::signal
<void (const std::shared_ptr
<const CBlock
> &, const CBlockIndex
*pindex
, const std::vector
<CTransactionRef
>&)> BlockConnected
;
24 boost::signals2::signal
<void (const std::shared_ptr
<const CBlock
> &)> BlockDisconnected
;
25 boost::signals2::signal
<void (const CTransactionRef
&)> TransactionRemovedFromMempool
;
26 boost::signals2::signal
<void (const CBlockLocator
&)> SetBestChain
;
27 boost::signals2::signal
<void (const uint256
&)> Inventory
;
28 boost::signals2::signal
<void (int64_t nBestBlockTime
, CConnman
* connman
)> Broadcast
;
29 boost::signals2::signal
<void (const CBlock
&, const CValidationState
&)> BlockChecked
;
30 boost::signals2::signal
<void (const CBlockIndex
*, const std::shared_ptr
<const CBlock
>&)> NewPoWValidBlock
;
32 // We are not allowed to assume the scheduler only runs in one thread,
33 // but must ensure all callbacks happen in-order, so we end up creating
34 // our own queue here :(
35 SingleThreadedSchedulerClient m_schedulerClient
;
37 explicit MainSignalsInstance(CScheduler
*pscheduler
) : m_schedulerClient(pscheduler
) {}
40 static CMainSignals g_signals
;
42 void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler
& scheduler
) {
44 m_internals
.reset(new MainSignalsInstance(&scheduler
));
47 void CMainSignals::UnregisterBackgroundSignalScheduler() {
48 m_internals
.reset(nullptr);
51 void CMainSignals::FlushBackgroundCallbacks() {
53 m_internals
->m_schedulerClient
.EmptyQueue();
57 void CMainSignals::RegisterWithMempoolSignals(CTxMemPool
& pool
) {
58 pool
.NotifyEntryRemoved
.connect(boost::bind(&CMainSignals::MempoolEntryRemoved
, this, _1
, _2
));
61 void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool
& pool
) {
62 pool
.NotifyEntryRemoved
.disconnect(boost::bind(&CMainSignals::MempoolEntryRemoved
, this, _1
, _2
));
65 CMainSignals
& GetMainSignals()
70 void RegisterValidationInterface(CValidationInterface
* pwalletIn
) {
71 g_signals
.m_internals
->UpdatedBlockTip
.connect(boost::bind(&CValidationInterface::UpdatedBlockTip
, pwalletIn
, _1
, _2
, _3
));
72 g_signals
.m_internals
->TransactionAddedToMempool
.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool
, pwalletIn
, _1
));
73 g_signals
.m_internals
->BlockConnected
.connect(boost::bind(&CValidationInterface::BlockConnected
, pwalletIn
, _1
, _2
, _3
));
74 g_signals
.m_internals
->BlockDisconnected
.connect(boost::bind(&CValidationInterface::BlockDisconnected
, pwalletIn
, _1
));
75 g_signals
.m_internals
->TransactionRemovedFromMempool
.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool
, pwalletIn
, _1
));
76 g_signals
.m_internals
->SetBestChain
.connect(boost::bind(&CValidationInterface::SetBestChain
, pwalletIn
, _1
));
77 g_signals
.m_internals
->Inventory
.connect(boost::bind(&CValidationInterface::Inventory
, pwalletIn
, _1
));
78 g_signals
.m_internals
->Broadcast
.connect(boost::bind(&CValidationInterface::ResendWalletTransactions
, pwalletIn
, _1
, _2
));
79 g_signals
.m_internals
->BlockChecked
.connect(boost::bind(&CValidationInterface::BlockChecked
, pwalletIn
, _1
, _2
));
80 g_signals
.m_internals
->NewPoWValidBlock
.connect(boost::bind(&CValidationInterface::NewPoWValidBlock
, pwalletIn
, _1
, _2
));
83 void UnregisterValidationInterface(CValidationInterface
* pwalletIn
) {
84 g_signals
.m_internals
->BlockChecked
.disconnect(boost::bind(&CValidationInterface::BlockChecked
, pwalletIn
, _1
, _2
));
85 g_signals
.m_internals
->Broadcast
.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions
, pwalletIn
, _1
, _2
));
86 g_signals
.m_internals
->Inventory
.disconnect(boost::bind(&CValidationInterface::Inventory
, pwalletIn
, _1
));
87 g_signals
.m_internals
->SetBestChain
.disconnect(boost::bind(&CValidationInterface::SetBestChain
, pwalletIn
, _1
));
88 g_signals
.m_internals
->TransactionAddedToMempool
.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool
, pwalletIn
, _1
));
89 g_signals
.m_internals
->BlockConnected
.disconnect(boost::bind(&CValidationInterface::BlockConnected
, pwalletIn
, _1
, _2
, _3
));
90 g_signals
.m_internals
->BlockDisconnected
.disconnect(boost::bind(&CValidationInterface::BlockDisconnected
, pwalletIn
, _1
));
91 g_signals
.m_internals
->TransactionRemovedFromMempool
.disconnect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool
, pwalletIn
, _1
));
92 g_signals
.m_internals
->UpdatedBlockTip
.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip
, pwalletIn
, _1
, _2
, _3
));
93 g_signals
.m_internals
->NewPoWValidBlock
.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock
, pwalletIn
, _1
, _2
));
96 void UnregisterAllValidationInterfaces() {
97 if (!g_signals
.m_internals
) {
100 g_signals
.m_internals
->BlockChecked
.disconnect_all_slots();
101 g_signals
.m_internals
->Broadcast
.disconnect_all_slots();
102 g_signals
.m_internals
->Inventory
.disconnect_all_slots();
103 g_signals
.m_internals
->SetBestChain
.disconnect_all_slots();
104 g_signals
.m_internals
->TransactionAddedToMempool
.disconnect_all_slots();
105 g_signals
.m_internals
->BlockConnected
.disconnect_all_slots();
106 g_signals
.m_internals
->BlockDisconnected
.disconnect_all_slots();
107 g_signals
.m_internals
->TransactionRemovedFromMempool
.disconnect_all_slots();
108 g_signals
.m_internals
->UpdatedBlockTip
.disconnect_all_slots();
109 g_signals
.m_internals
->NewPoWValidBlock
.disconnect_all_slots();
112 void CallFunctionInValidationInterfaceQueue(std::function
<void ()> func
) {
113 g_signals
.m_internals
->m_schedulerClient
.AddToProcessQueue(std::move(func
));
116 void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx
, MemPoolRemovalReason reason
) {
117 if (reason
!= MemPoolRemovalReason::BLOCK
&& reason
!= MemPoolRemovalReason::CONFLICT
) {
118 m_internals
->m_schedulerClient
.AddToProcessQueue([ptx
, this] {
119 m_internals
->TransactionRemovedFromMempool(ptx
);
124 void CMainSignals::UpdatedBlockTip(const CBlockIndex
*pindexNew
, const CBlockIndex
*pindexFork
, bool fInitialDownload
) {
125 m_internals
->m_schedulerClient
.AddToProcessQueue([pindexNew
, pindexFork
, fInitialDownload
, this] {
126 m_internals
->UpdatedBlockTip(pindexNew
, pindexFork
, fInitialDownload
);
130 void CMainSignals::TransactionAddedToMempool(const CTransactionRef
&ptx
) {
131 m_internals
->m_schedulerClient
.AddToProcessQueue([ptx
, this] {
132 m_internals
->TransactionAddedToMempool(ptx
);
136 void CMainSignals::BlockConnected(const std::shared_ptr
<const CBlock
> &pblock
, const CBlockIndex
*pindex
, const std::shared_ptr
<const std::vector
<CTransactionRef
>>& pvtxConflicted
) {
137 m_internals
->m_schedulerClient
.AddToProcessQueue([pblock
, pindex
, pvtxConflicted
, this] {
138 m_internals
->BlockConnected(pblock
, pindex
, *pvtxConflicted
);
142 void CMainSignals::BlockDisconnected(const std::shared_ptr
<const CBlock
> &pblock
) {
143 m_internals
->m_schedulerClient
.AddToProcessQueue([pblock
, this] {
144 m_internals
->BlockDisconnected(pblock
);
148 void CMainSignals::SetBestChain(const CBlockLocator
&locator
) {
149 m_internals
->m_schedulerClient
.AddToProcessQueue([locator
, this] {
150 m_internals
->SetBestChain(locator
);
154 void CMainSignals::Inventory(const uint256
&hash
) {
155 m_internals
->m_schedulerClient
.AddToProcessQueue([hash
, this] {
156 m_internals
->Inventory(hash
);
160 void CMainSignals::Broadcast(int64_t nBestBlockTime
, CConnman
* connman
) {
161 m_internals
->Broadcast(nBestBlockTime
, connman
);
164 void CMainSignals::BlockChecked(const CBlock
& block
, const CValidationState
& state
) {
165 m_internals
->BlockChecked(block
, state
);
168 void CMainSignals::NewPoWValidBlock(const CBlockIndex
*pindex
, const std::shared_ptr
<const CBlock
> &block
) {
169 m_internals
->NewPoWValidBlock(pindex
, block
);