From 421c1af6cd90f1b1af77c303b2ba2e74760b8781 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Tue, 22 Aug 2023 16:17:44 +0200 Subject: [PATCH] bitcoind: fix the detection of unconfirmed RBF spending txs As we walk through the spend transactions in the wallet, we may return the txid of the transaction that was replaced instead of the new one. --- src/bitcoin/d/mod.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index 9f011590..1d75f428 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -916,9 +916,25 @@ impl BitcoinD { let input_outpoint = bitcoin::OutPoint { txid, vout }; if spent_outpoint == &input_outpoint { - return bitcoin::Txid::from_str(spending_txid) - .map(Some) - .expect("Must be a valid txid"); + let spending_txid = + bitcoin::Txid::from_str(spending_txid).expect("Must be a valid txid"); + + // If the spending transaction is unconfirmed, there may more than one of them. + // Make sure to not return one that RBF'd. + let confs = gettx_res + .get("confirmations") + .and_then(Json::as_i64) + .expect("A valid number of confirmations must always be present."); + let conflicts = gettx_res + .get("walletconflicts") + .and_then(Json::as_array) + .expect("A valid list of wallet conflicts must always be present."); + if confs == 0 && !conflicts.is_empty() && !self.is_in_mempool(&spending_txid) { + log::debug!("Noticed '{}' as spending '{}', but is unconfirmed with conflicts and is not in mempool anymore. Discarding it.", &spending_txid, &spent_outpoint); + break; + } + + return Some(spending_txid); } } }