]> Untitled Git - bdk/commitdiff
Enable signing taproot transactions with only `non_witness_utxos`
authorAlekos Filini <alekos.filini@gmail.com>
Mon, 19 Sep 2022 08:54:55 +0000 (10:54 +0200)
committerAlekos Filini <alekos.filini@gmail.com>
Mon, 19 Sep 2022 08:54:55 +0000 (10:54 +0200)
Some wallets may only specify the `non_witness_utxo` for a PSBT input.
If that's the case, BDK should still be able to sign.

This was pointed out in the discussion of #734

src/wallet/mod.rs
src/wallet/signer.rs

index 04c5a6508c167172fe5719c414719680b140e872..5d757e12d6bcc6306ed7bb19d97fc9db525cb737 100644 (file)
@@ -4964,6 +4964,29 @@ pub(crate) mod test {
         );
     }
 
+    #[test]
+    fn test_taproot_sign_using_non_witness_utxo() {
+        let (wallet, _, prev_txid) = get_funded_wallet(get_test_tr_single_sig());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        psbt.inputs[0].witness_utxo = None;
+        psbt.inputs[0].non_witness_utxo = wallet.database().get_raw_tx(&prev_txid).unwrap();
+        assert!(
+            psbt.inputs[0].non_witness_utxo.is_some(),
+            "Previous tx should be present in the database"
+        );
+
+        let result = wallet.sign(&mut psbt, Default::default());
+        assert!(result.is_ok(), "Signing should have worked");
+        assert!(
+            result.unwrap(),
+            "Should finalize the input since we can produce signatures"
+        );
+    }
+
     #[test]
     fn test_taproot_foreign_utxo() {
         let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
index 1feb15d697287d17cd574e7a498b98d4c5826622..a20a232143e55cc1655b0667b67e9f17ce384e78 100644 (file)
@@ -103,6 +103,7 @@ use miniscript::{Legacy, MiniscriptKey, Segwitv0, Tap};
 
 use super::utils::SecpCtx;
 use crate::descriptor::{DescriptorMeta, XKeyUtils};
+use crate::psbt::PsbtUtils;
 
 /// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
 /// multiple of them
@@ -921,11 +922,8 @@ impl ComputeSighash for Tap {
             .unwrap_or_else(|| SchnorrSighashType::Default.into())
             .schnorr_hash_ty()
             .map_err(|_| SignerError::InvalidSighash)?;
-        let witness_utxos = psbt
-            .inputs
-            .iter()
-            .cloned()
-            .map(|i| i.witness_utxo)
+        let witness_utxos = (0..psbt.inputs.len())
+            .map(|i| psbt.get_utxo_for(i))
             .collect::<Vec<_>>();
         let mut all_witness_utxos = vec![];