@ -157,6 +157,39 @@ namespace {
set < int > setDirtyFileInfo ;
set < int > setDirtyFileInfo ;
} // anon namespace
} // anon namespace
/* Use this class to start tracking transactions that are removed from the
* mempool and pass all those transactions through SyncTransaction when the
* object goes out of scope . This is currently only used to call SyncTransaction
* on conflicts removed from the mempool during block connection . Applied in
* ActivateBestChain around ActivateBestStep which in turn calls :
* ConnectTip - > removeForBlock - > removeConflicts
*/
class MemPoolConflictRemovalTracker
{
private :
std : : vector < CTransactionRef > conflictedTxs ;
CTxMemPool & pool ;
public :
MemPoolConflictRemovalTracker ( CTxMemPool & _pool ) : pool ( _pool ) {
pool . NotifyEntryRemoved . connect ( boost : : bind ( & MemPoolConflictRemovalTracker : : NotifyEntryRemoved , this , _1 , _2 ) ) ;
}
void NotifyEntryRemoved ( CTransactionRef txRemoved , MemPoolRemovalReason reason ) {
if ( reason = = MemPoolRemovalReason : : CONFLICT ) {
conflictedTxs . push_back ( txRemoved ) ;
}
}
~ MemPoolConflictRemovalTracker ( ) {
pool . NotifyEntryRemoved . disconnect ( boost : : bind ( & MemPoolConflictRemovalTracker : : NotifyEntryRemoved , this , _1 , _2 ) ) ;
for ( const auto & tx : conflictedTxs ) {
GetMainSignals ( ) . SyncTransaction ( * tx , NULL , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
}
conflictedTxs . clear ( ) ;
}
} ;
CBlockIndex * FindForkInGlobalIndex ( const CChain & chain , const CBlockLocator & locator )
CBlockIndex * FindForkInGlobalIndex ( const CChain & chain , const CBlockLocator & locator )
{
{
// Find the first block the caller has in the main chain
// Find the first block the caller has in the main chain
@ -2453,6 +2486,14 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
bool fInitialDownload ;
bool fInitialDownload ;
{
{
LOCK ( cs_main ) ;
LOCK ( cs_main ) ;
{ // TODO: Tempoarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
// receive another notification and there is a race condition where
// notification of a connected conflict might cause an outside process
// to abandon a transaction and then have it inadvertantly cleared by
// the notification that the conflicted transaction was evicted.
MemPoolConflictRemovalTracker mrt ( mempool ) ;
CBlockIndex * pindexOldTip = chainActive . Tip ( ) ;
CBlockIndex * pindexOldTip = chainActive . Tip ( ) ;
if ( pindexMostWork = = NULL ) {
if ( pindexMostWork = = NULL ) {
pindexMostWork = FindMostWorkChain ( ) ;
pindexMostWork = FindMostWorkChain ( ) ;
@ -2476,6 +2517,10 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
fInitialDownload = IsInitialBlockDownload ( ) ;
fInitialDownload = IsInitialBlockDownload ( ) ;
// throw all transactions though the signal-interface
// throw all transactions though the signal-interface
} // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified
// Transactions in the connnected block are notified
for ( const auto & pair : connectTrace . blocksConnected ) {
for ( const auto & pair : connectTrace . blocksConnected ) {
assert ( pair . second ) ;
assert ( pair . second ) ;
const CBlock & block = * ( pair . second ) ;
const CBlock & block = * ( pair . second ) ;