From 923162ae9d2696cd065d268f28a2db7888922ad6 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 8 Mar 2018 10:05:00 -0700 Subject: [PATCH] WIP: process timestamps --- src/accountant.rs | 42 ++++++++++++++++++++++++++++++------------ src/event.rs | 12 +++++++++++- src/mint.rs | 3 ++- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index d496b3207500b6..2bbe4090eed4c9 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -10,7 +10,7 @@ use signature::{KeyPair, PublicKey, Signature}; use mint::Mint; use historian::{reserve_signature, Historian}; use std::sync::mpsc::SendError; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::result; use chrono::prelude::*; @@ -29,7 +29,9 @@ pub struct Accountant { pub balances: HashMap, pub first_id: Hash, pub last_id: Hash, - pub pending: HashMap>, + pending: HashMap>, + time_sources: HashSet, + last_time: DateTime, } impl Accountant { @@ -51,6 +53,8 @@ impl Accountant { first_id: start_hash, last_id: start_hash, pending: HashMap::new(), + time_sources: HashSet::new(), + last_time: Utc.timestamp(0, 0), }; // The second item in the log is a special transaction where the to and from @@ -97,6 +101,16 @@ impl Accountant { Ok(()) } + fn complete_transaction(self: &mut Self, tr: &Transaction) { + if self.balances.contains_key(&tr.to) { + if let Some(x) = self.balances.get_mut(&tr.to) { + *x += tr.asset; + } + } else { + self.balances.insert(tr.to, tr.asset); + } + } + fn process_verified_transaction( self: &mut Self, tr: &Transaction, @@ -121,14 +135,7 @@ impl Accountant { return Ok(()); } - if self.balances.contains_key(&tr.to) { - if let Some(x) = self.balances.get_mut(&tr.to) { - *x += tr.asset; - } - } else { - self.balances.insert(tr.to, tr.asset); - } - + self.complete_transaction(tr); Ok(()) } @@ -146,7 +153,18 @@ impl Accountant { Ok(()) } - fn process_verified_timestamp(&mut self, _from: PublicKey, _dt: DateTime) -> Result<()> { + fn process_verified_timestamp(&mut self, from: PublicKey, dt: DateTime) -> Result<()> { + // If this is the first timestamp we've seen, it probably came from the genesis block, + // so we'll trust it. + if self.last_time == Utc.timestamp(0, 0) { + self.time_sources.insert(from); + } + + if self.time_sources.contains(&from) { + if dt > self.last_time { + self.last_time = dt; + } + } // TODO: Lookup pending Transaction waiting on time, signed by a whitelisted PublicKey. // Expire: @@ -154,7 +172,7 @@ impl Accountant { // and remove the tx from this map. // Process postponed: - // otherwise, if "Signature(from) is in if_all, remove it. If that causes that list + // otherwise, if "Timestamp(dt) >= self.last_time" is in if_all, remove it. If that causes that list // to be empty, add the asset to to, and remove the tx from this map. Ok(()) } diff --git a/src/event.rs b/src/event.rs index 444f21b9c82282..0d6642b3f31156 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,6 +1,6 @@ //! The `event` crate provides the data structures for log events. -use signature::{PublicKey, Signature, SignatureUtil}; +use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil}; use transaction::Transaction; use chrono::prelude::*; use bincode::serialize; @@ -27,6 +27,16 @@ pub enum Event { } impl Event { + pub fn new_timestamp(from: &KeyPair, dt: DateTime) -> Self { + let sign_data = serialize(&dt).unwrap(); + let sig = Signature::clone_from_slice(from.sign(&sign_data).as_ref()); + Event::Timestamp { + from: from.pubkey(), + dt, + sig, + } + } + // TODO: Rename this to transaction_signature(). pub fn get_signature(&self) -> Option { match *self { diff --git a/src/mint.rs b/src/mint.rs index 5a7d297d82b812..6beeeea9860c64 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -42,7 +42,8 @@ impl Mint { } pub fn create_events(&self) -> Vec { - let tr = Transaction::new(&self.keypair(), self.pubkey(), self.tokens, self.seed()); + let keypair = self.keypair(); + let tr = Transaction::new(&keypair, self.pubkey(), self.tokens, self.seed()); vec![Event::Tick, Event::Transaction(tr)] }