Skip to content

Commit 1cd2df0

Browse files
committed
test: Add test for derivation path
1 parent 0076e0d commit 1cd2df0

File tree

4 files changed

+42
-20
lines changed

4 files changed

+42
-20
lines changed

bdk-ffi/src/bitcoin.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use crate::error::{
33
PsbtParseError, TransactionError,
44
};
55
use crate::error::{ParseAmountError, PsbtFinalizeError};
6+
use crate::keys::DerivationPath;
7+
68
use crate::{impl_from_core_type, impl_hash_like, impl_into_core_type};
79
use std::collections::HashMap;
810

@@ -523,7 +525,7 @@ pub struct KeySource {
523525
/// A fingerprint
524526
pub fingerprint: String,
525527
/// A BIP-32 derivation path.
526-
pub path: String,
528+
pub path: Arc<DerivationPath>,
527529
}
528530

529531
#[derive(Clone, Debug, uniffi::Record, Hash, Eq, PartialEq)]
@@ -655,7 +657,7 @@ impl From<&BdkInput> for Input {
655657
pk.to_string(),
656658
KeySource {
657659
fingerprint: fingerprint.to_string(),
658-
path: deriv_path.to_string(),
660+
path: Arc::new(deriv_path.clone().into()),
659661
},
660662
)
661663
})
@@ -723,7 +725,7 @@ impl From<&BdkInput> for Input {
723725
tap_leaf_hashes: v.0.iter().map(|h| h.to_string()).collect(),
724726
key_source: KeySource {
725727
fingerprint: v.1 .0.to_string(),
726-
path: v.1 .1.to_string(),
728+
path: Arc::new(v.1 .1.clone().into()),
727729
},
728730
};
729731
(key, value)

bdk-ffi/src/keys.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
use crate::error::{Bip32Error, Bip39Error, DescriptorKeyError};
2+
use crate::{impl_from_core_type, impl_into_core_type};
23

3-
use bdk_wallet::bitcoin::Network;
44
use bdk_wallet::bitcoin::bip32::DerivationPath as BdkDerivationPath;
55
use bdk_wallet::bitcoin::key::Secp256k1;
66
use bdk_wallet::bitcoin::secp256k1::rand;
77
use bdk_wallet::bitcoin::secp256k1::rand::Rng;
8+
use bdk_wallet::bitcoin::Network;
89
use bdk_wallet::keys::bip39::WordCount;
910
use bdk_wallet::keys::bip39::{Language, Mnemonic as BdkMnemonic};
1011
use bdk_wallet::keys::{
1112
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
1213
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
1314
};
14-
use bdk_wallet::miniscript::BareCtx;
1515
use bdk_wallet::miniscript::descriptor::{DescriptorXKey, Wildcard};
16+
use bdk_wallet::miniscript::BareCtx;
1617

1718
use std::fmt::Display;
1819
use std::str::FromStr;
@@ -64,7 +65,7 @@ impl Display for Mnemonic {
6465
}
6566

6667
/// A BIP-32 derivation path.
67-
#[derive(uniffi::Object)]
68+
#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Object)]
6869
pub struct DerivationPath(pub(crate) BdkDerivationPath);
6970

7071
#[uniffi::export]
@@ -80,40 +81,34 @@ impl DerivationPath {
8081
/// Returns derivation path for a master key (i.e. empty derivation path)
8182
#[uniffi::constructor]
8283
pub fn master() -> Arc<Self> {
83-
Arc::new(DerivationPath {
84-
inner_mutex: Mutex::new(BdkDerivationPath::master()),
85-
})
84+
Arc::new(BdkDerivationPath::master().into())
8685
}
8786

8887
/// Returns whether derivation path represents master key (i.e. it's length
8988
/// is empty). True for `m` path.
9089
pub fn is_master(&self) -> bool {
91-
self.get_derivation_path().is_master()
90+
self.0.is_master()
9291
}
9392

9493
/// Returns length of the derivation path
9594
pub fn len(&self) -> u64 {
96-
self.get_derivation_path().len() as u64
95+
self.0.len() as u64
9796
}
9897

9998
/// Returns `true` if the derivation path is empty
10099
pub fn is_empty(&self) -> bool {
101-
self.get_derivation_path().is_empty()
100+
self.0.is_empty()
102101
}
103102
}
104103

105104
impl Display for DerivationPath {
106105
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107-
let path = self.get_derivation_path();
108-
write!(f, "{}", path)
106+
write!(f, "{}", self.0)
109107
}
110108
}
111109

112-
impl DerivationPath {
113-
pub(crate) fn get_derivation_path(&self) -> MutexGuard<'_, BdkDerivationPath> {
114-
self.inner_mutex.lock().expect("derivation path")
115-
}
116-
}
110+
impl_from_core_type!(BdkDerivationPath, DerivationPath);
111+
impl_into_core_type!(DerivationPath, BdkDerivationPath);
117112

118113
/// A descriptor containing secret data.
119114
#[derive(Debug, uniffi::Object)]

bdk-ffi/src/tests/bitcoin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ fn test_psbt_input_bip32_derivation() {
442442
"Fingerprint does not match the expected value"
443443
);
444444

445-
let derivation_path = &derivation.unwrap().path;
445+
let derivation_path = &derivation.unwrap().path.to_string();
446446
let expected_derivation_path = "84'/1'/0'/0/0";
447447
assert_eq!(
448448
derivation_path, &expected_derivation_path,

bdk-ffi/src/tests/keys.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,28 @@ fn test_derive_hardened_path_using_public() {
112112
let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h");
113113
assert!(derived_dpk.is_err());
114114
}
115+
116+
#[test]
117+
fn test_derivation_path_parsing() {
118+
let path_str = "m/44h/0h/0h/0/0";
119+
let expected_path = "44'/0'/0'/0/0";
120+
let path_str_2 = "m";
121+
122+
let derivation_path = DerivationPath::new(path_str.to_string()).unwrap();
123+
assert_eq!(derivation_path.to_string(), expected_path);
124+
125+
let derivation_path2 = DerivationPath::new(path_str_2.to_string()).unwrap();
126+
assert!(derivation_path2.is_master());
127+
128+
let derivation_path3 = DerivationPath::master();
129+
assert!(derivation_path3.is_master());
130+
131+
assert!(!derivation_path.is_master());
132+
}
133+
134+
#[test]
135+
fn test_invalid_derivation_path() {
136+
let invalid_path_str = "m/44x/0h/0h/0/0";
137+
let result = DerivationPath::new(invalid_path_str.to_string());
138+
assert!(result.is_err());
139+
}

0 commit comments

Comments
 (0)