@@ -753,7 +753,7 @@ bool CWallet::IsSpent(const COutPoint& outpoint) const
753
753
const auto mit = mapWallet.find (wtxid);
754
754
if (mit != mapWallet.end ()) {
755
755
const auto & wtx = mit->second ;
756
- if (!wtx.isAbandoned () && !wtx.isBlockConflicted ())
756
+ if (!wtx.isAbandoned () && !wtx.isBlockConflicted () && !wtx. isMempoolConflicted () )
757
757
return true ; // Spent
758
758
}
759
759
}
@@ -1360,7 +1360,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
1360
1360
void CWallet::RecursiveUpdateTxState (const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1361
1361
// Do not flush the wallet here for performance reasons
1362
1362
WalletBatch batch (GetDatabase (), false );
1363
+ RecursiveUpdateTxState (&batch, tx_hash, try_updating_state);
1364
+ }
1363
1365
1366
+ void CWallet::RecursiveUpdateTxState (WalletBatch* batch, const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
1364
1367
std::set<uint256> todo;
1365
1368
std::set<uint256> done;
1366
1369
@@ -1377,7 +1380,7 @@ void CWallet::RecursiveUpdateTxState(const uint256& tx_hash, const TryUpdatingSt
1377
1380
TxUpdate update_state = try_updating_state (wtx);
1378
1381
if (update_state != TxUpdate::UNCHANGED) {
1379
1382
wtx.MarkDirty ();
1380
- batch. WriteTx (wtx);
1383
+ if ( batch) batch-> WriteTx (wtx);
1381
1384
// Iterate over all its outputs, and update those tx states as well (if applicable)
1382
1385
for (unsigned int i = 0 ; i < wtx.tx ->vout .size (); ++i) {
1383
1386
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) {
1418
1421
if (it != mapWallet.end ()) {
1419
1422
RefreshMempoolStatus (it->second , chain ());
1420
1423
}
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
+ }
1421
1438
}
1422
1439
1423
1440
void CWallet::transactionRemovedFromMempool (const CTransactionRef& tx, MemPoolRemovalReason reason) {
@@ -1455,6 +1472,21 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe
1455
1472
// https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1456
1473
SyncTransaction (tx, TxStateInactive{});
1457
1474
}
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
+ }
1458
1490
}
1459
1491
1460
1492
void CWallet::blockConnected (ChainstateRole role, const interfaces::BlockInfo& block)
0 commit comments