]> Untitled Git - bdk-cli/commitdiff
fix(combine_psbt): Propagate Psbt::combine errors
authorVihiga Tyonum <withtvpeter@gmail.com>
Wed, 16 Sep 2026 10:49:59 +0000 (11:49 +0100)
committerVihiga Tyonum <withtvpeter@gmail.com>
Wed, 16 Sep 2026 10:57:08 +0000 (11:57 +0100)
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

src/handlers/offline.rs
tests/integration/online.rs

index fe4097e42f49cfba456cc1c905b0daba48114b7c..13955374e5188bc93505a9835f749842d3b0211d 100644 (file)
@@ -765,7 +765,7 @@ impl AppCommand<AppContext<OfflineOperations<'_>>> for CombinePsbtCommand {
             psbts
                 .into_iter()
                 .try_fold::<_, _, Result<Psbt, Error>>(init_psbt, |mut acc, x| {
-                    let _ = acc.combine(x);
+                    acc.combine(x)?;
                     Ok(acc)
                 })?;
 
index 2e63e216c4a3bafeea3a8e5af5f88935cc73d658..b9dcc7b4a1efb31aed3a0b80dff5fec1f8e732ce 100644 (file)
@@ -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();