Skip to content

Commit f404334

Browse files
committed
Handle SyncTransaction in ActivateBestChain instead of ConnectTrace
This makes a later change to move it all into one per-block callback simpler.
1 parent a147687 commit f404334

File tree

1 file changed

+48
-26
lines changed

1 file changed

+48
-26
lines changed

src/validation.cpp

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,22 +2174,35 @@ static int64_t nTimeFlush = 0;
21742174
static int64_t nTimeChainState = 0;
21752175
static int64_t nTimePostConnect = 0;
21762176

2177+
struct PerBlockConnectTrace {
2178+
CBlockIndex* pindex = NULL;
2179+
std::shared_ptr<const CBlock> pblock;
2180+
std::shared_ptr<std::vector<CTransactionRef>> conflictedTxs;
2181+
PerBlockConnectTrace() : conflictedTxs(std::make_shared<std::vector<CTransactionRef>>()) {}
2182+
};
21772183
/**
21782184
* Used to track blocks whose transactions were applied to the UTXO state as a
21792185
* part of a single ActivateBestChainStep call.
21802186
*
21812187
* This class also tracks transactions that are removed from the mempool as
21822188
* conflicts (per block) and can be used to pass all those transactions
21832189
* through SyncTransaction.
2190+
*
2191+
* This class assumes (and asserts) that the conflicted transactions for a given
2192+
* block are added via mempool callbacks prior to the BlockConnected() associated
2193+
* with those transactions. If any transactions are marked conflicted, it is
2194+
* assumed that an associated block will always be added.
2195+
*
2196+
* This class is single-use, once you call GetBlocksConnected() you have to throw
2197+
* it away and make a new one.
21842198
*/
21852199
class ConnectTrace {
21862200
private:
2187-
std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > > blocksConnected;
2188-
std::vector<std::vector<CTransactionRef> > conflictedTxs;
2201+
std::vector<PerBlockConnectTrace> blocksConnected;
21892202
CTxMemPool &pool;
21902203

21912204
public:
2192-
ConnectTrace(CTxMemPool &_pool) : conflictedTxs(1), pool(_pool) {
2205+
ConnectTrace(CTxMemPool &_pool) : blocksConnected(1), pool(_pool) {
21932206
pool.NotifyEntryRemoved.connect(boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2));
21942207
}
21952208

@@ -2198,29 +2211,32 @@ class ConnectTrace {
21982211
}
21992212

22002213
void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
2201-
blocksConnected.emplace_back(pindex, std::move(pblock));
2202-
conflictedTxs.emplace_back();
2203-
}
2204-
2205-
std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > >& GetBlocksConnected() {
2214+
assert(!blocksConnected.back().pindex);
2215+
assert(pindex);
2216+
assert(pblock);
2217+
blocksConnected.back().pindex = pindex;
2218+
blocksConnected.back().pblock = std::move(pblock);
2219+
blocksConnected.emplace_back();
2220+
}
2221+
2222+
std::vector<PerBlockConnectTrace>& GetBlocksConnected() {
2223+
// We always keep one extra block at the end of our list because
2224+
// blocks are added after all the conflicted transactions have
2225+
// been filled in. Thus, the last entry should always be an empty
2226+
// one waiting for the transactions from the next block. We pop
2227+
// the last entry here to make sure the list we return is sane.
2228+
assert(!blocksConnected.back().pindex);
2229+
assert(blocksConnected.back().conflictedTxs->empty());
2230+
blocksConnected.pop_back();
22062231
return blocksConnected;
22072232
}
22082233

22092234
void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) {
2235+
assert(!blocksConnected.back().pindex);
22102236
if (reason == MemPoolRemovalReason::CONFLICT) {
2211-
conflictedTxs.back().push_back(txRemoved);
2237+
blocksConnected.back().conflictedTxs->emplace_back(std::move(txRemoved));
22122238
}
22132239
}
2214-
2215-
void CallSyncTransactionOnConflictedTransactions() {
2216-
for (const auto& txRemovedForBlock : conflictedTxs) {
2217-
for (const auto& tx : txRemovedForBlock) {
2218-
GetMainSignals().SyncTransaction(*tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
2219-
}
2220-
}
2221-
conflictedTxs.clear();
2222-
conflictedTxs.emplace_back();
2223-
}
22242240
};
22252241

22262242
/**
@@ -2495,9 +2511,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
24952511
pindexFork = chainActive.FindFork(pindexOldTip);
24962512
fInitialDownload = IsInitialBlockDownload();
24972513

2498-
// throw all transactions though the signal-interface
2499-
connectTrace.CallSyncTransactionOnConflictedTransactions();
2500-
25012514
// TODO: Temporarily ensure that mempool removals are notified before
25022515
// connected transactions. This shouldn't matter, but the abandoned
25032516
// state of transactions in our wallet is currently cleared when we
@@ -2506,12 +2519,21 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
25062519
// to abandon a transaction and then have it inadvertently cleared by
25072520
// the notification that the conflicted transaction was evicted.
25082521

2522+
// throw all transactions though the signal-interface
2523+
auto blocksConnected = connectTrace.GetBlocksConnected();
2524+
for (const PerBlockConnectTrace& trace : blocksConnected) {
2525+
assert(trace.conflictedTxs);
2526+
for (const auto& tx : *trace.conflictedTxs) {
2527+
GetMainSignals().SyncTransaction(*tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
2528+
}
2529+
}
2530+
25092531
// Transactions in the connected block are notified
2510-
for (const auto& pair : connectTrace.GetBlocksConnected()) {
2511-
assert(pair.second);
2512-
const CBlock& block = *(pair.second);
2532+
for (const PerBlockConnectTrace& trace : blocksConnected) {
2533+
assert(trace.pblock && trace.pindex);
2534+
const CBlock& block = *(trace.pblock);
25132535
for (unsigned int i = 0; i < block.vtx.size(); i++)
2514-
GetMainSignals().SyncTransaction(*block.vtx[i], pair.first, i);
2536+
GetMainSignals().SyncTransaction(*block.vtx[i], trace.pindex, i);
25152537
}
25162538
}
25172539
// When we reach this point, we switched to a new tip (stored in pindexNewTip).

0 commit comments

Comments
 (0)