mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 14:09:25 +00:00
add monero seed support (#252)
* add monero seed support * fix some of the pr comments * remove languages module and unnecessary error returns * Clean classic seed impl Fixes a few issues regarding Zeroize usage/API safety. Mainly a cleanup. --------- Co-authored-by: Luke Parker <lukeparker5132@gmail.com>
This commit is contained in:
92
coins/monero/src/wallet/seed/mod.rs
Normal file
92
coins/monero/src/wallet/seed/mod.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use core::fmt;
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
pub(crate) mod classic;
|
||||
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
|
||||
|
||||
/// Error when decoding a seed.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||
pub enum SeedError {
|
||||
#[error("invalid number of words in seed")]
|
||||
InvalidSeedLength,
|
||||
#[error("unknown language")]
|
||||
UnknownLanguage,
|
||||
#[error("invalid checksum")]
|
||||
InvalidChecksum,
|
||||
#[error("english old seeds don't support checksums")]
|
||||
EnglishOldWithChecksum,
|
||||
#[error("invalid seed")]
|
||||
InvalidSeed,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum Language {
|
||||
Chinese,
|
||||
English,
|
||||
Dutch,
|
||||
French,
|
||||
Spanish,
|
||||
German,
|
||||
Italian,
|
||||
Portuguese,
|
||||
Japanese,
|
||||
Russian,
|
||||
Esperanto,
|
||||
Lojban,
|
||||
EnglishOld,
|
||||
}
|
||||
|
||||
/// A Monero seed.
|
||||
// TODO: Add polyseed to enum
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
pub enum Seed {
|
||||
Classic(ClassicSeed),
|
||||
}
|
||||
|
||||
impl fmt::Debug for Seed {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Seed::Classic(_) => f.debug_struct("Seed::Classic").finish_non_exhaustive(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Seed {
|
||||
/// Create a new seed.
|
||||
pub fn new<R: RngCore + CryptoRng>(rng: &mut R, lang: Language) -> Seed {
|
||||
Seed::Classic(ClassicSeed::new(rng, lang))
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
_ => Err(SeedError::InvalidSeedLength)?,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a Seed from entropy.
|
||||
pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<Seed> {
|
||||
ClassicSeed::from_entropy(lang, entropy).map(Seed::Classic)
|
||||
}
|
||||
|
||||
/// Convert a seed to a String.
|
||||
pub fn to_string(&self) -> Zeroizing<String> {
|
||||
match self {
|
||||
Seed::Classic(seed) => seed.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the entropy for this seed.
|
||||
pub fn entropy(&self) -> Zeroizing<[u8; 32]> {
|
||||
match self {
|
||||
Seed::Classic(seed) => seed.entropy(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user