From 619532cd74be787cd9974c28d910db59a7dddadb Mon Sep 17 00:00:00 2001 From: Joseph Goulden Date: Fri, 13 May 2022 15:40:31 +0100 Subject: [PATCH 1/2] feat: Add function to calculate checksum and last word of a manually generated mnemonic --- src/lib.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 05963e3..e93b4b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -529,6 +529,28 @@ impl Mnemonic { let (arr, len) = self.to_entropy_array(); arr[0..len].to_vec() } + + /// Calculates the final word (based on the checksum) of a manually generated mnemonic. + /// There are multiple valid checksums, the first one (alphabetically) is picked. + #[cfg(feature = "std")] + pub fn finalize_mnemonic<'a, S: Into>>(s: S) -> Result { + let mut words = s.into(); + Mnemonic::normalize_utf8_cow(&mut words); + let language = Mnemonic::language_of(&words)?; + + for word in language.word_list() { + let potential_mnemonic = format!("{} {}", words, word); + match Mnemonic::parse_in_normalized(language, &potential_mnemonic) { + Ok(mnemonic) => return Ok(mnemonic), + Err(e) => match e { + Error::InvalidChecksum => {}, // Keep searching. + _ => return Err(e) + } + } + } + Err(Error::InvalidChecksum) + } + } impl fmt::Display for Mnemonic { @@ -1023,4 +1045,30 @@ mod tests { assert_eq!(seed, &mnemonic.to_seed(passphrase)[..], "failed vector: {}", mnemonic_str); } } + + #[test] + fn test_finalize_mnemonic() { + let vectors = [ + ( + "ozone drill grab fiber curtain grace pudding thank cruise elder eight", + "about" + ), + ( + "light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud", + "access" + ), + ( + "hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay", + "balance" + ), + ( + "あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん", + "あおぞら" + ) + ]; + + for vector in &vectors { + assert_eq!(Mnemonic::parse(format!("{} {}", vector.0, vector.1)), Mnemonic::finalize_mnemonic(vector.0)); + } + } } From c0b9d39786c7390a9cedb885a5c739525581df95 Mon Sep 17 00:00:00 2001 From: Joseph Goulden Date: Mon, 16 May 2022 11:05:54 +0100 Subject: [PATCH 2/2] fix: simplify match clause in finalize_mnemonic --- src/lib.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e93b4b6..3fd61f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -542,10 +542,8 @@ impl Mnemonic { let potential_mnemonic = format!("{} {}", words, word); match Mnemonic::parse_in_normalized(language, &potential_mnemonic) { Ok(mnemonic) => return Ok(mnemonic), - Err(e) => match e { - Error::InvalidChecksum => {}, // Keep searching. - _ => return Err(e) - } + Err(Error::InvalidChecksum) => {}, // Keep searching. + Err(e) => return Err(e) } } Err(Error::InvalidChecksum) @@ -1061,10 +1059,10 @@ mod tests { "hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay", "balance" ), - ( + ( "あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん", - "あおぞら" - ) + "あおぞら" + ) ]; for vector in &vectors {