Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use rust-bip39 instead of tiny-bip39 #462

Merged
merged 4 commits into from
Nov 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,7 @@ cc = { version = ">=1.0.64", optional = true }
socks = { version = "0.3", optional = true }
lazy_static = { version = "1.4", optional = true }

# the latest 0.8 version of tiny-bip39 depends on zeroize_derive 1.2 which has MSRV 1.51 and our
# MSRV is 1.46, to fix this until we update our MSRV or replace the tiny-bip39
# dependency https://github.com/bitcoindevkit/bdk/issues/399 we can only use an older version
tiny-bip39 = { version = "< 0.8", optional = true }
# backtrace > 0.3.61 includes object v0.27 which doesn't compile on 1.46. this is used by
# tiny-bip39
backtrace = { version = "=0.3.61", optional = true }

bip39 = { version = "1.0.1", optional = true }
bitcoinconsensus = { version = "0.19.0-3", optional = true }

# Needed by bdk_blockchain_tests macro
Expand All @@ -65,7 +58,7 @@ sqlite = ["rusqlite", "ahash"]
compact_filters = ["rocksdb", "socks", "lazy_static", "cc"]
key-value-db = ["sled"]
all-keys = ["keys-bip39"]
keys-bip39 = ["tiny-bip39", "backtrace"]
keys-bip39 = ["bip39"]
rpc = ["core-rpc"]

# We currently provide mulitple implementations of `Blockchain`, all are
Expand Down
48 changes: 33 additions & 15 deletions src/keys/bip39.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,23 @@ use bitcoin::Network;

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::{
any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
Expand All @@ -40,7 +56,7 @@ pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
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(
Expand All @@ -60,7 +76,7 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
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()
}
Expand Down Expand Up @@ -101,15 +117,15 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
type Entropy = [u8; 32];

type Options = (MnemonicType, Language);
type Error = Option<bip39::ErrorKind>;
type Options = (WordsCount, Language);
type Error = Option<bip39::Error>;

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

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

use bitcoin::util::bip32;

use bip39::{Language, Mnemonic, MnemonicType};
use bip39::{Language, Mnemonic};

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

use super::WordsCount;

#[test]
fn test_keys_bip39_mnemonic() {
let mnemonic =
"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 key = (mnemonic, path);
Expand All @@ -143,7 +161,7 @@ mod test {
fn test_keys_bip39_mnemonic_passphrase() {
let mnemonic =
"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 key = ((mnemonic, Some("passphrase".into())), path);
Expand All @@ -157,7 +175,7 @@ mod test {
fn test_keys_generate_bip39() {
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
Mnemonic::generate_with_entropy(
(MnemonicType::Words12, Language::English),
(WordsCount::Words12, Language::English),
crate::keys::test::TEST_ENTROPY,
)
.unwrap();
Expand All @@ -169,7 +187,7 @@ mod test {

let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
Mnemonic::generate_with_entropy(
(MnemonicType::Words24, Language::English),
(WordsCount::Words24, Language::English),
crate::keys::test::TEST_ENTROPY,
)
.unwrap();
Expand All @@ -180,11 +198,11 @@ mod test {
#[test]
fn test_keys_generate_bip39_random() {
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());

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());
}
}
4 changes: 2 additions & 2 deletions src/keys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,9 @@ use bdk::keys::bip39::{Mnemonic, Language};

# fn main() -> Result<(), Box<dyn std::error::Error>> {
let xkey: ExtendedKey =
Mnemonic::from_phrase(
Mnemonic::parse_in(
Language::English,
"jelly crash boy whisper mouse ecology tuna soccer memory million news short",
Language::English
)?
.into_extended_key()?;
let xprv = xkey.into_xprv(Network::Bitcoin).unwrap();
Expand Down