Skip to content

Commit 53b6077

Browse files
committed
feat: Add function to calculate checksum and last word of a manually generated mnemonic
1 parent da75ba3 commit 53b6077

File tree

1 file changed

+46
-4
lines changed

1 file changed

+46
-4
lines changed

src/lib.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl fmt::Debug for Error {
8787
}
8888

8989
impl error::Error for Error {
90-
fn cause(&self) -> Option<&error::Error> {
90+
fn cause(&self) -> Option<&dyn error::Error> {
9191
None
9292
}
9393

@@ -162,7 +162,7 @@ impl Mnemonic {
162162
}
163163

164164
/// Generate a new Mnemonic in the given language.
165-
/// For the different supported word counts, see documentation on [Mnemonoc].
165+
/// For the different supported word counts, see documentation on [Mnemonic].
166166
#[cfg(feature = "rand")]
167167
pub fn generate_in(language: Language, word_count: usize) -> Result<Mnemonic, Error> {
168168
if word_count < 6 || word_count % 6 != 0 || word_count > 24 {
@@ -177,7 +177,7 @@ impl Mnemonic {
177177
}
178178

179179
/// Generate a new Mnemonic in English.
180-
/// For the different supported word counts, see documentation on [Mnemonoc].
180+
/// For the different supported word counts, see documentation on [Mnemonic].
181181
#[cfg(feature = "rand")]
182182
pub fn generate(word_count: usize) -> Result<Mnemonic, Error> {
183183
Mnemonic::generate_in(Language::English, word_count)
@@ -349,6 +349,26 @@ impl Mnemonic {
349349
entropy.truncate(entropy_bytes);
350350
entropy
351351
}
352+
353+
/// Calculates the final word (based on the checksum) of a manually generated mnemonic.
354+
/// There are multiple valid checksums, the first one (alphabetically) is picked.
355+
pub fn finalize_mnemonic<'a, S: Into<Cow<'a, str>>>(s: S) -> Result<Mnemonic, Error> {
356+
let mut cow = s.into();
357+
Mnemonic::normalize_utf8_cow(&mut cow);
358+
let language = Self::language_of(&cow)?;
359+
360+
for word in language.word_list() {
361+
let mnemonic = format!("{} {}", cow, word);
362+
match Self::validate_in(language, &mnemonic) {
363+
Ok(()) => return Ok(Mnemonic(mnemonic)),
364+
Err(e) => match e {
365+
Error::InvalidChecksum => {},
366+
_ => return Err(e)
367+
}
368+
}
369+
}
370+
Err(Error::InvalidChecksum)
371+
}
352372
}
353373

354374
impl fmt::Display for Mnemonic {
@@ -519,7 +539,7 @@ mod tests {
519539
let entropy = Vec::<u8>::from_hex(&vector.0).unwrap();
520540
let mnemonic_str = vector.1;
521541
let seed = Vec::<u8>::from_hex(&vector.2).unwrap();
522-
542+
523543
let mnemonic = Mnemonic::from_entropy(&entropy).unwrap();
524544

525545
assert_eq!(&mnemonic.to_string(), mnemonic_str,
@@ -760,4 +780,26 @@ mod tests {
760780
"failed vector: {}", mnemonic_str);
761781
}
762782
}
783+
784+
#[test]
785+
fn test_finalize_mnemonic() {
786+
let vectors = [
787+
(
788+
"ozone drill grab fiber curtain grace pudding thank cruise elder eight",
789+
"about"
790+
),
791+
(
792+
"light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud",
793+
"access"
794+
),
795+
(
796+
"hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay",
797+
"balance"
798+
),
799+
];
800+
801+
for vector in &vectors {
802+
assert_eq!(format!("{} {}", vector.0, vector.1), Mnemonic::finalize_mnemonic(vector.0).unwrap().0);
803+
}
804+
}
763805
}

0 commit comments

Comments
 (0)