Skip to content

Commit

Permalink
Merge #278: Add tr descriptor
Browse files Browse the repository at this point in the history
7195bd7 tr: clean up TaprootSpendInfo locking logic (Andrew Poelstra)
954b12f qualify `Tree` symbol (Andrew Poelstra)
5b5bf46 replace manual 'ch > 0x7f' checks with `is_ascii` (Andrew Poelstra)
b1cb8e0 replace length checks with is_empty (Andrew Poelstra)
f5c8d7f implement satisfier for psbt (sanket1729)
82ab565 Add psbt finalizer support (sanket1729)
48f6bb0 Add Tr descriptor (sanket1729)
dc21a79 Update satisfy API for taproot support (sanket1729)
74460e7 Update descriptor trait (sanket1729)
a0ef37f Add iterator for taptree (sanket1729)
81d1658 Add roundtrip tests (sanket1729)
6a717bf Implement Taproot descriptor tree parsing (SarcasticNastik)

Pull request description:

ACKs for top commit:
  apoelstra:
    ACK 7195bd7

Tree-SHA512: 3837daca158688f2cc080cd58c2e3feac9f86399c2c7aa3118df6fdf82c8eb1a32d3f00fa8ed182fe2b85a4ec69f7f9a13dc691bbbd773c7ab4e1b61fb2bc304
  • Loading branch information
sanket1729 committed Feb 9, 2022
2 parents 3d6c8d0 + 7195bd7 commit f621bbf
Show file tree
Hide file tree
Showing 17 changed files with 1,662 additions and 198 deletions.
9 changes: 5 additions & 4 deletions examples/htlc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ extern crate bitcoin;
extern crate miniscript;

use bitcoin::Network;
use miniscript::descriptor::Wsh;
use miniscript::policy::{Concrete, Liftable};
use miniscript::{Descriptor, DescriptorTrait};
use miniscript::DescriptorTrait;
use std::str::FromStr;

fn main() {
Expand All @@ -31,7 +32,7 @@ fn main() {
expiry = "4444"
)).unwrap();

let htlc_descriptor = Descriptor::new_wsh(
let htlc_descriptor = Wsh::new(
htlc_policy
.compile()
.expect("Policy compilation only fails on resource limits or mixed timelocks"),
Expand All @@ -54,12 +55,12 @@ fn main() {
);

assert_eq!(
format!("{:x}", htlc_descriptor.script_pubkey()),
format!("{:x}", htlc_descriptor.spk()),
"0020d853877af928a8d2a569c9c0ed14bd16f6a80ce9cccaf8a6150fd8f7f8867ae2"
);

assert_eq!(
format!("{:x}", htlc_descriptor.explicit_script()),
format!("{:x}", htlc_descriptor.inner_script()),
"21022222222222222222222222222222222222222222222222222222222222222222ac6476a91451814f108670aced2d77c1805ddd6634bc9d473188ad025c11b26782012088a82011111111111111111111111111111111111111111111111111111111111111118768"
);

Expand Down
31 changes: 25 additions & 6 deletions examples/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
extern crate bitcoin;
extern crate miniscript;

use miniscript::{descriptor::DescriptorType, DescriptorTrait};
use miniscript::{descriptor::DescriptorType, Descriptor, DescriptorTrait};
use std::str::FromStr;

fn main() {
Expand All @@ -32,17 +32,36 @@ fn main() {
// Or they contain a combination of timelock and heightlock.
assert!(my_descriptor.sanity_check().is_ok());

// Sometimes it is necesarry to have additional information to get the bitcoin::PublicKey
// from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
// when calculating the script pubkey of a descriptor with xpubs, the secp context and
// child information maybe required.
// Compute the script pubkey. As mentioned in the documentation, script_pubkey only fails
// for Tr descriptors that don't have some pre-computed data
assert_eq!(
format!("{:x}", my_descriptor.script_pubkey()),
"0020daef16dd7c946a3e735a6e43310cb2ce33dfd14a04f76bf8241a16654cb2f0f9"
);

// Another way to compute script pubkey
// We can also compute the type of descriptor
let desc_type = my_descriptor.desc_type();
assert_eq!(desc_type, DescriptorType::Wsh);
// Since we know the type of descriptor, we can get the Wsh struct from Descriptor
// This allows us to call infallible methods for getting script pubkey
if let Descriptor::Wsh(wsh) = &my_descriptor {
assert_eq!(
format!("{:x}", wsh.spk()),
"0020daef16dd7c946a3e735a6e43310cb2ce33dfd14a04f76bf8241a16654cb2f0f9"
);
} else {
// We checked for the descriptor type earlier
}

// Get the inner script inside the descriptor
assert_eq!(
format!("{:x}", my_descriptor.explicit_script()),
format!(
"{:x}",
my_descriptor
.explicit_script()
.expect("Wsh descriptors have inner scripts")
),
"21020202020202020202020202020202020202020202020202020202020202020202ac"
);

Expand Down
7 changes: 6 additions & 1 deletion examples/sign_multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ fn main() {
);

assert_eq!(
format!("{:x}", my_descriptor.explicit_script()),
format!(
"{:x}",
my_descriptor
.explicit_script()
.expect("wsh descriptors have unique inner script")
),
"52\
21020202020202020202020202020202020202020202020202020202020202020202\
21020102030405060708010203040506070801020304050607080000000000000000\
Expand Down
70 changes: 58 additions & 12 deletions src/descriptor/bare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ impl<Pk: MiniscriptKey> Bare<Pk> {
}
}

impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> {
/// Obtain the corresponding script pubkey for this descriptor
/// Non failing verion of [`DescriptorTrait::script_pubkey`] for this descriptor
pub fn spk(&self) -> Script {
self.ms.encode()
}

/// Obtain the underlying miniscript for this descriptor
/// Non failing verion of [`DescriptorTrait::explicit_script`] for this descriptor
pub fn inner_script(&self) -> Script {
self.spk()
}

/// Obtain the pre bip-340 signature script code for this descriptor
/// Non failing verion of [`DescriptorTrait::script_code`] for this descriptor
pub fn ecdsa_sighash_script_code(&self) -> Script {
self.spk()
}
}

impl<Pk: MiniscriptKey> fmt::Debug for Bare<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.ms)
Expand Down Expand Up @@ -130,7 +150,7 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
where
Pk: ToPublicKey,
{
self.ms.encode()
self.spk()
}

fn unsigned_script_sig(&self) -> Script
Expand All @@ -140,11 +160,11 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
Script::new()
}

fn explicit_script(&self) -> Script
fn explicit_script(&self) -> Result<Script, Error>
where
Pk: ToPublicKey,
{
self.ms.encode()
Ok(self.inner_script())
}

fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
Expand Down Expand Up @@ -174,11 +194,11 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
Ok(4 * (varint_len(scriptsig_len) + scriptsig_len))
}

fn script_code(&self) -> Script
fn script_code(&self) -> Result<Script, Error>
where
Pk: ToPublicKey,
{
self.script_pubkey()
Ok(self.ecdsa_sighash_script_code())
}
}

Expand Down Expand Up @@ -238,6 +258,33 @@ impl<Pk: MiniscriptKey> Pkh<Pk> {
}
}

impl<Pk: MiniscriptKey + ToPublicKey> Pkh<Pk> {
/// Obtain the corresponding script pubkey for this descriptor
/// Non failing verion of [`DescriptorTrait::script_pubkey`] for this descriptor
pub fn spk(&self) -> Script {
let addr = bitcoin::Address::p2pkh(&self.pk.to_public_key(), bitcoin::Network::Bitcoin);
addr.script_pubkey()
}

/// Obtain the corresponding script pubkey for this descriptor
/// Non failing verion of [`DescriptorTrait::address`] for this descriptor
pub fn addr(&self, network: bitcoin::Network) -> bitcoin::Address {
bitcoin::Address::p2pkh(&self.pk.to_public_key(), network)
}

/// Obtain the underlying miniscript for this descriptor
/// Non failing verion of [`DescriptorTrait::explicit_script`] for this descriptor
pub fn inner_script(&self) -> Script {
self.spk()
}

/// Obtain the pre bip-340 signature script code for this descriptor
/// Non failing verion of [`DescriptorTrait::script_code`] for this descriptor
pub fn ecdsa_sighash_script_code(&self) -> Script {
self.spk()
}
}

impl<Pk: MiniscriptKey> fmt::Debug for Pkh<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "pkh({:?})", self.pk)
Expand Down Expand Up @@ -305,15 +352,14 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
where
Pk: ToPublicKey,
{
Ok(bitcoin::Address::p2pkh(&self.pk.to_public_key(), network))
Ok(self.addr(network))
}

fn script_pubkey(&self) -> Script
where
Pk: ToPublicKey,
{
let addr = bitcoin::Address::p2pkh(&self.pk.to_public_key(), bitcoin::Network::Bitcoin);
addr.script_pubkey()
self.spk()
}

fn unsigned_script_sig(&self) -> Script
Expand All @@ -323,11 +369,11 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
Script::new()
}

fn explicit_script(&self) -> Script
fn explicit_script(&self) -> Result<Script, Error>
where
Pk: ToPublicKey,
{
self.script_pubkey()
Ok(self.inner_script())
}

fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
Expand Down Expand Up @@ -360,11 +406,11 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
Ok(4 * (1 + 73 + BareCtx::pk_len(&self.pk)))
}

fn script_code(&self) -> Script
fn script_code(&self) -> Result<Script, Error>
where
Pk: ToPublicKey,
{
self.script_pubkey()
Ok(self.ecdsa_sighash_script_code())
}
}

Expand Down

0 comments on commit f621bbf

Please sign in to comment.