Rename end_hash to id

This commit is contained in:
Greg Fitzgerald
2018-03-04 07:34:38 -07:00
parent 608def9c78
commit b1e9512f44
8 changed files with 50 additions and 50 deletions

View File

@ -71,9 +71,9 @@ fn main() {
Running the program should produce a log similar to: Running the program should produce a log similar to:
```rust ```rust
Entry { num_hashes: 0, end_hash: [0, ...], event: Tick } Entry { num_hashes: 0, id: [0, ...], event: Tick }
Entry { num_hashes: 2, end_hash: [67, ...], event: Transaction { data: [37, ...] } } Entry { num_hashes: 2, id: [67, ...], event: Transaction { data: [37, ...] } }
Entry { num_hashes: 3, end_hash: [123, ...], event: Tick } Entry { num_hashes: 3, id: [123, ...], event: Tick }
``` ```
Proof-of-History Proof-of-History
@ -86,7 +86,7 @@ assert!(verify_slice(&entries, &seed));
``` ```
[It's a proof!](https://en.wikipedia.org/wiki/CurryHoward_correspondence) For each entry returned by the [It's a proof!](https://en.wikipedia.org/wiki/CurryHoward_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 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. included in the hash, the events cannot be reordered without regenerating all the hashes.

View File

@ -1,17 +1,17 @@
msc { msc {
client,historian,logger; 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 = "h1 = hash(h0)" ] ;
logger=>logger [ label = "h2 = hash(h1)" ] ; logger=>logger [ label = "h2 = hash(h1)" ] ;
client=>historian [ label = "Claim(d0)" ] ; client=>historian [ label = "Claim(d0)" ] ;
historian=>logger [ label = "Claim(d0)" ] ; historian=>logger [ label = "Claim(d0)" ] ;
logger=>logger [ label = "h3 = hash(h2 + 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 = "h4 = hash(h3)" ] ;
logger=>logger [ label = "h5 = hash(h4)" ] ; logger=>logger [ label = "h5 = hash(h4)" ] ;
logger=>logger [ label = "h6 = hash(h5)" ] ; 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()" ] ; client=>historian [ label = "collect()" ] ;
historian=>client [ label = "entries = [e0, e1, e2]" ] ; historian=>client [ label = "entries = [e0, e1, e2]" ] ;
client=>client [ label = "verify_slice(entries, h0)" ] ; client=>client [ label = "verify_slice(entries, h0)" ] ;

View File

@ -25,7 +25,7 @@ pub type Result<T> = result::Result<T, AccountingError>;
pub struct Accountant { pub struct Accountant {
pub historian: Historian<u64>, pub historian: Historian<u64>,
pub balances: HashMap<PublicKey, u64>, pub balances: HashMap<PublicKey, u64>,
pub end_hash: Sha256Hash, pub last_id: Sha256Hash,
} }
impl Accountant { impl Accountant {
@ -35,7 +35,7 @@ impl Accountant {
let mut acc = Accountant { let mut acc = Accountant {
historian: hist, historian: hist,
balances: HashMap::new(), balances: HashMap::new(),
end_hash: start_hash, last_id: start_hash,
}; };
for (i, event) in gen.create_events().into_iter().enumerate() { for (i, event) in gen.create_events().into_iter().enumerate() {
acc.process_verified_event(event, i < 2).unwrap(); acc.process_verified_event(event, i < 2).unwrap();
@ -50,7 +50,7 @@ impl Accountant {
} }
if let Some(last_entry) = entries.last() { if let Some(last_entry) = entries.last() {
self.end_hash = last_entry.end_hash; self.last_id = last_entry.id;
} }
entries entries

View File

@ -22,7 +22,7 @@ fn main() {
drop(logger.sender); drop(logger.sender);
let entries = receiver.iter().collect::<Vec<_>>(); let entries = receiver.iter().collect::<Vec<_>>();
verify_slice_u64(&entries, &entries[0].end_hash); verify_slice_u64(&entries, &entries[0].id);
println!("["); println!("[");
let len = entries.len(); let len = entries.len();
for (i, x) in entries.iter().enumerate() { for (i, x) in entries.iter().enumerate() {

View File

@ -2,9 +2,9 @@
//! an ordered log of events in time. //! an ordered log of events in time.
/// Each log entry contains three pieces of data. The 'num_hashes' field is the number /// 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 hashes performed since the previous entry. The 'id' field is the result
/// of hashing 'end_hash' from the previous entry 'num_hashes' times. The 'event' /// of hashing 'id' from the previous entry 'num_hashes' times. The 'event'
/// field points to an Event that took place shortly after 'end_hash' was generated. /// 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 /// 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 /// get a duration estimate since the last event. Since processing power increases
@ -27,7 +27,7 @@ pub type Signature = GenericArray<u8, U64>;
/// When 'event' is Tick, the event represents a simple clock tick, and exists for the /// 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 /// 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 /// 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. /// of the preceding tick to seed its hashing.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Event<T> { pub enum Event<T> {

View File

@ -53,7 +53,7 @@ impl<T: 'static + Serialize + Clone + Debug + Send> Historian<T> {
if let Err(err) = logger.log_events(now, ms_per_tick) { if let Err(err) = logger.log_events(now, ms_per_tick) {
return err; return err;
} }
logger.end_hash = hash(&logger.end_hash); logger.last_id = hash(&logger.last_id);
logger.num_hashes += 1; logger.num_hashes += 1;
} }
}) })

View File

@ -2,9 +2,9 @@
//! an ordered log of events in time. //! an ordered log of events in time.
/// Each log entry contains three pieces of data. The 'num_hashes' field is the number /// 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 hashes performed since the previous entry. The 'id' field is the result
/// of hashing 'end_hash' from the previous entry 'num_hashes' times. The 'event' /// of hashing 'id' from the previous entry 'num_hashes' times. The 'event'
/// field points to an Event that took place shortly after 'end_hash' was generated. /// 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 /// 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 /// get a duration estimate since the last event. Since processing power increases
@ -26,17 +26,17 @@ pub type Sha256Hash = GenericArray<u8, U32>;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Entry<T> { pub struct Entry<T> {
pub num_hashes: u64, pub num_hashes: u64,
pub end_hash: Sha256Hash, pub id: Sha256Hash,
pub event: Event<T>, pub event: Event<T>,
} }
impl<T> Entry<T> { impl<T> Entry<T> {
/// Creates a Entry from the number of hashes 'num_hashes' since the previous event /// Creates a Entry from the number of hashes 'num_hashes' since the previous event
/// and that resulting 'end_hash'. /// and that resulting 'id'.
pub fn new_tick(num_hashes: u64, end_hash: &Sha256Hash) -> Self { pub fn new_tick(num_hashes: u64, id: &Sha256Hash) -> Self {
Entry { Entry {
num_hashes, num_hashes,
end_hash: *end_hash, id: *id,
event: Event::Tick, 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. /// Return the hash of the given hash extended with the given value.
pub fn extend_and_hash(end_hash: &Sha256Hash, val: &[u8]) -> Sha256Hash { pub fn extend_and_hash(id: &Sha256Hash, val: &[u8]) -> Sha256Hash {
let mut hash_data = end_hash.to_vec(); let mut hash_data = id.to_vec();
hash_data.extend_from_slice(val); hash_data.extend_from_slice(val);
hash(&hash_data) hash(&hash_data)
} }
pub fn hash_event<T>(end_hash: &Sha256Hash, event: &Event<T>) -> Sha256Hash { pub fn hash_event<T>(id: &Sha256Hash, event: &Event<T>) -> Sha256Hash {
match get_signature(event) { match get_signature(event) {
None => *end_hash, None => *id,
Some(sig) => extend_and_hash(end_hash, &sig), Some(sig) => extend_and_hash(id, &sig),
} }
} }
@ -69,11 +69,11 @@ pub fn next_hash<T: Serialize>(
num_hashes: u64, num_hashes: u64,
event: &Event<T>, event: &Event<T>,
) -> Sha256Hash { ) -> Sha256Hash {
let mut end_hash = *start_hash; let mut id = *start_hash;
for _ in 0..num_hashes { 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'. /// Creates the next Tick Entry 'num_hashes' after 'start_hash'.
@ -84,7 +84,7 @@ pub fn next_entry<T: Serialize>(
) -> Entry<T> { ) -> Entry<T> {
Entry { Entry {
num_hashes, num_hashes,
end_hash: next_hash(start_hash, num_hashes, &event), id: next_hash(start_hash, num_hashes, &event),
event, event,
} }
} }
@ -96,7 +96,7 @@ pub fn next_entry_mut<T: Serialize>(
event: Event<T>, event: Event<T>,
) -> Entry<T> { ) -> Entry<T> {
let entry = next_entry(start_hash, num_hashes, event); let entry = next_entry(start_hash, num_hashes, event);
*start_hash = entry.end_hash; *start_hash = entry.id;
entry entry
} }
@ -105,34 +105,34 @@ pub fn next_tick<T: Serialize>(start_hash: &Sha256Hash, num_hashes: u64) -> Entr
next_entry(start_hash, num_hashes, Event::Tick) 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. /// If the event is not a Tick, then hash that as well.
pub fn verify_entry<T: Serialize>(entry: &Entry<T>, start_hash: &Sha256Hash) -> bool { pub fn verify_entry<T: Serialize>(entry: &Entry<T>, start_hash: &Sha256Hash) -> bool {
if !verify_event(&entry.event) { if !verify_event(&entry.event) {
return false; 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. /// Verifies the hashes and counts of a slice of events are all consistent.
pub fn verify_slice(events: &[Entry<Sha256Hash>], start_hash: &Sha256Hash) -> bool { pub fn verify_slice(events: &[Entry<Sha256Hash>], start_hash: &Sha256Hash) -> bool {
let genesis = [Entry::new_tick(Default::default(), start_hash)]; let genesis = [Entry::new_tick(Default::default(), start_hash)];
let event_pairs = genesis.par_iter().chain(events).zip(events); 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. /// Verifies the hashes and counts of a slice of events are all consistent.
pub fn verify_slice_u64(events: &[Entry<u64>], start_hash: &Sha256Hash) -> bool { pub fn verify_slice_u64(events: &[Entry<u64>], start_hash: &Sha256Hash) -> bool {
let genesis = [Entry::new_tick(Default::default(), start_hash)]; let genesis = [Entry::new_tick(Default::default(), start_hash)];
let event_pairs = genesis.par_iter().chain(events).zip(events); 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. /// Verifies the hashes and events serially. Exists only for reference.
pub fn verify_slice_seq<T: Serialize>(events: &[Entry<T>], start_hash: &Sha256Hash) -> bool { pub fn verify_slice_seq<T: Serialize>(events: &[Entry<T>], start_hash: &Sha256Hash) -> bool {
let genesis = [Entry::new_tick(0, start_hash)]; let genesis = [Entry::new_tick(0, start_hash)];
let mut event_pairs = genesis.iter().chain(events).zip(events); 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<T: Serialize>( pub fn create_entries<T: Serialize>(
@ -140,10 +140,10 @@ pub fn create_entries<T: Serialize>(
num_hashes: u64, num_hashes: u64,
events: Vec<Event<T>>, events: Vec<Event<T>>,
) -> Vec<Entry<T>> { ) -> Vec<Entry<T>> {
let mut end_hash = *start_hash; let mut id = *start_hash;
events events
.into_iter() .into_iter()
.map(|event| next_entry_mut(&mut end_hash, num_hashes, event)) .map(|event| next_entry_mut(&mut id, num_hashes, event))
.collect() .collect()
} }
@ -153,10 +153,10 @@ pub fn create_ticks(
num_hashes: u64, num_hashes: u64,
len: usize, len: usize,
) -> Vec<Entry<Sha256Hash>> { ) -> Vec<Entry<Sha256Hash>> {
let mut end_hash = *start_hash; let mut id = *start_hash;
iter::repeat(Event::Tick) iter::repeat(Event::Tick)
.take(len) .take(len)
.map(|event| next_entry_mut(&mut end_hash, num_hashes, event)) .map(|event| next_entry_mut(&mut id, num_hashes, event))
.collect() .collect()
} }
@ -189,7 +189,7 @@ mod tests {
assert!(verify_slice(&create_ticks(&zero, 0, 2), &zero)); // inductive step assert!(verify_slice(&create_ticks(&zero, 0, 2), &zero)); // inductive step
let mut bad_ticks = create_ticks(&zero, 0, 2); 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 assert!(!verify_slice(&bad_ticks, &zero)); // inductive step, bad
} }

View File

@ -22,7 +22,7 @@ pub enum ExitReason {
pub struct Logger<T> { pub struct Logger<T> {
pub sender: SyncSender<Entry<T>>, pub sender: SyncSender<Entry<T>>,
pub receiver: Receiver<Event<T>>, pub receiver: Receiver<Event<T>>,
pub end_hash: Sha256Hash, pub last_id: Sha256Hash,
pub num_hashes: u64, pub num_hashes: u64,
pub num_ticks: u64, pub num_ticks: u64,
} }
@ -52,16 +52,16 @@ impl<T: Serialize + Clone + Debug> Logger<T> {
Logger { Logger {
receiver, receiver,
sender, sender,
end_hash: start_hash, last_id: start_hash,
num_hashes: 0, num_hashes: 0,
num_ticks: 0, num_ticks: 0,
} }
} }
pub fn log_event(&mut self, event: Event<T>) -> Result<(), (Entry<T>, ExitReason)> { pub fn log_event(&mut self, event: Event<T>) -> Result<(), (Entry<T>, ExitReason)> {
self.end_hash = hash_event(&self.end_hash, &event); self.last_id = hash_event(&self.last_id, &event);
let entry = Entry { let entry = Entry {
end_hash: self.end_hash, id: self.last_id,
num_hashes: self.num_hashes, num_hashes: self.num_hashes,
event, event,
}; };
@ -93,7 +93,7 @@ impl<T: Serialize + Clone + Debug> Logger<T> {
} }
Err(TryRecvError::Disconnected) => { Err(TryRecvError::Disconnected) => {
let entry = Entry { let entry = Entry {
end_hash: self.end_hash, id: self.last_id,
num_hashes: self.num_hashes, num_hashes: self.num_hashes,
event: Event::Tick, event: Event::Tick,
}; };
@ -148,12 +148,12 @@ mod tests {
#[test] #[test]
fn test_genesis_no_creators() { fn test_genesis_no_creators() {
let entries = run_genesis(Genesis::new(100, vec![])); 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] #[test]
fn test_genesis() { fn test_genesis() {
let entries = run_genesis(Genesis::new(100, vec![Creator::new(42)])); 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));
} }
} }