Skip to content

Commit

Permalink
implement satisfier for psbt
Browse files Browse the repository at this point in the history
  • Loading branch information
sanket1729 committed Jan 15, 2022
1 parent 63136bd commit 6d920ed
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
3 changes: 0 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ pub use miniscript::decode::Terminal;
pub use miniscript::satisfy::{Preimage32, Satisfier};
pub use miniscript::Miniscript;

// Use schnorr pubkey as Xonlykey
pub(crate) use bitcoin::schnorr::PublicKey as XOnlyKey;

///Public key trait which can be converted to Hash type
pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
/// Check if the publicKey is uncompressed. The default
Expand Down
12 changes: 7 additions & 5 deletions src/psbt/finalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use util::{script_is_v1_tr, witness_size};
use super::{sanity_check, Psbt};
use super::{Error, InputError, PsbtInputSatisfier};
use bitcoin::blockdata::witness::Witness;
use bitcoin::secp256k1::XOnlyPublicKey;
use bitcoin::secp256k1::{self, Secp256k1};
use bitcoin::util::taproot::LeafVersion;
use bitcoin::{self, PublicKey, Script};
Expand All @@ -32,7 +33,6 @@ use interpreter;
use Descriptor;
use Miniscript;
use Satisfier;
use XOnlyKey;
use {BareCtx, Legacy, Segwitv0, Tap};

// Satisfy the taproot descriptor. It is not possible to infer the complete
Expand All @@ -47,20 +47,22 @@ fn construct_tap_witness(
assert!(script_is_v1_tr(&spk));

// try the script spend path first
if let Some(sig) = <PsbtInputSatisfier as Satisfier<XOnlyKey>>::lookup_tap_key_spend_sig(sat) {
if let Some(sig) =
<PsbtInputSatisfier as Satisfier<XOnlyPublicKey>>::lookup_tap_key_spend_sig(sat)
{
return Ok(vec![sig.to_vec()]);
}
// Next script spends
let (mut min_wit, mut min_wit_len) = (None, None);
if let Some(block_map) =
<PsbtInputSatisfier as Satisfier<XOnlyKey>>::lookup_tap_control_block_map(sat)
<PsbtInputSatisfier as Satisfier<XOnlyPublicKey>>::lookup_tap_control_block_map(sat)
{
for (control_block, (script, ver)) in block_map {
if *ver != LeafVersion::default() {
if *ver != LeafVersion::TapScript {
// We don't know how to satisfy non default version scripts yet
continue;
}
let ms = match Miniscript::<XOnlyKey, Tap>::parse_insane(script) {
let ms = match Miniscript::<XOnlyPublicKey, Tap>::parse_insane(script) {
Ok(ms) => ms,
Err(..) => continue, // try another script
};
Expand Down
33 changes: 33 additions & 0 deletions src/psbt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
//! `https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki`
//!

use std::collections::BTreeMap;
use std::{error, fmt};

use bitcoin;
Expand All @@ -28,6 +29,7 @@ use bitcoin::secp256k1::{self, Secp256k1};
use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
use bitcoin::Script;

use bitcoin::util::taproot::{ControlBlock, LeafVersion, TapLeafHash};
use interpreter;
use miniscript::limits::SEQUENCE_LOCKTIME_DISABLE_FLAG;
use miniscript::satisfy::{After, Older};
Expand Down Expand Up @@ -232,6 +234,37 @@ impl<'psbt> PsbtInputSatisfier<'psbt> {
}

impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfier<'psbt> {
fn lookup_tap_key_spend_sig(&self) -> Option<bitcoin::SchnorrSig> {
self.psbt.inputs[self.index].tap_key_sig
}

fn lookup_tap_leaf_script_sig(&self, pk: &Pk, lh: &TapLeafHash) -> Option<bitcoin::SchnorrSig> {
self.psbt.inputs[self.index]
.tap_script_sigs
.get(&(pk.to_x_only_pubkey(), *lh))
.map(|x| *x) // replace by copied in 1.36
}

fn lookup_tap_control_block_map(
&self,
) -> Option<&BTreeMap<ControlBlock, (bitcoin::Script, LeafVersion)>> {
Some(&self.psbt.inputs[self.index].tap_scripts)
}

fn lookup_pkh_tap_leaf_script_sig(
&self,
pkh: &(Pk::Hash, TapLeafHash),
) -> Option<(bitcoin::secp256k1::XOnlyPublicKey, bitcoin::SchnorrSig)> {
self.psbt.inputs[self.index]
.tap_script_sigs
.iter()
.filter(|&((pubkey, lh), _sig)| {
pubkey.to_pubkeyhash() == Pk::hash_to_hash160(&pkh.0) && *lh == pkh.1
})
.next()
.map(|((x_only_pk, _leaf_hash), sig)| (*x_only_pk, *sig))
}

fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option<bitcoin::EcdsaSig> {
self.psbt.inputs[self.index]
.partial_sigs
Expand Down

0 comments on commit 6d920ed

Please sign in to comment.