From 9834c251d0e04f80631da42fbbed52e20eb71f2d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 7 Mar 2018 11:05:06 -0700 Subject: [PATCH] Boot genesis block helper Before this change, if you wanted to use a new Transaction feature in the genesis block, you'd need to extend its Creator object and associated methods. With yesterday's addtions to Transcation, it's now so easy to work with Transactions directly that we can get rid of the middleman. Also added a KeyPair type alias, so that ring could be easily swapped out with a competing library, if needed. --- src/accountant.rs | 26 ++++++------- src/accountant_stub.rs | 15 ++++---- src/bin/genesis-file-demo.rs | 33 ++++++++++------ src/genesis.rs | 73 +++++++----------------------------- src/signature.rs | 5 ++- src/transaction.rs | 7 ++-- 6 files changed, 61 insertions(+), 98 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index c7d881ce9..72bf12b8c 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -6,10 +6,9 @@ use hash::Hash; use entry::Entry; use event::Event; use transaction::Transaction; -use signature::{PublicKey, Signature}; +use signature::{KeyPair, PublicKey, Signature}; use genesis::Genesis; use historian::{reserve_signature, Historian}; -use ring::signature::Ed25519KeyPair; use std::sync::mpsc::SendError; use std::collections::HashMap; use std::result; @@ -131,7 +130,7 @@ impl Accountant { pub fn transfer( self: &mut Self, n: i64, - keypair: &Ed25519KeyPair, + keypair: &KeyPair, to: PublicKey, ) -> Result { let tr = Transaction::new(keypair, to, n, self.last_id); @@ -149,14 +148,15 @@ mod tests { use super::*; use signature::{generate_keypair, get_pubkey}; use logger::ExitReason; - use genesis::Creator; #[test] fn test_accountant() { - let bob = Creator::new(1_000); - let bob_pubkey = bob.pubkey; - let alice = Genesis::new(10_000, vec![bob]); + let alice = Genesis::new(10_000); + let bob_pubkey = get_pubkey(&generate_keypair()); let mut acc = Accountant::new(&alice, Some(2)); + acc.transfer(1_000, &alice.get_keypair(), bob_pubkey) + .unwrap(); + assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000); acc.transfer(500, &alice.get_keypair(), bob_pubkey).unwrap(); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500); @@ -170,10 +170,11 @@ mod tests { #[test] fn test_invalid_transfer() { - let bob = Creator::new(1_000); - let bob_pubkey = bob.pubkey; - let alice = Genesis::new(11_000, vec![bob]); + let alice = Genesis::new(11_000); let mut acc = Accountant::new(&alice, Some(2)); + let bob_pubkey = get_pubkey(&generate_keypair()); + acc.transfer(1_000, &alice.get_keypair(), bob_pubkey) + .unwrap(); assert_eq!( acc.transfer(10_001, &alice.get_keypair(), bob_pubkey), Err(AccountingError::InsufficientFunds) @@ -192,11 +193,10 @@ mod tests { #[test] fn test_transfer_to_newb() { - let alice = Genesis::new(10_000, vec![]); + let alice = Genesis::new(10_000); let mut acc = Accountant::new(&alice, Some(2)); let alice_keypair = alice.get_keypair(); - let bob_keypair = generate_keypair(); - let bob_pubkey = get_pubkey(&bob_keypair); + let bob_pubkey = get_pubkey(&generate_keypair()); acc.transfer(500, &alice_keypair, bob_pubkey).unwrap(); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 500); diff --git a/src/accountant_stub.rs b/src/accountant_stub.rs index f36e94048..f3097022a 100644 --- a/src/accountant_stub.rs +++ b/src/accountant_stub.rs @@ -6,10 +6,9 @@ use std::net::UdpSocket; use std::io; use bincode::{deserialize, serialize}; use transaction::Transaction; -use signature::{PublicKey, Signature}; +use signature::{KeyPair, PublicKey, Signature}; use hash::Hash; use entry::Entry; -use ring::signature::Ed25519KeyPair; use accountant_skel::{Request, Response}; pub struct AccountantStub { @@ -36,7 +35,7 @@ impl AccountantStub { pub fn transfer( &self, n: i64, - keypair: &Ed25519KeyPair, + keypair: &KeyPair, to: PublicKey, last_id: &Hash, ) -> io::Result { @@ -116,16 +115,16 @@ mod tests { use accountant_skel::AccountantSkel; use std::thread::{sleep, spawn}; use std::time::Duration; - use genesis::{Creator, Genesis}; + use genesis::Genesis; + use signature::{generate_keypair, get_pubkey}; #[test] fn test_accountant_stub() { let addr = "127.0.0.1:9000"; let send_addr = "127.0.0.1:9001"; - let bob = Creator::new(1_000); - let bob_pubkey = bob.pubkey; - let alice = Genesis::new(10_000, vec![bob]); + let alice = Genesis::new(10_000); let acc = Accountant::new(&alice, None); + let bob_pubkey = get_pubkey(&generate_keypair()); spawn(move || AccountantSkel::new(acc).serve(addr).unwrap()); sleep(Duration::from_millis(30)); @@ -135,6 +134,6 @@ mod tests { let sig = acc.transfer(500, &alice.get_keypair(), bob_pubkey, &last_id) .unwrap(); acc.wait_on_signature(&sig).unwrap(); - assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 1_500); + assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 500); } } diff --git a/src/bin/genesis-file-demo.rs b/src/bin/genesis-file-demo.rs index 8a8adf5d6..a1bd49058 100644 --- a/src/bin/genesis-file-demo.rs +++ b/src/bin/genesis-file-demo.rs @@ -1,19 +1,28 @@ extern crate serde_json; extern crate silk; -use silk::genesis::{Creator, Genesis}; -use silk::signature::{generate_keypair, get_pubkey}; +use silk::genesis::Genesis; +use silk::event::Event; +use silk::transaction::Transaction; +use silk::log::create_entries; +use silk::signature::{generate_keypair, get_pubkey, KeyPair, PublicKey}; +use silk::hash::Hash; + +fn transfer(from: &KeyPair, (to, tokens): (PublicKey, i64), last_id: Hash) -> Event { + Event::Transaction(Transaction::new(&from, to, tokens, last_id)) +} fn main() { - let alice = Creator { - tokens: 200, - pubkey: get_pubkey(&generate_keypair()), - }; - let bob = Creator { - tokens: 100, - pubkey: get_pubkey(&generate_keypair()), - }; - let creators = vec![alice, bob]; - let gen = Genesis::new(500, creators); + let alice = (get_pubkey(&generate_keypair()), 200); + let bob = (get_pubkey(&generate_keypair()), 100); + + let gen = Genesis::new(500); + let from = gen.get_keypair(); + let seed = gen.get_seed(); + let mut events = gen.create_events(); + events.push(transfer(&from, alice, seed)); + events.push(transfer(&from, bob, seed)); + + create_entries(&seed, events); println!("{}", serde_json::to_string(&gen).unwrap()); } diff --git a/src/genesis.rs b/src/genesis.rs index 94e09fb96..5c410b2ad 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -2,7 +2,7 @@ use event::Event; use transaction::Transaction; -use signature::{generate_keypair, get_pubkey, PublicKey}; +use signature::{get_pubkey, PublicKey}; use entry::Entry; use log::create_entries; use hash::{hash, Hash}; @@ -10,37 +10,17 @@ use ring::rand::SystemRandom; use ring::signature::Ed25519KeyPair; use untrusted::Input; -#[derive(Serialize, Deserialize, Debug)] -pub struct Creator { - pub pubkey: PublicKey, - pub tokens: i64, -} - -impl Creator { - pub fn new(tokens: i64) -> Self { - Creator { - pubkey: get_pubkey(&generate_keypair()), - tokens, - } - } -} - #[derive(Serialize, Deserialize, Debug)] pub struct Genesis { pub pkcs8: Vec, pub tokens: i64, - pub creators: Vec, } impl Genesis { - pub fn new(tokens: i64, creators: Vec) -> Self { + pub fn new(tokens: i64) -> Self { let rnd = SystemRandom::new(); let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rnd).unwrap().to_vec(); - Genesis { - pkcs8, - tokens, - creators, - } + Genesis { pkcs8, tokens } } pub fn get_seed(&self) -> Hash { @@ -55,23 +35,14 @@ impl Genesis { get_pubkey(&self.get_keypair()) } - pub fn create_transaction(&self, asset: i64, to: &PublicKey) -> Event { - let tr = Transaction::new(&self.get_keypair(), *to, asset, self.get_seed()); - Event::Transaction(tr) - } - pub fn create_events(&self) -> Vec { - let pubkey = self.get_pubkey(); - let event0 = Event::Tick; - let event1 = self.create_transaction(self.tokens, &pubkey); - let mut events = vec![event0, event1]; - - for x in &self.creators { - let tx = self.create_transaction(x.tokens, &x.pubkey); - events.push(tx); - } - - events + let tr = Transaction::new( + &self.get_keypair(), + self.get_pubkey(), + self.tokens, + self.get_seed(), + ); + vec![Event::Tick, Event::Transaction(tr)] } pub fn create_entries(&self) -> Vec { @@ -86,35 +57,19 @@ mod tests { #[test] fn test_create_events() { - let mut events = Genesis::new(100, vec![]).create_events().into_iter(); + let mut events = Genesis::new(100).create_events().into_iter(); assert_eq!(events.next().unwrap(), Event::Tick); - if let Event::Transaction(Transaction { from, to, .. }) = events.next().unwrap() { - assert_eq!(from, to); + if let Event::Transaction(tr) = events.next().unwrap() { + assert_eq!(tr.from, tr.to); } else { assert!(false); } assert_eq!(events.next(), None); } - #[test] - fn test_create_creator() { - assert_eq!( - Genesis::new(100, vec![Creator::new(42)]) - .create_events() - .len(), - 3 - ); - } - #[test] fn test_verify_entries() { - let entries = Genesis::new(100, vec![]).create_entries(); - assert!(verify_slice(&entries, &entries[0].id)); - } - - #[test] - fn test_verify_entries_with_transactions() { - let entries = Genesis::new(100, vec![Creator::new(42)]).create_entries(); + let entries = Genesis::new(100).create_entries(); assert!(verify_slice(&entries, &entries[0].id)); } } diff --git a/src/signature.rs b/src/signature.rs index c36325262..06b705dde 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -6,18 +6,19 @@ use ring::signature::Ed25519KeyPair; use ring::{rand, signature}; use untrusted; +pub type KeyPair = Ed25519KeyPair; pub type PublicKey = GenericArray; pub type Signature = GenericArray; /// Return a new ED25519 keypair -pub fn generate_keypair() -> Ed25519KeyPair { +pub fn generate_keypair() -> KeyPair { let rng = rand::SystemRandom::new(); let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap() } /// Return the public key for the given keypair -pub fn get_pubkey(keypair: &Ed25519KeyPair) -> PublicKey { +pub fn get_pubkey(keypair: &KeyPair) -> PublicKey { GenericArray::clone_from_slice(keypair.public_key_bytes()) } diff --git a/src/transaction.rs b/src/transaction.rs index 209a5dc7c..ff2bc5f8d 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,7 +1,6 @@ //! The `transaction` crate provides functionality for creating log transactions. -use signature::{get_pubkey, verify_signature, PublicKey, Signature}; -use ring::signature::Ed25519KeyPair; +use signature::{get_pubkey, verify_signature, KeyPair, PublicKey, Signature}; use serde::Serialize; use bincode::serialize; use hash::Hash; @@ -16,7 +15,7 @@ pub struct Transaction { } impl Transaction { - pub fn new(from_keypair: &Ed25519KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self { + pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self { let mut tr = Transaction { from: get_pubkey(&from_keypair), to, @@ -32,7 +31,7 @@ impl Transaction { serialize(&(&self.from, &self.to, &self.asset, &self.last_id)).unwrap() } - pub fn sign(&mut self, keypair: &Ed25519KeyPair) { + pub fn sign(&mut self, keypair: &KeyPair) { let sign_data = self.get_sign_data(); self.sig = Signature::clone_from_slice(keypair.sign(&sign_data).as_ref()); }