Skip to content

Commit

Permalink
support loading keys from seed and add a new flag for it (#46)
Browse files Browse the repository at this point in the history
* support loading keys from seed and add a new flag for it

* add tests for loading a key from mnemonics/seed

* tests: add a check for ed25519 seed

* use the previously defined SEED

* use from_string instead of from_string_with_seed
  • Loading branch information
abom authored Jun 3, 2022
1 parent 5d87e61 commit 00fdc4b
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 22 deletions.
40 changes: 33 additions & 7 deletions src/identity/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ impl From<&AccountId32> for Ed25519Identity {
#[derive(Clone)]
pub struct Ed25519Signer {
pair: EdPair,
#[allow(unused)]
seed: [u8; 32],
}

impl Signer for Ed25519Signer {
Expand All @@ -59,12 +57,11 @@ impl Identity for Ed25519Signer {

impl TryFrom<&str> for Ed25519Signer {
type Error = anyhow::Error;
fn try_from(phrase: &str) -> std::result::Result<Self, Self::Error> {
// let (pair, seed) = sp_keyring::ed25519::Pair::from_phrase(phrase, None)?;
let (pair, seed) = sp_core::ed25519::Pair::from_phrase(phrase, None)
.map_err(|err| anyhow!("{:?}", err))?;
fn try_from(s: &str) -> std::result::Result<Self, Self::Error> {
let pair =
sp_core::ed25519::Pair::from_string(s, None).map_err(|err| anyhow!("{:?}", err))?;

Ok(Self { pair, seed })
Ok(Self { pair })
}
}

Expand All @@ -74,3 +71,32 @@ fn verify<P: AsRef<[u8]>, M: AsRef<[u8]>>(pk: &Public, sig: P, message: M) -> bo
assert_eq!(sig[0], PREFIX, "invalid signature type");
EdPair::verify_weak(&sig[1..], message, pk)
}

#[cfg(test)]
mod tests {
use super::*;

const WORDS: &str = "neck stage box cup core magic produce exercise happy rely vocal then";
const SEED: &str = "0xaa4e323bade8609a595108b585c4135855430c411ccf7923f81438cd8a188fce";

#[test]
fn test_load_from_mnemonics() {
Ed25519Signer::try_from(WORDS).expect("key must be loaded");

let err = Ed25519Signer::try_from("invalid words");
assert_eq!(err.is_err(), true);
}

#[test]
fn test_load_from_seed() {
let s = Ed25519Signer::try_from(SEED).expect("key must be loaded");

let result = hex::decode(&SEED[2..SEED.len()]).expect("must be decoded");

let bytes: [u8; 32] = result.as_slice().try_into().expect("key of size 32");
assert_eq!(s.pair.seed(), &bytes);

let err = Ed25519Signer::try_from("0xinvalidseed");
assert_eq!(err.is_err(), true);
}
}
36 changes: 29 additions & 7 deletions src/identity/sr25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ impl From<&AccountId32> for Sr25519Identity {
#[derive(Clone)]
pub struct Sr25519Signer {
pair: SrPair,
#[allow(unused)]
seed: [u8; 32],
}

impl Signer for Sr25519Signer {
Expand All @@ -60,12 +58,11 @@ impl Identity for Sr25519Signer {
impl TryFrom<&str> for Sr25519Signer {
type Error = anyhow::Error;

fn try_from(phrase: &str) -> std::result::Result<Self, Self::Error> {
// let (pair, seed) = sp_keyring::sr25519::Pair::from_phrase(phrase, None)?;
let (pair, seed) = sp_core::sr25519::Pair::from_phrase(phrase, None)
.map_err(|err| anyhow::anyhow!("{:?}", err))?;
fn try_from(s: &str) -> std::result::Result<Self, Self::Error> {
let pair =
sp_core::sr25519::Pair::from_string(s, None).map_err(|err| anyhow!("{:?}", err))?;

Ok(Self { pair, seed })
Ok(Self { pair })
}
}

Expand All @@ -75,3 +72,28 @@ fn verify<P: AsRef<[u8]>, M: AsRef<[u8]>>(pk: &Public, sig: P, message: M) -> bo
assert_eq!(sig[0], PREFIX, "invalid signature type");
SrPair::verify_weak(&sig[1..], message, pk)
}

#[cfg(test)]
mod tests {
use super::*;

const WORDS: &str =
"volume behind cable present pull exchange wish loyal avocado snap film increase";
const SEED: &str = "0xb37231837527c7173dc212bb23a7fe795d5dae540e7c21366a5fb9f4cc398a36";

#[test]
fn test_load_from_mnemonics() {
Sr25519Signer::try_from(WORDS).expect("key must be loaded");

let err = Sr25519Signer::try_from("invalid words");
assert_eq!(err.is_err(), true);
}

#[test]
fn test_load_from_seed() {
Sr25519Signer::try_from(SEED).expect("key must be loaded");

let err = Sr25519Signer::try_from("0xinvalidseed");
assert_eq!(err.is_err(), true);
}
}
34 changes: 26 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use clap::Parser;
use http_api::HttpApi;
use identity::Identity;
use proxy::ProxyWorker;
use std::fmt::Display;
use std::fmt::{Debug, Display};
use std::str::FromStr;
use std::time::Duration;
use storage::{RedisStorage, Storage};
Expand Down Expand Up @@ -66,17 +66,21 @@ fn between<T: Ord>(v: T, min: T, max: T) -> T {
v
}

/// Simple program to greet a person
/// the grid message bus
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// key type
#[clap(short, long, default_value_t = KeyType::Ed25519)]
#[clap(short, long, default_value_t = KeyType::Sr25519)]
key_type: KeyType,

/// key mnemonics
#[clap(short, long)]
mnemonics: String,
mnemonics: Option<String>,

/// seed as hex
#[clap(long, conflicts_with = "mnemonics")]
seed: Option<String>,

/// redis address
#[clap(short, long, default_value_t = String::from("redis://localhost:6379"))]
Expand Down Expand Up @@ -114,15 +118,29 @@ async fn app(args: &Args) -> Result<()> {
.with_module_level("substrate_api_client", log::LevelFilter::Off)
.init()?;

// this will get either a prefixed "0x" seed or mnemonics
let secret = if let Some(seed) = &args.seed {
if !seed.to_lowercase().starts_with("0x") {
format!("0x{}", seed)
} else {
seed.clone()
}
} else {
match &args.mnemonics {
Some(mnemonics) => mnemonics.clone(),
None => bail!("either mnemonics or seed must be provided"),
}
};

let identity = match args.key_type {
KeyType::Ed25519 => {
let sk = identity::Ed25519Signer::try_from(args.mnemonics.as_str())
.context("failed to load ed25519 key from mnemonics")?;
let sk = identity::Ed25519Signer::try_from(secret.as_str())
.context("failed to load ed25519 key from mnemonics or seed")?;
identity::Signers::Ed25519(sk)
}
KeyType::Sr25519 => {
let sk = identity::Sr25519Signer::try_from(args.mnemonics.as_str())
.context("failed to load sr25519 key from mnemonics")?;
let sk = identity::Sr25519Signer::try_from(secret.as_str())
.context("failed to load sr25519 key from mnemonics or seed")?;
identity::Signers::Sr25519(sk)
}
};
Expand Down

0 comments on commit 00fdc4b

Please sign in to comment.