@@ -753,7 +753,7 @@ bool CWallet::IsSpent(const COutPoint& outpoint) const
753753 const auto mit = mapWallet.find (wtxid);
754754 if (mit != mapWallet.end ()) {
755755 const auto & wtx = mit->second ;
756- if (!wtx.isAbandoned () && !wtx.isBlockConflicted ())
756+ if (!wtx.isAbandoned () && !wtx.isBlockConflicted () && !wtx. isMempoolConflicted () )
757757 return true ; // Spent
758758 }
759759 }
@@ -1360,7 +1360,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
13601360void CWallet::RecursiveUpdateTxState (const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
13611361 // Do not flush the wallet here for performance reasons
13621362 WalletBatch batch (GetDatabase (), false );
1363+ RecursiveUpdateTxState (&batch, tx_hash, try_updating_state);
1364+ }
13631365
1366+ void CWallet::RecursiveUpdateTxState (WalletBatch* batch, const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
13641367 std::set<uint256> todo;
13651368 std::set<uint256> done;
13661369
@@ -1377,7 +1380,7 @@ void CWallet::RecursiveUpdateTxState(const uint256& tx_hash, const TryUpdatingSt
13771380 TxUpdate update_state = try_updating_state (wtx);
13781381 if (update_state != TxUpdate::UNCHANGED) {
13791382 wtx.MarkDirty ();
1380- batch. WriteTx (wtx);
1383+ if ( batch) batch-> WriteTx (wtx);
13811384 // Iterate over all its outputs, and update those tx states as well (if applicable)
13821385 for (unsigned int i = 0 ; i < wtx.tx ->vout .size (); ++i) {
13831386 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range (COutPoint (Txid::FromUint256 (now), i));
@@ -1418,6 +1421,20 @@ void CWallet::transactionAddedToMempool(const CTransactionRef& tx) {
14181421 if (it != mapWallet.end ()) {
14191422 RefreshMempoolStatus (it->second , chain ());
14201423 }
1424+
1425+ const Txid& txid = tx->GetHash ();
1426+
1427+ for (const CTxIn& tx_in : tx->vin ) {
1428+ // For each wallet transaction spending this prevout..
1429+ for (auto range = mapTxSpends.equal_range (tx_in.prevout ); range.first != range.second ; range.first ++) {
1430+ const uint256& spent_id = range.first ->second ;
1431+ // Skip the recently added tx
1432+ if (spent_id == txid) continue ;
1433+ RecursiveUpdateTxState (/* batch=*/ nullptr , spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED (cs_wallet) {
1434+ return wtx.mempool_conflicts .insert (txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1435+ });
1436+ }
1437+ }
14211438}
14221439
14231440void CWallet::transactionRemovedFromMempool (const CTransactionRef& tx, MemPoolRemovalReason reason) {
@@ -1455,6 +1472,21 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe
14551472 // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
14561473 SyncTransaction (tx, TxStateInactive{});
14571474 }
1475+
1476+ const Txid& txid = tx->GetHash ();
1477+
1478+ for (const CTxIn& tx_in : tx->vin ) {
1479+ // Iterate over all wallet transactions spending txin.prev
1480+ // and recursively mark them as no longer conflicting with
1481+ // txid
1482+ for (auto range = mapTxSpends.equal_range (tx_in.prevout ); range.first != range.second ; range.first ++) {
1483+ const uint256& spent_id = range.first ->second ;
1484+
1485+ RecursiveUpdateTxState (/* batch=*/ nullptr , spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED (cs_wallet) {
1486+ return wtx.mempool_conflicts .erase (txid) ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
1487+ });
1488+ }
1489+ }
14581490}
14591491
14601492void CWallet::blockConnected (ChainstateRole role, const interfaces::BlockInfo& block)
0 commit comments