Merge bitcoindevkit/bdk#757: Enable signing taproot transactions with only non_witness_utxos

5e9965fca7fb50708af0d293a9f6cd27d0c85fed Enable signing taproot transactions with only `non_witness_utxos` (Alekos Filini)

Pull request description:

  ### Description

  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

  ### Changelog notice

  - Enable signing taproot transactions that only specify the `non_witness_utxo`

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### Bugfixes:

  * [ ] This pull request breaks the existing API
  * [x] I've added tests to reproduce the issue which are now passing
  * [x] I'm linking the issue being fixed by this PR

ACKs for top commit:
  danielabrozzoni:
    tACK 5e9965fca7fb50708af0d293a9f6cd27d0c85fed - the code looks good to me, I played around with the test you provided (inspecting the PSBT, adding/removing the witness and non-witness utxos, etc) and everything works as expected.

Tree-SHA512: 2f205286263bfee4c76de8e8c81ae1349b1c3b255b72045488f8d629c05cab64c6f775307e831674dc036e5a3a760f95d9cdc1beaf48afb4c475aee838131a33
This commit is contained in:
Alekos Filini 2022-09-23 11:52:06 +02:00
commit aad5461ee1
No known key found for this signature in database
GPG Key ID: 431401E4A4530061
2 changed files with 26 additions and 5 deletions

View 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] #[test]
fn test_taproot_foreign_utxo() { fn test_taproot_foreign_utxo() {
let (wallet1, _, _) = get_funded_wallet(get_test_wpkh()); let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());

View File

@ -103,6 +103,7 @@ use miniscript::{Legacy, MiniscriptKey, Segwitv0, Tap};
use super::utils::SecpCtx; use super::utils::SecpCtx;
use crate::descriptor::{DescriptorMeta, XKeyUtils}; 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 /// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
/// multiple of them /// multiple of them
@ -921,11 +922,8 @@ impl ComputeSighash for Tap {
.unwrap_or_else(|| SchnorrSighashType::Default.into()) .unwrap_or_else(|| SchnorrSighashType::Default.into())
.schnorr_hash_ty() .schnorr_hash_ty()
.map_err(|_| SignerError::InvalidSighash)?; .map_err(|_| SignerError::InvalidSighash)?;
let witness_utxos = psbt let witness_utxos = (0..psbt.inputs.len())
.inputs .map(|i| psbt.get_utxo_for(i))
.iter()
.cloned()
.map(|i| i.witness_utxo)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut all_witness_utxos = vec![]; let mut all_witness_utxos = vec![];