From d1b62068584caade2a854b576a08166981007785 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 6 Mar 2018 20:22:30 -0700 Subject: [PATCH] Monomorphisize Entry and Event Transaction turned out to be the only struct worth making generic. --- src/accountant.rs | 12 ++++-------- src/accountant_skel.rs | 2 +- src/bin/demo.rs | 7 +++---- src/bin/genesis-block.rs | 4 ++-- src/entry.rs | 29 ++++++++++++----------------- src/event.rs | 7 +++---- src/genesis.rs | 12 ++++++------ src/historian.rs | 18 ++++++++---------- src/log.rs | 39 +++++++-------------------------------- src/logger.rs | 18 ++++++------------ 10 files changed, 52 insertions(+), 96 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 96bbb03366..c7d881ce95 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -25,7 +25,7 @@ pub enum AccountingError { pub type Result = result::Result; pub struct Accountant { - pub historian: Historian, + pub historian: Historian, pub balances: HashMap, pub first_id: Hash, pub last_id: Hash, @@ -34,7 +34,7 @@ pub struct Accountant { impl Accountant { pub fn new_from_entries(entries: I, ms_per_tick: Option) -> Self where - I: IntoIterator>, + I: IntoIterator, { let mut entries = entries.into_iter(); @@ -43,7 +43,7 @@ impl Accountant { let entry0 = entries.next().unwrap(); let start_hash = entry0.id; - let hist = Historian::::new(&start_hash, ms_per_tick); + let hist = Historian::new(&start_hash, ms_per_tick); let mut acc = Accountant { historian: hist, balances: HashMap::new(), @@ -121,11 +121,7 @@ impl Accountant { Ok(()) } - fn process_verified_event( - self: &mut Self, - event: &Event, - allow_deposits: bool, - ) -> Result<()> { + fn process_verified_event(self: &mut Self, event: &Event, allow_deposits: bool) -> Result<()> { match *event { Event::Tick => Ok(()), Event::Transaction(ref tr) => self.process_verified_transaction(tr, allow_deposits), diff --git a/src/accountant_skel.rs b/src/accountant_skel.rs index c5afe6bc7b..5ef7f5471c 100644 --- a/src/accountant_skel.rs +++ b/src/accountant_skel.rs @@ -22,7 +22,7 @@ pub enum Request { #[derive(Serialize, Deserialize, Debug)] pub enum Response { Balance { key: PublicKey, val: Option }, - Entries { entries: Vec> }, + Entries { entries: Vec }, Id { id: Hash, is_last: bool }, } diff --git a/src/bin/demo.rs b/src/bin/demo.rs index 4aad34f20c..59cd7e9164 100644 --- a/src/bin/demo.rs +++ b/src/bin/demo.rs @@ -11,11 +11,10 @@ use std::thread::sleep; use std::time::Duration; use std::sync::mpsc::SendError; -fn create_log(hist: &Historian, seed: &Hash) -> Result<(), SendError>> { +fn create_log(hist: &Historian, seed: &Hash) -> Result<(), SendError> { sleep(Duration::from_millis(15)); - let asset = Hash::default(); let keypair = generate_keypair(); - let tr = Transaction::new(&keypair, get_pubkey(&keypair), asset, *seed); + let tr = Transaction::new(&keypair, get_pubkey(&keypair), 42, *seed); let event0 = Event::Transaction(tr); hist.sender.send(event0)?; sleep(Duration::from_millis(10)); @@ -27,7 +26,7 @@ fn main() { let hist = Historian::new(&seed, Some(10)); create_log(&hist, &seed).expect("send error"); drop(hist.sender); - let entries: Vec> = hist.receiver.iter().collect(); + let entries: Vec = hist.receiver.iter().collect(); for entry in &entries { println!("{:?}", entry); } diff --git a/src/bin/genesis-block.rs b/src/bin/genesis-block.rs index dc620ff2e1..44cd5d9948 100644 --- a/src/bin/genesis-block.rs +++ b/src/bin/genesis-block.rs @@ -5,13 +5,13 @@ extern crate serde_json; extern crate silk; use silk::genesis::Genesis; -use silk::log::verify_slice_i64; +use silk::log::verify_slice; use std::io::stdin; fn main() { let gen: Genesis = serde_json::from_reader(stdin()).unwrap(); let entries = gen.create_entries(); - verify_slice_i64(&entries, &entries[0].id); + verify_slice(&entries, &entries[0].id); for x in entries { println!("{}", serde_json::to_string(&x).unwrap()); } diff --git a/src/entry.rs b/src/entry.rs index 82b691087b..67a6ea7ae8 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,15 +1,14 @@ use hash::{extend_and_hash, hash, Hash}; -use serde::Serialize; use event::Event; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub struct Entry { +pub struct Entry { pub num_hashes: u64, pub id: Hash, - pub event: Event, + pub event: Event, } -impl Entry { +impl Entry { /// Creates a Entry from the number of hashes 'num_hashes' since the previous event /// and that resulting 'id'. pub fn new_tick(num_hashes: u64, id: &Hash) -> Self { @@ -33,7 +32,7 @@ impl Entry { /// Creates the hash 'num_hashes' after start_hash. If the event contains /// signature, the final hash will be a hash of both the previous ID and /// the signature. -pub fn next_hash(start_hash: &Hash, num_hashes: u64, event: &Event) -> Hash { +pub fn next_hash(start_hash: &Hash, num_hashes: u64, event: &Event) -> Hash { let mut id = *start_hash; let sig = event.get_signature(); let start_index = if sig.is_some() { 1 } else { 0 }; @@ -47,7 +46,7 @@ pub fn next_hash(start_hash: &Hash, num_hashes: u64, event: &Event } /// Creates the next Entry 'num_hashes' after 'start_hash'. -pub fn create_entry(start_hash: &Hash, cur_hashes: u64, event: Event) -> Entry { +pub fn create_entry(start_hash: &Hash, cur_hashes: u64, event: Event) -> Entry { let sig = event.get_signature(); let num_hashes = cur_hashes + if sig.is_some() { 1 } else { 0 }; let id = next_hash(start_hash, 0, &event); @@ -59,11 +58,7 @@ pub fn create_entry(start_hash: &Hash, cur_hashes: u64, event: Eve } /// Creates the next Tick Entry 'num_hashes' after 'start_hash'. -pub fn create_entry_mut( - start_hash: &mut Hash, - cur_hashes: &mut u64, - event: Event, -) -> Entry { +pub fn create_entry_mut(start_hash: &mut Hash, cur_hashes: &mut u64, event: Event) -> Entry { let entry = create_entry(start_hash, *cur_hashes, event); *start_hash = entry.id; *cur_hashes = 0; @@ -71,7 +66,7 @@ pub fn create_entry_mut( } /// Creates the next Tick Entry 'num_hashes' after 'start_hash'. -pub fn next_tick(start_hash: &Hash, num_hashes: u64) -> Entry { +pub fn next_tick(start_hash: &Hash, num_hashes: u64) -> Entry { let event = Event::Tick; Entry { num_hashes, @@ -88,15 +83,15 @@ mod tests { fn test_event_verify() { let zero = Hash::default(); let one = hash(&zero); - assert!(Entry::::new_tick(0, &zero).verify(&zero)); // base case - assert!(!Entry::::new_tick(0, &zero).verify(&one)); // base case, bad - assert!(next_tick::(&zero, 1).verify(&zero)); // inductive step - assert!(!next_tick::(&zero, 1).verify(&one)); // inductive step, bad + assert!(Entry::new_tick(0, &zero).verify(&zero)); // base case + assert!(!Entry::new_tick(0, &zero).verify(&one)); // base case, bad + assert!(next_tick(&zero, 1).verify(&zero)); // inductive step + assert!(!next_tick(&zero, 1).verify(&one)); // inductive step, bad } #[test] fn test_next_tick() { let zero = Hash::default(); - assert_eq!(next_tick::(&zero, 1).num_hashes, 1) + assert_eq!(next_tick(&zero, 1).num_hashes, 1) } } diff --git a/src/event.rs b/src/event.rs index 791edcd3a3..12a848ab5f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -2,7 +2,6 @@ use signature::Signature; use transaction::Transaction; -use serde::Serialize; /// When 'event' is Tick, the event represents a simple clock tick, and exists for the /// sole purpose of improving the performance of event log verification. A tick can @@ -10,12 +9,12 @@ use serde::Serialize; /// a hash alongside the tick, each tick and be verified in parallel using the 'id' /// of the preceding tick to seed its hashing. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub enum Event { +pub enum Event { Tick, - Transaction(Transaction), + Transaction(Transaction), } -impl Event { +impl Event { pub fn get_signature(&self) -> Option { match *self { Event::Tick => None, diff --git a/src/genesis.rs b/src/genesis.rs index 4d95e24eb6..b6faeb6d3a 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -56,12 +56,12 @@ impl Genesis { get_pubkey(&self.get_keypair()) } - pub fn create_transaction(&self, asset: i64, to: &PublicKey) -> Event { + 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> { + pub fn create_events(&self) -> Vec { let pubkey = self.get_pubkey(); let event0 = Event::Tick; let event1 = self.create_transaction(self.tokens, &pubkey); @@ -75,7 +75,7 @@ impl Genesis { events } - pub fn create_entries(&self) -> Vec> { + pub fn create_entries(&self) -> Vec { create_entries(&self.get_seed(), self.create_events()) } } @@ -83,7 +83,7 @@ impl Genesis { #[cfg(test)] mod tests { use super::*; - use log::verify_slice_i64; + use log::verify_slice; #[test] fn test_create_events() { @@ -110,12 +110,12 @@ mod tests { #[test] fn test_verify_entries() { let entries = Genesis::new(100, vec![]).create_entries(); - assert!(verify_slice_i64(&entries, &entries[0].id)); + 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(); - assert!(verify_slice_i64(&entries, &entries[0].id)); + assert!(verify_slice(&entries, &entries[0].id)); } } diff --git a/src/historian.rs b/src/historian.rs index 6d335819e0..83e5b7bae5 100644 --- a/src/historian.rs +++ b/src/historian.rs @@ -10,17 +10,15 @@ use entry::Entry; use logger::{ExitReason, Logger}; use signature::Signature; use event::Event; -use serde::Serialize; -use std::fmt::Debug; -pub struct Historian { - pub sender: SyncSender>, - pub receiver: Receiver>, +pub struct Historian { + pub sender: SyncSender, + pub receiver: Receiver, pub thread_hdl: JoinHandle, pub signatures: HashSet, } -impl Historian { +impl Historian { pub fn new(start_hash: &Hash, ms_per_tick: Option) -> Self { let (sender, event_receiver) = sync_channel(1000); let (entry_sender, receiver) = sync_channel(1000); @@ -40,8 +38,8 @@ impl Historian { fn create_logger( start_hash: Hash, ms_per_tick: Option, - receiver: Receiver>, - sender: SyncSender>, + receiver: Receiver, + sender: SyncSender, ) -> JoinHandle { spawn(move || { let mut logger = Logger::new(receiver, sender, start_hash); @@ -100,7 +98,7 @@ mod tests { #[test] fn test_historian_closed_sender() { let zero = Hash::default(); - let hist = Historian::::new(&zero, None); + let hist = Historian::new(&zero, None); drop(hist.receiver); hist.sender.send(Event::Tick).unwrap(); assert_eq!( @@ -124,7 +122,7 @@ mod tests { sleep(Duration::from_millis(30)); hist.sender.send(Event::Tick).unwrap(); drop(hist.sender); - let entries: Vec> = hist.receiver.iter().collect(); + let entries: Vec = hist.receiver.iter().collect(); // Ensure one entry is sent back for each tick sent in. assert_eq!(entries.len(), 1); diff --git a/src/log.rs b/src/log.rs index 78f287c742..de3284b434 100644 --- a/src/log.rs +++ b/src/log.rs @@ -14,33 +14,18 @@ /// was generated by the fastest processor at the time the entry was logged. use hash::Hash; -use serde::Serialize; use entry::{create_entry_mut, next_tick, Entry}; use event::Event; use rayon::prelude::*; /// Verifies the hashes and counts of a slice of events are all consistent. -pub fn verify_slice(events: &[Entry], start_hash: &Hash) -> bool { +pub fn verify_slice(events: &[Entry], start_hash: &Hash) -> bool { let genesis = [Entry::new_tick(Default::default(), start_hash)]; let event_pairs = genesis.par_iter().chain(events).zip(events); event_pairs.all(|(x0, x1)| x1.verify(&x0.id)) } -/// Verifies the hashes and counts of a slice of events are all consistent. -pub fn verify_slice_i64(events: &[Entry], start_hash: &Hash) -> bool { - let genesis = [Entry::new_tick(Default::default(), start_hash)]; - let event_pairs = genesis.par_iter().chain(events).zip(events); - event_pairs.all(|(x0, x1)| x1.verify(&x0.id)) -} - -/// Verifies the hashes and events serially. Exists only for reference. -pub fn verify_slice_seq(events: &[Entry], start_hash: &Hash) -> bool { - let genesis = [Entry::new_tick(0, start_hash)]; - let mut event_pairs = genesis.iter().chain(events).zip(events); - event_pairs.all(|(x0, x1)| x1.verify(&x0.id)) -} - -pub fn create_entries(start_hash: &Hash, events: Vec>) -> Vec> { +pub fn create_entries(start_hash: &Hash, events: Vec) -> Vec { let mut id = *start_hash; events .into_iter() @@ -49,7 +34,7 @@ pub fn create_entries(start_hash: &Hash, events: Vec>) -> } /// Create a vector of Ticks of length 'len' from 'start_hash' hash and 'num_hashes'. -pub fn next_ticks(start_hash: &Hash, num_hashes: u64, len: usize) -> Vec> { +pub fn next_ticks(start_hash: &Hash, num_hashes: u64, len: usize) -> Vec { let mut id = *start_hash; let mut ticks = vec![]; for _ in 0..len { @@ -67,7 +52,8 @@ mod tests { use transaction::Transaction; use hash::hash; - fn verify_slice_generic(verify_slice: fn(&[Entry], &Hash) -> bool) { + #[test] + fn test_verify_slice() { let zero = Hash::default(); let one = hash(&zero); assert!(verify_slice(&vec![], &zero)); // base case @@ -80,25 +66,14 @@ mod tests { assert!(!verify_slice(&bad_ticks, &zero)); // inductive step, bad } - #[test] - fn test_verify_slice() { - verify_slice_generic(verify_slice); - } - - #[test] - fn test_verify_slice_seq() { - verify_slice_generic(verify_slice_seq::); - } - #[test] fn test_reorder_attack() { let zero = Hash::default(); - let one = hash(&zero); // First, verify entries let keypair = generate_keypair(); - let tr0 = Transaction::new(&keypair, get_pubkey(&keypair), zero, zero); - let tr1 = Transaction::new(&keypair, get_pubkey(&keypair), one, zero); + let tr0 = Transaction::new(&keypair, get_pubkey(&keypair), 0, zero); + let tr1 = Transaction::new(&keypair, get_pubkey(&keypair), 1, zero); let events = vec![Event::Transaction(tr0), Event::Transaction(tr1)]; let mut entries = create_entries(&zero, events); assert!(verify_slice(&entries, &zero)); diff --git a/src/logger.rs b/src/logger.rs index 2d839809a0..b5affd2901 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -10,8 +10,6 @@ use std::time::{Duration, Instant}; use hash::Hash; use entry::{create_entry_mut, Entry}; use event::Event; -use serde::Serialize; -use std::fmt::Debug; use serde_json; #[derive(Debug, PartialEq, Eq)] @@ -20,20 +18,16 @@ pub enum ExitReason { SendDisconnected, } -pub struct Logger { - pub sender: SyncSender>, - pub receiver: Receiver>, +pub struct Logger { + pub sender: SyncSender, + pub receiver: Receiver, pub last_id: Hash, pub num_hashes: u64, pub num_ticks: u64, } -impl Logger { - pub fn new( - receiver: Receiver>, - sender: SyncSender>, - start_hash: Hash, - ) -> Self { +impl Logger { + pub fn new(receiver: Receiver, sender: SyncSender, start_hash: Hash) -> Self { Logger { receiver, sender, @@ -43,7 +37,7 @@ impl Logger { } } - pub fn log_event(&mut self, event: Event) -> Result, ExitReason> { + pub fn log_event(&mut self, event: Event) -> Result { let entry = create_entry_mut(&mut self.last_id, &mut self.num_hashes, event); println!("{}", serde_json::to_string(&entry).unwrap()); Ok(entry)