diff --git a/fuzz/fuzz_targets/miniscript_satisfy.rs b/fuzz/fuzz_targets/miniscript_satisfy.rs index 98dc6f1bf..34590f539 100644 --- a/fuzz/fuzz_targets/miniscript_satisfy.rs +++ b/fuzz/fuzz_targets/miniscript_satisfy.rs @@ -23,7 +23,7 @@ impl FuzzSatisfier<'_> { } impl Satisfier for FuzzSatisfier<'_> { - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self, _: &FuzzPk) -> Option { let b = self.read_byte()?; if b & 1 == 1 { // FIXME in later version of rust-secp we can use from_byte_array @@ -34,8 +34,8 @@ impl Satisfier for FuzzSatisfier<'_> { } } - fn lookup_tap_leaf_script_sig(&self, _: &FuzzPk, _: &TapLeafHash) -> Option { - self.lookup_tap_key_spend_sig() + fn lookup_tap_leaf_script_sig(&self, pk: &FuzzPk, _: &TapLeafHash) -> Option { + self.lookup_tap_key_spend_sig(pk) } // todo @@ -85,7 +85,7 @@ impl Satisfier for FuzzSatisfier<'_> { (h, _): &(hash160::Hash, TapLeafHash), ) -> Option<(XOnlyPublicKey, Signature)> { self.lookup_raw_pkh_x_only_pk(h) - .zip(self.lookup_tap_key_spend_sig()) + .zip(self.lookup_tap_key_spend_sig(&FuzzPk::new_from_control_byte(0))) } fn lookup_sha256(&self, b: &u8) -> Option<[u8; 32]> { diff --git a/src/miniscript/satisfy.rs b/src/miniscript/satisfy.rs index c6a0bd3bf..25c781798 100644 --- a/src/miniscript/satisfy.rs +++ b/src/miniscript/satisfy.rs @@ -35,7 +35,7 @@ pub trait Satisfier { fn lookup_ecdsa_sig(&self, _: &Pk) -> Option { None } /// Lookup the tap key spend sig - fn lookup_tap_key_spend_sig(&self) -> Option { None } + fn lookup_tap_key_spend_sig(&self, _: &Pk) -> Option { None } /// Given a public key and a associated leaf hash, look up an schnorr signature with that key fn lookup_tap_leaf_script_sig( @@ -290,8 +290,8 @@ impl> Satisfier for &S { (**self).lookup_raw_pkh_ecdsa_sig(pkh) } - fn lookup_tap_key_spend_sig(&self) -> Option { - (**self).lookup_tap_key_spend_sig() + fn lookup_tap_key_spend_sig(&self, pk: &Pk) -> Option { + (**self).lookup_tap_key_spend_sig(pk) } fn lookup_raw_pkh_tap_leaf_script_sig( @@ -335,8 +335,8 @@ impl> Satisfier for &mut S (**self).lookup_tap_leaf_script_sig(p, h) } - fn lookup_tap_key_spend_sig(&self) -> Option { - (**self).lookup_tap_key_spend_sig() + fn lookup_tap_key_spend_sig(&self, pk: &Pk) -> Option { + (**self).lookup_tap_key_spend_sig(pk) } fn lookup_raw_pkh_pk(&self, pkh: &hash160::Hash) -> Option { @@ -400,10 +400,10 @@ macro_rules! impl_tuple_satisfier { None } - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self, pk: &Pk) -> Option { let &($(ref $ty,)*) = self; $( - if let Some(result) = $ty.lookup_tap_key_spend_sig() { + if let Some(result) = $ty.lookup_tap_key_spend_sig(pk) { return Some(result); } )* @@ -678,12 +678,13 @@ impl Placeholder { debug_assert!(s.len() == *size); s }), - Placeholder::SchnorrSigPk(_, _, size) => { - sat.lookup_tap_key_spend_sig().map(|s| s.to_vec()).map(|s| { + Placeholder::SchnorrSigPk(pk, _, size) => sat + .lookup_tap_key_spend_sig(pk) + .map(|s| s.to_vec()) + .map(|s| { debug_assert!(s.len() == *size); s - }) - } + }), Placeholder::SchnorrSigPkHash(pkh, tap_leaf_hash, size) => sat .lookup_raw_pkh_tap_leaf_script_sig(&(*pkh, *tap_leaf_hash)) .map(|(_, s)| { diff --git a/src/plan.rs b/src/plan.rs index 52eebbed5..384ca2f7a 100644 --- a/src/plan.rs +++ b/src/plan.rs @@ -147,8 +147,8 @@ where Satisfier::lookup_ecdsa_sig(self, pk).is_some() } - fn provider_lookup_tap_key_spend_sig(&self, _: &Pk) -> Option { - Satisfier::lookup_tap_key_spend_sig(self).map(|s| s.to_vec().len()) + fn provider_lookup_tap_key_spend_sig(&self, pk: &Pk) -> Option { + Satisfier::lookup_tap_key_spend_sig(self, pk).map(|s| s.to_vec().len()) } fn provider_lookup_tap_leaf_script_sig( diff --git a/src/psbt/finalizer.rs b/src/psbt/finalizer.rs index af25bfd33..2bfb24a88 100644 --- a/src/psbt/finalizer.rs +++ b/src/psbt/finalizer.rs @@ -53,11 +53,13 @@ fn construct_tap_witness( } assert!(spk.is_p2tr()); - // try the key spend path first - if let Some(sig) = - >::lookup_tap_key_spend_sig(sat) - { - return Ok(vec![sig.to_vec()]); + // try the key spend path firsti + if let Some(ref key) = sat.psbt_input().tap_internal_key { + if let Some(sig) = + >::lookup_tap_key_spend_sig(sat, key) + { + return Ok(vec![sig.to_vec()]); + } } // Next script spends let (mut min_wit, mut min_wit_len) = (None, None); diff --git a/src/psbt/mod.rs b/src/psbt/mod.rs index 84924f42e..bf698e1dc 100644 --- a/src/psbt/mod.rs +++ b/src/psbt/mod.rs @@ -243,20 +243,31 @@ impl From for InputError { /// is more than number of inputs in pbst pub struct PsbtInputSatisfier<'psbt> { /// pbst - pub psbt: &'psbt Psbt, + psbt: &'psbt Psbt, /// input index - pub index: usize, + index: usize, } impl<'psbt> PsbtInputSatisfier<'psbt> { /// create a new PsbtInputsatisfier from /// psbt and index pub fn new(psbt: &'psbt Psbt, index: usize) -> Self { Self { psbt, index } } + + /// Accessor for the PSBT this satisfier is associated with. + pub fn psbt(&self) -> &'psbt Psbt { self.psbt } + + /// Accessor for the input this satisfier is associated with. + pub fn psbt_input(&self) -> &psbt::Input { &self.psbt.inputs[self.index] } } impl Satisfier for PsbtInputSatisfier<'_> { - fn lookup_tap_key_spend_sig(&self) -> Option { - self.psbt.inputs[self.index].tap_key_sig + fn lookup_tap_key_spend_sig(&self, pk: &Pk) -> Option { + if let Some(key) = self.psbt_input().tap_internal_key { + if pk.to_x_only_pubkey() == key { + return self.psbt_input().tap_key_sig; + } + } + None } fn lookup_tap_leaf_script_sig( @@ -264,14 +275,14 @@ impl Satisfier for PsbtInputSatisfier<'_> { pk: &Pk, lh: &TapLeafHash, ) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .tap_script_sigs .get(&(pk.to_x_only_pubkey(), *lh)) .copied() } fn lookup_raw_pkh_pk(&self, pkh: &hash160::Hash) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .bip32_derivation .iter() .find(|&(pubkey, _)| pubkey.to_pubkeyhash(SigType::Ecdsa) == *pkh) @@ -281,14 +292,14 @@ impl Satisfier for PsbtInputSatisfier<'_> { fn lookup_tap_control_block_map( &self, ) -> Option<&BTreeMap> { - Some(&self.psbt.inputs[self.index].tap_scripts) + Some(&self.psbt_input().tap_scripts) } fn lookup_raw_pkh_tap_leaf_script_sig( &self, pkh: &(hash160::Hash, TapLeafHash), ) -> Option<(bitcoin::secp256k1::XOnlyPublicKey, bitcoin::taproot::Signature)> { - self.psbt.inputs[self.index] + self.psbt_input() .tap_script_sigs .iter() .find(|&((pubkey, lh), _sig)| { @@ -298,7 +309,7 @@ impl Satisfier for PsbtInputSatisfier<'_> { } fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .partial_sigs .get(&pk.to_public_key()) .copied() @@ -308,7 +319,7 @@ impl Satisfier for PsbtInputSatisfier<'_> { &self, pkh: &hash160::Hash, ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { - self.psbt.inputs[self.index] + self.psbt_input() .partial_sigs .iter() .find(|&(pubkey, _sig)| pubkey.to_pubkeyhash(SigType::Ecdsa) == *pkh) @@ -337,28 +348,28 @@ impl Satisfier for PsbtInputSatisfier<'_> { } fn lookup_hash160(&self, h: &Pk::Hash160) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .hash160_preimages .get(&Pk::to_hash160(h)) .and_then(|x: &Vec| <[u8; 32]>::try_from(&x[..]).ok()) } fn lookup_sha256(&self, h: &Pk::Sha256) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .sha256_preimages .get(&Pk::to_sha256(h)) .and_then(|x: &Vec| <[u8; 32]>::try_from(&x[..]).ok()) } fn lookup_hash256(&self, h: &Pk::Hash256) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .hash256_preimages .get(&sha256d::Hash::from_byte_array(Pk::to_hash256(h).to_byte_array())) // upstream psbt operates on hash256 .and_then(|x: &Vec| <[u8; 32]>::try_from(&x[..]).ok()) } fn lookup_ripemd160(&self, h: &Pk::Ripemd160) -> Option { - self.psbt.inputs[self.index] + self.psbt_input() .ripemd160_preimages .get(&Pk::to_ripemd160(h)) .and_then(|x: &Vec| <[u8; 32]>::try_from(&x[..]).ok())