Merge bitcoindevkit/bdk#1033: Backport new taproot descriptor template (BIP86)
7587f1603d66d17906378cc7c9227227931fd9cc feat(descriptor): backport from master branch new taproot descriptor template (BIP86) (Steve Myers) 177c96db5a2a8416f5ae8a14d7a3086f05dd0b10 Create taproot descriptor template (Vladimir Fomene) Pull request description: ### Description This PR solves #836 for the release/0.28 branch. This PR adds a P2TR descriptor template and a BIP86 taproot descriptor template. With this, users can now create a taproot descriptor with templates. ### Notes to the reviewers The commit from #840 is cherry-picked from the `master` branch to the `release/0.28` branch without any changes. ### Changelog notice Add taproot descriptor template (BIP-86). ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature ACKs for top commit: danielabrozzoni: utACK 7587f1603d66d17906378cc7c9227227931fd9cc Tree-SHA512: e5b07473e27bba8ca5ec58854fa318c5a82cb67ce751d352ef17e9926dd08f8e6b7a720a77170b6f6f018c58ed9f8741cee396dc8e8721f4022c33ef2904815f
This commit is contained in:
		
						commit
						d0f7543f69
					
				| @ -17,7 +17,7 @@ | |||||||
| use bitcoin::util::bip32; | use bitcoin::util::bip32; | ||||||
| use bitcoin::Network; | use bitcoin::Network; | ||||||
| 
 | 
 | ||||||
| use miniscript::{Legacy, Segwitv0}; | use miniscript::{Legacy, Segwitv0, Tap}; | ||||||
| 
 | 
 | ||||||
| use super::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap}; | use super::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap}; | ||||||
| use crate::descriptor::DescriptorError; | use crate::descriptor::DescriptorError; | ||||||
| @ -170,6 +170,35 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// P2TR template. Expands to a descriptor `tr(key)`
 | ||||||
|  | ///
 | ||||||
|  | /// ## Example
 | ||||||
|  | ///
 | ||||||
|  | /// ```
 | ||||||
|  | /// # use bdk::bitcoin::{PrivateKey, Network};
 | ||||||
|  | /// # use bdk::Wallet;
 | ||||||
|  | /// # use bdk::database::MemoryDatabase;
 | ||||||
|  | /// # use bdk::wallet::AddressIndex::New;
 | ||||||
|  | /// use bdk::template::P2TR;
 | ||||||
|  | ///
 | ||||||
|  | /// let key =
 | ||||||
|  | ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
 | ||||||
|  | /// let mut wallet = Wallet::new(P2TR(key), None, Network::Testnet, MemoryDatabase::default())?;
 | ||||||
|  | ///
 | ||||||
|  | /// assert_eq!(
 | ||||||
|  | ///     wallet.get_address(New)?.to_string(),
 | ||||||
|  | ///     "tb1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xq7hps46"
 | ||||||
|  | /// );
 | ||||||
|  | /// # Ok::<_, Box<dyn std::error::Error>>(())
 | ||||||
|  | /// ```
 | ||||||
|  | pub struct P2TR<K: IntoDescriptorKey<Tap>>(pub K); | ||||||
|  | 
 | ||||||
|  | impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> { | ||||||
|  |     fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> { | ||||||
|  |         descriptor!(tr(self.0)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// BIP44 template. Expands to `pkh(key/44'/{0,1}'/0'/{0,1}/*)`
 | /// BIP44 template. Expands to `pkh(key/44'/{0,1}'/0'/{0,1}/*)`
 | ||||||
| ///
 | ///
 | ||||||
| /// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
 | /// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
 | ||||||
| @ -407,6 +436,85 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// BIP86 template. Expands to `tr(key/86'/{0,1}'/0'/{0,1}/*)`
 | ||||||
|  | ///
 | ||||||
|  | /// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
 | ||||||
|  | ///
 | ||||||
|  | /// See [`Bip86Public`] for a template that can work with a `xpub`/`tpub`.
 | ||||||
|  | ///
 | ||||||
|  | /// ## Example
 | ||||||
|  | ///
 | ||||||
|  | /// ```
 | ||||||
|  | /// # use std::str::FromStr;
 | ||||||
|  | /// # use bdk::bitcoin::{PrivateKey, Network};
 | ||||||
|  | /// # use bdk::{Wallet,  KeychainKind};
 | ||||||
|  | /// # use bdk::database::MemoryDatabase;
 | ||||||
|  | /// # use bdk::wallet::AddressIndex::New;
 | ||||||
|  | /// use bdk::template::Bip86;
 | ||||||
|  | ///
 | ||||||
|  | /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
 | ||||||
|  | /// let mut wallet = Wallet::new(
 | ||||||
|  | ///     Bip86(key.clone(), KeychainKind::External),
 | ||||||
|  | ///     Some(Bip86(key, KeychainKind::Internal)),
 | ||||||
|  | ///     Network::Testnet,
 | ||||||
|  | ///     MemoryDatabase::default()
 | ||||||
|  | /// )?;
 | ||||||
|  | ///
 | ||||||
|  | /// assert_eq!(wallet.get_address(New)?.to_string(), "tb1p5unlj09djx8xsjwe97269kqtxqpwpu2epeskgqjfk4lnf69v4tnqpp35qu");
 | ||||||
|  | /// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDCiHofpEs47kx358bPdJmTZHmCDqQ8qw32upCSxHrSEdeeBs2T5Mq6QMB2ukeMqhNBiyhosBvJErteVhfURPGXPv3qLJPw5MVpHUewsbP2m/0/*)#dkgvr5hm");
 | ||||||
|  | /// # Ok::<_, Box<dyn std::error::Error>>(())
 | ||||||
|  | /// ```
 | ||||||
|  | pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind); | ||||||
|  | 
 | ||||||
|  | impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> { | ||||||
|  |     fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> { | ||||||
|  |         P2TR(segwit_v1::make_bipxx_private(86, self.0, self.1, network)?).build(network) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// BIP86 public template. Expands to `tr(key/{0,1}/*)`
 | ||||||
|  | ///
 | ||||||
|  | /// This assumes that the key used has already been derived with `m/86'/0'/0'` for Mainnet or `m/86'/1'/0'` for Testnet.
 | ||||||
|  | ///
 | ||||||
|  | /// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
 | ||||||
|  | ///
 | ||||||
|  | /// See [`Bip86`] for a template that does the full derivation, but requires private data
 | ||||||
|  | /// for the key.
 | ||||||
|  | ///
 | ||||||
|  | /// ## Example
 | ||||||
|  | ///
 | ||||||
|  | /// ```
 | ||||||
|  | /// # use std::str::FromStr;
 | ||||||
|  | /// # use bdk::bitcoin::{PrivateKey, Network};
 | ||||||
|  | /// # use bdk::{Wallet,  KeychainKind};
 | ||||||
|  | /// # use bdk::database::MemoryDatabase;
 | ||||||
|  | /// # use bdk::wallet::AddressIndex::New;
 | ||||||
|  | /// use bdk::template::Bip86Public;
 | ||||||
|  | ///
 | ||||||
|  | /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
 | ||||||
|  | /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
 | ||||||
|  | /// let mut wallet = Wallet::new(
 | ||||||
|  | ///     Bip86Public(key.clone(), fingerprint, KeychainKind::External),
 | ||||||
|  | ///     Some(Bip86Public(key, fingerprint, KeychainKind::Internal)),
 | ||||||
|  | ///     Network::Testnet,
 | ||||||
|  | ///     MemoryDatabase::default()
 | ||||||
|  | /// )?;
 | ||||||
|  | ///
 | ||||||
|  | /// assert_eq!(wallet.get_address(New)?.to_string(), "tb1pwjp9f2k5n0xq73ecuu0c5njvgqr3vkh7yaylmpqvsuuaafymh0msvcmh37");
 | ||||||
|  | /// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#2p65srku");
 | ||||||
|  | /// # Ok::<_, Box<dyn std::error::Error>>(())
 | ||||||
|  | /// ```
 | ||||||
|  | pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub KeychainKind); | ||||||
|  | 
 | ||||||
|  | impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86Public<K> { | ||||||
|  |     fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> { | ||||||
|  |         P2TR(segwit_v1::make_bipxx_public( | ||||||
|  |             86, self.0, self.1, self.2, network, | ||||||
|  |         )?) | ||||||
|  |         .build(network) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| macro_rules! expand_make_bipxx { | macro_rules! expand_make_bipxx { | ||||||
|     ( $mod_name:ident, $ctx:ty ) => { |     ( $mod_name:ident, $ctx:ty ) => { | ||||||
|         mod $mod_name { |         mod $mod_name { | ||||||
| @ -473,6 +581,7 @@ macro_rules! expand_make_bipxx { | |||||||
| 
 | 
 | ||||||
| expand_make_bipxx!(legacy, Legacy); | expand_make_bipxx!(legacy, Legacy); | ||||||
| expand_make_bipxx!(segwit_v0, Segwitv0); | expand_make_bipxx!(segwit_v0, Segwitv0); | ||||||
|  | expand_make_bipxx!(segwit_v1, Tap); | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test { | mod test { | ||||||
| @ -484,7 +593,6 @@ mod test { | |||||||
|     use crate::descriptor::{DescriptorError, DescriptorMeta}; |     use crate::descriptor::{DescriptorError, DescriptorMeta}; | ||||||
|     use crate::keys::ValidNetworks; |     use crate::keys::ValidNetworks; | ||||||
|     use assert_matches::assert_matches; |     use assert_matches::assert_matches; | ||||||
|     use bitcoin::network::constants::Network::Regtest; |  | ||||||
|     use miniscript::descriptor::{DescriptorPublicKey, KeyMap}; |     use miniscript::descriptor::{DescriptorPublicKey, KeyMap}; | ||||||
|     use miniscript::Descriptor; |     use miniscript::Descriptor; | ||||||
| 
 | 
 | ||||||
| @ -526,11 +634,14 @@ mod test { | |||||||
|     fn check( |     fn check( | ||||||
|         desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>, |         desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>, | ||||||
|         is_witness: bool, |         is_witness: bool, | ||||||
|  |         is_taproot: bool, | ||||||
|         is_fixed: bool, |         is_fixed: bool, | ||||||
|  |         network: Network, | ||||||
|         expected: &[&str], |         expected: &[&str], | ||||||
|     ) { |     ) { | ||||||
|         let (desc, _key_map, _networks) = desc.unwrap(); |         let (desc, _key_map, _networks) = desc.unwrap(); | ||||||
|         assert_eq!(desc.is_witness(), is_witness); |         assert_eq!(desc.is_witness(), is_witness); | ||||||
|  |         assert_eq!(desc.is_taproot(), is_taproot); | ||||||
|         assert_eq!(!desc.has_wildcard(), is_fixed); |         assert_eq!(!desc.has_wildcard(), is_fixed); | ||||||
|         for i in 0..expected.len() { |         for i in 0..expected.len() { | ||||||
|             let index = i as u32; |             let index = i as u32; | ||||||
| @ -539,7 +650,7 @@ mod test { | |||||||
|             } else { |             } else { | ||||||
|                 desc.at_derivation_index(index) |                 desc.at_derivation_index(index) | ||||||
|             }; |             }; | ||||||
|             let address = child_desc.address(Regtest).unwrap(); |             let address = child_desc.address(network).unwrap(); | ||||||
|             assert_eq!(address.to_string(), *expected.get(i).unwrap()); |             assert_eq!(address.to_string(), *expected.get(i).unwrap()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -553,7 +664,9 @@ mod test { | |||||||
|         check( |         check( | ||||||
|             P2Pkh(prvkey).build(Network::Bitcoin), |             P2Pkh(prvkey).build(Network::Bitcoin), | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|             true, |             true, | ||||||
|  |             Network::Regtest, | ||||||
|             &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"], |             &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"], | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
| @ -564,7 +677,9 @@ mod test { | |||||||
|         check( |         check( | ||||||
|             P2Pkh(pubkey).build(Network::Bitcoin), |             P2Pkh(pubkey).build(Network::Bitcoin), | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|             true, |             true, | ||||||
|  |             Network::Regtest, | ||||||
|             &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"], |             &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"], | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -578,7 +693,9 @@ mod test { | |||||||
|         check( |         check( | ||||||
|             P2Wpkh_P2Sh(prvkey).build(Network::Bitcoin), |             P2Wpkh_P2Sh(prvkey).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|  |             false, | ||||||
|             true, |             true, | ||||||
|  |             Network::Regtest, | ||||||
|             &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"], |             &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"], | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
| @ -589,7 +706,9 @@ mod test { | |||||||
|         check( |         check( | ||||||
|             P2Wpkh_P2Sh(pubkey).build(Network::Bitcoin), |             P2Wpkh_P2Sh(pubkey).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|  |             false, | ||||||
|             true, |             true, | ||||||
|  |             Network::Regtest, | ||||||
|             &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"], |             &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"], | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -603,7 +722,9 @@ mod test { | |||||||
|         check( |         check( | ||||||
|             P2Wpkh(prvkey).build(Network::Bitcoin), |             P2Wpkh(prvkey).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|  |             false, | ||||||
|             true, |             true, | ||||||
|  |             Network::Regtest, | ||||||
|             &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"], |             &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"], | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
| @ -614,11 +735,42 @@ mod test { | |||||||
|         check( |         check( | ||||||
|             P2Wpkh(pubkey).build(Network::Bitcoin), |             P2Wpkh(pubkey).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|  |             false, | ||||||
|             true, |             true, | ||||||
|  |             Network::Regtest, | ||||||
|             &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"], |             &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"], | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // P2TR `tr(key)`
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_p2tr_template() { | ||||||
|  |         let prvkey = | ||||||
|  |             bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um") | ||||||
|  |                 .unwrap(); | ||||||
|  |         check( | ||||||
|  |             P2TR(prvkey).build(Network::Bitcoin), | ||||||
|  |             false, | ||||||
|  |             true, | ||||||
|  |             true, | ||||||
|  |             Network::Regtest, | ||||||
|  |             &["bcrt1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xqnwtkqq"], | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         let pubkey = bitcoin::PublicKey::from_str( | ||||||
|  |             "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd", | ||||||
|  |         ) | ||||||
|  |         .unwrap(); | ||||||
|  |         check( | ||||||
|  |             P2TR(pubkey).build(Network::Bitcoin), | ||||||
|  |             false, | ||||||
|  |             true, | ||||||
|  |             true, | ||||||
|  |             Network::Regtest, | ||||||
|  |             &["bcrt1pw74tdcrxlzn5r8z6ku2vztr86fgq0m245s72mjktf4afwzsf8ugs4evwdf"], | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
 |     // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_bip44_template() { |     fn test_bip44_template() { | ||||||
| @ -627,6 +779,8 @@ mod test { | |||||||
|             Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin), |             Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin), | ||||||
|             false, |             false, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5", |                 "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5", | ||||||
|                 "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP", |                 "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP", | ||||||
| @ -637,6 +791,8 @@ mod test { | |||||||
|             Bip44(prvkey, KeychainKind::Internal).build(Network::Bitcoin), |             Bip44(prvkey, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|             false, |             false, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "muHF98X9KxEzdKrnFAX85KeHv96eXopaip", |                 "muHF98X9KxEzdKrnFAX85KeHv96eXopaip", | ||||||
|                 "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR", |                 "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR", | ||||||
| @ -654,6 +810,8 @@ mod test { | |||||||
|             Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), |             Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), | ||||||
|             false, |             false, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "miNG7dJTzJqNbFS19svRdTCisC65dsubtR", |                 "miNG7dJTzJqNbFS19svRdTCisC65dsubtR", | ||||||
|                 "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg", |                 "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg", | ||||||
| @ -664,6 +822,8 @@ mod test { | |||||||
|             Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), |             Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|             false, |             false, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H", |                 "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H", | ||||||
|                 "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG", |                 "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG", | ||||||
| @ -680,6 +840,8 @@ mod test { | |||||||
|             Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin), |             Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV", |                 "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV", | ||||||
|                 "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS", |                 "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS", | ||||||
| @ -690,6 +852,8 @@ mod test { | |||||||
|             Bip49(prvkey, KeychainKind::Internal).build(Network::Bitcoin), |             Bip49(prvkey, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG", |                 "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG", | ||||||
|                 "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p", |                 "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p", | ||||||
| @ -707,6 +871,8 @@ mod test { | |||||||
|             Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), |             Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt", |                 "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt", | ||||||
|                 "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX", |                 "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX", | ||||||
| @ -717,6 +883,8 @@ mod test { | |||||||
|             Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), |             Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ", |                 "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ", | ||||||
|                 "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH", |                 "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH", | ||||||
| @ -733,6 +901,8 @@ mod test { | |||||||
|             Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin), |             Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s", |                 "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s", | ||||||
|                 "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp", |                 "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp", | ||||||
| @ -743,6 +913,8 @@ mod test { | |||||||
|             Bip84(prvkey, KeychainKind::Internal).build(Network::Bitcoin), |             Bip84(prvkey, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa", |                 "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa", | ||||||
|                 "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45", |                 "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45", | ||||||
| @ -760,6 +932,8 @@ mod test { | |||||||
|             Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), |             Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h", |                 "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h", | ||||||
|                 "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana", |                 "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana", | ||||||
| @ -770,6 +944,8 @@ mod test { | |||||||
|             Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), |             Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|             true, |             true, | ||||||
|             false, |             false, | ||||||
|  |             false, | ||||||
|  |             Network::Regtest, | ||||||
|             &[ |             &[ | ||||||
|                 "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2", |                 "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2", | ||||||
|                 "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp", |                 "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp", | ||||||
| @ -777,4 +953,67 @@ mod test { | |||||||
|             ], |             ], | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     // BIP86 `tr(key/86'/0'/0'/{0,1}/*)`
 | ||||||
|  |     // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_bip86_template() { | ||||||
|  |         let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap(); | ||||||
|  |         check( | ||||||
|  |             Bip86(prvkey, KeychainKind::External).build(Network::Bitcoin), | ||||||
|  |             false, | ||||||
|  |             true, | ||||||
|  |             false, | ||||||
|  |             Network::Bitcoin, | ||||||
|  |             &[ | ||||||
|  |                 "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", | ||||||
|  |                 "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh", | ||||||
|  |                 "bc1p0d0rhyynq0awa9m8cqrcr8f5nxqx3aw29w4ru5u9my3h0sfygnzs9khxz8", | ||||||
|  |             ], | ||||||
|  |         ); | ||||||
|  |         check( | ||||||
|  |             Bip86(prvkey, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|  |             false, | ||||||
|  |             true, | ||||||
|  |             false, | ||||||
|  |             Network::Bitcoin, | ||||||
|  |             &[ | ||||||
|  |                 "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7", | ||||||
|  |                 "bc1ptdg60grjk9t3qqcqczp4tlyy3z47yrx9nhlrjsmw36q5a72lhdrs9f00nj", | ||||||
|  |                 "bc1pgcwgsu8naxp7xlp5p7ufzs7emtfza2las7r2e7krzjhe5qj5xz2q88kmk5", | ||||||
|  |             ], | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // BIP86 public `tr(key/{0,1}/*)`
 | ||||||
|  |     // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_bip86_public_template() { | ||||||
|  |         let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ").unwrap(); | ||||||
|  |         let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("73c5da0a").unwrap(); | ||||||
|  |         check( | ||||||
|  |             Bip86Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), | ||||||
|  |             false, | ||||||
|  |             true, | ||||||
|  |             false, | ||||||
|  |             Network::Bitcoin, | ||||||
|  |             &[ | ||||||
|  |                 "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", | ||||||
|  |                 "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh", | ||||||
|  |                 "bc1p0d0rhyynq0awa9m8cqrcr8f5nxqx3aw29w4ru5u9my3h0sfygnzs9khxz8", | ||||||
|  |             ], | ||||||
|  |         ); | ||||||
|  |         check( | ||||||
|  |             Bip86Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin), | ||||||
|  |             false, | ||||||
|  |             true, | ||||||
|  |             false, | ||||||
|  |             Network::Bitcoin, | ||||||
|  |             &[ | ||||||
|  |                 "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7", | ||||||
|  |                 "bc1ptdg60grjk9t3qqcqczp4tlyy3z47yrx9nhlrjsmw36q5a72lhdrs9f00nj", | ||||||
|  |                 "bc1pgcwgsu8naxp7xlp5p7ufzs7emtfza2las7r2e7krzjhe5qj5xz2q88kmk5", | ||||||
|  |             ], | ||||||
|  |         ); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user