Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ void PrepareShutdown()
// Disconnect all slots
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);

#ifndef WIN32
try {
Expand Down Expand Up @@ -1253,7 +1252,6 @@ bool AppInitMain()
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
GetMainSignals().RegisterWithMempoolSignals(mempool);

// Initialize Sapling circuit parameters
LoadSaplingParams();
Expand Down
3 changes: 1 addition & 2 deletions src/test/librust/sapling_rpc_wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,7 @@ BOOST_AUTO_TEST_CASE(rpc_shieldsendmany_taddr_to_sapling)
chainActive.SetTip(&fakeIndex);
BOOST_CHECK(chainActive.Contains(&fakeIndex));
BOOST_CHECK_EQUAL(1, chainActive.Height());
std::vector<CTransactionRef> vtxConflicted;
pwalletMain->BlockConnected(std::make_shared<CBlock>(block), mi->second, vtxConflicted);
pwalletMain->BlockConnected(std::make_shared<CBlock>(block), mi->second);
BOOST_CHECK_MESSAGE(pwalletMain->GetAvailableBalance() > 0, "tx not confirmed");

// Context that shieldsendmany requires
Expand Down
3 changes: 1 addition & 2 deletions src/test/librust/sapling_wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,7 @@ BOOST_AUTO_TEST_CASE(SaplingNullifierIsSpent) {
BOOST_CHECK(chainActive.Contains(&fakeIndex));
BOOST_CHECK_EQUAL(0, chainActive.Height());

std::vector<CTransactionRef> vtxConflicted;
wallet.BlockConnected(std::make_shared<CBlock>(block), mi->second, vtxConflicted);
wallet.BlockConnected(std::make_shared<CBlock>(block), mi->second);

// Verify note has been spent
BOOST_CHECK(wallet.GetSaplingScriptPubKeyMan()->IsSaplingSpent(nullifier));
Expand Down
2 changes: 1 addition & 1 deletion src/test/policyestimator_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(policyestimator_tests, BasicTestingSetup)
BOOST_FIXTURE_TEST_SUITE(policyestimator_tests, TestingSetup)

BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
Expand Down
2 changes: 0 additions & 2 deletions src/test/test_pivx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ TestingSetup::TestingSetup()
// callbacks via CValidationInterface are unreliable, but that's OK,
// our unit tests aren't testing multiple parts of the code at once.
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
GetMainSignals().RegisterWithMempoolSignals(mempool);

// Ideally we'd move all the RPC tests to the functional testing framework
// instead of unit tests, but for now we need these here.
Expand Down Expand Up @@ -102,7 +101,6 @@ TestingSetup::~TestingSetup()
GetMainSignals().FlushBackgroundCallbacks();
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);
UnloadBlockIndex();
delete pcoinsTip;
delete pcoinsdbview;
Expand Down
3 changes: 2 additions & 1 deletion src/test/validation_block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct TestSubscriber : public CValidationInterface {
BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash());
}

void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex, const std::vector<CTransactionRef>& txnConflicted)
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
{
BOOST_CHECK_EQUAL(m_expected_tip, block->hashPrevBlock);
BOOST_CHECK_EQUAL(m_expected_tip, pindex->pprev->GetBlockHash());
Expand Down Expand Up @@ -170,6 +170,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
MilliSleep(100);
}

SyncWithValidationInterfaceQueue();
UnregisterValidationInterface(&sub);

BOOST_CHECK_EQUAL(sub.m_expected_tip, WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash()));
Expand Down
11 changes: 9 additions & 2 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "utiltime.h"
#include "version.h"
#include "validation.h"
#include "validationinterface.h"



Expand Down Expand Up @@ -370,7 +371,6 @@ void CTxMemPool::AddTransactionsUpdated(unsigned int n)

bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fCurrentEstimate)
{
NotifyEntryAdded(entry.GetSharedTx());
// Add to memory pool without checking anything.
// Used by AcceptToMemoryPool(), which DOES do all the appropriate checks.
LOCK(cs);
Expand Down Expand Up @@ -434,7 +434,14 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,

void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
{
NotifyEntryRemoved(it->GetSharedTx(), reason);
if (reason != MemPoolRemovalReason::BLOCK) {
// Notify clients that a transaction has been removed from the mempool
// for any reason except being included in a block. Clients interested
// in transactions included in blocks can subscribe to the BlockConnected
// notification.
GetMainSignals().TransactionRemovedFromMempool(it->GetSharedTx(), reason);
}

AssertLockHeld(cs);
const CTransaction& tx = it->GetTx();
for (const CTxIn& txin : tx.vin)
Expand Down
5 changes: 0 additions & 5 deletions src/txmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#include "boost/multi_index/hashed_index.hpp"
#include <boost/multi_index/sequenced_index.hpp>

#include <boost/signals2/signal.hpp>

class CAutoFile;

inline double AllowFreeThreshold()
Expand Down Expand Up @@ -684,9 +682,6 @@ class CTxMemPool

size_t DynamicMemoryUsage() const;

boost::signals2::signal<void (CTransactionRef)> NotifyEntryAdded;
boost::signals2::signal<void (CTransactionRef, MemPoolRemovalReason)> NotifyEntryRemoved;

private:
/** UpdateForDescendants is used by UpdateTransactionsFromBlock to update
* the descendants for a single transaction that has been added to the
Expand Down
34 changes: 4 additions & 30 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2011,39 +2011,21 @@ static int64_t nTimePostConnect = 0;
struct PerBlockConnectTrace {
CBlockIndex* pindex = nullptr;
std::shared_ptr<const CBlock> pblock;
std::shared_ptr<std::vector<CTransactionRef>> conflictedTxs;
PerBlockConnectTrace() : conflictedTxs(std::make_shared<std::vector<CTransactionRef>>()) {}
PerBlockConnectTrace() {}
};
/**
* Used to track blocks whose transactions were applied to the UTXO state as a
* part of a single ActivateBestChainStep call.
*
* This class also tracks transactions that are removed from the mempool as
* conflicts (per block) and can be used to pass all those transactions
* through SyncTransaction.
*
* This class assumes (and asserts) that the conflicted transactions for a given
* block are added via mempool callbacks prior to the BlockConnected() associated
* with those transactions. If any transactions are marked conflicted, it is
* assumed that an associated block will always be added.
*
* This class is single-use, once you call GetBlocksConnected() you have to throw
* it away and make a new one.
*/
class ConnectTrace {
private:
std::vector<PerBlockConnectTrace> blocksConnected;
CTxMemPool &pool;
std::unique_ptr<interfaces::Handler> m_handler_notify_entry_removed;

public:
ConnectTrace(CTxMemPool &_pool) : blocksConnected(1), pool(_pool) {
m_handler_notify_entry_removed = interfaces::MakeHandler(pool.NotifyEntryRemoved.connect(std::bind(&ConnectTrace::NotifyEntryRemoved, this, std::placeholders::_1, std::placeholders::_2)));
}

~ConnectTrace() {
m_handler_notify_entry_removed->disconnect();
}
ConnectTrace() : blocksConnected(1) {}

void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
assert(!blocksConnected.back().pindex);
Expand All @@ -2061,17 +2043,9 @@ class ConnectTrace {
// one waiting for the transactions from the next block. We pop
// the last entry here to make sure the list we return is sane.
assert(!blocksConnected.back().pindex);
assert(blocksConnected.back().conflictedTxs->empty());
blocksConnected.pop_back();
return blocksConnected;
}

void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) {
assert(!blocksConnected.back().pindex);
if (reason == MemPoolRemovalReason::CONFLICT) {
blocksConnected.back().conflictedTxs->emplace_back(std::move(txRemoved));
}
}
};

/**
Expand Down Expand Up @@ -2353,7 +2327,7 @@ bool ActivateBestChain(CValidationState& state, std::shared_ptr<const CBlock> pb
do {
// We absolutely may not unlock cs_main until we've made forward progress
// (with the exception of shutdown due to hardware issues, low disk space, etc).
ConnectTrace connectTrace(mempool); // Destructed before cs_main is unlocked
ConnectTrace connectTrace; // Destructed before cs_main is unlocked

if (pindexMostWork == nullptr) {
pindexMostWork = FindMostWorkChain();
Expand All @@ -2378,7 +2352,7 @@ bool ActivateBestChain(CValidationState& state, std::shared_ptr<const CBlock> pb

for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) {
assert(trace.pblock && trace.pindex);
GetMainSignals().BlockConnected(trace.pblock, trace.pindex, trace.conflictedTxs);
GetMainSignals().BlockConnected(trace.pblock, trace.pindex);
}
} while (!chainActive.Tip() || (starting_tip && CBlockIndexWorkComparator()(chainActive.Tip(), starting_tip)));
if (!blocks_connected) return true;
Expand Down
37 changes: 13 additions & 24 deletions src/validationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "validationinterface.h"
#include "scheduler.h"
#include "txmempool.h"
#include "validation.h"

#include <future>
Expand Down Expand Up @@ -35,11 +34,11 @@ struct MainSignalsInstance {
* Notifies listeners of a block being connected.
* Provides a vector of transactions evicted from the mempool as a result.
*/
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef> &)> BlockConnected;
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex)> BlockConnected;
/** Notifies listeners of a block being disconnected */
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const uint256& blockHash, int nBlockHeight, int64_t blockTime)> BlockDisconnected;
/** Notifies listeners of a transaction removal from the mempool */
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
boost::signals2::signal<void (const CTransactionRef &, MemPoolRemovalReason reason)> TransactionRemovedFromMempool;
/** Notifies listeners of a new active block chain. */
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
/** Tells listeners to broadcast their data. */
Expand Down Expand Up @@ -79,14 +78,6 @@ size_t CMainSignals::CallbacksPending() {
return m_internals->m_schedulerClient.CallbacksPending();
}

void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) {
pool.NotifyEntryRemoved.connect(std::bind(&CMainSignals::MempoolEntryRemoved, this, std::placeholders::_1, std::placeholders::_2));
}

void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) {
pool.NotifyEntryRemoved.disconnect_all_slots();
}

CMainSignals& GetMainSignals()
{
return g_signals;
Expand All @@ -97,9 +88,9 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn)
ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2));
conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect(std::bind(&CValidationInterface::BlockDisconnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1));
conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1, std::placeholders::_2));
conns.SetBestChain = g_signals.m_internals->SetBestChain.connect(std::bind(&CValidationInterface::SetBestChain, pwalletIn, std::placeholders::_1));
conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1));
conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
Expand Down Expand Up @@ -137,14 +128,6 @@ void SyncWithValidationInterfaceQueue() {
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, const CBlockIndex* pindexFork, bool fInitialDownload) {
// Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
// the chain actually updates. One way to ensure this is for the caller to invoke this signal
Expand All @@ -161,9 +144,15 @@ void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
});
}

void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) {
m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, pvtxConflicted, this] {
m_internals->BlockConnected(pblock, pindex, *pvtxConflicted);
void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef& ptx, MemPoolRemovalReason reason) {
m_internals->m_schedulerClient.AddToProcessQueue([ptx, reason, this] {
m_internals->TransactionRemovedFromMempool(ptx, reason);
});
}

void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex) {
m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, this] {
m_internals->BlockConnected(pblock, pindex);
});
}

Expand Down
45 changes: 30 additions & 15 deletions src/validationinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class CValidationInterface;
class CValidationState;
class uint256;
class CScheduler;
class CTxMemPool;
enum class MemPoolRemovalReason;

// These functions dispatch to one or all registered wallets
Expand Down Expand Up @@ -92,21 +91,43 @@ class CValidationInterface {
/**
* Notifies listeners of a transaction leaving mempool.
*
* This only fires for transactions which leave mempool because of expiry,
* size limiting, reorg (changes in lock times/coinbase/coinstake maturity), or
* replacement. This does not include any transactions which are included
* in BlockConnectedDisconnected either in block->vtx or in txnConflicted.
* This notification fires for transactions that are removed from the
* mempool for the following reasons:
*
* - EXPIRY (expired from mempool after -mempoolexpiry hours)
* - SIZELIMIT (removed in size limiting if the mempool exceeds -maxmempool megabytes)
* - REORG (removed during a reorg)
* - CONFLICT (removed because it conflicts with in-block transaction)
* - REPLACED (removed due to RBF replacement) -- not supported yet --
*
* This does not fire for transactions that are removed from the mempool
* because they have been included in a block. Any client that is interested
* in transactions removed from the mempool for inclusion in a block can learn
* about those transactions from the BlockConnected notification.
*
* Transactions that are removed from the mempool because they conflict
* with a transaction in the new block will have
* TransactionRemovedFromMempool events fired *before* the BlockConnected
* event is fired. If multiple blocks are connected in one step, then the
* ordering could be:
*
* - TransactionRemovedFromMempool(tx1 from block A)
* - TransactionRemovedFromMempool(tx2 from block A)
* - TransactionRemovedFromMempool(tx1 from block B)
* - TransactionRemovedFromMempool(tx2 from block B)
* - BlockConnected(A)
* - BlockConnected(B)
*
* Called on a background thread.
*/
virtual void TransactionRemovedFromMempool(const CTransactionRef &ptx) {}
virtual void TransactionRemovedFromMempool(const CTransactionRef &ptx, MemPoolRemovalReason reason) {}
/**
* Notifies listeners of a block being connected.
* Provides a vector of transactions evicted from the mempool as a result.
*
* Called on a background thread.
*/
virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, const std::vector<CTransactionRef> &txnConflicted) {}
virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex) {}
/**
* Notifies listeners of a block being disconnected
*
Expand All @@ -132,8 +153,6 @@ class CMainSignals {
private:
std::unique_ptr<MainSignalsInstance> m_internals;

void MempoolEntryRemoved(CTransactionRef tx, MemPoolRemovalReason reason);

friend void ::RegisterValidationInterface(CValidationInterface*);
friend void ::UnregisterValidationInterface(CValidationInterface*);
friend void ::UnregisterAllValidationInterfaces();
Expand All @@ -149,14 +168,10 @@ class CMainSignals {

size_t CallbacksPending();

/** Register with mempool to call TransactionRemovedFromMempool callbacks */
void RegisterWithMempoolSignals(CTxMemPool& pool);
/** Unregister with mempool */
void UnregisterWithMempoolSignals(CTxMemPool& pool);

void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void TransactionAddedToMempool(const CTransactionRef &ptxn);
void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason);
void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex);
void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const uint256& blockHash, int nBlockHeight, int64_t blockTime);
void SetBestChain(const CBlockLocator &);
void Broadcast(CConnman* connman);
Expand Down
Loading