Skip to content

Instantly share code, notes, and snippets.

@jbesraa
Created April 23, 2022 08:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbesraa/1e807a730e45746371b2d1dbf65d47fd to your computer and use it in GitHub Desktop.
Save jbesraa/1e807a730e45746371b2d1dbf65d47fd to your computer and use it in GitHub Desktop.
diff --git a/src/descriptor/template.rs b/src/descriptor/template.rs
index fb4e7b0..2ab515a 100644
--- a/src/descriptor/template.rs
+++ b/src/descriptor/template.rs
@@ -51,7 +51,7 @@ pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);
/// ```
pub trait DescriptorTemplate {
/// Build the complete descriptor
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError>;
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError>;
}
/// Turns a [`DescriptorTemplate`] into a valid wallet descriptor by calling its
@@ -62,7 +62,7 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
secp: &SecpCtx,
network: Network,
) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
- self.build()?.into_wallet_descriptor(secp, network)
+ self.build(network)?.into_wallet_descriptor(secp, network)
}
}
@@ -95,7 +95,7 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
+ fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
descriptor!(pkh(self.0))
}
}
@@ -130,7 +130,7 @@ impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
+ fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
descriptor!(sh(wpkh(self.0)))
}
}
@@ -164,7 +164,7 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
+ fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
descriptor!(wpkh(self.0))
}
}
@@ -200,8 +200,8 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
- P2Pkh(legacy::make_bipxx_private(44, self.0, self.1)?).build()
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+ P2Pkh(legacy::make_bipxx_private(44, self.0, self.1, network)?).build(network)
}
}
@@ -240,8 +240,8 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
- P2Pkh(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+ P2Pkh(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build(network)
}
}
@@ -276,8 +276,8 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
- P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+ P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1, network)?).build(network)
}
}
@@ -316,8 +316,8 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
- P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+ P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build(network)
}
}
@@ -352,8 +352,8 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
- P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+ P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1, network)?).build(network)
}
}
@@ -392,8 +392,8 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
- fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
- P2Wpkh(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()
+ fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+ P2Wpkh(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build(network)
}
}
@@ -406,10 +406,19 @@ macro_rules! expand_make_bipxx {
bip: u32,
key: K,
keychain: KeychainKind,
+ network: Network,
) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
let mut derivation_path = Vec::with_capacity(4);
derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
- derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+
+ match network {
+ Network::Bitcoin => {
+ derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+ }
+ _ => {
+ derivation_path.push(bip32::ChildNumber::from_hardened_idx(1)?);
+ }
+ }
derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
match keychain {
@@ -466,6 +475,42 @@ mod test {
use miniscript::descriptor::{DescriptorPublicKey, DescriptorTrait, KeyMap};
use miniscript::Descriptor;
+ // BIP44 `pkh(key/44'/{0,1}'/0'/{0,1}/*)`
+ #[test]
+ fn test_bip44_template_cointype() {
+ use bitcoin::util::bip32::ChildNumber::{self, Hardened};
+
+ let xprvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K2fpbqApQL69a4oKdGVnVN52R82Ft7d1pSqgKmajF62acJo3aMszZb6qQ22QsVECSFxvf9uyxFUvFYQMq3QbtwtRSMjLAhMf").unwrap();
+ println!("bitcoin prvkey: {}", xprvkey.network);
+ assert_eq!(Network::Bitcoin, xprvkey.network);
+ let xdesc = Bip44(xprvkey, KeychainKind::Internal)
+ .build(Network::Bitcoin)
+ .unwrap();
+
+ if let ExtendedDescriptor::Pkh(pkh) = xdesc.0 {
+ let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().into();
+ let purpose = path.get(0).unwrap();
+ assert!(matches!(purpose, Hardened { index: 44 }));
+ let coin_type = path.get(1).unwrap();
+ assert!(matches!(coin_type, Hardened { index: 0 }));
+ }
+
+ let tprvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+ println!("testnet prvkey: {}", tprvkey.network);
+ assert_eq!(Network::Testnet, tprvkey.network);
+ let tdesc = Bip44(tprvkey, KeychainKind::Internal)
+ .build(Network::Testnet)
+ .unwrap();
+
+ if let ExtendedDescriptor::Pkh(pkh) = tdesc.0 {
+ let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().into();
+ let purpose = path.get(0).unwrap();
+ assert!(matches!(purpose, Hardened { index: 44 }));
+ let coin_type = path.get(1).unwrap();
+ assert!(matches!(coin_type, Hardened { index: 1 }));
+ }
+ }
+
// verify template descriptor generates expected address(es)
fn check(
desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
@@ -497,7 +542,7 @@ mod test {
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
.unwrap();
check(
- P2Pkh(prvkey).build(),
+ P2Pkh(prvkey).build(Network::Bitcoin),
false,
true,
&["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
@@ -508,7 +553,7 @@ mod test {
)
.unwrap();
check(
- P2Pkh(pubkey).build(),
+ P2Pkh(pubkey).build(Network::Bitcoin),
false,
true,
&["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
@@ -522,7 +567,7 @@ mod test {
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
.unwrap();
check(
- P2Wpkh_P2Sh(prvkey).build(),
+ P2Wpkh_P2Sh(prvkey).build(Network::Bitcoin),
true,
true,
&["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
@@ -533,7 +578,7 @@ mod test {
)
.unwrap();
check(
- P2Wpkh_P2Sh(pubkey).build(),
+ P2Wpkh_P2Sh(pubkey).build(Network::Bitcoin),
true,
true,
&["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
@@ -547,7 +592,7 @@ mod test {
bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
.unwrap();
check(
- P2Wpkh(prvkey).build(),
+ P2Wpkh(prvkey).build(Network::Bitcoin),
true,
true,
&["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
@@ -558,7 +603,7 @@ mod test {
)
.unwrap();
check(
- P2Wpkh(pubkey).build(),
+ P2Wpkh(pubkey).build(Network::Bitcoin),
true,
true,
&["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
@@ -570,7 +615,7 @@ mod test {
fn test_bip44_template() {
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
check(
- Bip44(prvkey, KeychainKind::External).build(),
+ Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin),
false,
false,
&[
@@ -580,7 +625,7 @@ mod test {
],
);
check(
- Bip44(prvkey, KeychainKind::Internal).build(),
+ Bip44(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
false,
false,
&[
@@ -597,7 +642,7 @@ mod test {
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
check(
- Bip44Public(pubkey, fingerprint, KeychainKind::External).build(),
+ Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
false,
false,
&[
@@ -607,7 +652,7 @@ mod test {
],
);
check(
- Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+ Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
false,
false,
&[
@@ -623,7 +668,7 @@ mod test {
fn test_bip49_template() {
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
check(
- Bip49(prvkey, KeychainKind::External).build(),
+ Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin),
true,
false,
&[
@@ -633,7 +678,7 @@ mod test {
],
);
check(
- Bip49(prvkey, KeychainKind::Internal).build(),
+ Bip49(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
true,
false,
&[
@@ -650,7 +695,7 @@ mod test {
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
check(
- Bip49Public(pubkey, fingerprint, KeychainKind::External).build(),
+ Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
true,
false,
&[
@@ -660,7 +705,7 @@ mod test {
],
);
check(
- Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+ Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
true,
false,
&[
@@ -676,7 +721,7 @@ mod test {
fn test_bip84_template() {
let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
check(
- Bip84(prvkey, KeychainKind::External).build(),
+ Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin),
true,
false,
&[
@@ -686,7 +731,7 @@ mod test {
],
);
check(
- Bip84(prvkey, KeychainKind::Internal).build(),
+ Bip84(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
true,
false,
&[
@@ -703,7 +748,7 @@ mod test {
let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
check(
- Bip84Public(pubkey, fingerprint, KeychainKind::External).build(),
+ Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
true,
false,
&[
@@ -713,7 +758,7 @@ mod test {
],
);
check(
- Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+ Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
true,
false,
&[
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment