use super::{Bip39Error, Mnemonic};
use bitcoin::bip32::Xpriv;
use std::str::FromStr;
type Result<T> = std::result::Result<T, Bip39Error>;
pub trait Bip39 {
fn mnemonic_to_master(&self, salt: &str) -> Result<Xpriv>;
}
impl<T> Bip39 for T
where
T: AsRef<str>,
{
#[inline]
fn mnemonic_to_master(&self, salt: &str) -> Result<Xpriv> {
Mnemonic::from_str(self.as_ref())?.to_master(salt)
}
}
#[cfg(test)]
mod bip39_test_english {
use super::*;
#[test]
fn test_bip39() -> Result<()> {
#[cfg(not(feature = "testnet"))]
const TEST_DATA: &[[&str; 3]] = &[[
"theme rain hollow final expire proud detect wife hotel taxi witness strategy park head forest",
"๐๐๐ญ๐",
"xprv9s21ZrQH143K2k5PPw697AeKWWdeQueM2JCKu8bsmF7M7dDmPGHecHJJNGeujWTJ97Fy9PfobsgZfxhcpWaYyAauFMxcy4fo3x7JNnbYQyD",
]];
#[cfg(feature = "testnet")]
const TEST_DATA: &[[&str; 3]] = &[[
"theme rain hollow final expire proud detect wife hotel taxi witness strategy park head forest",
"๐๐๐ญ๐",
"tprv8ZgxMBicQKsPdZJv4VweGpGJpe3reRgMMr7SmZ2LFDbpuDxrNddQ82fkHSpZjsqcWYnk9VHZmEGN8pFMwivVnDrVn1AvdRPqy3ripW55kfq",
]];
for x in TEST_DATA {
let xpriv = x[0].mnemonic_to_master(x[1])?;
assert_eq!(xpriv.to_string(), x[2]);
}
Ok(())
}
}
#[cfg(not(feature = "testnet"))]
#[cfg(test)]
mod bip39_test_multilingual {
use super::*;
#[test]
fn test_bip39() -> Result<()> {
const TEST_DATA: &[[&str; 3]] = &[
[
"solda osso frasco encontro donzela oficina colono vidraria fruteira sinal visto sacola mirtilo flamingo ereto",
"",
"xprv9s21ZrQH143K2KFS6iHoFXZC9Y5AWVKwxZis4GMRkQeaTFHiNRTkrjCsnBZ46s7VNihoMapH64FE93ZbzZ28Ld2oiHh6FYQx4eA8jEisYsc",
],
[
"ๅฒ ่ทจ ๅฐ ๅ ่ ้ฆ ่ฐ ๆ ๆ
ข ๅญ ็
ๅ ้ป ๅฅ ็ฎ",
"้ปๅฅ็ฎ",
"xprv9s21ZrQH143K2SwhdXXWCKa3Sj3mw6123eUe4osWEbHavCv7FDqgFChzfedPDmgnHm9qnQrdveb8sVrywNxxBYCXTdaeNyxRRmhF4q33ovb",
],
[
"แแ
ณแฏแ
แ
ฅแธ แแ
กแจแแ
ก แแ
ฉแแ
ฅแฏ แแ
ฎแแ
ฉแจ แแ
งแฏแแ
ฉ แแ
ตแฏแแ
ฅแผ แแ
ฉแแ
ณแท แแ
ชแจแแ
กแผ แแ
ฉแแ
งแผ แแ
ฉแทแแ
ณแฏแ
แ
ฆแจแแ
ณ แแ
ฌแแ
ฉแจ แแ
ฉแบแแ
ฎแฏ แแ
ฑแแ
ฅแผ แแ
ฅแผแแ
งแฏ แแ
ตแแ
กแ
แ
กแท",
"๐",
"xprv9s21ZrQH143K43d7XRnapkCsoE2bLUJfA57hYseNpDaJxf5rpuhHgHjSXNMGMpaGYNNZfxxBzv1e2kW5CSy7p1rddfWYXtvYhgC6MPfHd9Z",
],
[
"theme rain hollow final expire proud detect wife hotel taxi witness strategy park head forest",
"๐๐๐ญ๐",
"xprv9s21ZrQH143K2k5PPw697AeKWWdeQueM2JCKu8bsmF7M7dDmPGHecHJJNGeujWTJ97Fy9PfobsgZfxhcpWaYyAauFMxcy4fo3x7JNnbYQyD",
],
];
for x in TEST_DATA {
let xpriv = x[0].mnemonic_to_master(x[1])?;
assert_eq!(xpriv.to_string(), x[2]);
}
const INVALID_CHECKSUM: &[&str] = &[
"solda osso frasco encontro donzela oficina colono vidraria fruteira sinal visto sacola mirtilo flamingo final",
"theme rain hollow sinal expire proud detect wife hotel taxi witness strategy park head forest",
"ๅฒ ่ทจ ๅฐ ๅ ่ ้ฆ ่ฐ ๆ ๆ
ข ๅญ ็
ๅฅ ๅ ้ป ็ฎ",
];
for x in INVALID_CHECKSUM {
let r = x.mnemonic_to_master("");
assert!(matches!(r, Err(Bip39Error::InvalidChecksum)));
}
const INVALID_LENGTH: &[&str] = &[
" ่ทจ ๅฐ ๅ ่ ้ฆ ่ฐ ๆ ๆ
ข ๅญ ็
ๅฅ ๅ ้ป ็ฎ",
"theme rain hollow sinal expire proud detect wife hotel taxi witness",
];
for x in INVALID_LENGTH {
let r = x.mnemonic_to_master("");
assert!(matches!(r, Err(Bip39Error::InvalidSize)));
}
Ok(())
}
}