Skip to content

Commit 7f18a2a

Browse files
Replace tiny-bip39 with rust-bip39
Use rust-bip39 for mnemonic derivation everywhere. This requires our own WordCount enum as rust-bip39 doesn't have explicit mnemonic type definition.
1 parent 3c8416b commit 7f18a2a

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

src/keys/bip39.rs

+33-15
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,23 @@ use bitcoin::Network;
1919

2020
use miniscript::ScriptContext;
2121

22-
pub use bip39::{Language, Mnemonic, MnemonicType, Seed};
22+
pub use bip39::{Language, Mnemonic};
23+
24+
type Seed = [u8; 64];
25+
26+
/// Type describing entropy length (aka word count) in the mnemonic
27+
pub enum WordCount {
28+
/// 12 words mnemonic (128 bits entropy)
29+
Words12 = 128,
30+
/// 15 words mnemonic (160 bits entropy)
31+
Words15 = 160,
32+
/// 18 words mnemonic (192 bits entropy)
33+
Words18 = 192,
34+
/// 21 words mnemonic (224 bits entropy)
35+
Words21 = 224,
36+
/// 24 words mnemonic (256 bits entropy)
37+
Words24 = 256,
38+
}
2339

2440
use super::{
2541
any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
@@ -40,7 +56,7 @@ pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
4056
#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
4157
impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
4258
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
43-
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, self.as_bytes())?.into())
59+
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self[..])?.into())
4460
}
4561

4662
fn into_descriptor_key(
@@ -60,7 +76,7 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
6076
impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
6177
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
6278
let (mnemonic, passphrase) = self;
63-
let seed = Seed::new(&mnemonic, passphrase.as_deref().unwrap_or(""));
79+
let seed: Seed = mnemonic.to_seed(passphrase.unwrap_or("".to_string()));
6480

6581
seed.into_extended_key()
6682
}
@@ -101,15 +117,15 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
101117
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
102118
type Entropy = [u8; 32];
103119

104-
type Options = (MnemonicType, Language);
105-
type Error = Option<bip39::ErrorKind>;
120+
type Options = (WordCount, Language);
121+
type Error = Option<bip39::Error>;
106122

107123
fn generate_with_entropy(
108-
(mnemonic_type, language): Self::Options,
124+
(word_count, language): Self::Options,
109125
entropy: Self::Entropy,
110126
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
111-
let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
112-
let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
127+
let entropy = &entropy.as_ref()[..(word_count as usize / 8)];
128+
let mnemonic = Mnemonic::from_entropy_in(language, entropy)?;
113129

114130
Ok(GeneratedKey::new(mnemonic, any_network()))
115131
}
@@ -121,15 +137,17 @@ mod test {
121137

122138
use bitcoin::util::bip32;
123139

124-
use bip39::{Language, Mnemonic, MnemonicType};
140+
use bip39::{Language, Mnemonic};
125141

126142
use crate::keys::{any_network, GeneratableKey, GeneratedKey};
127143

144+
use super::WordCount;
145+
128146
#[test]
129147
fn test_keys_bip39_mnemonic() {
130148
let mnemonic =
131149
"aim bunker wash balance finish force paper analyst cabin spoon stable organ";
132-
let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
150+
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic).unwrap();
133151
let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
134152

135153
let key = (mnemonic, path);
@@ -143,7 +161,7 @@ mod test {
143161
fn test_keys_bip39_mnemonic_passphrase() {
144162
let mnemonic =
145163
"aim bunker wash balance finish force paper analyst cabin spoon stable organ";
146-
let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
164+
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic).unwrap();
147165
let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
148166

149167
let key = ((mnemonic, Some("passphrase".into())), path);
@@ -157,7 +175,7 @@ mod test {
157175
fn test_keys_generate_bip39() {
158176
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
159177
Mnemonic::generate_with_entropy(
160-
(MnemonicType::Words12, Language::English),
178+
(WordCount::Words12, Language::English),
161179
crate::keys::test::TEST_ENTROPY,
162180
)
163181
.unwrap();
@@ -169,7 +187,7 @@ mod test {
169187

170188
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
171189
Mnemonic::generate_with_entropy(
172-
(MnemonicType::Words24, Language::English),
190+
(WordCount::Words24, Language::English),
173191
crate::keys::test::TEST_ENTROPY,
174192
)
175193
.unwrap();
@@ -180,11 +198,11 @@ mod test {
180198
#[test]
181199
fn test_keys_generate_bip39_random() {
182200
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
183-
Mnemonic::generate((MnemonicType::Words12, Language::English)).unwrap();
201+
Mnemonic::generate((WordCount::Words12, Language::English)).unwrap();
184202
assert_eq!(generated_mnemonic.valid_networks, any_network());
185203

186204
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
187-
Mnemonic::generate((MnemonicType::Words24, Language::English)).unwrap();
205+
Mnemonic::generate((WordCount::Words24, Language::English)).unwrap();
188206
assert_eq!(generated_mnemonic.valid_networks, any_network());
189207
}
190208
}

0 commit comments

Comments
 (0)