diff --git a/libcuda_verify_ed25519.a b/libcuda_verify_ed25519.a new file mode 100644 index 000000000..3fcefffed Binary files /dev/null and b/libcuda_verify_ed25519.a differ diff --git a/src/bin/client-demo.rs b/src/bin/client-demo.rs index a1a5dee7d..3e4f01e88 100644 --- a/src/bin/client-demo.rs +++ b/src/bin/client-demo.rs @@ -11,7 +11,7 @@ use getopts::Options; use isatty::stdin_isatty; use rayon::prelude::*; use solana::mint::MintDemo; -use solana::signature::{KeyPair, KeyPairUtil}; +use solana::signature::{GenKeys, KeyPair, KeyPairUtil}; use solana::thin_client::ThinClient; use solana::transaction::Transaction; use std::env; @@ -93,9 +93,14 @@ fn main() { let last_id = accountant.get_last_id().wait().unwrap(); println!("Got last ID {:?}", last_id); + let rnd = GenKeys::new(demo.mint.keypair().public_key_bytes()); + let tokens_per_user = 1_000; + + let users = rnd.gen_n_keys(demo.num_accounts, tokens_per_user); + println!("Creating keypairs..."); - let txs = demo.users.len() / 2; - let keypairs: Vec<_> = demo.users + let txs = demo.num_accounts / 2; + let keypairs: Vec<_> = users .into_par_iter() .map(|(pkcs8, _)| KeyPair::from_pkcs8(Input::from(&pkcs8)).unwrap()) .collect(); diff --git a/src/bin/genesis-demo.rs b/src/bin/genesis-demo.rs index 626c335ee..926a695f1 100644 --- a/src/bin/genesis-demo.rs +++ b/src/bin/genesis-demo.rs @@ -11,7 +11,7 @@ use solana::accountant::MAX_ENTRY_IDS; use solana::entry::{create_entry, next_entry}; use solana::event::Event; use solana::mint::MintDemo; -use solana::signature::{KeyPair, KeyPairUtil}; +use solana::signature::{GenKeys, KeyPair, KeyPairUtil}; use solana::transaction::Transaction; use std::io::{stdin, Read}; use std::process::exit; @@ -36,14 +36,20 @@ fn main() { exit(1); }); - let num_accounts = demo.users.len(); - let last_id = demo.mint.last_id(); + let rnd = GenKeys::new(demo.mint.keypair().public_key_bytes()); + let num_accounts = demo.num_accounts; + let tokens_per_user = 1_000; + + let users = rnd.gen_n_keys(num_accounts, tokens_per_user); + let mint_keypair = demo.mint.keypair(); + let last_id = demo.mint.last_id(); eprintln!("Signing {} transactions...", num_accounts); - let events: Vec<_> = demo.users + let events: Vec<_> = users .into_par_iter() .map(|(pkcs8, tokens)| { + let last_id = demo.mint.last_id(); let rando = KeyPair::from_pkcs8(Input::from(&pkcs8)).unwrap(); let tr = Transaction::new(&mint_keypair, rando.pubkey(), tokens, last_id); Event::Transaction(tr) diff --git a/src/bin/mint-demo.rs b/src/bin/mint-demo.rs index 1127ce19b..0054c21f6 100644 --- a/src/bin/mint-demo.rs +++ b/src/bin/mint-demo.rs @@ -3,10 +3,7 @@ extern crate ring; extern crate serde_json; extern crate solana; -use rayon::prelude::*; -use ring::rand::SystemRandom; use solana::mint::{Mint, MintDemo}; -use solana::signature::KeyPair; use std::io; fn main() { @@ -18,16 +15,7 @@ fn main() { let mint = Mint::new(tokens); let tokens_per_user = 1_000; let num_accounts = tokens / tokens_per_user; - let rnd = SystemRandom::new(); - let users: Vec<_> = (0..num_accounts) - .into_par_iter() - .map(|_| { - let pkcs8 = KeyPair::generate_pkcs8(&rnd).unwrap().to_vec(); - (pkcs8, tokens_per_user) - }) - .collect(); - - let demo = MintDemo { mint, users }; + let demo = MintDemo { mint, num_accounts }; println!("{}", serde_json::to_string(&demo).unwrap()); } diff --git a/src/mint.rs b/src/mint.rs index 39bc4348d..52a685e3e 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -64,7 +64,7 @@ impl Mint { #[derive(Serialize, Deserialize, Debug)] pub struct MintDemo { pub mint: Mint, - pub users: Vec<(Vec, i64)>, + pub num_accounts: i64, } #[cfg(test)] diff --git a/src/signature.rs b/src/signature.rs index 8f8e9b075..8966e3b20 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -1,9 +1,13 @@ //! The `signature` module provides functionality for public, and private keys. use generic_array::typenum::{U32, U64}; -use generic_array::GenericArray; +use rand::{ChaChaRng, Rng, SeedableRng}; +use ring::error::Unspecified; +use ring::rand::SecureRandom; use ring::signature::Ed25519KeyPair; use ring::{rand, signature}; +use std::cell::RefCell; +use std::mem; use untrusted; pub type KeyPair = Ed25519KeyPair; @@ -43,3 +47,74 @@ impl SignatureUtil for GenericArray { signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok() } } + +pub struct GenKeys { + // This is necessary because the rng needs to mutate its state to remain + // deterministic, and the fill trait requires an immuatble reference to self + generator: RefCell, +} + +impl GenKeys { + pub fn new(seed_values: &[u8]) -> GenKeys { + let seed: &[u8] = &seed_values[..]; + let rng: ChaChaRng = SeedableRng::from_seed(unsafe { mem::transmute(seed) }); + GenKeys { + generator: RefCell::new(rng), + } + } + + pub fn new_key(&self) -> Vec { + KeyPair::generate_pkcs8(self).unwrap().to_vec() + } + + pub fn gen_n_keys(&self, n_keys: i64, tokens_per_user: i64) -> Vec<(Vec, i64)> { + let users: Vec<_> = (0..n_keys) + .into_iter() + .map(|_| { + let pkcs8 = self.new_key(); + (pkcs8, tokens_per_user) + }) + .collect(); + users + } +} + +impl SecureRandom for GenKeys { + fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified> { + let mut rng = self.generator.borrow_mut(); + rng.fill_bytes(dest); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + use std::iter::FromIterator; + + #[test] + fn test_new_key_is_redundant() { + let seed: &[_] = &[1, 2, 3, 4]; + let rnd = GenKeys::new(seed); + let rnd2 = GenKeys::new(seed); + + for _ in 0..100 { + assert_eq!(rnd.new_key(), rnd2.new_key()); + } + } + + #[test] + fn test_gen_n_keys() { + let seed: &[_] = &[1, 2, 3, 4]; + let rnd = GenKeys::new(seed); + let rnd2 = GenKeys::new(seed); + + let users1 = rnd.gen_n_keys(50, 1); + let users2 = rnd2.gen_n_keys(50, 1); + + let users1_set: HashSet<(Vec, i64)> = HashSet::from_iter(users1.iter().cloned()); + let users2_set: HashSet<(Vec, i64)> = HashSet::from_iter(users2.iter().cloned()); + assert_eq!(users1_set, users2_set); + } +}