]> Untitled Git - bdk/commitdiff
continue signing when finding already finalized inputs
authorRiccardo Casatta <riccardo@casatta.it>
Thu, 6 May 2021 15:11:43 +0000 (17:11 +0200)
committerAlekos Filini <alekos.filini@gmail.com>
Fri, 7 May 2021 14:32:24 +0000 (16:32 +0200)
src/psbt/mod.rs
src/wallet/mod.rs
src/wallet/signer.rs

index d83f18a3628b674ed4f3e6f95111ad5755fbfeb8..ff950db72bf051f139315fffd49533c5f2820df9 100644 (file)
@@ -99,4 +99,23 @@ mod test {
         };
         let _ = wallet.sign(&mut psbt, options).unwrap();
     }
+
+    #[test]
+    fn test_psbt_sign_with_finalized() {
+        let psbt_bip: PSBT = deserialize(&base64::decode(PSBT_STR).unwrap()).unwrap();
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let send_to = wallet.get_address(AddressIndex::New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(send_to.script_pubkey(), 10_000);
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        // add a finalized input
+        psbt.inputs.push(psbt_bip.inputs[0].clone());
+        psbt.global
+            .unsigned_tx
+            .input
+            .push(psbt_bip.global.unsigned_tx.input[0].clone());
+
+        let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
+    }
 }
index ac32cb639c035ae860101e1794cbe65e60e4d57f..5352269532b2a531b531f987e5c7f810c123e401 100644 (file)
@@ -861,10 +861,14 @@ where
         // this helps us doing our job later
         self.add_input_hd_keypaths(psbt)?;
 
-        // If we aren't allowed to use `witness_utxo`, ensure that every input has the
-        // `non_witness_utxo`
+        // If we aren't allowed to use `witness_utxo`, ensure that every input but finalized one
+        // has the `non_witness_utxo`
         if !sign_options.trust_witness_utxo
-            && psbt.inputs.iter().any(|i| i.non_witness_utxo.is_none())
+            && psbt
+                .inputs
+                .iter()
+                .filter(|i| i.final_script_witness.is_none() && i.final_script_sig.is_none())
+                .any(|i| i.non_witness_utxo.is_none())
         {
             return Err(Error::Signer(signer::SignerError::MissingNonWitnessUtxo));
         }
index 04f4d2ad07bd4d0b5e179a92fe8a1083e3dbc3cc..76ffc3d7912506f60a3f6b83a71fc4724c89de6a 100644 (file)
@@ -206,6 +206,12 @@ impl Signer for DescriptorXKey<ExtendedPrivKey> {
             return Err(SignerError::InputIndexOutOfRange);
         }
 
+        if psbt.inputs[input_index].final_script_sig.is_some()
+            || psbt.inputs[input_index].final_script_witness.is_some()
+        {
+            return Ok(());
+        }
+
         let (public_key, full_path) = match psbt.inputs[input_index]
             .bip32_derivation
             .iter()
@@ -261,10 +267,16 @@ impl Signer for PrivateKey {
         secp: &SecpCtx,
     ) -> Result<(), SignerError> {
         let input_index = input_index.unwrap();
-        if input_index >= psbt.inputs.len() {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.global.unsigned_tx.input.len() {
             return Err(SignerError::InputIndexOutOfRange);
         }
 
+        if psbt.inputs[input_index].final_script_sig.is_some()
+            || psbt.inputs[input_index].final_script_witness.is_some()
+        {
+            return Ok(());
+        }
+
         let pubkey = self.public_key(&secp);
         if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
             return Ok(());