@@ -676,45 +676,49 @@ impl DescriptorSecretKey {
676676 let secp = Secp256k1 :: new ( ) ;
677677 let descriptor_secret_key = self . descriptor_secret_key_mutex . lock ( ) . unwrap ( ) ;
678678 let path = path. derivation_path_mutex . lock ( ) . unwrap ( ) . deref ( ) . clone ( ) ;
679- let descriptor_x_key = match descriptor_secret_key. deref ( ) {
680- BdkDescriptorSecretKey :: XPrv ( descriptor_x_key) => Some ( descriptor_x_key) ,
681- _ => None ,
679+ match descriptor_secret_key. deref ( ) {
680+ BdkDescriptorSecretKey :: XPrv ( descriptor_x_key) => {
681+ let derived_xprv = descriptor_x_key. xkey . derive_priv ( & secp, & path) ?;
682+ let key_source = match descriptor_x_key. origin . clone ( ) {
683+ Some ( ( fingerprint, origin_path) ) => ( fingerprint, origin_path. extend ( path) ) ,
684+ None => ( descriptor_x_key. xkey . fingerprint ( & secp) , path) ,
685+ } ;
686+ let derived_descriptor_secret_key = BdkDescriptorSecretKey :: XPrv ( DescriptorXKey {
687+ origin : Some ( key_source) ,
688+ xkey : derived_xprv,
689+ derivation_path : BdkDerivationPath :: default ( ) ,
690+ wildcard : descriptor_x_key. wildcard ,
691+ } ) ;
692+ Ok ( Arc :: new ( Self {
693+ descriptor_secret_key_mutex : Mutex :: new ( derived_descriptor_secret_key) ,
694+ } ) )
695+ }
696+ BdkDescriptorSecretKey :: SinglePriv ( _) => {
697+ unreachable ! ( )
698+ }
682699 }
683- . unwrap ( ) ;
684- let derived_xprv = descriptor_x_key. xkey . derive_priv ( & secp, & path) ?;
685- let key_source = match descriptor_x_key. origin . clone ( ) {
686- Some ( ( fingerprint, origin_path) ) => ( fingerprint, origin_path. extend ( path) ) ,
687- None => ( descriptor_x_key. xkey . fingerprint ( & secp) , path) ,
688- } ;
689- let derived_descriptor_secret_key = BdkDescriptorSecretKey :: XPrv ( DescriptorXKey {
690- origin : Some ( key_source) ,
691- xkey : derived_xprv,
692- derivation_path : BdkDerivationPath :: default ( ) ,
693- wildcard : descriptor_x_key. wildcard ,
694- } ) ;
695- Ok ( Arc :: new ( Self {
696- descriptor_secret_key_mutex : Mutex :: new ( derived_descriptor_secret_key) ,
697- } ) )
698700 }
699701
700702 fn extend ( & self , path : Arc < DerivationPath > ) -> Arc < Self > {
701703 let descriptor_secret_key = self . descriptor_secret_key_mutex . lock ( ) . unwrap ( ) ;
702704 let path = path. derivation_path_mutex . lock ( ) . unwrap ( ) . deref ( ) . clone ( ) ;
703- let descriptor_x_key = match descriptor_secret_key. deref ( ) {
704- BdkDescriptorSecretKey :: XPrv ( descriptor_x_key) => Some ( descriptor_x_key) ,
705- _ => None ,
705+ match descriptor_secret_key. deref ( ) {
706+ BdkDescriptorSecretKey :: XPrv ( descriptor_x_key) => {
707+ let extended_path = descriptor_x_key. derivation_path . extend ( path) ;
708+ let extended_descriptor_secret_key = BdkDescriptorSecretKey :: XPrv ( DescriptorXKey {
709+ origin : descriptor_x_key. origin . clone ( ) ,
710+ xkey : descriptor_x_key. xkey ,
711+ derivation_path : extended_path,
712+ wildcard : descriptor_x_key. wildcard ,
713+ } ) ;
714+ Arc :: new ( Self {
715+ descriptor_secret_key_mutex : Mutex :: new ( extended_descriptor_secret_key) ,
716+ } )
717+ }
718+ BdkDescriptorSecretKey :: SinglePriv ( _) => {
719+ unreachable ! ( )
720+ }
706721 }
707- . unwrap ( ) ;
708- let extended_path = descriptor_x_key. derivation_path . extend ( path) ;
709- let extended_descriptor_secret_key = BdkDescriptorSecretKey :: XPrv ( DescriptorXKey {
710- origin : descriptor_x_key. origin . clone ( ) ,
711- xkey : descriptor_x_key. xkey ,
712- derivation_path : extended_path,
713- wildcard : descriptor_x_key. wildcard ,
714- } ) ;
715- Arc :: new ( Self {
716- descriptor_secret_key_mutex : Mutex :: new ( extended_descriptor_secret_key) ,
717- } )
718722 }
719723
720724 fn as_public ( & self ) -> Arc < DescriptorPublicKey > {
@@ -744,45 +748,50 @@ impl DescriptorPublicKey {
744748 let secp = Secp256k1 :: new ( ) ;
745749 let descriptor_public_key = self . descriptor_public_key_mutex . lock ( ) . unwrap ( ) ;
746750 let path = path. derivation_path_mutex . lock ( ) . unwrap ( ) . deref ( ) . clone ( ) ;
747- let descriptor_x_key = match descriptor_public_key. deref ( ) {
748- BdkDescriptorPublicKey :: XPub ( descriptor_x_key) => Some ( descriptor_x_key) ,
749- _ => None ,
751+
752+ match descriptor_public_key. deref ( ) {
753+ BdkDescriptorPublicKey :: XPub ( descriptor_x_key) => {
754+ let derived_xpub = descriptor_x_key. xkey . derive_pub ( & secp, & path) ?;
755+ let key_source = match descriptor_x_key. origin . clone ( ) {
756+ Some ( ( fingerprint, origin_path) ) => ( fingerprint, origin_path. extend ( path) ) ,
757+ None => ( descriptor_x_key. xkey . fingerprint ( ) , path) ,
758+ } ;
759+ let derived_descriptor_public_key = BdkDescriptorPublicKey :: XPub ( DescriptorXKey {
760+ origin : Some ( key_source) ,
761+ xkey : derived_xpub,
762+ derivation_path : BdkDerivationPath :: default ( ) ,
763+ wildcard : descriptor_x_key. wildcard ,
764+ } ) ;
765+ Ok ( Arc :: new ( Self {
766+ descriptor_public_key_mutex : Mutex :: new ( derived_descriptor_public_key) ,
767+ } ) )
768+ }
769+ BdkDescriptorPublicKey :: SinglePub ( _) => {
770+ unreachable ! ( )
771+ }
750772 }
751- . unwrap ( ) ;
752- let derived_xpub = descriptor_x_key. xkey . derive_pub ( & secp, & path) ?;
753- let key_source = match descriptor_x_key. origin . clone ( ) {
754- Some ( ( fingerprint, origin_path) ) => ( fingerprint, origin_path. extend ( path) ) ,
755- None => ( descriptor_x_key. xkey . fingerprint ( ) , path) ,
756- } ;
757- let derived_descriptor_public_key = BdkDescriptorPublicKey :: XPub ( DescriptorXKey {
758- origin : Some ( key_source) ,
759- xkey : derived_xpub,
760- derivation_path : BdkDerivationPath :: default ( ) ,
761- wildcard : descriptor_x_key. wildcard ,
762- } ) ;
763- Ok ( Arc :: new ( Self {
764- descriptor_public_key_mutex : Mutex :: new ( derived_descriptor_public_key) ,
765- } ) )
766773 }
767774
768775 fn extend ( & self , path : Arc < DerivationPath > ) -> Arc < Self > {
769- let descriptor_secret_key = self . descriptor_public_key_mutex . lock ( ) . unwrap ( ) ;
776+ let descriptor_public_key = self . descriptor_public_key_mutex . lock ( ) . unwrap ( ) ;
770777 let path = path. derivation_path_mutex . lock ( ) . unwrap ( ) . deref ( ) . clone ( ) ;
771- let descriptor_x_key = match descriptor_secret_key. deref ( ) {
772- BdkDescriptorPublicKey :: XPub ( descriptor_x_key) => Some ( descriptor_x_key) ,
773- _ => None ,
778+ match descriptor_public_key. deref ( ) {
779+ BdkDescriptorPublicKey :: XPub ( descriptor_x_key) => {
780+ let extended_path = descriptor_x_key. derivation_path . extend ( path) ;
781+ let extended_descriptor_public_key = BdkDescriptorPublicKey :: XPub ( DescriptorXKey {
782+ origin : descriptor_x_key. origin . clone ( ) ,
783+ xkey : descriptor_x_key. xkey ,
784+ derivation_path : extended_path,
785+ wildcard : descriptor_x_key. wildcard ,
786+ } ) ;
787+ Arc :: new ( Self {
788+ descriptor_public_key_mutex : Mutex :: new ( extended_descriptor_public_key) ,
789+ } )
790+ }
791+ BdkDescriptorPublicKey :: SinglePub ( _) => {
792+ unreachable ! ( )
793+ }
774794 }
775- . unwrap ( ) ;
776- let extended_path = descriptor_x_key. derivation_path . extend ( path) ;
777- let extended_descriptor_public_key = BdkDescriptorPublicKey :: XPub ( DescriptorXKey {
778- origin : descriptor_x_key. origin . clone ( ) ,
779- xkey : descriptor_x_key. xkey ,
780- derivation_path : extended_path,
781- wildcard : descriptor_x_key. wildcard ,
782- } ) ;
783- Arc :: new ( Self {
784- descriptor_public_key_mutex : Mutex :: new ( extended_descriptor_public_key) ,
785- } )
786795 }
787796
788797 fn as_string ( & self ) -> String {
@@ -797,7 +806,7 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
797806// crate.
798807#[ cfg( test) ]
799808mod test {
800- use crate :: { TxBuilder , Wallet } ;
809+ use crate :: * ;
801810 use bdk:: bitcoin:: Address ;
802811 use bdk:: bitcoin:: Network :: Testnet ;
803812 use bdk:: wallet:: get_funded_wallet;
@@ -857,4 +866,112 @@ mod test {
857866 let output_value = psbt. unsigned_tx . output . get ( 0 ) . cloned ( ) . unwrap ( ) . value ;
858867 assert_eq ! ( output_value, 49_890_u64 ) ; // input - fee
859868 }
869+
870+ fn get_descriptor_secret_key ( ) -> DescriptorSecretKey {
871+ let mnemonic =
872+ "chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect" . to_string ( ) ;
873+ DescriptorSecretKey :: new ( Network :: Testnet , mnemonic, None ) . unwrap ( )
874+ }
875+
876+ fn derive_dsk (
877+ key : & DescriptorSecretKey ,
878+ path : & str ,
879+ ) -> Result < Arc < DescriptorSecretKey > , BdkError > {
880+ let path = Arc :: new ( DerivationPath :: new ( path. to_string ( ) ) . unwrap ( ) ) ;
881+ key. derive ( path)
882+ }
883+
884+ fn extend_dsk ( key : & DescriptorSecretKey , path : & str ) -> Arc < DescriptorSecretKey > {
885+ let path = Arc :: new ( DerivationPath :: new ( path. to_string ( ) ) . unwrap ( ) ) ;
886+ key. extend ( path)
887+ }
888+
889+ fn derive_dpk (
890+ key : & DescriptorPublicKey ,
891+ path : & str ,
892+ ) -> Result < Arc < DescriptorPublicKey > , BdkError > {
893+ let path = Arc :: new ( DerivationPath :: new ( path. to_string ( ) ) . unwrap ( ) ) ;
894+ key. derive ( path)
895+ }
896+
897+ fn extend_dpk ( key : & DescriptorPublicKey , path : & str ) -> Arc < DescriptorPublicKey > {
898+ let path = Arc :: new ( DerivationPath :: new ( path. to_string ( ) ) . unwrap ( ) ) ;
899+ key. extend ( path)
900+ }
901+
902+ #[ test]
903+ fn test_generate_descriptor_secret_key ( ) {
904+ let master_dsk = get_descriptor_secret_key ( ) ;
905+ assert_eq ! ( master_dsk. as_string( ) , "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*" ) ;
906+ assert_eq ! ( master_dsk. as_public( ) . as_string( ) , "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*" ) ;
907+ }
908+
909+ #[ test]
910+ fn test_derive_self ( ) {
911+ let master_dsk = get_descriptor_secret_key ( ) ;
912+ let derived_dsk: & DescriptorSecretKey = & derive_dsk ( & master_dsk, "m" ) . unwrap ( ) ;
913+ assert_eq ! ( derived_dsk. as_string( ) , "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*" ) ;
914+
915+ let master_dpk: & DescriptorPublicKey = & master_dsk. as_public ( ) ;
916+ let derived_dpk: & DescriptorPublicKey = & derive_dpk ( master_dpk, "m" ) . unwrap ( ) ;
917+ assert_eq ! ( derived_dpk. as_string( ) , "[d1d04177]tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*" ) ;
918+ }
919+
920+ #[ test]
921+ fn test_derive_descriptors_keys ( ) {
922+ let master_dsk = get_descriptor_secret_key ( ) ;
923+ let derived_dsk: & DescriptorSecretKey = & derive_dsk ( & master_dsk, "m/0" ) . unwrap ( ) ;
924+ assert_eq ! ( derived_dsk. as_string( ) , "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*" ) ;
925+
926+ let master_dpk: & DescriptorPublicKey = & master_dsk. as_public ( ) ;
927+ let derived_dpk: & DescriptorPublicKey = & derive_dpk ( master_dpk, "m/0" ) . unwrap ( ) ;
928+ assert_eq ! ( derived_dpk. as_string( ) , "[d1d04177/0]tpubD9oaCiP1MPmQdndm7DCD3D3QU34pWd6BbKSRedoZF1UJcNhEk3PJwkALNYkhxeTKL29oGNR7psqvT1KZydCGqUDEKXN6dVQJY2R8ooLPy8m/*" ) ;
929+ }
930+
931+ #[ test]
932+ fn test_extend_descriptor_keys ( ) {
933+ let master_dsk = get_descriptor_secret_key ( ) ;
934+ let extended_dsk: & DescriptorSecretKey = & extend_dsk ( & master_dsk, "m/0" ) ;
935+ assert_eq ! ( extended_dsk. as_string( ) , "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*" ) ;
936+
937+ let master_dpk: & DescriptorPublicKey = & master_dsk. as_public ( ) ;
938+ let extended_dpk: & DescriptorPublicKey = & extend_dpk ( master_dpk, "m/0" ) ;
939+ assert_eq ! ( extended_dpk. as_string( ) , "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/0/*" ) ;
940+ }
941+
942+ #[ test]
943+ fn test_derive_and_extend_descriptor_secret_key ( ) {
944+ let master_dsk = get_descriptor_secret_key ( ) ;
945+
946+ // derive DescriptorSecretKey with path "m/0" from master
947+ let derived_dsk: & DescriptorSecretKey = & derive_dsk ( & master_dsk, "m/0" ) . unwrap ( ) ;
948+ assert_eq ! ( derived_dsk. as_string( ) , "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*" ) ;
949+
950+ // extend derived_dsk with path "m/0"
951+ let extended_dsk: & DescriptorSecretKey = & extend_dsk ( derived_dsk, "m/0" ) ;
952+ assert_eq ! ( extended_dsk. as_string( ) , "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*" ) ;
953+ let extended_dsk_mutex = extended_dsk. descriptor_secret_key_mutex . lock ( ) . unwrap ( ) ;
954+
955+ // checking extended derivation_path
956+ assert_eq ! (
957+ match extended_dsk_mutex. deref( ) {
958+ BdkDescriptorSecretKey :: XPrv ( xkey) => {
959+ Some ( xkey. derivation_path. clone( ) )
960+ }
961+ _ => {
962+ None
963+ }
964+ }
965+ . unwrap( )
966+ . to_string( ) ,
967+ BdkDerivationPath :: from_str( "m/0" ) . unwrap( ) . to_string( )
968+ ) ;
969+ }
970+
971+ #[ test]
972+ fn test_derive_hardened_path_using_public ( ) {
973+ let master_dpk = get_descriptor_secret_key ( ) . as_public ( ) ;
974+ let derived_dpk = & derive_dpk ( & master_dpk, "m/84h/1h/0h" ) ;
975+ assert ! ( derived_dpk. is_err( ) ) ;
976+ }
860977}
0 commit comments