From d88d1b2a098e4c49cba6efe355e05d63658f6927 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 19 Feb 2018 12:00:56 -0700 Subject: [PATCH] Reset historian's hasher between events Hasher will generate different hashes for the same input if it had already generated a hash. Also add a binary to ensure the example in the README works. --- Cargo.toml | 4 ++++ README.md | 45 ++++++++++++++++++++++++++++++++++----------- src/bin/demo.rs | 28 ++++++++++++++++++++++++++++ src/historian.rs | 27 ++++++++++++++++++--------- 4 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 src/bin/demo.rs diff --git a/Cargo.toml b/Cargo.toml index ef4e903c2..0f6900c6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ authors = [ ] license = "Apache-2.0" +[[bin]] +name = "silk-demo" +path = "src/bin/demo.rs" + [badges] codecov = { repository = "loomprotocol/silk", branch = "master", service = "github" } diff --git a/README.md b/README.md index 88b5edb87..f23d0e4e3 100644 --- a/README.md +++ b/README.md @@ -25,22 +25,45 @@ is tagged with the historian's latest *hash*. Then ensure the order of events wa with by verifying each entry's hash can be generated from the hash in the previous entry: ```rust -use historian::Historian; -use log::{Event, verify_slice}; +extern crate silk; + +use silk::historian::Historian; +use silk::log::{verify_slice, Entry, Event}; +use std::{thread, time}; + +fn create_log(hist: &Historian) -> Vec { + hist.sender.send(Event::Tick).unwrap(); + thread::sleep(time::Duration::new(0, 100_000)); + hist.sender.send(Event::UserDataKey(0xdeadbeef)).unwrap(); + thread::sleep(time::Duration::new(0, 100_000)); + hist.sender.send(Event::Tick).unwrap(); + + let entry0 = hist.receiver.recv().unwrap(); + let entry1 = hist.receiver.recv().unwrap(); + let entry2 = hist.receiver.recv().unwrap(); + vec![entry0, entry1, entry2] +} fn main() { - let hist = Historian::new(0); - - hist.sender.send(Event::Tick).unwrap(); - let entry0 = hist.receiver.recv().unwrap(); - - hist.sender.send(Event::UserDataKey(0xdeadbeef)).unwrap(); - let entry1 = hist.receiver.recv().unwrap(); - - assert!(verify_slice(&[entry0, entry1], 0)); + let seed = 0; + let hist = Historian::new(seed); + let entries = create_log(&hist); + for entry in &entries { + println!("{:?}", entry); + } + assert!(verify_slice(&entries, seed)); } ``` +Running the program should produce a log similar to: + +``` +Entry { num_hashes: 0, end_hash: 0, event: Tick } +Entry { num_hashes: 245, end_hash: 11504657626326377539, event: UserDataKey(3735928559) } +Entry { num_hashes: 154, end_hash: 13410333856574024888, event: Tick } +``` + + # Developing Building diff --git a/src/bin/demo.rs b/src/bin/demo.rs new file mode 100644 index 000000000..bdb5328ea --- /dev/null +++ b/src/bin/demo.rs @@ -0,0 +1,28 @@ +extern crate silk; + +use silk::historian::Historian; +use silk::log::{verify_slice, Entry, Event}; +use std::{thread, time}; + +fn create_log(hist: &Historian) -> Vec { + hist.sender.send(Event::Tick).unwrap(); + thread::sleep(time::Duration::new(0, 100_000)); + hist.sender.send(Event::UserDataKey(0xdeadbeef)).unwrap(); + thread::sleep(time::Duration::new(0, 100_000)); + hist.sender.send(Event::Tick).unwrap(); + + let entry0 = hist.receiver.recv().unwrap(); + let entry1 = hist.receiver.recv().unwrap(); + let entry2 = hist.receiver.recv().unwrap(); + vec![entry0, entry1, entry2] +} + +fn main() { + let seed = 0; + let hist = Historian::new(seed); + let entries = create_log(&hist); + for entry in &entries { + println!("{:?}", entry); + } + assert!(verify_slice(&entries, seed)); +} diff --git a/src/historian.rs b/src/historian.rs index 88a7d8734..bb9311d05 100644 --- a/src/historian.rs +++ b/src/historian.rs @@ -73,7 +73,11 @@ pub fn create_logger( let mut num_hashes = 0; loop { match log_events(&receiver, &sender, num_hashes, end_hash) { - Ok(n) => num_hashes = n, + Ok(0) => { + num_hashes = 0; + hasher = DefaultHasher::new(); + } + Ok(_) => {} Err(err) => return err, } end_hash.hash(&mut hasher); @@ -104,17 +108,22 @@ mod tests { #[test] fn test_historian() { + use std::thread::sleep; + use std::time::Duration; + let hist = Historian::new(0); - let event = Event::Tick; - hist.sender.send(event.clone()).unwrap(); - let entry0 = hist.receiver.recv().unwrap(); - assert_eq!(entry0.event, event); + hist.sender.send(Event::Tick).unwrap(); + sleep(Duration::new(0, 100_000)); + hist.sender.send(Event::UserDataKey(0xdeadbeef)).unwrap(); + sleep(Duration::new(0, 100_000)); + hist.sender.send(Event::Tick).unwrap(); - let event = Event::UserDataKey(0xdeadbeef); - hist.sender.send(event.clone()).unwrap(); + let entry0 = hist.receiver.recv().unwrap(); let entry1 = hist.receiver.recv().unwrap(); - assert_eq!(entry1.event, event); + let entry2 = hist.receiver.recv().unwrap(); + assert!(entry1.num_hashes != 0); + assert!(entry2.num_hashes != 0); drop(hist.sender); assert_eq!( @@ -122,7 +131,7 @@ mod tests { ExitReason::RecvDisconnected ); - assert!(verify_slice(&[entry0, entry1], 0)); + assert!(verify_slice(&[entry0, entry1, entry2], 0)); } #[test]