]> Untitled Git - bdk/commitdiff
[wallet] Add witness and redeem scripts to PSBT outputs
authorJustin Moon <mail@justinmoon.com>
Mon, 16 Nov 2020 22:25:16 +0000 (16:25 -0600)
committerJustin Moon <mail@justinmoon.com>
Wed, 18 Nov 2020 17:40:34 +0000 (11:40 -0600)
src/wallet/mod.rs
src/wallet/tx_builder.rs

index 4759b5a0faba405618a259a0c02e48e2658b0d4d..8d7530d57c5469866dc14b1e5a3fc5b5b4d39f42 100644 (file)
@@ -1220,6 +1220,11 @@ where
             {
                 let (desc, _) = self.get_descriptor_for_script_type(script_type);
                 psbt_output.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
+                if builder.include_output_redeem_witness_script {
+                    let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
+                    psbt_output.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
+                    psbt_output.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
+                };
             }
         }
 
@@ -3231,4 +3236,22 @@ mod test {
         let extracted = signed_psbt.extract_tx();
         assert_eq!(extracted.input[0].witness.len(), 2);
     }
+
+    #[test]
+    fn test_include_output_redeem_witness_script() {
+        let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)])
+                    .include_output_redeem_witness_script(),
+            )
+            .unwrap();
+
+        // p2sh-p2wsh transaction should contain both witness and redeem scripts
+        assert!(psbt
+            .outputs
+            .iter()
+            .any(|output| output.redeem_script.is_some() && output.witness_script.is_some()));
+    }
 }
index 672602f770e68c3df0a53574ba331cfbab46211e..393797e5c0ffcd0b4f3cfd97e5b6ddc7bd01c820 100644 (file)
@@ -90,6 +90,7 @@ pub struct TxBuilder<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderC
     pub(crate) change_policy: ChangeSpendPolicy,
     pub(crate) force_non_witness_utxo: bool,
     pub(crate) coin_selection: Cs,
+    pub(crate) include_output_redeem_witness_script: bool,
 
     phantom: PhantomData<(D, Ctx)>,
 }
@@ -131,6 +132,7 @@ where
             change_policy: Default::default(),
             force_non_witness_utxo: Default::default(),
             coin_selection: Default::default(),
+            include_output_redeem_witness_script: Default::default(),
 
             phantom: PhantomData,
         }
@@ -374,10 +376,20 @@ impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> TxBuilde
             change_policy: self.change_policy,
             force_non_witness_utxo: self.force_non_witness_utxo,
             coin_selection,
+            include_output_redeem_witness_script: self.include_output_redeem_witness_script,
 
             phantom: PhantomData,
         }
     }
+
+    /// Fill-in the [`psbt::Output::redeem_script`](bitcoin::util::psbt::Output::redeem_script) and
+    /// [`psbt::Output::witness_script`](bitcoin::util::psbt::Output::witness_script) fields.
+    ///
+    /// This is useful for signers which always require it, like ColdCard hardware wallets.
+    pub fn include_output_redeem_witness_script(mut self) -> Self {
+        self.include_output_redeem_witness_script = true;
+        self
+    }
 }
 
 // methods supported only by create_tx, and only for `DefaultCoinSelectionAlgorithm`