policy: Consider tap_key_origins when looking for sigs in PSBTs

We used to only look at `bip32_derivations` which is only used for ECDSA
keys.
This commit is contained in:
Alekos Filini 2022-05-24 15:50:49 +02:00
parent 572c3ee70d
commit c67116fb55
No known key found for this signature in database
GPG Key ID: 431401E4A4530061

View File

@ -44,7 +44,6 @@ use serde::ser::SerializeMap;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use bitcoin::hashes::*; use bitcoin::hashes::*;
use bitcoin::secp256k1;
use bitcoin::util::bip32::Fingerprint; use bitcoin::util::bip32::Fingerprint;
use bitcoin::{PublicKey, XOnlyPublicKey}; use bitcoin::{PublicKey, XOnlyPublicKey};
@ -766,27 +765,25 @@ fn make_generic_signature<M: Fn() -> SatisfiableItem, F: Fn(&Psbt) -> bool>(
} }
fn generic_sig_in_psbt< fn generic_sig_in_psbt<
// C is for "check", it's a closure we use to *check* if a psbt input contains the signature
// for a specific key
C: Fn(&PsbtInput, &SinglePubKey) -> bool, C: Fn(&PsbtInput, &SinglePubKey) -> bool,
M: Fn(&secp256k1::PublicKey) -> SinglePubKey, // E is for "extract", it extracts a key from the bip32 derivations found in the psbt input
E: Fn(&PsbtInput, Fingerprint) -> Option<SinglePubKey>,
>( >(
psbt: &Psbt, psbt: &Psbt,
key: &DescriptorPublicKey, key: &DescriptorPublicKey,
secp: &SecpCtx, secp: &SecpCtx,
map: M,
check: C, check: C,
extract: E,
) -> bool { ) -> bool {
//TODO check signature validity //TODO check signature validity
psbt.inputs.iter().all(|input| match key { psbt.inputs.iter().all(|input| match key {
DescriptorPublicKey::SinglePub(DescriptorSinglePub { key, .. }) => check(input, key), DescriptorPublicKey::SinglePub(DescriptorSinglePub { key, .. }) => check(input, key),
DescriptorPublicKey::XPub(xpub) => { DescriptorPublicKey::XPub(xpub) => {
let pubkey = input
.bip32_derivation
.iter()
.find(|(_, (f, _))| *f == xpub.root_fingerprint(secp))
.map(|(p, _)| p);
//TODO check actual derivation matches //TODO check actual derivation matches
match pubkey { match extract(input, xpub.root_fingerprint(secp)) {
Some(pubkey) => check(input, &map(pubkey)), Some(pubkey) => check(input, &pubkey),
None => false, None => false,
} }
} }
@ -838,7 +835,6 @@ impl<T: ScriptContext + 'static> SigExt for T {
psbt, psbt,
key, key,
secp, secp,
|pk| SinglePubKey::XOnly((*pk).into()),
|input, pk| { |input, pk| {
let pk = match pk { let pk = match pk {
SinglePubKey::XOnly(pk) => pk, SinglePubKey::XOnly(pk) => pk,
@ -851,17 +847,30 @@ impl<T: ScriptContext + 'static> SigExt for T {
input.tap_script_sigs.keys().any(|(sk, _)| sk == pk) input.tap_script_sigs.keys().any(|(sk, _)| sk == pk)
} }
}, },
|input, fing| {
input
.tap_key_origins
.iter()
.find(|(_, (_, (f, _)))| f == &fing)
.map(|(pk, _)| SinglePubKey::XOnly(*pk))
},
) )
} else { } else {
generic_sig_in_psbt( generic_sig_in_psbt(
psbt, psbt,
key, key,
secp, secp,
|pk| SinglePubKey::FullKey(PublicKey::new(*pk)),
|input, pk| match pk { |input, pk| match pk {
SinglePubKey::FullKey(pk) => input.partial_sigs.contains_key(pk), SinglePubKey::FullKey(pk) => input.partial_sigs.contains_key(pk),
_ => false, _ => false,
}, },
|input, fing| {
input
.bip32_derivation
.iter()
.find(|(_, (f, _))| f == &fing)
.map(|(pk, _)| SinglePubKey::FullKey(PublicKey::new(*pk)))
},
) )
} }
} }