From bcb21bc1d84ddf404cb32a8931b0157b124c9266 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sun, 4 Mar 2018 07:20:17 -0700 Subject: [PATCH 1/5] Delete dead code --- src/accountant.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 8f9f3595ab..77601f46df 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -54,17 +54,6 @@ impl Accountant { entries } - pub fn deposit(self: &mut Self, n: u64, keypair: &Ed25519KeyPair) -> Result { - use event::{get_pubkey, sign_claim_data}; - let to = get_pubkey(keypair); - let sig = sign_claim_data(&n, keypair); - let event = Event::new_claim(to, n, sig); - if !self.historian.verify_event(&event) { - return Err(AccountingError::InvalidEvent); - } - self.process_verified_event(event, true).map(|_| sig) - } - fn is_deposit(allow_deposits: bool, from: &PublicKey, to: &PublicKey) -> bool { allow_deposits && from == to } @@ -210,9 +199,6 @@ mod tests { let mut acc = Accountant::new(&alice, Some(2)); let alice_keypair = alice.get_keypair(); let bob_keypair = generate_keypair(); - let sig = acc.deposit(10_000, &alice_keypair).unwrap(); - acc.wait_on_signature(&sig); - let bob_pubkey = get_pubkey(&bob_keypair); let sig = acc.transfer(500, &alice_keypair, bob_pubkey).unwrap(); acc.wait_on_signature(&sig); From 608def9c78ff8c2eb0514547379755dafaf7fda0 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sun, 4 Mar 2018 07:28:51 -0700 Subject: [PATCH 2/5] Consolidate imports --- src/accountant.rs | 11 +++++------ src/accountant_skel.rs | 4 ++-- src/accountant_stub.rs | 3 +-- src/bin/client-demo.rs | 20 +++++++++----------- src/event.rs | 9 +++------ src/historian.rs | 5 ++--- src/log.rs | 7 +++---- src/logger.rs | 3 +-- 8 files changed, 26 insertions(+), 36 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 77601f46df..8fe0c04a1f 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -3,13 +3,15 @@ //! transfer funds to other users. use log::{hash, Entry, Sha256Hash}; -use event::{Event, PublicKey, Signature}; +use event::{get_pubkey, sign_transaction_data, Event, PublicKey, Signature}; use genesis::Genesis; use historian::Historian; use ring::signature::Ed25519KeyPair; use std::sync::mpsc::SendError; use std::collections::HashMap; use std::result; +use std::thread::sleep; +use std::time::Duration; #[derive(Debug, PartialEq, Eq)] pub enum AccountingError { @@ -107,7 +109,6 @@ impl Accountant { keypair: &Ed25519KeyPair, to: PublicKey, ) -> Result { - use event::{get_pubkey, sign_transaction_data}; let from = get_pubkey(keypair); let sig = sign_transaction_data(&n, keypair, &to); let event = Event::Transaction { @@ -124,8 +125,6 @@ impl Accountant { } pub fn wait_on_signature(self: &mut Self, wait_sig: &Signature) { - use std::thread::sleep; - use std::time::Duration; let mut entries = self.sync(); let mut found = false; while !found { @@ -147,6 +146,8 @@ mod tests { use event::{generate_keypair, get_pubkey}; use logger::ExitReason; use genesis::Creator; + use std::thread::sleep; + use std::time::Duration; #[test] fn test_accountant() { @@ -169,8 +170,6 @@ mod tests { #[test] fn test_invalid_transfer() { - use std::thread::sleep; - use std::time::Duration; let bob = Creator::new(1_000); let bob_pubkey = bob.pubkey; let alice = Genesis::new(11_000, vec![bob]); diff --git a/src/accountant_skel.rs b/src/accountant_skel.rs index 7164e690e3..af9365ffe1 100644 --- a/src/accountant_skel.rs +++ b/src/accountant_skel.rs @@ -1,6 +1,8 @@ use std::io; use accountant::Accountant; use event::{Event, PublicKey, Signature}; +use std::net::UdpSocket; +use bincode::{deserialize, serialize}; pub struct AccountantSkel { pub obj: Accountant, @@ -60,8 +62,6 @@ impl AccountantSkel { /// UDP Server that forwards messages to Accountant methods. pub fn serve(self: &mut Self, addr: &str) -> io::Result<()> { - use std::net::UdpSocket; - use bincode::{deserialize, serialize}; let socket = UdpSocket::bind(addr)?; let mut buf = vec![0u8; 1024]; loop { diff --git a/src/accountant_stub.rs b/src/accountant_stub.rs index 8ce5feb3b9..6d5929f688 100644 --- a/src/accountant_stub.rs +++ b/src/accountant_stub.rs @@ -5,7 +5,7 @@ use std::net::UdpSocket; use std::io; use bincode::{deserialize, serialize}; -use event::{PublicKey, Signature}; +use event::{get_pubkey, sign_transaction_data, PublicKey, Signature}; use ring::signature::Ed25519KeyPair; use accountant_skel::{Request, Response}; @@ -40,7 +40,6 @@ impl AccountantStub { keypair: &Ed25519KeyPair, to: PublicKey, ) -> io::Result { - use event::{get_pubkey, sign_transaction_data}; let from = get_pubkey(keypair); let sig = sign_transaction_data(&n, keypair, &to); self.transfer_signed(from, to, n, sig).map(|_| sig) diff --git a/src/bin/client-demo.rs b/src/bin/client-demo.rs index a5dc6ab8f3..7cd4220b3a 100644 --- a/src/bin/client-demo.rs +++ b/src/bin/client-demo.rs @@ -1,19 +1,18 @@ //extern crate serde_json; extern crate silk; +use silk::accountant_stub::AccountantStub; +use silk::accountant_skel::AccountantSkel; +use silk::accountant::Accountant; +use silk::event::{generate_keypair, get_pubkey, sign_transaction_data, verify_event, Event}; +use silk::genesis::Genesis; +use std::time::Instant; +use std::net::UdpSocket; +use std::thread::{sleep, spawn}; +use std::time::Duration; //use std::io::stdin; fn main() { - use silk::accountant_stub::AccountantStub; - use silk::accountant_skel::AccountantSkel; - use silk::accountant::Accountant; - use silk::event::{generate_keypair, get_pubkey, sign_transaction_data}; - use silk::genesis::Genesis; - use std::time::Instant; - use std::net::UdpSocket; - use std::thread::{sleep, spawn}; - use std::time::Duration; - let addr = "127.0.0.1:8000"; let send_addr = "127.0.0.1:8001"; @@ -53,7 +52,6 @@ fn main() { ); println!("Verify signatures..."); - use silk::event::{verify_event, Event}; let now = Instant::now(); for &(k, s) in &sigs { let e = Event::Transaction { diff --git a/src/event.rs b/src/event.rs index ef57121c64..01f5538f05 100644 --- a/src/event.rs +++ b/src/event.rs @@ -16,7 +16,10 @@ use generic_array::GenericArray; use generic_array::typenum::{U32, U64}; use ring::signature::Ed25519KeyPair; +use ring::{rand, signature}; +use untrusted; use serde::Serialize; +use bincode::serialize; pub type PublicKey = GenericArray; pub type Signature = GenericArray; @@ -50,8 +53,6 @@ impl Event { /// Return a new ED25519 keypair pub fn generate_keypair() -> Ed25519KeyPair { - use ring::{rand, signature}; - use untrusted; let rng = rand::SystemRandom::new(); let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap() @@ -64,7 +65,6 @@ pub fn get_pubkey(keypair: &Ed25519KeyPair) -> PublicKey { /// Return a signature for the given data using the private key from the given keypair. fn sign_serialized(data: &T, keypair: &Ed25519KeyPair) -> Signature { - use bincode::serialize; let serialized = serialize(data).unwrap(); GenericArray::clone_from_slice(keypair.sign(&serialized).as_ref()) } @@ -86,8 +86,6 @@ pub fn sign_claim_data(data: &T, keypair: &Ed25519KeyPair) -> Sign /// Verify a signed message with the given public key. pub fn verify_signature(peer_public_key_bytes: &[u8], msg_bytes: &[u8], sig_bytes: &[u8]) -> bool { - use untrusted; - use ring::signature; let peer_public_key = untrusted::Input::from(peer_public_key_bytes); let msg = untrusted::Input::from(msg_bytes); let sig = untrusted::Input::from(sig_bytes); @@ -102,7 +100,6 @@ pub fn get_signature(event: &Event) -> Option { } pub fn verify_event(event: &Event) -> bool { - use bincode::serialize; if let Event::Transaction { from, to, diff --git a/src/historian.rs b/src/historian.rs index 446570642e..532e295888 100644 --- a/src/historian.rs +++ b/src/historian.rs @@ -3,13 +3,14 @@ use std::thread::JoinHandle; use std::collections::HashSet; -use std::sync::mpsc::{Receiver, SyncSender}; +use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use std::time::Instant; use log::{hash, Entry, Sha256Hash}; use logger::{verify_event_and_reserve_signature, ExitReason, Logger}; use event::{Event, Signature}; use serde::Serialize; use std::fmt::Debug; +use std::thread; pub struct Historian { pub sender: SyncSender>, @@ -20,7 +21,6 @@ pub struct Historian { impl Historian { pub fn new(start_hash: &Sha256Hash, ms_per_tick: Option) -> Self { - use std::sync::mpsc::sync_channel; let (sender, event_receiver) = sync_channel(1000); let (entry_sender, receiver) = sync_channel(1000); let thread_hdl = @@ -46,7 +46,6 @@ impl Historian { receiver: Receiver>, sender: SyncSender>, ) -> JoinHandle<(Entry, ExitReason)> { - use std::thread; thread::spawn(move || { let mut logger = Logger::new(receiver, sender, start_hash); let now = Instant::now(); diff --git a/src/log.rs b/src/log.rs index 8878445f21..318694961a 100644 --- a/src/log.rs +++ b/src/log.rs @@ -17,6 +17,9 @@ use generic_array::GenericArray; use generic_array::typenum::U32; use serde::Serialize; use event::*; +use sha2::{Digest, Sha256}; +use rayon::prelude::*; +use std::iter; pub type Sha256Hash = GenericArray; @@ -41,7 +44,6 @@ impl Entry { /// Return a Sha256 hash for the given data. pub fn hash(val: &[u8]) -> Sha256Hash { - use sha2::{Digest, Sha256}; let mut hasher = Sha256::default(); hasher.input(val); hasher.result() @@ -114,7 +116,6 @@ pub fn verify_entry(entry: &Entry, start_hash: &Sha256Hash) -> /// Verifies the hashes and counts of a slice of events are all consistent. pub fn verify_slice(events: &[Entry], start_hash: &Sha256Hash) -> bool { - use rayon::prelude::*; let genesis = [Entry::new_tick(Default::default(), start_hash)]; let event_pairs = genesis.par_iter().chain(events).zip(events); event_pairs.all(|(x0, x1)| verify_entry(&x1, &x0.end_hash)) @@ -122,7 +123,6 @@ pub fn verify_slice(events: &[Entry], start_hash: &Sha256Hash) -> bo /// Verifies the hashes and counts of a slice of events are all consistent. pub fn verify_slice_u64(events: &[Entry], start_hash: &Sha256Hash) -> bool { - use rayon::prelude::*; let genesis = [Entry::new_tick(Default::default(), start_hash)]; let event_pairs = genesis.par_iter().chain(events).zip(events); event_pairs.all(|(x0, x1)| verify_entry(&x1, &x0.end_hash)) @@ -153,7 +153,6 @@ pub fn create_ticks( num_hashes: u64, len: usize, ) -> Vec> { - use std::iter; let mut end_hash = *start_hash; iter::repeat(Event::Tick) .take(len) diff --git a/src/logger.rs b/src/logger.rs index 3d930814c4..091767677a 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -6,7 +6,7 @@ //! The resulting stream of entries represents ordered events in time. use std::collections::HashSet; -use std::sync::mpsc::{Receiver, SyncSender}; +use std::sync::mpsc::{Receiver, SyncSender, TryRecvError}; use std::time::{Duration, Instant}; use log::{hash_event, Entry, Sha256Hash}; use event::{get_signature, verify_event, Event, Signature}; @@ -77,7 +77,6 @@ impl Logger { epoch: Instant, ms_per_tick: Option, ) -> Result<(), (Entry, ExitReason)> { - use std::sync::mpsc::TryRecvError; loop { if let Some(ms) = ms_per_tick { if epoch.elapsed() > Duration::from_millis((self.num_ticks + 1) * ms) { From b1e9512f449313114fb048df21531d6c6579d141 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sun, 4 Mar 2018 07:34:38 -0700 Subject: [PATCH 3/5] Rename end_hash to id --- README.md | 8 +++--- diagrams/historian.msc | 6 ++--- src/accountant.rs | 6 ++--- src/bin/genesis-block.rs | 2 +- src/event.rs | 8 +++--- src/historian.rs | 2 +- src/log.rs | 54 ++++++++++++++++++++-------------------- src/logger.rs | 14 +++++------ 8 files changed, 50 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 62b451a7a9..560f5e75e1 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,9 @@ fn main() { Running the program should produce a log similar to: ```rust -Entry { num_hashes: 0, end_hash: [0, ...], event: Tick } -Entry { num_hashes: 2, end_hash: [67, ...], event: Transaction { data: [37, ...] } } -Entry { num_hashes: 3, end_hash: [123, ...], event: Tick } +Entry { num_hashes: 0, id: [0, ...], event: Tick } +Entry { num_hashes: 2, id: [67, ...], event: Transaction { data: [37, ...] } } +Entry { num_hashes: 3, id: [123, ...], event: Tick } ``` Proof-of-History @@ -86,7 +86,7 @@ assert!(verify_slice(&entries, &seed)); ``` [It's a proof!](https://en.wikipedia.org/wiki/Curry–Howard_correspondence) For each entry returned by the -historian, we can verify that `end_hash` is the result of applying a sha256 hash to the previous `end_hash` +historian, we can verify that `id` is the result of applying a sha256 hash to the previous `id` exactly `num_hashes` times, and then hashing then event data on top of that. Because the event data is included in the hash, the events cannot be reordered without regenerating all the hashes. diff --git a/diagrams/historian.msc b/diagrams/historian.msc index 75cf1615ae..0a97b70c67 100644 --- a/diagrams/historian.msc +++ b/diagrams/historian.msc @@ -1,17 +1,17 @@ msc { client,historian,logger; - logger=>historian [ label = "e0 = Entry{hash: h0, n: 0, event: Tick}" ] ; + logger=>historian [ label = "e0 = Entry{id: h0, n: 0, event: Tick}" ] ; logger=>logger [ label = "h1 = hash(h0)" ] ; logger=>logger [ label = "h2 = hash(h1)" ] ; client=>historian [ label = "Claim(d0)" ] ; historian=>logger [ label = "Claim(d0)" ] ; logger=>logger [ label = "h3 = hash(h2 + d0)" ] ; - logger=>historian [ label = "e1 = Entry{hash: hash(h3), n: 2, event: Claim(d0)}" ] ; + logger=>historian [ label = "e1 = Entry{id: hash(h3), n: 2, event: Claim(d0)}" ] ; logger=>logger [ label = "h4 = hash(h3)" ] ; logger=>logger [ label = "h5 = hash(h4)" ] ; logger=>logger [ label = "h6 = hash(h5)" ] ; - logger=>historian [ label = "e2 = Entry{hash: h6, n: 3, event: Tick}" ] ; + logger=>historian [ label = "e2 = Entry{id: h6, n: 3, event: Tick}" ] ; client=>historian [ label = "collect()" ] ; historian=>client [ label = "entries = [e0, e1, e2]" ] ; client=>client [ label = "verify_slice(entries, h0)" ] ; diff --git a/src/accountant.rs b/src/accountant.rs index 8fe0c04a1f..74c4922c6b 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -25,7 +25,7 @@ pub type Result = result::Result; pub struct Accountant { pub historian: Historian, pub balances: HashMap, - pub end_hash: Sha256Hash, + pub last_id: Sha256Hash, } impl Accountant { @@ -35,7 +35,7 @@ impl Accountant { let mut acc = Accountant { historian: hist, balances: HashMap::new(), - end_hash: start_hash, + last_id: start_hash, }; for (i, event) in gen.create_events().into_iter().enumerate() { acc.process_verified_event(event, i < 2).unwrap(); @@ -50,7 +50,7 @@ impl Accountant { } if let Some(last_entry) = entries.last() { - self.end_hash = last_entry.end_hash; + self.last_id = last_entry.id; } entries diff --git a/src/bin/genesis-block.rs b/src/bin/genesis-block.rs index eeb7c1730c..d72c7c9045 100644 --- a/src/bin/genesis-block.rs +++ b/src/bin/genesis-block.rs @@ -22,7 +22,7 @@ fn main() { drop(logger.sender); let entries = receiver.iter().collect::>(); - verify_slice_u64(&entries, &entries[0].end_hash); + verify_slice_u64(&entries, &entries[0].id); println!("["); let len = entries.len(); for (i, x) in entries.iter().enumerate() { diff --git a/src/event.rs b/src/event.rs index 01f5538f05..7c263e437a 100644 --- a/src/event.rs +++ b/src/event.rs @@ -2,9 +2,9 @@ //! an ordered log of events in time. /// Each log entry contains three pieces of data. The 'num_hashes' field is the number -/// of hashes performed since the previous entry. The 'end_hash' field is the result -/// of hashing 'end_hash' from the previous entry 'num_hashes' times. The 'event' -/// field points to an Event that took place shortly after 'end_hash' was generated. +/// of hashes performed since the previous entry. The 'id' field is the result +/// of hashing 'id' from the previous entry 'num_hashes' times. The 'event' +/// field points to an Event that took place shortly after 'id' was generated. /// /// If you divide 'num_hashes' by the amount of time it takes to generate a new hash, you /// get a duration estimate since the last event. Since processing power increases @@ -27,7 +27,7 @@ pub type Signature = GenericArray; /// 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 /// be generated in 'num_hashes' hashes and verified in 'num_hashes' hashes. By logging -/// a hash alongside the tick, each tick and be verified in parallel using the 'end_hash' +/// 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 { diff --git a/src/historian.rs b/src/historian.rs index 532e295888..745416c0aa 100644 --- a/src/historian.rs +++ b/src/historian.rs @@ -53,7 +53,7 @@ impl Historian { if let Err(err) = logger.log_events(now, ms_per_tick) { return err; } - logger.end_hash = hash(&logger.end_hash); + logger.last_id = hash(&logger.last_id); logger.num_hashes += 1; } }) diff --git a/src/log.rs b/src/log.rs index 318694961a..1050b22786 100644 --- a/src/log.rs +++ b/src/log.rs @@ -2,9 +2,9 @@ //! an ordered log of events in time. /// Each log entry contains three pieces of data. The 'num_hashes' field is the number -/// of hashes performed since the previous entry. The 'end_hash' field is the result -/// of hashing 'end_hash' from the previous entry 'num_hashes' times. The 'event' -/// field points to an Event that took place shortly after 'end_hash' was generated. +/// of hashes performed since the previous entry. The 'id' field is the result +/// of hashing 'id' from the previous entry 'num_hashes' times. The 'event' +/// field points to an Event that took place shortly after 'id' was generated. /// /// If you divide 'num_hashes' by the amount of time it takes to generate a new hash, you /// get a duration estimate since the last event. Since processing power increases @@ -26,17 +26,17 @@ pub type Sha256Hash = GenericArray; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Entry { pub num_hashes: u64, - pub end_hash: Sha256Hash, + pub id: Sha256Hash, pub event: Event, } impl Entry { /// Creates a Entry from the number of hashes 'num_hashes' since the previous event - /// and that resulting 'end_hash'. - pub fn new_tick(num_hashes: u64, end_hash: &Sha256Hash) -> Self { + /// and that resulting 'id'. + pub fn new_tick(num_hashes: u64, id: &Sha256Hash) -> Self { Entry { num_hashes, - end_hash: *end_hash, + id: *id, event: Event::Tick, } } @@ -50,16 +50,16 @@ pub fn hash(val: &[u8]) -> Sha256Hash { } /// Return the hash of the given hash extended with the given value. -pub fn extend_and_hash(end_hash: &Sha256Hash, val: &[u8]) -> Sha256Hash { - let mut hash_data = end_hash.to_vec(); +pub fn extend_and_hash(id: &Sha256Hash, val: &[u8]) -> Sha256Hash { + let mut hash_data = id.to_vec(); hash_data.extend_from_slice(val); hash(&hash_data) } -pub fn hash_event(end_hash: &Sha256Hash, event: &Event) -> Sha256Hash { +pub fn hash_event(id: &Sha256Hash, event: &Event) -> Sha256Hash { match get_signature(event) { - None => *end_hash, - Some(sig) => extend_and_hash(end_hash, &sig), + None => *id, + Some(sig) => extend_and_hash(id, &sig), } } @@ -69,11 +69,11 @@ pub fn next_hash( num_hashes: u64, event: &Event, ) -> Sha256Hash { - let mut end_hash = *start_hash; + let mut id = *start_hash; for _ in 0..num_hashes { - end_hash = hash(&end_hash); + id = hash(&id); } - hash_event(&end_hash, event) + hash_event(&id, event) } /// Creates the next Tick Entry 'num_hashes' after 'start_hash'. @@ -84,7 +84,7 @@ pub fn next_entry( ) -> Entry { Entry { num_hashes, - end_hash: next_hash(start_hash, num_hashes, &event), + id: next_hash(start_hash, num_hashes, &event), event, } } @@ -96,7 +96,7 @@ pub fn next_entry_mut( event: Event, ) -> Entry { let entry = next_entry(start_hash, num_hashes, event); - *start_hash = entry.end_hash; + *start_hash = entry.id; entry } @@ -105,34 +105,34 @@ pub fn next_tick(start_hash: &Sha256Hash, num_hashes: u64) -> Entr next_entry(start_hash, num_hashes, Event::Tick) } -/// Verifies self.end_hash is the result of hashing a 'start_hash' 'self.num_hashes' times. +/// Verifies self.id is the result of hashing a 'start_hash' 'self.num_hashes' times. /// If the event is not a Tick, then hash that as well. pub fn verify_entry(entry: &Entry, start_hash: &Sha256Hash) -> bool { if !verify_event(&entry.event) { return false; } - entry.end_hash == next_hash(start_hash, entry.num_hashes, &entry.event) + entry.id == next_hash(start_hash, entry.num_hashes, &entry.event) } /// Verifies the hashes and counts of a slice of events are all consistent. pub fn verify_slice(events: &[Entry], start_hash: &Sha256Hash) -> 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)| verify_entry(&x1, &x0.end_hash)) + event_pairs.all(|(x0, x1)| verify_entry(&x1, &x0.id)) } /// Verifies the hashes and counts of a slice of events are all consistent. pub fn verify_slice_u64(events: &[Entry], start_hash: &Sha256Hash) -> 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)| verify_entry(&x1, &x0.end_hash)) + event_pairs.all(|(x0, x1)| verify_entry(&x1, &x0.id)) } /// Verifies the hashes and events serially. Exists only for reference. pub fn verify_slice_seq(events: &[Entry], start_hash: &Sha256Hash) -> bool { let genesis = [Entry::new_tick(0, start_hash)]; let mut event_pairs = genesis.iter().chain(events).zip(events); - event_pairs.all(|(x0, x1)| verify_entry(&x1, &x0.end_hash)) + event_pairs.all(|(x0, x1)| verify_entry(&x1, &x0.id)) } pub fn create_entries( @@ -140,10 +140,10 @@ pub fn create_entries( num_hashes: u64, events: Vec>, ) -> Vec> { - let mut end_hash = *start_hash; + let mut id = *start_hash; events .into_iter() - .map(|event| next_entry_mut(&mut end_hash, num_hashes, event)) + .map(|event| next_entry_mut(&mut id, num_hashes, event)) .collect() } @@ -153,10 +153,10 @@ pub fn create_ticks( num_hashes: u64, len: usize, ) -> Vec> { - let mut end_hash = *start_hash; + let mut id = *start_hash; iter::repeat(Event::Tick) .take(len) - .map(|event| next_entry_mut(&mut end_hash, num_hashes, event)) + .map(|event| next_entry_mut(&mut id, num_hashes, event)) .collect() } @@ -189,7 +189,7 @@ mod tests { assert!(verify_slice(&create_ticks(&zero, 0, 2), &zero)); // inductive step let mut bad_ticks = create_ticks(&zero, 0, 2); - bad_ticks[1].end_hash = one; + bad_ticks[1].id = one; assert!(!verify_slice(&bad_ticks, &zero)); // inductive step, bad } diff --git a/src/logger.rs b/src/logger.rs index 091767677a..37abf76f98 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -22,7 +22,7 @@ pub enum ExitReason { pub struct Logger { pub sender: SyncSender>, pub receiver: Receiver>, - pub end_hash: Sha256Hash, + pub last_id: Sha256Hash, pub num_hashes: u64, pub num_ticks: u64, } @@ -52,16 +52,16 @@ impl Logger { Logger { receiver, sender, - end_hash: start_hash, + last_id: start_hash, num_hashes: 0, num_ticks: 0, } } pub fn log_event(&mut self, event: Event) -> Result<(), (Entry, ExitReason)> { - self.end_hash = hash_event(&self.end_hash, &event); + self.last_id = hash_event(&self.last_id, &event); let entry = Entry { - end_hash: self.end_hash, + id: self.last_id, num_hashes: self.num_hashes, event, }; @@ -93,7 +93,7 @@ impl Logger { } Err(TryRecvError::Disconnected) => { let entry = Entry { - end_hash: self.end_hash, + id: self.last_id, num_hashes: self.num_hashes, event: Event::Tick, }; @@ -148,12 +148,12 @@ mod tests { #[test] fn test_genesis_no_creators() { let entries = run_genesis(Genesis::new(100, vec![])); - assert!(verify_slice_u64(&entries, &entries[0].end_hash)); + assert!(verify_slice_u64(&entries, &entries[0].id)); } #[test] fn test_genesis() { let entries = run_genesis(Genesis::new(100, vec![Creator::new(42)])); - assert!(verify_slice_u64(&entries, &entries[0].end_hash)); + assert!(verify_slice_u64(&entries, &entries[0].id)); } } From 8503a0a58fa28835afc1cf597daacfe9e76ac94f Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sun, 4 Mar 2018 09:21:45 -0700 Subject: [PATCH 4/5] Refactor --- src/log.rs | 15 ++++++--------- src/logger.rs | 6 ++++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/log.rs b/src/log.rs index 1050b22786..cc5881b2b1 100644 --- a/src/log.rs +++ b/src/log.rs @@ -16,7 +16,7 @@ use generic_array::GenericArray; use generic_array::typenum::U32; use serde::Serialize; -use event::*; +use event::{get_signature, verify_event, Event}; use sha2::{Digest, Sha256}; use rayon::prelude::*; use std::iter; @@ -56,13 +56,6 @@ pub fn extend_and_hash(id: &Sha256Hash, val: &[u8]) -> Sha256Hash { hash(&hash_data) } -pub fn hash_event(id: &Sha256Hash, event: &Event) -> Sha256Hash { - match get_signature(event) { - None => *id, - Some(sig) => extend_and_hash(id, &sig), - } -} - /// Creates the hash 'num_hashes' after start_hash, plus an additional hash for any event data. pub fn next_hash( start_hash: &Sha256Hash, @@ -73,7 +66,10 @@ pub fn next_hash( for _ in 0..num_hashes { id = hash(&id); } - hash_event(&id, event) + match get_signature(event) { + None => id, + Some(sig) => extend_and_hash(&id, &sig), + } } /// Creates the next Tick Entry 'num_hashes' after 'start_hash'. @@ -163,6 +159,7 @@ pub fn create_ticks( #[cfg(test)] mod tests { use super::*; + use event::{generate_keypair, get_pubkey, sign_claim_data, sign_transaction_data}; #[test] fn test_event_verify() { diff --git a/src/logger.rs b/src/logger.rs index 37abf76f98..627ce75e6d 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -8,7 +8,7 @@ use std::collections::HashSet; use std::sync::mpsc::{Receiver, SyncSender, TryRecvError}; use std::time::{Duration, Instant}; -use log::{hash_event, Entry, Sha256Hash}; +use log::{extend_and_hash, Entry, Sha256Hash}; use event::{get_signature, verify_event, Event, Signature}; use serde::Serialize; use std::fmt::Debug; @@ -59,7 +59,9 @@ impl Logger { } pub fn log_event(&mut self, event: Event) -> Result<(), (Entry, ExitReason)> { - self.last_id = hash_event(&self.last_id, &event); + if let Some(sig) = get_signature(&event) { + self.last_id = extend_and_hash(&self.last_id, &sig); + } let entry = Entry { id: self.last_id, num_hashes: self.num_hashes, From ff82fbf1129f33561f0935155d6b66fb4ee93828 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sun, 4 Mar 2018 09:52:33 -0700 Subject: [PATCH 5/5] Make num_hashes mean the num_hashes since the last ID Before this change, num_hashes meant the number of hashes since the last ID, minus any hashing done on the event data. It made no difference for Tick events, but logged Transaction events with one less hash than actually occurred. --- README.md | 2 +- diagrams/historian.msc | 6 +++--- src/log.rs | 16 ++++++++++------ src/logger.rs | 1 + 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 560f5e75e1..efd238c10b 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Running the program should produce a log similar to: ```rust Entry { num_hashes: 0, id: [0, ...], event: Tick } -Entry { num_hashes: 2, id: [67, ...], event: Transaction { data: [37, ...] } } +Entry { num_hashes: 3, id: [67, ...], event: Transaction { data: [37, ...] } } Entry { num_hashes: 3, id: [123, ...], event: Tick } ``` diff --git a/diagrams/historian.msc b/diagrams/historian.msc index 0a97b70c67..91e93539d3 100644 --- a/diagrams/historian.msc +++ b/diagrams/historian.msc @@ -4,10 +4,10 @@ msc { logger=>historian [ label = "e0 = Entry{id: h0, n: 0, event: Tick}" ] ; logger=>logger [ label = "h1 = hash(h0)" ] ; logger=>logger [ label = "h2 = hash(h1)" ] ; - client=>historian [ label = "Claim(d0)" ] ; - historian=>logger [ label = "Claim(d0)" ] ; + client=>historian [ label = "Transaction(d0)" ] ; + historian=>logger [ label = "Transaction(d0)" ] ; logger=>logger [ label = "h3 = hash(h2 + d0)" ] ; - logger=>historian [ label = "e1 = Entry{id: hash(h3), n: 2, event: Claim(d0)}" ] ; + logger=>historian [ label = "e1 = Entry{id: hash(h3), n: 3, event: Transaction(d0)}" ] ; logger=>logger [ label = "h4 = hash(h3)" ] ; logger=>logger [ label = "h5 = hash(h4)" ] ; logger=>logger [ label = "h6 = hash(h5)" ] ; diff --git a/src/log.rs b/src/log.rs index cc5881b2b1..68a437d6b1 100644 --- a/src/log.rs +++ b/src/log.rs @@ -56,23 +56,27 @@ pub fn extend_and_hash(id: &Sha256Hash, val: &[u8]) -> Sha256Hash { hash(&hash_data) } -/// Creates the hash 'num_hashes' after start_hash, plus an additional hash for any event data. +/// 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: &Sha256Hash, num_hashes: u64, event: &Event, ) -> Sha256Hash { let mut id = *start_hash; - for _ in 0..num_hashes { + let sig = get_signature(event); + let start_index = if sig.is_some() { 1 } else { 0 }; + for _ in start_index..num_hashes { id = hash(&id); } - match get_signature(event) { - None => id, - Some(sig) => extend_and_hash(&id, &sig), + if let Some(sig) = sig { + id = extend_and_hash(&id, &sig); } + id } -/// Creates the next Tick Entry 'num_hashes' after 'start_hash'. +/// Creates the next Entry 'num_hashes' after 'start_hash'. pub fn next_entry( start_hash: &Sha256Hash, num_hashes: u64, diff --git a/src/logger.rs b/src/logger.rs index 627ce75e6d..ae54dd1821 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -61,6 +61,7 @@ impl Logger { pub fn log_event(&mut self, event: Event) -> Result<(), (Entry, ExitReason)> { if let Some(sig) = get_signature(&event) { self.last_id = extend_and_hash(&self.last_id, &sig); + self.num_hashes += 1; } let entry = Entry { id: self.last_id,