forked from bitcoin/bitcoin
/
validationinterface.cpp
146 lines (123 loc) · 7.09 KB
/
validationinterface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2017-2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "validationinterface.h"
#include "scheduler.h"
#include "sync.h"
#include "util.h"
#include <list>
#include <atomic>
#include <boost/signals2/signal.hpp>
struct MainSignalsInstance {
// XX42 boost::signals2::signal<void(const uint256&)> EraseTransaction;
/** Notifies listeners of updated block chain tip */
boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
/** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */
static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1;
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
boost::signals2::signal<void (const CTransaction &, const CBlockIndex *pindex, int posInBlock)> SyncTransaction;
/** Notifies listeners of an updated transaction lock without new data. */
boost::signals2::signal<void (const CTransaction &)> NotifyTransactionLock;
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<bool (const uint256 &)> UpdatedTransaction;
/** Notifies listeners of a new active block chain. */
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
/** Tells listeners to broadcast their data. */
boost::signals2::signal<void (CConnman* connman)> Broadcast;
/** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
/** Notifies listeners that a block has been successfully mined */
boost::signals2::signal<void (const uint256 &)> BlockFound;
/** Notifies listeners of a change to the tip of the active block chain. */
boost::signals2::signal<void (const CBlockIndex *, const CBlock *, Optional<SaplingMerkleTree>)> ChainTip;
// We are not allowed to assume the scheduler only runs in one thread,
// but must ensure all callbacks happen in-order, so we end up creating
// our own queue here :(
SingleThreadedSchedulerClient m_schedulerClient;
MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
};
static CMainSignals g_signals;
void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
assert(!m_internals);
m_internals.reset(new MainSignalsInstance(&scheduler));
}
void CMainSignals::UnregisterBackgroundSignalScheduler() {
m_internals.reset(nullptr);
}
void CMainSignals::FlushBackgroundCallbacks() {
if (m_internals) {
m_internals->m_schedulerClient.EmptyQueue();
}
}
CMainSignals& GetMainSignals()
{
return g_signals;
}
void RegisterValidationInterface(CValidationInterface* pwalletIn)
{
g_signals.m_internals->UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3));
g_signals.m_internals->ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1));
g_signals.m_internals->UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.m_internals->BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn)
{
g_signals.m_internals->BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1));
g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.m_internals->UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.m_internals->NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1));
g_signals.m_internals->SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3));
g_signals.m_internals->ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
}
void UnregisterAllValidationInterfaces()
{
if (!g_signals.m_internals) {
return;
}
g_signals.m_internals->BlockFound.disconnect_all_slots();
g_signals.m_internals->BlockChecked.disconnect_all_slots();
g_signals.m_internals->Broadcast.disconnect_all_slots();
g_signals.m_internals->SetBestChain.disconnect_all_slots();
g_signals.m_internals->UpdatedTransaction.disconnect_all_slots();
g_signals.m_internals->NotifyTransactionLock.disconnect_all_slots();
g_signals.m_internals->SyncTransaction.disconnect_all_slots();
g_signals.m_internals->ChainTip.disconnect_all_slots();
g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots();
}
void CMainSignals::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) {
m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
}
void CMainSignals::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) {
m_internals->SyncTransaction(tx, pindex, posInBlock);
}
void CMainSignals::NotifyTransactionLock(const CTransaction& tx) {
m_internals->NotifyTransactionLock(tx);
}
void CMainSignals::UpdatedTransaction(const uint256& hash) {
m_internals->UpdatedTransaction(hash);
}
void CMainSignals::SetBestChain(const CBlockLocator& locator) {
m_internals->SetBestChain(locator);
}
void CMainSignals::Broadcast(CConnman* connman) {
m_internals->Broadcast(connman);
}
void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
m_internals->BlockChecked(block, state);
}
void CMainSignals::BlockFound(const uint256& hash) {
m_internals->BlockFound(hash);
}
void CMainSignals::ChainTip(const CBlockIndex* pindex, const CBlock* block, Optional<SaplingMerkleTree> tree) {
m_internals->ChainTip(pindex, block, tree);
}