@@ -27,7 +27,7 @@ use bitcoin::{
2727 bip32,
2828 key:: XOnlyPublicKey ,
2929 secp256k1:: { self , Secp256k1 , Signing } ,
30- Network , NetworkKind , PrivateKey , PublicKey ,
30+ NetworkKind , PrivateKey , PublicKey ,
3131} ;
3232use miniscript:: {
3333 descriptor:: { Descriptor , DescriptorMultiXKey , DescriptorXKey , Wildcard } ,
@@ -618,7 +618,7 @@ pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
618618 /// Type specifying the amount of entropy required e.g. `[u8;32]`
619619 type Entropy : AsMut < [ u8 ] > + Default ;
620620
621- /// Extra options required by the `generate_with_entropy`
621+ /// Extra options required to generate the key.
622622 type Options ;
623623 /// Returned error in case of failure
624624 type Error : core:: fmt:: Debug ;
@@ -697,16 +697,35 @@ where
697697impl < Ctx : ScriptContext > GeneratableKey < Ctx > for bip32:: Xpriv {
698698 type Entropy = [ u8 ; 32 ] ;
699699
700- type Options = ( ) ;
700+ type Options = XprivGenerateOptions ;
701701 type Error = bip32:: Error ;
702702
703703 fn generate_with_entropy (
704- _ : Self :: Options ,
704+ options : Self :: Options ,
705705 entropy : Self :: Entropy ,
706706 ) -> Result < GeneratedKey < Self , Ctx > , Self :: Error > {
707- // Pick an arbitrary network kind here, but say that we support all of them.
708- let xprv = bip32:: Xpriv :: new_master ( NetworkKind :: Main , entropy. as_ref ( ) ) ?;
709- Ok ( GeneratedKey :: new ( xprv, any_network_kind ( ) ) )
707+ let ( kind, valid_networks) = if options. network . is_mainnet ( ) {
708+ ( NetworkKind :: Main , mainnet_network_kind ( ) )
709+ } else {
710+ ( NetworkKind :: Test , test_network_kind ( ) )
711+ } ;
712+ let xprv = bip32:: Xpriv :: new_master ( kind, entropy. as_ref ( ) ) ?;
713+ Ok ( GeneratedKey :: new ( xprv, valid_networks) )
714+ }
715+ }
716+
717+ /// Options for generating a [`bip32::Xpriv`].
718+ #[ derive( Debug , Copy , Clone ) ]
719+ pub struct XprivGenerateOptions {
720+ /// The network to be used when generating the xprv, default to `NetworkKind::Main`
721+ pub network : NetworkKind ,
722+ }
723+
724+ impl Default for XprivGenerateOptions {
725+ fn default ( ) -> Self {
726+ XprivGenerateOptions {
727+ network : NetworkKind :: Main ,
728+ }
710729 }
711730}
712731
@@ -717,11 +736,16 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
717736pub struct PrivateKeyGenerateOptions {
718737 /// Whether the generated key should be "compressed" or not.
719738 pub compressed : bool ,
739+ /// The kind of network to be used, defaults to `NetworkKind::Main`.
740+ pub network : NetworkKind ,
720741}
721742
722743impl Default for PrivateKeyGenerateOptions {
723744 fn default ( ) -> Self {
724- PrivateKeyGenerateOptions { compressed : true }
745+ PrivateKeyGenerateOptions {
746+ compressed : true ,
747+ network : NetworkKind :: Main ,
748+ }
725749 }
726750}
727751
@@ -735,15 +759,19 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey {
735759 options : Self :: Options ,
736760 entropy : Self :: Entropy ,
737761 ) -> Result < GeneratedKey < Self , Ctx > , Self :: Error > {
738- // pick a arbitrary network here, but say that we support all of them
739762 let inner = secp256k1:: SecretKey :: from_slice ( & entropy) ?;
740763 let private_key = PrivateKey {
741764 compressed : options. compressed ,
742- network : Network :: Bitcoin . into ( ) ,
765+ network : options . network ,
743766 inner,
744767 } ;
768+ let valid_networks = if private_key. network . is_mainnet ( ) {
769+ mainnet_network_kind ( )
770+ } else {
771+ test_network_kind ( )
772+ } ;
745773
746- Ok ( GeneratedKey :: new ( private_key, any_network_kind ( ) ) )
774+ Ok ( GeneratedKey :: new ( private_key, valid_networks ) )
747775 }
748776}
749777
@@ -1021,12 +1049,38 @@ mod test {
10211049
10221050 pub const TEST_ENTROPY : [ u8 ; 32 ] = [ 0xAA ; 32 ] ;
10231051
1052+ #[ test]
1053+ fn test_xpriv_generate_options ( ) {
1054+ use bitcoin:: bip32:: Xpriv ;
1055+ let secp = SecpCtx :: new ( ) ;
1056+ // Test
1057+ let options = XprivGenerateOptions {
1058+ network : NetworkKind :: Test ,
1059+ } ;
1060+ let xpriv: GeneratedKey < Xpriv , miniscript:: Segwitv0 > = Xpriv :: generate ( options) . unwrap ( ) ;
1061+ let desc_key = xpriv
1062+ . into_descriptor_key ( None , "m/84h/1h/0h" . parse ( ) . unwrap ( ) )
1063+ . unwrap ( ) ;
1064+ let desc_pk = desc_key. extract ( & secp) . unwrap ( ) . 0 ;
1065+ assert ! ( desc_pk. to_string( ) . contains( "tpub" ) ) ;
1066+ // Main
1067+ let options = XprivGenerateOptions {
1068+ network : NetworkKind :: Main ,
1069+ } ;
1070+ let xpriv: GeneratedKey < Xpriv , miniscript:: Segwitv0 > = Xpriv :: generate ( options) . unwrap ( ) ;
1071+ let desc_key = xpriv
1072+ . into_descriptor_key ( None , "m/84h/1h/0h" . parse ( ) . unwrap ( ) )
1073+ . unwrap ( ) ;
1074+ let desc_pk = desc_key. extract ( & secp) . unwrap ( ) . 0 ;
1075+ assert ! ( desc_pk. to_string( ) . contains( "xpub" ) ) ;
1076+ }
1077+
10241078 #[ test]
10251079 fn test_keys_generate_xprv ( ) {
10261080 let generated_xprv: GeneratedKey < _ , miniscript:: Segwitv0 > =
10271081 bip32:: Xpriv :: generate_with_entropy_default ( TEST_ENTROPY ) . unwrap ( ) ;
10281082
1029- assert_eq ! ( generated_xprv. valid_network_kinds, any_network_kind ( ) ) ;
1083+ assert_eq ! ( generated_xprv. valid_network_kinds, mainnet_network_kind ( ) ) ;
10301084 assert_eq ! ( generated_xprv. to_string( ) , "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q" ) ;
10311085 }
10321086
@@ -1035,7 +1089,7 @@ mod test {
10351089 let generated_wif: GeneratedKey < _ , miniscript:: Segwitv0 > =
10361090 bitcoin:: PrivateKey :: generate_with_entropy_default ( TEST_ENTROPY ) . unwrap ( ) ;
10371091
1038- assert_eq ! ( generated_wif. valid_network_kinds, any_network_kind ( ) ) ;
1092+ assert_eq ! ( generated_wif. valid_network_kinds, mainnet_network_kind ( ) ) ;
10391093 assert_eq ! (
10401094 generated_wif. to_string( ) ,
10411095 "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch"
0 commit comments