@@ -27,9 +27,11 @@ pub fn attach_stdlib(scope: &ScopeRef<Mutable>) {
27
27
. set_fn ( "xpriv::from_seed" , fns:: xpriv_from_seed)
28
28
. unwrap ( ) ;
29
29
30
- scope. set_fn ( "xonly" , fns:: xonly) . unwrap ( ) ;
31
-
32
30
scope. set_fn ( "singles" , fns:: singles) . unwrap ( ) ;
31
+
32
+ scope. set_fn ( "xonly" , fns:: xonly) . unwrap ( ) ; // xonly is always derived single
33
+ scope. set_fn ( "derived" , fns:: derived) . unwrap ( ) ;
34
+ scope. set_fn ( "xderived" , fns:: xderived) . unwrap ( ) ;
33
35
}
34
36
35
37
/// BIP32 key derivation using the Slash operator
@@ -116,37 +118,115 @@ pub mod fns {
116
118
Ok ( Xpriv :: new_master ( network, & seed) ?. into ( ) )
117
119
}
118
120
121
+ /// Convert a multi-path PubKey/SecKey/Descriptor into an array of singles
122
+ ///
123
+ /// singles(PubKey<Multi>|SecKey<Multi>|Descriptor<Multi>) -> Array<PubKey|SecKey|Descriptor>
124
+ pub fn singles ( args : Array , _: & ScopeRef ) -> Result < Value > {
125
+ Ok ( match args. arg_into ( ) ? {
126
+ Value :: PubKey ( pk) => pk. into_single_keys ( ) . into ( ) ,
127
+ Value :: SecKey ( sk) => sk. into_single_keys ( ) . into ( ) ,
128
+ Value :: Descriptor ( desc) => desc. into_single_descriptors ( ) ?. into ( ) ,
129
+ other => bail ! ( Error :: InvalidValue ( other. into( ) ) ) ,
130
+ } )
131
+ }
132
+
119
133
/// Convert the pubkey into an x-only pubkey.
120
- /// Always returned as a single (non-xpub ) pubkey (x-only xpubs cannot be represented as an Xpub/ DescriptorPublicKey).
134
+ /// Always returned as a single (non-Xpub ) pubkey (x-only keys cannot be represented as a DescriptorPublicKey::XPub ).
121
135
///
122
- /// xonly(PubKey) -> PubKey
136
+ /// xonly(PubKey<Xpub|Single> ) -> PubKey<Single>
123
137
pub fn xonly ( args : Array , _: & ScopeRef ) -> Result < Value > {
124
138
let pk: DescriptorPublicKey = args. arg_into ( ) ?;
125
139
126
140
Ok ( if pk. is_x_only_key ( ) {
127
141
pk
128
142
} else {
129
- // Convert into an x-only single pubkey with BIP32 origin information
130
- let pk = pk. definite ( ) ?;
131
- let derived_single_pk = pk. derive_public_key ( & EC ) ?;
132
- let derived_path = pk. full_derivation_path ( ) . ok_or ( Error :: InvalidMultiXpub ) ?;
143
+ let full_path = pk. full_derivation_path ( ) . ok_or ( Error :: InvalidMultiXpub ) ?;
144
+ let master_fp = pk. master_fingerprint ( ) ;
145
+ let derived_pk = pk. derive_definite ( ) ?;
133
146
134
147
DescriptorPublicKey :: Single ( SinglePub {
135
- key : SinglePubKey :: XOnly ( derived_single_pk . into ( ) ) ,
136
- origin : Some ( ( pk . master_fingerprint ( ) , derived_path ) ) ,
148
+ key : SinglePubKey :: XOnly ( derived_pk . into ( ) ) ,
149
+ origin : Some ( ( master_fp , full_path ) ) ,
137
150
} )
138
151
}
139
152
. into ( ) )
140
153
}
141
154
142
- /// Convert a multi-path PubKey/SecKey/Descriptor into an array of singles
155
+ /// Apply Xpub/Xpriv derivation steps to arrive at the final child as a single key
143
156
///
144
- /// singles(PubKey<Multi>|SecKey<Multi>|Descriptor<Multi>) -> Array<PubKey|SecKey|Descriptor>
145
- pub fn singles ( args : Array , _: & ScopeRef ) -> Result < Value > {
157
+ /// derived(PubKey<Xpub>) -> PubKey<Single>
158
+ /// derived(SecKey<Xpriv>) -> SecKey<Single>
159
+ pub fn derived ( args : Array , _: & ScopeRef ) -> Result < Value > {
146
160
Ok ( match args. arg_into ( ) ? {
147
- Value :: PubKey ( pk) => pk. into_single_keys ( ) . into ( ) ,
148
- Value :: SecKey ( sk) => sk. into_single_keys ( ) . into ( ) ,
149
- Value :: Descriptor ( desc) => desc. into_single_descriptors ( ) ?. into ( ) ,
161
+ // Derive Xpubs
162
+ Value :: PubKey ( ref pk @ DescriptorPublicKey :: XPub ( ref xpub) ) => {
163
+ let derived_pk = xpub. xkey . derive_pub ( & EC , & xpub. derivation_path ) ?. public_key ;
164
+ let full_path = pk
165
+ . full_derivation_path ( )
166
+ . expect ( "must exists for DPK::Xpub" ) ;
167
+ DescriptorPublicKey :: Single ( SinglePub {
168
+ key : SinglePubKey :: FullKey ( derived_pk. into ( ) ) ,
169
+ origin : Some ( ( pk. master_fingerprint ( ) , full_path) ) ,
170
+ } )
171
+ . into ( )
172
+ }
173
+ // Derive Xprivs
174
+ Value :: SecKey ( ref sk @ DescriptorSecretKey :: XPrv ( ref xpriv) ) => {
175
+ let derived_sk = xpriv
176
+ . xkey
177
+ . derive_priv ( & EC , & xpriv. derivation_path ) ?
178
+ . private_key ;
179
+ let full_path = sk
180
+ . full_derivation_path ( )
181
+ . expect ( "must exists for DPK::Xprv" ) ;
182
+ DescriptorSecretKey :: Single ( SinglePriv {
183
+ key : bitcoin:: PrivateKey :: new ( derived_sk, Network :: Testnet ) , // XXX always uses Testnet
184
+ origin : Some ( ( sk. master_fingerprint ( ) , full_path) ) ,
185
+ } )
186
+ . into ( )
187
+ }
188
+ // Return Single keys as-is
189
+ single @ Value :: PubKey ( DescriptorPublicKey :: Single ( _) )
190
+ | single @ Value :: SecKey ( DescriptorSecretKey :: Single ( _) ) => single,
191
+
192
+ other => bail ! ( Error :: InvalidValue ( other. into( ) ) ) ,
193
+ } )
194
+ }
195
+
196
+ /// Apply Xpub/Xpriv derivation steps to arrive at the final child Xpub/Xpriv
197
+ ///
198
+ /// xderived(PubKey<Xpub>) -> PubKey<Xpub>
199
+ /// xderived(SecKey<Xpriv>) -> SecKey<Xpriv>
200
+ pub fn xderived ( args : Array , _: & ScopeRef ) -> Result < Value > {
201
+ Ok ( match args. arg_into ( ) ? {
202
+ // Derive Xpubs
203
+ Value :: PubKey ( ref pk @ DescriptorPublicKey :: XPub ( ref xpub) ) => {
204
+ let derived_xpub = xpub. xkey . derive_pub ( & EC , & xpub. derivation_path ) ?;
205
+ let full_path = pk
206
+ . full_derivation_path ( )
207
+ . expect ( "must exists for DPK::Xpub" ) ;
208
+ DescriptorPublicKey :: XPub ( DescriptorXKey {
209
+ xkey : derived_xpub,
210
+ derivation_path : DerivationPath :: master ( ) ,
211
+ wildcard : xpub. wildcard ,
212
+ origin : Some ( ( pk. master_fingerprint ( ) , full_path) ) ,
213
+ } )
214
+ . into ( )
215
+ }
216
+ // Derive Xprivs
217
+ Value :: SecKey ( ref sk @ DescriptorSecretKey :: XPrv ( ref xprv) ) => {
218
+ let derived_xpriv = xprv. xkey . derive_priv ( & EC , & xprv. derivation_path ) ?;
219
+ let full_path = sk
220
+ . full_derivation_path ( )
221
+ . expect ( "must exists for DPK::Xprv" ) ;
222
+ DescriptorSecretKey :: XPrv ( DescriptorXKey {
223
+ xkey : derived_xpriv,
224
+ derivation_path : DerivationPath :: master ( ) ,
225
+ wildcard : xprv. wildcard ,
226
+ origin : Some ( ( sk. master_fingerprint ( ) , full_path) ) ,
227
+ } )
228
+ . into ( )
229
+ }
150
230
other => bail ! ( Error :: InvalidValue ( other. into( ) ) ) ,
151
231
} )
152
232
}
0 commit comments