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.
This commit is contained in:
parent
3c8416bf31
commit
d2ce2714f2
@ -19,7 +19,23 @@ use bitcoin::Network;
|
|||||||
|
|
||||||
use miniscript::ScriptContext;
|
use miniscript::ScriptContext;
|
||||||
|
|
||||||
pub use bip39::{Language, Mnemonic, MnemonicType, Seed};
|
pub use bip39::{Language, Mnemonic};
|
||||||
|
|
||||||
|
type Seed = [u8; 64];
|
||||||
|
|
||||||
|
/// Type describing entropy length (aka word count) in the mnemonic
|
||||||
|
pub enum WordsCount {
|
||||||
|
/// 12 words mnemonic (128 bits entropy)
|
||||||
|
Words12 = 128,
|
||||||
|
/// 15 words mnemonic (160 bits entropy)
|
||||||
|
Words15 = 160,
|
||||||
|
/// 18 words mnemonic (192 bits entropy)
|
||||||
|
Words18 = 192,
|
||||||
|
/// 21 words mnemonic (224 bits entropy)
|
||||||
|
Words21 = 224,
|
||||||
|
/// 24 words mnemonic (256 bits entropy)
|
||||||
|
Words24 = 256,
|
||||||
|
}
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
|
any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
|
||||||
@ -40,7 +56,7 @@ pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
|
|||||||
#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
|
||||||
impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
|
impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
|
||||||
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
||||||
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, self.as_bytes())?.into())
|
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self[..])?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_descriptor_key(
|
fn into_descriptor_key(
|
||||||
@ -60,7 +76,7 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
|
|||||||
impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
|
impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
|
||||||
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
||||||
let (mnemonic, passphrase) = self;
|
let (mnemonic, passphrase) = self;
|
||||||
let seed = Seed::new(&mnemonic, passphrase.as_deref().unwrap_or(""));
|
let seed: Seed = mnemonic.to_seed(passphrase.as_deref().unwrap_or(""));
|
||||||
|
|
||||||
seed.into_extended_key()
|
seed.into_extended_key()
|
||||||
}
|
}
|
||||||
@ -101,15 +117,15 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
|
|||||||
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
|
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
|
||||||
type Entropy = [u8; 32];
|
type Entropy = [u8; 32];
|
||||||
|
|
||||||
type Options = (MnemonicType, Language);
|
type Options = (WordsCount, Language);
|
||||||
type Error = Option<bip39::ErrorKind>;
|
type Error = Option<bip39::Error>;
|
||||||
|
|
||||||
fn generate_with_entropy(
|
fn generate_with_entropy(
|
||||||
(mnemonic_type, language): Self::Options,
|
(word_count, language): Self::Options,
|
||||||
entropy: Self::Entropy,
|
entropy: Self::Entropy,
|
||||||
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
||||||
let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
|
let entropy = &entropy.as_ref()[..(word_count as usize / 8)];
|
||||||
let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
|
let mnemonic = Mnemonic::from_entropy_in(language, entropy)?;
|
||||||
|
|
||||||
Ok(GeneratedKey::new(mnemonic, any_network()))
|
Ok(GeneratedKey::new(mnemonic, any_network()))
|
||||||
}
|
}
|
||||||
@ -121,15 +137,17 @@ mod test {
|
|||||||
|
|
||||||
use bitcoin::util::bip32;
|
use bitcoin::util::bip32;
|
||||||
|
|
||||||
use bip39::{Language, Mnemonic, MnemonicType};
|
use bip39::{Language, Mnemonic};
|
||||||
|
|
||||||
use crate::keys::{any_network, GeneratableKey, GeneratedKey};
|
use crate::keys::{any_network, GeneratableKey, GeneratedKey};
|
||||||
|
|
||||||
|
use super::WordsCount;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_keys_bip39_mnemonic() {
|
fn test_keys_bip39_mnemonic() {
|
||||||
let mnemonic =
|
let mnemonic =
|
||||||
"aim bunker wash balance finish force paper analyst cabin spoon stable organ";
|
"aim bunker wash balance finish force paper analyst cabin spoon stable organ";
|
||||||
let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
|
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic).unwrap();
|
||||||
let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
|
let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
|
||||||
|
|
||||||
let key = (mnemonic, path);
|
let key = (mnemonic, path);
|
||||||
@ -143,7 +161,7 @@ mod test {
|
|||||||
fn test_keys_bip39_mnemonic_passphrase() {
|
fn test_keys_bip39_mnemonic_passphrase() {
|
||||||
let mnemonic =
|
let mnemonic =
|
||||||
"aim bunker wash balance finish force paper analyst cabin spoon stable organ";
|
"aim bunker wash balance finish force paper analyst cabin spoon stable organ";
|
||||||
let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
|
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic).unwrap();
|
||||||
let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
|
let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
|
||||||
|
|
||||||
let key = ((mnemonic, Some("passphrase".into())), path);
|
let key = ((mnemonic, Some("passphrase".into())), path);
|
||||||
@ -157,7 +175,7 @@ mod test {
|
|||||||
fn test_keys_generate_bip39() {
|
fn test_keys_generate_bip39() {
|
||||||
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
||||||
Mnemonic::generate_with_entropy(
|
Mnemonic::generate_with_entropy(
|
||||||
(MnemonicType::Words12, Language::English),
|
(WordsCount::Words12, Language::English),
|
||||||
crate::keys::test::TEST_ENTROPY,
|
crate::keys::test::TEST_ENTROPY,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -169,7 +187,7 @@ mod test {
|
|||||||
|
|
||||||
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
||||||
Mnemonic::generate_with_entropy(
|
Mnemonic::generate_with_entropy(
|
||||||
(MnemonicType::Words24, Language::English),
|
(WordsCount::Words24, Language::English),
|
||||||
crate::keys::test::TEST_ENTROPY,
|
crate::keys::test::TEST_ENTROPY,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -180,11 +198,11 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_keys_generate_bip39_random() {
|
fn test_keys_generate_bip39_random() {
|
||||||
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
||||||
Mnemonic::generate((MnemonicType::Words12, Language::English)).unwrap();
|
Mnemonic::generate((WordsCount::Words12, Language::English)).unwrap();
|
||||||
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
||||||
|
|
||||||
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
||||||
Mnemonic::generate((MnemonicType::Words24, Language::English)).unwrap();
|
Mnemonic::generate((WordsCount::Words24, Language::English)).unwrap();
|
||||||
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user