Skip to content

Commit 1198be7

Browse files
committed
examples: Refactor xpub_descriptors
In an effort to make the example more clear refactor the main function into two separate functions. This is an example not a test; remove the assertion on creating the address with xpubs passed in the opposite order, instead include a comment explaining as such.
1 parent de74dc0 commit 1198be7

File tree

1 file changed

+44
-36
lines changed

1 file changed

+44
-36
lines changed

examples/xpub_descriptors.rs

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,63 @@
1212
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
1313
//
1414

15-
//! Example: Parsing a xpub and getting address
15+
//! Example: Parsing a xpub and getting an address.
1616
17-
use miniscript::bitcoin::{self, secp256k1};
17+
use std::str::FromStr;
18+
19+
use miniscript::bitcoin::secp256k1::{Secp256k1, Verification};
20+
use miniscript::bitcoin::{Address, Network};
1821
use miniscript::{Descriptor, DescriptorPublicKey, DescriptorTrait, TranslatePk2};
1922

20-
use std::str::FromStr;
23+
const XPUB_1: &str = "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB";
24+
const XPUB_2: &str = "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH";
25+
2126
fn main() {
22-
// For deriving from descriptors, we need to provide a secp context
23-
let secp_ctx = secp256k1::Secp256k1::verification_only();
24-
// P2WSH and single xpubs
25-
let addr_one = Descriptor::<DescriptorPublicKey>::from_str(
26-
"wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))",
27-
)
28-
.unwrap()
29-
.translate_pk2(|xpk| xpk.derive_public_key(&secp_ctx))
30-
.unwrap()
31-
.address(bitcoin::Network::Bitcoin).unwrap();
27+
// For deriving from descriptors, we need to provide a secp context.
28+
let secp = Secp256k1::verification_only();
3229

33-
let addr_two = Descriptor::<DescriptorPublicKey>::from_str(
34-
"wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB))",
35-
)
30+
// P2WSH and single xpubs.
31+
let _ = p2wsh(&secp);
32+
33+
// P2WSH-P2SH and ranged xpubs.
34+
let _ = p2sh_p2wsh(&secp);
35+
}
36+
37+
/// Parses a P2WSH descriptor, returns the associated address.
38+
fn p2wsh<C: Verification>(secp: &Secp256k1<C>) -> Address {
39+
// It does not matter what order the two xpubs go in, the same address will be generated.
40+
let s = format!("wsh(sortedmulti(1,{},{}))", XPUB_1, XPUB_2);
41+
// let s = format!("wsh(sortedmulti(1,{},{}))", XPUB_2, XPUB_1);
42+
43+
let address = Descriptor::<DescriptorPublicKey>::from_str(&s)
3644
.unwrap()
37-
.translate_pk2(|xpk| xpk.derive_public_key(&secp_ctx))
45+
.translate_pk2(|xpk| xpk.derive_public_key(secp))
3846
.unwrap()
39-
.address(bitcoin::Network::Bitcoin).unwrap();
47+
.address(Network::Bitcoin)
48+
.unwrap();
49+
4050
let expected = bitcoin::Address::from_str(
4151
"bc1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcspx5y6a",
4252
)
4353
.unwrap();
44-
assert_eq!(addr_one, expected);
45-
assert_eq!(addr_two, expected);
54+
assert_eq!(address, expected);
55+
address
56+
}
4657

47-
// P2WSH-P2SH and ranged xpubs
48-
let addr_one = Descriptor::<DescriptorPublicKey>::from_str(
49-
"sh(wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)))",
50-
)
51-
.unwrap()
52-
.derived_descriptor(&secp_ctx, 5)
53-
.unwrap()
54-
.address(bitcoin::Network::Bitcoin).unwrap();
58+
/// Parses a P2SH-P2WSH descriptor, returns the associated address.
59+
fn p2sh_p2wsh<C: Verification>(secp: &Secp256k1<C>) -> Address {
60+
// It does not matter what order the two xpubs go in, the same address will be generated.
61+
let s = format!("sh(wsh(sortedmulti(1,{}/1/0/*,{}/0/0/*)))", XPUB_1, XPUB_2);
62+
// let s = format!("sh(wsh(sortedmulti(1,{}/1/0/*,{}/0/0/*)))", XPUB_2, XPUB_1);
5563

56-
let addr_two = Descriptor::<DescriptorPublicKey>::from_str(
57-
"sh(wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*)))",
58-
)
64+
let address = Descriptor::<DescriptorPublicKey>::from_str(&s)
5965
.unwrap()
60-
.derived_descriptor(&secp_ctx, 5)
66+
.derived_descriptor(&secp, 5)
6167
.unwrap()
62-
.address(bitcoin::Network::Bitcoin).unwrap();
63-
let expected = bitcoin::Address::from_str("325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s").unwrap();
64-
assert_eq!(addr_one, expected);
65-
assert_eq!(addr_two, expected);
68+
.address(Network::Bitcoin)
69+
.unwrap();
70+
71+
let expected = Address::from_str("325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s").unwrap();
72+
assert_eq!(address, expected);
73+
address
6674
}

0 commit comments

Comments
 (0)