Skip to content

Commit f621bbf

Browse files
committed
Merge #278: Add tr descriptor
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
2 parents 3d6c8d0 + 7195bd7 commit f621bbf

17 files changed

+1662
-198
lines changed

examples/htlc.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ extern crate bitcoin;
1818
extern crate miniscript;
1919

2020
use bitcoin::Network;
21+
use miniscript::descriptor::Wsh;
2122
use miniscript::policy::{Concrete, Liftable};
22-
use miniscript::{Descriptor, DescriptorTrait};
23+
use miniscript::DescriptorTrait;
2324
use std::str::FromStr;
2425

2526
fn main() {
@@ -31,7 +32,7 @@ fn main() {
3132
expiry = "4444"
3233
)).unwrap();
3334

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

5657
assert_eq!(
57-
format!("{:x}", htlc_descriptor.script_pubkey()),
58+
format!("{:x}", htlc_descriptor.spk()),
5859
"0020d853877af928a8d2a569c9c0ed14bd16f6a80ce9cccaf8a6150fd8f7f8867ae2"
5960
);
6061

6162
assert_eq!(
62-
format!("{:x}", htlc_descriptor.explicit_script()),
63+
format!("{:x}", htlc_descriptor.inner_script()),
6364
"21022222222222222222222222222222222222222222222222222222222222222222ac6476a91451814f108670aced2d77c1805ddd6634bc9d473188ad025c11b26782012088a82011111111111111111111111111111111111111111111111111111111111111118768"
6465
);
6566

examples/parse.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
extern crate bitcoin;
1818
extern crate miniscript;
1919

20-
use miniscript::{descriptor::DescriptorType, DescriptorTrait};
20+
use miniscript::{descriptor::DescriptorType, Descriptor, DescriptorTrait};
2121
use std::str::FromStr;
2222

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

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

42+
// Another way to compute script pubkey
43+
// We can also compute the type of descriptor
44+
let desc_type = my_descriptor.desc_type();
45+
assert_eq!(desc_type, DescriptorType::Wsh);
46+
// Since we know the type of descriptor, we can get the Wsh struct from Descriptor
47+
// This allows us to call infallible methods for getting script pubkey
48+
if let Descriptor::Wsh(wsh) = &my_descriptor {
49+
assert_eq!(
50+
format!("{:x}", wsh.spk()),
51+
"0020daef16dd7c946a3e735a6e43310cb2ce33dfd14a04f76bf8241a16654cb2f0f9"
52+
);
53+
} else {
54+
// We checked for the descriptor type earlier
55+
}
56+
57+
// Get the inner script inside the descriptor
4458
assert_eq!(
45-
format!("{:x}", my_descriptor.explicit_script()),
59+
format!(
60+
"{:x}",
61+
my_descriptor
62+
.explicit_script()
63+
.expect("Wsh descriptors have inner scripts")
64+
),
4665
"21020202020202020202020202020202020202020202020202020202020202020202ac"
4766
);
4867

examples/sign_multisig.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,12 @@ fn main() {
101101
);
102102

103103
assert_eq!(
104-
format!("{:x}", my_descriptor.explicit_script()),
104+
format!(
105+
"{:x}",
106+
my_descriptor
107+
.explicit_script()
108+
.expect("wsh descriptors have unique inner script")
109+
),
105110
"52\
106111
21020202020202020202020202020202020202020202020202020202020202020202\
107112
21020102030405060708010203040506070801020304050607080000000000000000\

src/descriptor/bare.rs

+58-12
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ impl<Pk: MiniscriptKey> Bare<Pk> {
6363
}
6464
}
6565

66+
impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> {
67+
/// Obtain the corresponding script pubkey for this descriptor
68+
/// Non failing verion of [`DescriptorTrait::script_pubkey`] for this descriptor
69+
pub fn spk(&self) -> Script {
70+
self.ms.encode()
71+
}
72+
73+
/// Obtain the underlying miniscript for this descriptor
74+
/// Non failing verion of [`DescriptorTrait::explicit_script`] for this descriptor
75+
pub fn inner_script(&self) -> Script {
76+
self.spk()
77+
}
78+
79+
/// Obtain the pre bip-340 signature script code for this descriptor
80+
/// Non failing verion of [`DescriptorTrait::script_code`] for this descriptor
81+
pub fn ecdsa_sighash_script_code(&self) -> Script {
82+
self.spk()
83+
}
84+
}
85+
6686
impl<Pk: MiniscriptKey> fmt::Debug for Bare<Pk> {
6787
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6888
write!(f, "{:?}", self.ms)
@@ -130,7 +150,7 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
130150
where
131151
Pk: ToPublicKey,
132152
{
133-
self.ms.encode()
153+
self.spk()
134154
}
135155

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

143-
fn explicit_script(&self) -> Script
163+
fn explicit_script(&self) -> Result<Script, Error>
144164
where
145165
Pk: ToPublicKey,
146166
{
147-
self.ms.encode()
167+
Ok(self.inner_script())
148168
}
149169

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

177-
fn script_code(&self) -> Script
197+
fn script_code(&self) -> Result<Script, Error>
178198
where
179199
Pk: ToPublicKey,
180200
{
181-
self.script_pubkey()
201+
Ok(self.ecdsa_sighash_script_code())
182202
}
183203
}
184204

@@ -238,6 +258,33 @@ impl<Pk: MiniscriptKey> Pkh<Pk> {
238258
}
239259
}
240260

261+
impl<Pk: MiniscriptKey + ToPublicKey> Pkh<Pk> {
262+
/// Obtain the corresponding script pubkey for this descriptor
263+
/// Non failing verion of [`DescriptorTrait::script_pubkey`] for this descriptor
264+
pub fn spk(&self) -> Script {
265+
let addr = bitcoin::Address::p2pkh(&self.pk.to_public_key(), bitcoin::Network::Bitcoin);
266+
addr.script_pubkey()
267+
}
268+
269+
/// Obtain the corresponding script pubkey for this descriptor
270+
/// Non failing verion of [`DescriptorTrait::address`] for this descriptor
271+
pub fn addr(&self, network: bitcoin::Network) -> bitcoin::Address {
272+
bitcoin::Address::p2pkh(&self.pk.to_public_key(), network)
273+
}
274+
275+
/// Obtain the underlying miniscript for this descriptor
276+
/// Non failing verion of [`DescriptorTrait::explicit_script`] for this descriptor
277+
pub fn inner_script(&self) -> Script {
278+
self.spk()
279+
}
280+
281+
/// Obtain the pre bip-340 signature script code for this descriptor
282+
/// Non failing verion of [`DescriptorTrait::script_code`] for this descriptor
283+
pub fn ecdsa_sighash_script_code(&self) -> Script {
284+
self.spk()
285+
}
286+
}
287+
241288
impl<Pk: MiniscriptKey> fmt::Debug for Pkh<Pk> {
242289
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243290
write!(f, "pkh({:?})", self.pk)
@@ -305,15 +352,14 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
305352
where
306353
Pk: ToPublicKey,
307354
{
308-
Ok(bitcoin::Address::p2pkh(&self.pk.to_public_key(), network))
355+
Ok(self.addr(network))
309356
}
310357

311358
fn script_pubkey(&self) -> Script
312359
where
313360
Pk: ToPublicKey,
314361
{
315-
let addr = bitcoin::Address::p2pkh(&self.pk.to_public_key(), bitcoin::Network::Bitcoin);
316-
addr.script_pubkey()
362+
self.spk()
317363
}
318364

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

326-
fn explicit_script(&self) -> Script
372+
fn explicit_script(&self) -> Result<Script, Error>
327373
where
328374
Pk: ToPublicKey,
329375
{
330-
self.script_pubkey()
376+
Ok(self.inner_script())
331377
}
332378

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

363-
fn script_code(&self) -> Script
409+
fn script_code(&self) -> Result<Script, Error>
364410
where
365411
Pk: ToPublicKey,
366412
{
367-
self.script_pubkey()
413+
Ok(self.ecdsa_sighash_script_code())
368414
}
369415
}
370416

0 commit comments

Comments
 (0)