monero: require seed lang when decoding seed (#502)

* monero: require seed lang when decoding seed

- Require the seed language when decoding a Classic|Polyseed seed string
	- As per https://github.com/monero-project/monero/issues/9089 and https://github.com/tevador/polyseed/issues/11
	- Fixes #478
	- Implementation note: I reused the `SeedType` enum and required it as a param to `Seed::from_string` because it seemed simplest, but perhaps there is a cleaner way to require the seed lang.
- Made sure the print statements from #487 print the seed as early as possible to help debug future issues
- A future PR could support deducing which languages a seed decodes to in order to support the UX @kayabaNerve suggested in https://github.com/monero-project/monero/issues/9089:
	- "Wallets can also try to abstract [language specification], by decoding with all languages, and only asking the user if/when multiple valid options show up ("Is this seed Spanish or Italian?")."

* Lint
This commit is contained in:
Justin Berman
2024-01-04 00:32:42 -06:00
committed by GitHub
parent 7eb388e546
commit 265261d3ba
4 changed files with 203 additions and 138 deletions

View File

@@ -61,13 +61,23 @@ impl Seed {
}
/// Parse a seed from a `String`.
pub fn from_string(words: Zeroizing<String>) -> Result<Seed, SeedError> {
match words.split_whitespace().count() {
CLASSIC_SEED_LENGTH | CLASSIC_SEED_LENGTH_WITH_CHECKSUM => {
ClassicSeed::from_string(words).map(Seed::Classic)
pub fn from_string(seed_type: SeedType, words: Zeroizing<String>) -> Result<Seed, SeedError> {
let word_count = words.split_whitespace().count();
match seed_type {
SeedType::Classic(lang) => {
if word_count != CLASSIC_SEED_LENGTH && word_count != CLASSIC_SEED_LENGTH_WITH_CHECKSUM {
Err(SeedError::InvalidSeedLength)?
} else {
ClassicSeed::from_string(lang, words).map(Seed::Classic)
}
}
SeedType::Polyseed(lang) => {
if word_count != POLYSEED_LENGTH {
Err(SeedError::InvalidSeedLength)?
} else {
Polyseed::from_string(lang, words).map(Seed::Polyseed)
}
}
POLYSEED_LENGTH => Polyseed::from_string(words).map(Seed::Polyseed),
_ => Err(SeedError::InvalidSeedLength)?,
}
}