};
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();
+ }
}
// 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));
}
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()
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(());