Skip to content

Commit 74bb68d

Browse files
committed
refactor: use macros for pub/private descriptor keys
1 parent b074c7a commit 74bb68d

File tree

4 files changed

+48
-64
lines changed

4 files changed

+48
-64
lines changed

bdk-ffi/src/bdk.udl

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -462,44 +462,6 @@ interface DerivationPath {
462462
constructor(string path);
463463
};
464464

465-
interface DescriptorSecretKey {
466-
constructor(Network network, [ByRef] Mnemonic mnemonic, string? password);
467-
468-
[Name=from_string, Throws=DescriptorKeyError]
469-
constructor(string secret_key);
470-
471-
[Throws=DescriptorKeyError]
472-
DescriptorSecretKey derive([ByRef] DerivationPath path);
473-
474-
[Throws=DescriptorKeyError]
475-
DescriptorSecretKey extend([ByRef] DerivationPath path);
476-
477-
DescriptorPublicKey as_public();
478-
479-
sequence<u8> secret_bytes();
480-
481-
string as_string();
482-
};
483-
484-
interface DescriptorPublicKey {
485-
[Name=from_string, Throws=DescriptorKeyError]
486-
constructor(string public_key);
487-
488-
[Throws=DescriptorKeyError]
489-
DescriptorPublicKey derive([ByRef] DerivationPath path);
490-
491-
[Throws=DescriptorKeyError]
492-
DescriptorPublicKey extend([ByRef] DerivationPath path);
493-
494-
string as_string();
495-
496-
/// Whether or not this key has multiple derivation paths.
497-
boolean is_multipath();
498-
499-
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
500-
string master_fingerprint();
501-
};
502-
503465
// ------------------------------------------------------------------------
504466
// bdk-ffi-defined types
505467
// ------------------------------------------------------------------------

bdk-ffi/src/descriptor.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,31 +338,31 @@ mod test {
338338
#[test]
339339
fn test_descriptor_templates() {
340340
let master: DescriptorSecretKey = get_descriptor_secret_key();
341-
println!("Master: {:?}", master.as_string());
341+
println!("Master: {:?}", master.to_string());
342342
// tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h
343343
let handmade_public_44 = master
344344
.derive(&DerivationPath::new("m/44h/1h/0h".to_string()).unwrap())
345345
.unwrap()
346346
.as_public();
347-
println!("Public 44: {}", handmade_public_44.as_string());
347+
println!("Public 44: {}", handmade_public_44);
348348
// Public 44: [d1d04177/44'/1'/0']tpubDCoPjomfTqh1e7o1WgGpQtARWtkueXQAepTeNpWiitS3Sdv8RKJ1yvTrGHcwjDXp2SKyMrTEca4LoN7gEUiGCWboyWe2rz99Kf4jK4m2Zmx/*
349349
let handmade_public_49 = master
350350
.derive(&DerivationPath::new("m/49h/1h/0h".to_string()).unwrap())
351351
.unwrap()
352352
.as_public();
353-
println!("Public 49: {}", handmade_public_49.as_string());
353+
println!("Public 49: {}", handmade_public_49);
354354
// Public 49: [d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/*
355355
let handmade_public_84 = master
356356
.derive(&DerivationPath::new("m/84h/1h/0h".to_string()).unwrap())
357357
.unwrap()
358358
.as_public();
359-
println!("Public 84: {}", handmade_public_84.as_string());
359+
println!("Public 84: {}", handmade_public_84);
360360
// Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/*
361361
let handmade_public_86 = master
362362
.derive(&DerivationPath::new("m/86h/1h/0h".to_string()).unwrap())
363363
.unwrap()
364364
.as_public();
365-
println!("Public 86: {}", handmade_public_86.as_string());
365+
println!("Public 86: {}", handmade_public_86);
366366
// Public 86: [d1d04177/86'/1'/0']tpubDCJzjbcGbdEfXMWaL6QmgVmuSfXkrue7m2YNoacWwyc7a2XjXaKojRqNEbo41CFL3PyYmKdhwg2fkGpLX4SQCbQjCGxAkWHJTw9WEeenrJb/*
367367
let template_private_44 =
368368
Descriptor::new_bip44(&master, KeychainKind::External, Network::Testnet);
@@ -405,7 +405,7 @@ mod test {
405405
println!("Template public 44: {}", template_public_44);
406406
println!("Template public 84: {}", template_public_84);
407407
println!("Template public 86: {}", template_public_86);
408-
// when using a public key, both to_string and as_string_private return the same string
408+
// when using a public key, both to_string and to_string_private return the same string
409409
assert_eq!(
410410
template_public_44.to_string_with_secret(),
411411
template_public_44.to_string()

bdk-ffi/src/keys.rs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,15 @@ impl DerivationPath {
6767
}
6868
}
6969

70-
#[derive(Debug)]
70+
/// A descriptor containing secret data.
71+
#[derive(Debug, uniffi::Object)]
72+
#[uniffi::export(Debug, Display)]
7173
pub struct DescriptorSecretKey(pub(crate) BdkDescriptorSecretKey);
7274

75+
#[uniffi::export]
7376
impl DescriptorSecretKey {
77+
/// Construct a secret descriptor using a mnemonic.
78+
#[uniffi::constructor]
7479
pub fn new(network: Network, mnemonic: &Mnemonic, password: Option<String>) -> Self {
7580
let mnemonic = mnemonic.0.clone();
7681
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
@@ -83,12 +88,15 @@ impl DescriptorSecretKey {
8388
Self(descriptor_secret_key)
8489
}
8590

91+
/// Attempt to parse a string as a descriptor secret key.
92+
#[uniffi::constructor]
8693
pub fn from_string(private_key: String) -> Result<Self, DescriptorKeyError> {
8794
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
8895
.map_err(DescriptorKeyError::from)?;
8996
Ok(Self(descriptor_secret_key))
9097
}
9198

99+
/// Derive a descriptor secret key at a given derivation path.
92100
pub fn derive(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
93101
let secp = Secp256k1::new();
94102
let descriptor_secret_key = &self.0;
@@ -116,6 +124,7 @@ impl DescriptorSecretKey {
116124
}
117125
}
118126

127+
/// Extend the descriptor secret key by the derivation path.
119128
pub fn extend(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
120129
let descriptor_secret_key = &self.0;
121130
let path = path.inner_mutex.lock().unwrap().deref().clone();
@@ -135,12 +144,14 @@ impl DescriptorSecretKey {
135144
}
136145
}
137146

147+
/// Return the descriptor public key corresponding to this secret.
138148
pub fn as_public(&self) -> Arc<DescriptorPublicKey> {
139149
let secp = Secp256k1::new();
140150
let descriptor_public_key = self.0.to_public(&secp).unwrap();
141151
Arc::new(DescriptorPublicKey(descriptor_public_key))
142152
}
143153

154+
/// Return the bytes of this descriptor secret key.
144155
pub fn secret_bytes(&self) -> Vec<u8> {
145156
let inner = &self.0;
146157
let secret_bytes: Vec<u8> = match inner {
@@ -157,22 +168,30 @@ impl DescriptorSecretKey {
157168

158169
secret_bytes
159170
}
171+
}
160172

161-
pub fn as_string(&self) -> String {
162-
self.0.to_string()
173+
impl Display for DescriptorSecretKey {
174+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175+
self.0.fmt(f)
163176
}
164177
}
165178

166-
#[derive(Debug)]
179+
/// A descriptor public key.
180+
#[derive(Debug, uniffi::Object)]
181+
#[uniffi::export(Debug, Display)]
167182
pub struct DescriptorPublicKey(pub(crate) BdkDescriptorPublicKey);
168183

184+
#[uniffi::export]
169185
impl DescriptorPublicKey {
186+
/// Attempt to parse a string as a descriptor public key.
187+
#[uniffi::constructor]
170188
pub fn from_string(public_key: String) -> Result<Self, DescriptorKeyError> {
171189
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
172190
.map_err(DescriptorKeyError::from)?;
173191
Ok(Self(descriptor_public_key))
174192
}
175193

194+
/// Derive the descriptor public key at the given derivation path.
176195
pub fn derive(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
177196
let secp = Secp256k1::new();
178197
let descriptor_public_key = &self.0;
@@ -201,6 +220,7 @@ impl DescriptorPublicKey {
201220
}
202221
}
203222

223+
/// Extend the descriptor public key by the given derivation path.
204224
pub fn extend(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
205225
let descriptor_public_key = &self.0;
206226
let path = path.inner_mutex.lock().unwrap().deref().clone();
@@ -220,19 +240,23 @@ impl DescriptorPublicKey {
220240
}
221241
}
222242

223-
pub fn as_string(&self) -> String {
224-
self.0.to_string()
225-
}
226-
243+
/// Whether or not this key has multiple derivation paths.
227244
pub fn is_multipath(&self) -> bool {
228245
self.0.is_multipath()
229246
}
230247

248+
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
231249
pub fn master_fingerprint(&self) -> String {
232250
self.0.master_fingerprint().to_string()
233251
}
234252
}
235253

254+
impl Display for DescriptorPublicKey {
255+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256+
self.0.fmt(f)
257+
}
258+
}
259+
236260
#[cfg(test)]
237261
mod test {
238262
use crate::error::DescriptorKeyError;
@@ -280,38 +304,38 @@ mod test {
280304
#[test]
281305
fn test_generate_descriptor_secret_key() {
282306
let master_dsk = get_inner();
283-
assert_eq!(master_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
284-
assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
307+
assert_eq!(master_dsk.to_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
308+
assert_eq!(master_dsk.as_public().to_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
285309
}
286310

287311
#[test]
288312
fn test_derive_self() {
289313
let master_dsk = get_inner();
290314
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m").unwrap();
291-
assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
315+
assert_eq!(derived_dsk.to_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
292316
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
293317
let derived_dpk: &DescriptorPublicKey = &derive_dpk(master_dpk, "m").unwrap();
294-
assert_eq!(derived_dpk.as_string(), "[d1d04177]tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
318+
assert_eq!(derived_dpk.to_string(), "[d1d04177]tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
295319
}
296320

297321
#[test]
298322
fn test_derive_descriptors_keys() {
299323
let master_dsk = get_inner();
300324
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
301-
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
325+
assert_eq!(derived_dsk.to_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
302326
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
303327
let derived_dpk: &DescriptorPublicKey = &derive_dpk(master_dpk, "m/0").unwrap();
304-
assert_eq!(derived_dpk.as_string(), "[d1d04177/0]tpubD9oaCiP1MPmQdndm7DCD3D3QU34pWd6BbKSRedoZF1UJcNhEk3PJwkALNYkhxeTKL29oGNR7psqvT1KZydCGqUDEKXN6dVQJY2R8ooLPy8m/*");
328+
assert_eq!(derived_dpk.to_string(), "[d1d04177/0]tpubD9oaCiP1MPmQdndm7DCD3D3QU34pWd6BbKSRedoZF1UJcNhEk3PJwkALNYkhxeTKL29oGNR7psqvT1KZydCGqUDEKXN6dVQJY2R8ooLPy8m/*");
305329
}
306330

307331
#[test]
308332
fn test_extend_descriptor_keys() {
309333
let master_dsk = get_inner();
310334
let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap();
311-
assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
335+
assert_eq!(extended_dsk.to_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
312336
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
313337
let extended_dpk: &DescriptorPublicKey = &extend_dpk(master_dpk, "m/0").unwrap();
314-
assert_eq!(extended_dpk.as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/0/*");
338+
assert_eq!(extended_dpk.to_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/0/*");
315339
let wif = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
316340
let extended_key = DescriptorSecretKey::from_string(wif.to_string()).unwrap();
317341
let result = extended_key.derive(&DerivationPath::new("m/0".to_string()).unwrap());
@@ -337,10 +361,10 @@ mod test {
337361
let master_dsk = get_inner();
338362
// derive DescriptorSecretKey with path "m/0" from master
339363
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
340-
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
364+
assert_eq!(derived_dsk.to_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
341365
// extend derived_dsk with path "m/0"
342366
let extended_dsk: &DescriptorSecretKey = &extend_dsk(derived_dsk, "m/0").unwrap();
343-
assert_eq!(extended_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*");
367+
assert_eq!(extended_dsk.to_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*");
344368
}
345369

346370
#[test]

bdk-ffi/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ use crate::error::PsbtParseError;
3434
use crate::error::RequestBuilderError;
3535
use crate::error::TransactionError;
3636
use crate::keys::DerivationPath;
37-
use crate::keys::DescriptorPublicKey;
38-
use crate::keys::DescriptorSecretKey;
3937
use crate::keys::Mnemonic;
4038
use crate::types::ChainPosition;
4139
use crate::types::Condition;

0 commit comments

Comments
 (0)