From: Vihiga Tyonum Date: Wed, 16 Sep 2026 10:49:59 +0000 (+0100) Subject: fix(combine_psbt): Propagate Psbt::combine errors X-Git-Url: http://internal-gitweb-vhost/-script/src/example_cli/struct.EncoderStringWriter.html?a=commitdiff_plain;h=682e4148b1994c452dd8619f5a5c43a8ef135e2d;p=bdk-cli fix(combine_psbt): Propagate Psbt::combine errors The fold merging the input PSBTs discarded each combine result with `let _ = acc.combine(x)`. Per BIP174, Psbt::combine returns Err whenever the two PSBTs do not describe the same unsigned transaction, so incompatible inputs left the accumulator untouched. This fix propagates the error with `?`. BDKCliError already converts from bitcoin::psbt::Error, so the command now exits non-zero. Fixes #323 --- diff --git a/src/handlers/offline.rs b/src/handlers/offline.rs index fe4097e..1395537 100644 --- a/src/handlers/offline.rs +++ b/src/handlers/offline.rs @@ -765,7 +765,7 @@ impl AppCommand>> for CombinePsbtCommand { psbts .into_iter() .try_fold::<_, _, Result>(init_psbt, |mut acc, x| { - let _ = acc.combine(x); + acc.combine(x)?; Ok(acc) })?; diff --git a/tests/integration/online.rs b/tests/integration/online.rs index 2e63e21..b9dcc7b 100644 --- a/tests/integration/online.rs +++ b/tests/integration/online.rs @@ -358,6 +358,35 @@ mod test_online { ); } + #[test] + fn test_combine_psbt_rejects_mismatched_psbts() { + let (cli, mut cmd_init, env) = setup_online_wallet(); + cmd_init.assert().success(); + fund_and_sync_wallet(&cli, &env); + + // Two PSBTs spending the same UTXO but paying different amounts: their + // unsigned transactions differ, so BIP174 forbids combining them. + let psbt_a = cli_create_tx(&cli, &format!("{RECIPIENT}:15000")); + let psbt_b = cli_create_tx(&cli, &format!("{RECIPIENT}:25000")); + + let output = cli + .wallet_cmd(&["--wallet", WALLET_NAME, "combine_psbt", &psbt_a, &psbt_b]) + .output() + .expect("failed to spawn `combine_psbt`"); + + assert!( + !output.status.success(), + "combine_psbt should fail on PSBTs with different unsigned transactions, got: {}", + String::from_utf8_lossy(&output.stdout) + ); + + let stderr = String::from_utf8_lossy(&output.stderr); + assert!( + stderr.contains("different unsigned transaction"), + "unexpected error message: {stderr}" + ); + } + #[test] fn test_bump_fee_replaces_unconfirmed_tx() { let (cli, mut cmd_init, env) = setup_online_wallet();