From 874d724c67ce7d804524e1f2a31f445998e5392a Mon Sep 17 00:00:00 2001 From: Cindy Date: Thu, 18 Jun 2026 05:45:08 -0300 Subject: [PATCH] fix: avoid UIH2 fingerprint in payjoin receiver input selection (#3304) Co-authored-by: Konstantin Ullrich --- cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart b/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart index ba0d8d0fb..641399504 100644 --- a/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart +++ b/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart @@ -179,7 +179,17 @@ class PayjoinReceiverWorker { final unspent = listUnspent as List; if (unspent.isEmpty) throw RecoverableError('No unspent outputs available'); - final selectedUtxo = await _inputPairFromUtxo(unspent[0]); + final candidateInputs = + await Future.wait(unspent.map(_inputPairFromUtxo)); + + // Prefer a UTXO that avoids the Unnecessary Input Heuristic (UIH2); + // fall back to the first candidate if none preserves privacy. + InputPair selectedUtxo = candidateInputs.first; + try { + selectedUtxo = + await pj5.tryPreservingPrivacy(candidateInputs: candidateInputs); + } catch (_) {} + final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]); final pj7 = await pj6.commitInputs();