Changeset View
Changeset View
Standalone View
Standalone View
src/validationinterface.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <validationinterface.h> | #include <validationinterface.h> | ||||
#include <primitives/block.h> | |||||
#include <scheduler.h> | #include <scheduler.h> | ||||
#include <txmempool.h> | |||||
#include <atomic> | #include <atomic> | ||||
#include <future> | #include <future> | ||||
#include <list> | #include <list> | ||||
#include <tuple> | #include <tuple> | ||||
#include <unordered_map> | |||||
#include <utility> | #include <utility> | ||||
#include <boost/signals2/signal.hpp> | #include <boost/signals2/signal.hpp> | ||||
struct ValidationInterfaceConnections { | struct ValidationInterfaceConnections { | ||||
boost::signals2::scoped_connection UpdatedBlockTip; | boost::signals2::scoped_connection UpdatedBlockTip; | ||||
boost::signals2::scoped_connection TransactionAddedToMempool; | boost::signals2::scoped_connection TransactionAddedToMempool; | ||||
boost::signals2::scoped_connection BlockConnected; | boost::signals2::scoped_connection BlockConnected; | ||||
Show All 33 Lines | std::unordered_map<CValidationInterface *, ValidationInterfaceConnections> | ||||
m_connMainSignals; | m_connMainSignals; | ||||
explicit MainSignalsInstance(CScheduler *pscheduler) | explicit MainSignalsInstance(CScheduler *pscheduler) | ||||
: m_schedulerClient(pscheduler) {} | : m_schedulerClient(pscheduler) {} | ||||
}; | }; | ||||
static CMainSignals g_signals; | static CMainSignals g_signals; | ||||
// This map has to be a separate global instead of a member of | |||||
// MainSignalsInstance, because RegisterWithMempoolSignals is currently called | |||||
// before RegisterBackgroundSignalScheduler, so MainSignalsInstance hasn't been | |||||
// created yet. | |||||
static std::unordered_map<CTxMemPool *, boost::signals2::scoped_connection> | |||||
g_connNotifyEntryRemoved; | |||||
void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler &scheduler) { | void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler &scheduler) { | ||||
assert(!m_internals); | assert(!m_internals); | ||||
m_internals.reset(new MainSignalsInstance(&scheduler)); | m_internals.reset(new MainSignalsInstance(&scheduler)); | ||||
} | } | ||||
void CMainSignals::UnregisterBackgroundSignalScheduler() { | void CMainSignals::UnregisterBackgroundSignalScheduler() { | ||||
m_internals.reset(nullptr); | m_internals.reset(nullptr); | ||||
} | } | ||||
void CMainSignals::FlushBackgroundCallbacks() { | void CMainSignals::FlushBackgroundCallbacks() { | ||||
if (m_internals) { | if (m_internals) { | ||||
m_internals->m_schedulerClient.EmptyQueue(); | m_internals->m_schedulerClient.EmptyQueue(); | ||||
} | } | ||||
} | } | ||||
size_t CMainSignals::CallbacksPending() { | size_t CMainSignals::CallbacksPending() { | ||||
if (!m_internals) { | if (!m_internals) { | ||||
return 0; | return 0; | ||||
} | } | ||||
return m_internals->m_schedulerClient.CallbacksPending(); | return m_internals->m_schedulerClient.CallbacksPending(); | ||||
} | } | ||||
void CMainSignals::RegisterWithMempoolSignals(CTxMemPool &pool) { | |||||
g_connNotifyEntryRemoved.emplace( | |||||
std::piecewise_construct, std::forward_as_tuple(&pool), | |||||
std::forward_as_tuple(pool.NotifyEntryRemoved.connect( | |||||
std::bind(&CMainSignals::MempoolEntryRemoved, this, | |||||
std::placeholders::_1, std::placeholders::_2)))); | |||||
} | |||||
void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool &pool) { | |||||
g_connNotifyEntryRemoved.erase(&pool); | |||||
} | |||||
CMainSignals &GetMainSignals() { | CMainSignals &GetMainSignals() { | ||||
return g_signals; | return g_signals; | ||||
} | } | ||||
void RegisterValidationInterface(CValidationInterface *pwalletIn) { | void RegisterValidationInterface(CValidationInterface *pwalletIn) { | ||||
ValidationInterfaceConnections &conns = | ValidationInterfaceConnections &conns = | ||||
g_signals.m_internals->m_connMainSignals[pwalletIn]; | g_signals.m_internals->m_connMainSignals[pwalletIn]; | ||||
conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect( | conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect( | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
void SyncWithValidationInterfaceQueue() { | void SyncWithValidationInterfaceQueue() { | ||||
AssertLockNotHeld(cs_main); | AssertLockNotHeld(cs_main); | ||||
// Block until the validation queue drains | // Block until the validation queue drains | ||||
std::promise<void> promise; | std::promise<void> promise; | ||||
CallFunctionInValidationInterfaceQueue([&promise] { promise.set_value(); }); | CallFunctionInValidationInterfaceQueue([&promise] { promise.set_value(); }); | ||||
promise.get_future().wait(); | promise.get_future().wait(); | ||||
} | } | ||||
void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, | |||||
MemPoolRemovalReason reason) { | |||||
if (reason != MemPoolRemovalReason::BLOCK && | |||||
reason != MemPoolRemovalReason::CONFLICT) { | |||||
m_internals->m_schedulerClient.AddToProcessQueue( | |||||
[ptx, this] { m_internals->TransactionRemovedFromMempool(ptx); }); | |||||
} | |||||
} | |||||
void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, | void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, | ||||
const CBlockIndex *pindexFork, | const CBlockIndex *pindexFork, | ||||
bool fInitialDownload) { | bool fInitialDownload) { | ||||
// Dependencies exist that require UpdatedBlockTip events to be delivered in | // Dependencies exist that require UpdatedBlockTip events to be delivered in | ||||
// the order in which the chain actually updates. One way to ensure this is | // the order in which the chain actually updates. One way to ensure this is | ||||
// for the caller to invoke this signal in the same critical section where | // for the caller to invoke this signal in the same critical section where | ||||
// the chain is updated | // the chain is updated | ||||
m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, | m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, | ||||
fInitialDownload, this] { | fInitialDownload, this] { | ||||
m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); | m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); | ||||
}); | }); | ||||
} | } | ||||
void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) { | void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) { | ||||
m_internals->m_schedulerClient.AddToProcessQueue( | m_internals->m_schedulerClient.AddToProcessQueue( | ||||
[ptx, this] { m_internals->TransactionAddedToMempool(ptx); }); | [ptx, this] { m_internals->TransactionAddedToMempool(ptx); }); | ||||
} | } | ||||
void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef &ptx) { | |||||
m_internals->m_schedulerClient.AddToProcessQueue( | |||||
[ptx, this] { m_internals->TransactionRemovedFromMempool(ptx); }); | |||||
} | |||||
void CMainSignals::BlockConnected( | void CMainSignals::BlockConnected( | ||||
const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, | const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, | ||||
const std::shared_ptr<const std::vector<CTransactionRef>> &pvtxConflicted) { | const std::shared_ptr<const std::vector<CTransactionRef>> &pvtxConflicted) { | ||||
m_internals->m_schedulerClient.AddToProcessQueue( | m_internals->m_schedulerClient.AddToProcessQueue( | ||||
[pblock, pindex, pvtxConflicted, this] { | [pblock, pindex, pvtxConflicted, this] { | ||||
m_internals->BlockConnected(pblock, pindex, *pvtxConflicted); | m_internals->BlockConnected(pblock, pindex, *pvtxConflicted); | ||||
}); | }); | ||||
} | } | ||||
Show All 21 Lines |