Fix nondeterministic key generation (#243)
Our one and only unsafe operation was ...unsafe.
This commit is contained in:
parent
504b318ef1
commit
84477835dc
|
@ -4,14 +4,13 @@ extern crate isatty;
|
|||
extern crate rayon;
|
||||
extern crate serde_json;
|
||||
extern crate solana;
|
||||
extern crate untrusted;
|
||||
|
||||
use futures::Future;
|
||||
use getopts::Options;
|
||||
use isatty::stdin_isatty;
|
||||
use rayon::prelude::*;
|
||||
use solana::mint::MintDemo;
|
||||
use solana::signature::{GenKeys, KeyPair, KeyPairUtil};
|
||||
use solana::signature::{GenKeys, KeyPairUtil};
|
||||
use solana::thin_client::ThinClient;
|
||||
use solana::transaction::Transaction;
|
||||
use std::env;
|
||||
|
@ -21,7 +20,6 @@ use std::process::exit;
|
|||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
use untrusted::Input;
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let mut brief = format!("Usage: cat <mint.json> | {} [options]\n\n", program);
|
||||
|
@ -110,16 +108,10 @@ fn main() {
|
|||
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.num_accounts / 2;
|
||||
let keypairs: Vec<_> = users
|
||||
.into_par_iter()
|
||||
.map(|(pkcs8, _)| KeyPair::from_pkcs8(Input::from(&pkcs8)).unwrap())
|
||||
.collect();
|
||||
let keypairs = rnd.gen_n_keypairs(demo.num_accounts);
|
||||
let keypair_pairs: Vec<_> = keypairs.chunks(2).collect();
|
||||
|
||||
println!("Signing transactions...");
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
extern crate isatty;
|
||||
extern crate rayon;
|
||||
extern crate ring;
|
||||
extern crate serde_json;
|
||||
extern crate solana;
|
||||
extern crate untrusted;
|
||||
|
||||
use isatty::stdin_isatty;
|
||||
use rayon::prelude::*;
|
||||
|
@ -11,11 +9,9 @@ use solana::bank::MAX_ENTRY_IDS;
|
|||
use solana::entry::{next_entry, Entry};
|
||||
use solana::event::Event;
|
||||
use solana::mint::MintDemo;
|
||||
use solana::signature::{GenKeys, KeyPair, KeyPairUtil};
|
||||
use solana::transaction::Transaction;
|
||||
use solana::signature::{GenKeys, KeyPairUtil};
|
||||
use std::io::{stdin, Read};
|
||||
use std::process::exit;
|
||||
use untrusted::Input;
|
||||
|
||||
// Generate a ledger with lots and lots of accounts.
|
||||
fn main() {
|
||||
|
@ -40,19 +36,17 @@ fn main() {
|
|||
let num_accounts = demo.num_accounts;
|
||||
let tokens_per_user = 1_000;
|
||||
|
||||
let users = rnd.gen_n_keys(num_accounts, tokens_per_user);
|
||||
let keypairs = rnd.gen_n_keypairs(num_accounts);
|
||||
|
||||
let mint_keypair = demo.mint.keypair();
|
||||
let last_id = demo.mint.last_id();
|
||||
|
||||
eprintln!("Signing {} transactions...", num_accounts);
|
||||
let events: Vec<_> = users
|
||||
let events: Vec<_> = keypairs
|
||||
.into_par_iter()
|
||||
.map(|(pkcs8, tokens)| {
|
||||
.map(|rando| {
|
||||
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)
|
||||
Event::new_transaction(&mint_keypair, rando.pubkey(), tokens_per_user, last_id)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ 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;
|
||||
|
@ -57,9 +56,9 @@ pub struct GenKeys {
|
|||
}
|
||||
|
||||
impl GenKeys {
|
||||
pub fn new(seed_values: &[u8]) -> GenKeys {
|
||||
let seed: &[u8] = &seed_values[..];
|
||||
let rng: ChaChaRng = SeedableRng::from_seed(unsafe { mem::transmute(seed) });
|
||||
pub fn new(seed: &[u8]) -> GenKeys {
|
||||
let seed32: Vec<_> = seed.iter().map(|&x| x as u32).collect();
|
||||
let rng = ChaChaRng::from_seed(&seed32);
|
||||
GenKeys {
|
||||
generator: RefCell::new(rng),
|
||||
}
|
||||
|
@ -69,24 +68,17 @@ impl GenKeys {
|
|||
KeyPair::generate_pkcs8(self).unwrap().to_vec()
|
||||
}
|
||||
|
||||
pub fn gen_n_seeds(&self, n_seeds: i64) -> Vec<[u8; 16]> {
|
||||
pub fn gen_n_seeds(&self, n: i64) -> Vec<[u8; 16]> {
|
||||
let mut rng = self.generator.borrow_mut();
|
||||
|
||||
(0..n_seeds)
|
||||
.into_iter()
|
||||
.map(|_| rng.gen::<[u8; 16]>())
|
||||
.collect()
|
||||
(0..n).map(|_| rng.gen()).collect()
|
||||
}
|
||||
|
||||
pub fn gen_n_keys(&self, n_keys: i64, tokens_per_user: i64) -> Vec<(Vec<u8>, i64)> {
|
||||
let seeds = self.gen_n_seeds(n_keys);
|
||||
|
||||
seeds
|
||||
pub fn gen_n_keypairs(&self, n: i64) -> Vec<KeyPair> {
|
||||
self.gen_n_seeds(n)
|
||||
.into_par_iter()
|
||||
.map(|seed| {
|
||||
let new: GenKeys = GenKeys::new(&seed[..]);
|
||||
let pkcs8 = KeyPair::generate_pkcs8(&new).unwrap().to_vec();
|
||||
(pkcs8, tokens_per_user)
|
||||
let pkcs8 = GenKeys::new(&seed).new_key();
|
||||
KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8)).unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -104,31 +96,30 @@ impl SecureRandom for GenKeys {
|
|||
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);
|
||||
fn test_new_key_is_deterministic() {
|
||||
let seed = [1, 2, 3, 4];
|
||||
let rng0 = GenKeys::new(&seed);
|
||||
let rng1 = GenKeys::new(&seed);
|
||||
|
||||
for _ in 0..100 {
|
||||
assert_eq!(rnd.new_key(), rnd2.new_key());
|
||||
assert_eq!(rng0.new_key(), rng1.new_key());
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_n_pubkeys(seed: &[u8], n: i64) -> HashSet<PublicKey> {
|
||||
GenKeys::new(&seed)
|
||||
.gen_n_keypairs(n)
|
||||
.into_iter()
|
||||
.map(|x| x.pubkey())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[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<u8>, i64)> = HashSet::from_iter(users1.iter().cloned());
|
||||
let users2_set: HashSet<(Vec<u8>, i64)> = HashSet::from_iter(users2.iter().cloned());
|
||||
assert_eq!(users1_set, users2_set);
|
||||
fn test_gen_n_pubkeys_deterministic() {
|
||||
let seed = [1, 2, 3, 4];
|
||||
assert_eq!(gen_n_pubkeys(&seed, 50), gen_n_pubkeys(&seed, 50));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +136,6 @@ mod bench {
|
|||
fn bench_gen_keys(b: &mut Bencher) {
|
||||
let seed: &[_] = &[1, 2, 3, 4];
|
||||
let rnd = GenKeys::new(seed);
|
||||
b.iter(|| rnd.gen_n_keys(1000, 1));
|
||||
b.iter(|| rnd.gen_n_keys(1000));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue