mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 21:49:26 +00:00
Smash out polyseed
This commit is contained in:
19
Cargo.lock
generated
19
Cargo.lock
generated
@@ -4867,7 +4867,6 @@ name = "monero-serai"
|
|||||||
version = "0.1.4-alpha"
|
version = "0.1.4-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"hex",
|
|
||||||
"hex-literal",
|
"hex-literal",
|
||||||
"monero-borromean",
|
"monero-borromean",
|
||||||
"monero-bulletproofs",
|
"monero-bulletproofs",
|
||||||
@@ -4877,8 +4876,6 @@ dependencies = [
|
|||||||
"monero-mlsag",
|
"monero-mlsag",
|
||||||
"monero-primitives",
|
"monero-primitives",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"std-shims",
|
"std-shims",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -4911,16 +4908,13 @@ dependencies = [
|
|||||||
"monero-rpc",
|
"monero-rpc",
|
||||||
"monero-serai",
|
"monero-serai",
|
||||||
"monero-simple-request-rpc",
|
"monero-simple-request-rpc",
|
||||||
"pbkdf2 0.12.2",
|
|
||||||
"rand",
|
"rand",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"rand_distr",
|
"rand_distr",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha3",
|
|
||||||
"std-shims",
|
"std-shims",
|
||||||
"subtle",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
@@ -5809,6 +5803,19 @@ dependencies = [
|
|||||||
"universal-hash",
|
"universal-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polyseed"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"pbkdf2 0.12.2",
|
||||||
|
"rand_core",
|
||||||
|
"sha3",
|
||||||
|
"std-shims",
|
||||||
|
"subtle",
|
||||||
|
"thiserror",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polyval"
|
name = "polyval"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ members = [
|
|||||||
"coins/monero/rpc",
|
"coins/monero/rpc",
|
||||||
"coins/monero/rpc/simple-request",
|
"coins/monero/rpc/simple-request",
|
||||||
"coins/monero/wallet",
|
"coins/monero/wallet",
|
||||||
|
"coins/monero/wallet/polyseed",
|
||||||
|
|
||||||
"message-queue",
|
"message-queue",
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ monero-borromean = { path = "ringct/borromean", version = "0.1", default-feature
|
|||||||
monero-bulletproofs = { path = "ringct/bulletproofs", version = "0.1", default-features = false }
|
monero-bulletproofs = { path = "ringct/bulletproofs", version = "0.1", default-features = false }
|
||||||
|
|
||||||
hex-literal = "0.4"
|
hex-literal = "0.4"
|
||||||
hex = { version = "0.4", default-features = false, features = ["alloc"] }
|
|
||||||
serde = { version = "1", default-features = false, features = ["derive", "alloc"] }
|
|
||||||
serde_json = { version = "1", default-features = false, features = ["alloc"] }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = [
|
std = [
|
||||||
@@ -50,10 +47,6 @@ std = [
|
|||||||
"monero-mlsag/std",
|
"monero-mlsag/std",
|
||||||
"monero-clsag/std",
|
"monero-clsag/std",
|
||||||
"monero-bulletproofs/std",
|
"monero-bulletproofs/std",
|
||||||
|
|
||||||
"hex/std",
|
|
||||||
"serde/std",
|
|
||||||
"serde_json/std",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
compile-time-generators = ["curve25519-dalek/precomputed-tables", "monero-bulletproofs/compile-time-generators"]
|
compile-time-generators = ["curve25519-dalek/precomputed-tables", "monero-bulletproofs/compile-time-generators"]
|
||||||
|
|||||||
@@ -3,7 +3,15 @@
|
|||||||
A modern Monero transaction library. It provides a modern, Rust-friendly view of
|
A modern Monero transaction library. It provides a modern, Rust-friendly view of
|
||||||
the Monero protocol.
|
the Monero protocol.
|
||||||
|
|
||||||
### Purpose and support
|
This library is usable under no-std when the `std` feature (on by default) is
|
||||||
|
disabled.
|
||||||
|
|
||||||
|
### Wallet Functionality
|
||||||
|
|
||||||
|
monero-serai originally included wallet functionality. That has been moved to
|
||||||
|
monero-wallet.
|
||||||
|
|
||||||
|
### Purpose and Support
|
||||||
|
|
||||||
monero-serai was written for Serai, a decentralized exchange aiming to support
|
monero-serai was written for Serai, a decentralized exchange aiming to support
|
||||||
Monero. Despite this, monero-serai is intended to be a widely usable library,
|
Monero. Despite this, monero-serai is intended to be a widely usable library,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ async-trait = { version = "0.1", default-features = false }
|
|||||||
thiserror = { version = "1", default-features = false, optional = true }
|
thiserror = { version = "1", default-features = false, optional = true }
|
||||||
|
|
||||||
zeroize = { version = "^1.5", default-features = false, features = ["zeroize_derive"] }
|
zeroize = { version = "^1.5", default-features = false, features = ["zeroize_derive"] }
|
||||||
subtle = { version = "^2.4", default-features = false }
|
|
||||||
|
|
||||||
rand_core = { version = "0.6", default-features = false }
|
rand_core = { version = "0.6", default-features = false }
|
||||||
# Used to send transactions
|
# Used to send transactions
|
||||||
@@ -31,9 +30,6 @@ rand_chacha = { version = "0.3", default-features = false }
|
|||||||
# Used to select decoys
|
# Used to select decoys
|
||||||
rand_distr = { version = "0.4", default-features = false }
|
rand_distr = { version = "0.4", default-features = false }
|
||||||
|
|
||||||
sha3 = { version = "0.10", default-features = false }
|
|
||||||
pbkdf2 = { version = "0.12", features = ["simple"], default-features = false }
|
|
||||||
|
|
||||||
group = { version = "0.13", default-features = false }
|
group = { version = "0.13", default-features = false }
|
||||||
curve25519-dalek = { version = "4", default-features = false, features = ["alloc", "zeroize", "group"] }
|
curve25519-dalek = { version = "4", default-features = false, features = ["alloc", "zeroize", "group"] }
|
||||||
|
|
||||||
@@ -66,16 +62,12 @@ std = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
||||||
"zeroize/std",
|
"zeroize/std",
|
||||||
"subtle/std",
|
|
||||||
|
|
||||||
"rand_core/std",
|
"rand_core/std",
|
||||||
"rand/std",
|
"rand/std",
|
||||||
"rand_chacha/std",
|
"rand_chacha/std",
|
||||||
"rand_distr/std",
|
"rand_distr/std",
|
||||||
|
|
||||||
"sha3/std",
|
|
||||||
"pbkdf2/std",
|
|
||||||
|
|
||||||
"hex/std",
|
"hex/std",
|
||||||
"base58-monero/std",
|
"base58-monero/std",
|
||||||
"serde/std",
|
"serde/std",
|
||||||
|
|||||||
@@ -1,6 +1,45 @@
|
|||||||
# Monero Wallet
|
# Monero Wallet
|
||||||
|
|
||||||
Wallet functionality for the Monero protocol, built around monero-serai.
|
Wallet functionality for the Monero protocol, built around monero-serai. This
|
||||||
|
library prides itself on resolving common pit falls developers may face.
|
||||||
|
|
||||||
|
monero-wallet also offers a FROST-inspired multisignature protocol orders of
|
||||||
|
magnitude more performant than Monero's own.
|
||||||
|
|
||||||
This library is usable under no-std when the `std` feature (on by default) is
|
This library is usable under no-std when the `std` feature (on by default) is
|
||||||
disabled.
|
disabled.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Scanning Monero transactions
|
||||||
|
- Sending Monero transactions
|
||||||
|
- Sending Monero transactions with a FROST-inspired threshold multisignature
|
||||||
|
protocol, orders of magnitude more performant than Monero's own.
|
||||||
|
|
||||||
|
### Caveats
|
||||||
|
|
||||||
|
This library DOES attempt to do the following:
|
||||||
|
|
||||||
|
- Create on-chain transactions identical to how wallet2 would (unless told not
|
||||||
|
to)
|
||||||
|
- Not be detectable as monero-serai when scanning outputs
|
||||||
|
- Not reveal spent outputs to the connected RPC node
|
||||||
|
|
||||||
|
This library DOES NOT attempt to do the following:
|
||||||
|
|
||||||
|
- Have identical RPC behavior when creating transactions
|
||||||
|
- Be a wallet
|
||||||
|
|
||||||
|
This means that monero-serai shouldn't be fingerprintable on-chain. It also
|
||||||
|
shouldn't be fingerprintable if a targeted attack occurs to detect if the
|
||||||
|
receiving wallet is monero-serai or wallet2. It also should be generally safe
|
||||||
|
for usage with remote nodes.
|
||||||
|
|
||||||
|
It won't hide from remote nodes it's monero-serai however, potentially
|
||||||
|
allowing a remote node to profile you. The implications of this are left to the
|
||||||
|
user to consider.
|
||||||
|
|
||||||
|
It also won't act as a wallet, just as a wallet functionality library. wallet2
|
||||||
|
has several *non-transaction-level* policies, such as always attempting to use
|
||||||
|
two inputs to create transactions. These are considered out of scope to
|
||||||
|
monero-serai.
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
# monero-serai
|
|
||||||
|
|
||||||
A modern Monero transaction library intended for usage in wallets. It prides
|
|
||||||
itself on accuracy, correctness, and removing common pit falls developers may
|
|
||||||
face.
|
|
||||||
|
|
||||||
monero-serai also offers the following features:
|
|
||||||
|
|
||||||
- Featured Addresses
|
|
||||||
- A FROST-based multisig orders of magnitude more performant than Monero's
|
|
||||||
|
|
||||||
### Purpose and support
|
|
||||||
|
|
||||||
monero-serai was written for Serai, a decentralized exchange aiming to support
|
|
||||||
Monero. Despite this, monero-serai is intended to be a widely usable library,
|
|
||||||
accurate to Monero. monero-serai guarantees the functionality needed for Serai,
|
|
||||||
yet will not deprive functionality from other users.
|
|
||||||
|
|
||||||
Various legacy transaction formats are not currently implemented, yet we are
|
|
||||||
willing to add support for them. There aren't active development efforts around
|
|
||||||
them however.
|
|
||||||
|
|
||||||
### Caveats
|
|
||||||
|
|
||||||
This library DOES attempt to do the following:
|
|
||||||
|
|
||||||
- Create on-chain transactions identical to how wallet2 would (unless told not
|
|
||||||
to)
|
|
||||||
- Not be detectable as monero-serai when scanning outputs
|
|
||||||
- Not reveal spent outputs to the connected RPC node
|
|
||||||
|
|
||||||
This library DOES NOT attempt to do the following:
|
|
||||||
|
|
||||||
- Have identical RPC behavior when creating transactions
|
|
||||||
- Be a wallet
|
|
||||||
|
|
||||||
This means that monero-serai shouldn't be fingerprintable on-chain. It also
|
|
||||||
shouldn't be fingerprintable if a targeted attack occurs to detect if the
|
|
||||||
receiving wallet is monero-serai or wallet2. It also should be generally safe
|
|
||||||
for usage with remote nodes.
|
|
||||||
|
|
||||||
It won't hide from remote nodes it's monero-serai however, potentially
|
|
||||||
allowing a remote node to profile you. The implications of this are left to the
|
|
||||||
user to consider.
|
|
||||||
|
|
||||||
It also won't act as a wallet, just as a transaction library. wallet2 has
|
|
||||||
several *non-transaction-level* policies, such as always attempting to use two
|
|
||||||
inputs to create transactions. These are considered out of scope to
|
|
||||||
monero-serai.
|
|
||||||
44
coins/monero/wallet/polyseed/Cargo.toml
Normal file
44
coins/monero/wallet/polyseed/Cargo.toml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
[package]
|
||||||
|
name = "polyseed"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Rust implementation of Polyseed"
|
||||||
|
license = "MIT"
|
||||||
|
repository = "https://github.com/serai-dex/serai/tree/develop/coins/monero/wallet.polyseed"
|
||||||
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.79"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
all-features = true
|
||||||
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
std-shims = { path = "../../../../common/std-shims", version = "^0.1.1", default-features = false }
|
||||||
|
|
||||||
|
thiserror = { version = "1", default-features = false, optional = true }
|
||||||
|
|
||||||
|
subtle = { version = "^2.4", default-features = false }
|
||||||
|
zeroize = { version = "^1.5", default-features = false, features = ["zeroize_derive"] }
|
||||||
|
rand_core = { version = "0.6", default-features = false }
|
||||||
|
|
||||||
|
sha3 = { version = "0.10", default-features = false }
|
||||||
|
pbkdf2 = { version = "0.12", features = ["simple"], default-features = false }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = [
|
||||||
|
"std-shims/std",
|
||||||
|
|
||||||
|
"thiserror",
|
||||||
|
|
||||||
|
"subtle/std",
|
||||||
|
"zeroize/std",
|
||||||
|
"rand_core/std",
|
||||||
|
|
||||||
|
"sha3/std",
|
||||||
|
"pbkdf2/std",
|
||||||
|
]
|
||||||
|
|
||||||
|
default = ["std"]
|
||||||
6
coins/monero/wallet/polyseed/README.md
Normal file
6
coins/monero/wallet/polyseed/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Polyseed
|
||||||
|
|
||||||
|
Rust implementation of [Polyseed](https://github.com/tevador/polyseed).
|
||||||
|
|
||||||
|
This library is usable under no-std when the `std` feature (on by default) is
|
||||||
|
disabled.
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std_shims::{sync::OnceLock, vec::Vec, string::String, collections::HashMap};
|
use std_shims::{sync::OnceLock, string::String, collections::HashMap};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
@@ -10,8 +15,6 @@ use rand_core::{RngCore, CryptoRng};
|
|||||||
use sha3::Sha3_256;
|
use sha3::Sha3_256;
|
||||||
use pbkdf2::pbkdf2_hmac;
|
use pbkdf2::pbkdf2_hmac;
|
||||||
|
|
||||||
use super::SeedError;
|
|
||||||
|
|
||||||
// Features
|
// Features
|
||||||
const FEATURE_BITS: u8 = 5;
|
const FEATURE_BITS: u8 = 5;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -34,7 +37,7 @@ fn polyseed_features_supported(features: u8) -> bool {
|
|||||||
const DATE_BITS: u8 = 10;
|
const DATE_BITS: u8 = 10;
|
||||||
const DATE_MASK: u16 = (1u16 << DATE_BITS) - 1;
|
const DATE_MASK: u16 = (1u16 << DATE_BITS) - 1;
|
||||||
const POLYSEED_EPOCH: u64 = 1635768000; // 1st November 2021 12:00 UTC
|
const POLYSEED_EPOCH: u64 = 1635768000; // 1st November 2021 12:00 UTC
|
||||||
pub(crate) const TIME_STEP: u64 = 2629746; // 30.436875 days = 1/12 of the Gregorian year
|
const TIME_STEP: u64 = 2629746; // 30.436875 days = 1/12 of the Gregorian year
|
||||||
|
|
||||||
// After ~85 years, this will roll over.
|
// After ~85 years, this will roll over.
|
||||||
fn birthday_encode(time: u64) -> u16 {
|
fn birthday_encode(time: u64) -> u16 {
|
||||||
@@ -61,9 +64,9 @@ const LAST_BYTE_SECRET_BITS_MASK: u8 = ((1 << (BITS_PER_BYTE - CLEAR_BITS)) - 1)
|
|||||||
const SECRET_BITS_PER_WORD: usize = 10;
|
const SECRET_BITS_PER_WORD: usize = 10;
|
||||||
|
|
||||||
// Amount of words in a seed
|
// Amount of words in a seed
|
||||||
pub(crate) const POLYSEED_LENGTH: usize = 16;
|
const POLYSEED_LENGTH: usize = 16;
|
||||||
// Amount of characters each word must have if trimmed
|
// Amount of characters each word must have if trimmed
|
||||||
pub(crate) const PREFIX_LEN: usize = 4;
|
const PREFIX_LEN: usize = 4;
|
||||||
|
|
||||||
const POLY_NUM_CHECK_DIGITS: usize = 1;
|
const POLY_NUM_CHECK_DIGITS: usize = 1;
|
||||||
const DATA_WORDS: usize = POLYSEED_LENGTH - POLY_NUM_CHECK_DIGITS;
|
const DATA_WORDS: usize = POLYSEED_LENGTH - POLY_NUM_CHECK_DIGITS;
|
||||||
@@ -98,30 +101,58 @@ const POLYSEED_KEYGEN_ITERATIONS: u32 = 10000;
|
|||||||
// See: https://github.com/tevador/polyseed/blob/master/include/polyseed.h#L58
|
// See: https://github.com/tevador/polyseed/blob/master/include/polyseed.h#L58
|
||||||
const COIN: u16 = 0;
|
const COIN: u16 = 0;
|
||||||
|
|
||||||
|
/// An error when working with a Polyseed.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||||
|
pub enum PolyseedError {
|
||||||
|
/// Unsupported feature bits were set.
|
||||||
|
#[cfg_attr(feature = "std", error("unsupported features"))]
|
||||||
|
UnsupportedFeatures,
|
||||||
|
/// The entropy was invalid.
|
||||||
|
#[cfg_attr(feature = "std", error("invalid entropy"))]
|
||||||
|
InvalidEntropy,
|
||||||
|
#[cfg_attr(feature = "std", error("invalid seed"))]
|
||||||
|
/// The seed was invalid.
|
||||||
|
InvalidSeed,
|
||||||
|
/// The checksum did not match the data.
|
||||||
|
#[cfg_attr(feature = "std", error("invalid checksum"))]
|
||||||
|
InvalidChecksum,
|
||||||
|
}
|
||||||
|
|
||||||
/// Language options for Polyseed.
|
/// Language options for Polyseed.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Zeroize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Zeroize)]
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
|
/// English language option.
|
||||||
English,
|
English,
|
||||||
|
/// Spanish language option.
|
||||||
Spanish,
|
Spanish,
|
||||||
|
/// French language option.
|
||||||
French,
|
French,
|
||||||
|
/// Italian language option.
|
||||||
Italian,
|
Italian,
|
||||||
|
/// Japanese language option.
|
||||||
Japanese,
|
Japanese,
|
||||||
|
/// Korean language option.
|
||||||
Korean,
|
Korean,
|
||||||
|
/// Czech language option.
|
||||||
Czech,
|
Czech,
|
||||||
|
/// Portuguese language option.
|
||||||
Portuguese,
|
Portuguese,
|
||||||
|
/// Simplified Chinese language option.
|
||||||
ChineseSimplified,
|
ChineseSimplified,
|
||||||
|
/// Traditional Chinese language option.
|
||||||
ChineseTraditional,
|
ChineseTraditional,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WordList {
|
struct WordList {
|
||||||
words: Vec<String>,
|
words: &'static [&'static str],
|
||||||
has_prefix: bool,
|
has_prefix: bool,
|
||||||
has_accent: bool,
|
has_accent: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WordList {
|
impl WordList {
|
||||||
fn new(words: &str, has_prefix: bool, has_accent: bool) -> WordList {
|
fn new(words: &'static [&'static str], has_prefix: bool, has_accent: bool) -> WordList {
|
||||||
let res = WordList { words: serde_json::from_str(words).unwrap(), has_prefix, has_accent };
|
let res = WordList { words, has_prefix, has_accent };
|
||||||
// This is needed for a later unwrap to not fails
|
// This is needed for a later unwrap to not fails
|
||||||
assert!(words.len() < usize::from(u16::MAX));
|
assert!(words.len() < usize::from(u16::MAX));
|
||||||
res
|
res
|
||||||
@@ -133,26 +164,27 @@ static LANGUAGES_CELL: OnceLock<HashMap<Language, WordList>> = OnceLock::new();
|
|||||||
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
|
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
|
||||||
LANGUAGES_CELL.get_or_init(|| {
|
LANGUAGES_CELL.get_or_init(|| {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(Language::Czech, WordList::new(include_str!("./polyseed/cs.json"), true, false)),
|
(Language::Czech, WordList::new(include!("./words/cs.rs"), true, false)),
|
||||||
(Language::French, WordList::new(include_str!("./polyseed/fr.json"), true, true)),
|
(Language::French, WordList::new(include!("./words/fr.rs"), true, true)),
|
||||||
(Language::Korean, WordList::new(include_str!("./polyseed/ko.json"), false, false)),
|
(Language::Korean, WordList::new(include!("./words/ko.rs"), false, false)),
|
||||||
(Language::English, WordList::new(include_str!("./polyseed/en.json"), true, false)),
|
(Language::English, WordList::new(include!("./words/en.rs"), true, false)),
|
||||||
(Language::Italian, WordList::new(include_str!("./polyseed/it.json"), true, false)),
|
(Language::Italian, WordList::new(include!("./words/it.rs"), true, false)),
|
||||||
(Language::Spanish, WordList::new(include_str!("./polyseed/es.json"), true, true)),
|
(Language::Spanish, WordList::new(include!("./words/es.rs"), true, true)),
|
||||||
(Language::Japanese, WordList::new(include_str!("./polyseed/ja.json"), false, false)),
|
(Language::Japanese, WordList::new(include!("./words/ja.rs"), false, false)),
|
||||||
(Language::Portuguese, WordList::new(include_str!("./polyseed/pt.json"), true, false)),
|
(Language::Portuguese, WordList::new(include!("./words/pt.rs"), true, false)),
|
||||||
(
|
(
|
||||||
Language::ChineseSimplified,
|
Language::ChineseSimplified,
|
||||||
WordList::new(include_str!("./polyseed/zh_simplified.json"), false, false),
|
WordList::new(include!("./words/zh_simplified.rs"), false, false),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Language::ChineseTraditional,
|
Language::ChineseTraditional,
|
||||||
WordList::new(include_str!("./polyseed/zh_traditional.json"), false, false),
|
WordList::new(include!("./words/zh_traditional.rs"), false, false),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A Polyseed.
|
||||||
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct Polyseed {
|
pub struct Polyseed {
|
||||||
language: Language,
|
language: Language,
|
||||||
@@ -222,13 +254,13 @@ impl Polyseed {
|
|||||||
masked_features: u8,
|
masked_features: u8,
|
||||||
encoded_birthday: u16,
|
encoded_birthday: u16,
|
||||||
entropy: Zeroizing<[u8; 32]>,
|
entropy: Zeroizing<[u8; 32]>,
|
||||||
) -> Result<Polyseed, SeedError> {
|
) -> Result<Polyseed, PolyseedError> {
|
||||||
if !polyseed_features_supported(masked_features) {
|
if !polyseed_features_supported(masked_features) {
|
||||||
Err(SeedError::UnsupportedFeatures)?;
|
Err(PolyseedError::UnsupportedFeatures)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !valid_entropy(&entropy) {
|
if !valid_entropy(&entropy) {
|
||||||
Err(SeedError::InvalidEntropy)?;
|
Err(PolyseedError::InvalidEntropy)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut res = Polyseed {
|
let mut res = Polyseed {
|
||||||
@@ -244,23 +276,24 @@ impl Polyseed {
|
|||||||
|
|
||||||
/// Create a new `Polyseed` with specific internals.
|
/// Create a new `Polyseed` with specific internals.
|
||||||
///
|
///
|
||||||
/// `birthday` is defined in seconds since the Unix epoch.
|
/// `birthday` is defined in seconds since the epoch.
|
||||||
pub fn from(
|
fn from(
|
||||||
language: Language,
|
language: Language,
|
||||||
features: u8,
|
features: u8,
|
||||||
birthday: u64,
|
birthday: u64,
|
||||||
entropy: Zeroizing<[u8; 32]>,
|
entropy: Zeroizing<[u8; 32]>,
|
||||||
) -> Result<Polyseed, SeedError> {
|
) -> Result<Polyseed, PolyseedError> {
|
||||||
Self::from_internal(language, user_features(features), birthday_encode(birthday), entropy)
|
Self::from_internal(language, user_features(features), birthday_encode(birthday), entropy)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `Polyseed`.
|
/// Create a new `Polyseed`.
|
||||||
///
|
///
|
||||||
/// This uses the system's time for the birthday, if available.
|
/// This uses the system's time for the birthday, if available, else 0.
|
||||||
pub fn new<R: RngCore + CryptoRng>(rng: &mut R, language: Language) -> Polyseed {
|
pub fn new<R: RngCore + CryptoRng>(rng: &mut R, language: Language) -> Polyseed {
|
||||||
// Get the birthday
|
// Get the birthday
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
let birthday = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
|
let birthday =
|
||||||
|
SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(core::time::Duration::ZERO).as_secs();
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
let birthday = 0;
|
let birthday = 0;
|
||||||
|
|
||||||
@@ -275,7 +308,7 @@ impl Polyseed {
|
|||||||
|
|
||||||
/// Create a new `Polyseed` from a String.
|
/// Create a new `Polyseed` from a String.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn from_string(lang: Language, seed: Zeroizing<String>) -> Result<Polyseed, SeedError> {
|
pub fn from_string(lang: Language, seed: Zeroizing<String>) -> Result<Polyseed, PolyseedError> {
|
||||||
// Decode the seed into its polynomial coefficients
|
// Decode the seed into its polynomial coefficients
|
||||||
let mut poly = [0; POLYSEED_LENGTH];
|
let mut poly = [0; POLYSEED_LENGTH];
|
||||||
|
|
||||||
@@ -325,7 +358,7 @@ impl Polyseed {
|
|||||||
} else {
|
} else {
|
||||||
check_if_matches(lang_word_list.has_prefix, lang_word_list.words.iter(), word)
|
check_if_matches(lang_word_list.has_prefix, lang_word_list.words.iter(), word)
|
||||||
}) else {
|
}) else {
|
||||||
Err(SeedError::InvalidSeed)?
|
Err(PolyseedError::InvalidSeed)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// WordList asserts the word list length is less than u16::MAX
|
// WordList asserts the word list length is less than u16::MAX
|
||||||
@@ -337,7 +370,7 @@ impl Polyseed {
|
|||||||
|
|
||||||
// Validate the checksum
|
// Validate the checksum
|
||||||
if poly_eval(&poly) != 0 {
|
if poly_eval(&poly) != 0 {
|
||||||
Err(SeedError::InvalidChecksum)?;
|
Err(PolyseedError::InvalidChecksum)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the polynomial into entropy
|
// Convert the polynomial into entropy
|
||||||
@@ -416,6 +449,7 @@ impl Polyseed {
|
|||||||
key
|
key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The String representation of this seed.
|
||||||
pub fn to_string(&self) -> Zeroizing<String> {
|
pub fn to_string(&self) -> Zeroizing<String> {
|
||||||
// Encode the polynomial with the existing checksum
|
// Encode the polynomial with the existing checksum
|
||||||
let mut poly = self.to_poly();
|
let mut poly = self.to_poly();
|
||||||
@@ -428,7 +462,7 @@ impl Polyseed {
|
|||||||
let mut seed = Zeroizing::new(String::new());
|
let mut seed = Zeroizing::new(String::new());
|
||||||
let words = &LANGUAGES()[&self.language].words;
|
let words = &LANGUAGES()[&self.language].words;
|
||||||
for i in 0 .. poly.len() {
|
for i in 0 .. poly.len() {
|
||||||
seed.push_str(&words[usize::from(poly[i])]);
|
seed.push_str(words[usize::from(poly[i])]);
|
||||||
if i < poly.len() - 1 {
|
if i < poly.len() - 1 {
|
||||||
seed.push(' ');
|
seed.push(' ');
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"abdikace",
|
"abdikace",
|
||||||
"abeceda",
|
"abeceda",
|
||||||
"adresa",
|
"adresa",
|
||||||
@@ -2047,4 +2047,4 @@
|
|||||||
"zvrat",
|
"zvrat",
|
||||||
"zvukovod",
|
"zvukovod",
|
||||||
"zvyk"
|
"zvyk"
|
||||||
]
|
]
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"abandon",
|
"abandon",
|
||||||
"ability",
|
"ability",
|
||||||
"able",
|
"able",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"ábaco",
|
"ábaco",
|
||||||
"abdomen",
|
"abdomen",
|
||||||
"abeja",
|
"abeja",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"abaisser",
|
"abaisser",
|
||||||
"abandon",
|
"abandon",
|
||||||
"abdiquer",
|
"abdiquer",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"abaco",
|
"abaco",
|
||||||
"abbaglio",
|
"abbaglio",
|
||||||
"abbinato",
|
"abbinato",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"あいこくしん",
|
"あいこくしん",
|
||||||
"あいさつ",
|
"あいさつ",
|
||||||
"あいだ",
|
"あいだ",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"가격",
|
"가격",
|
||||||
"가끔",
|
"가끔",
|
||||||
"가난",
|
"가난",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"abacate",
|
"abacate",
|
||||||
"abaixo",
|
"abaixo",
|
||||||
"abalar",
|
"abalar",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"的",
|
"的",
|
||||||
"一",
|
"一",
|
||||||
"是",
|
"是",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[
|
&[
|
||||||
"的",
|
"的",
|
||||||
"一",
|
"一",
|
||||||
"是",
|
"是",
|
||||||
6
coins/monero/wallet/seed/README.md
Normal file
6
coins/monero/wallet/seed/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Monero Seeds
|
||||||
|
|
||||||
|
A Rust implementation of Monero's seed algorithm.
|
||||||
|
|
||||||
|
This library is usable under no-std when the `std` feature (on by default) is
|
||||||
|
disabled.
|
||||||
@@ -5,7 +5,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
|||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
pub(crate) mod classic;
|
pub(crate) mod classic;
|
||||||
pub(crate) mod polyseed;
|
pub(crate) use polyseed;
|
||||||
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
|
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
|
||||||
use polyseed::{POLYSEED_LENGTH, Polyseed};
|
use polyseed::{POLYSEED_LENGTH, Polyseed};
|
||||||
|
|
||||||
|
|||||||
12
coins/monero/wallet/util/README.md
Normal file
12
coins/monero/wallet/util/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Monero Wallet Utilities
|
||||||
|
|
||||||
|
Additional utility functions for monero-wallet.
|
||||||
|
|
||||||
|
This library is isolated as it adds a notable amount of dependencies to the
|
||||||
|
tree, and to be a subject to a distinct versioning policy. This library may
|
||||||
|
more frequently undergo breaking API changes.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Support for Monero's seed algorithm
|
||||||
|
- Support for Polyseed
|
||||||
2
coins/monero/wallet/util/src/lib.rs
Normal file
2
coins/monero/wallet/util/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub use monero_seed as seed;
|
||||||
|
pub use monero_polyseed as seed;
|
||||||
Reference in New Issue
Block a user