diff --git a/src/accountant.rs b/src/accountant.rs index 3a54c7c46af23a..50b76e529ace25 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -29,6 +29,7 @@ pub struct Accountant { pub balances: HashMap, pub first_id: Hash, pub last_id: Hash, + pub pending: HashMap>, } impl Accountant { @@ -49,6 +50,7 @@ impl Accountant { balances: HashMap::new(), first_id: start_hash, last_id: start_hash, + pending: HashMap::new(), }; // The second item in the log is a special transaction where the to and from @@ -104,12 +106,20 @@ impl Accountant { return Err(AccountingError::InvalidTransferSignature); } + if !tr.unless_any.is_empty() { + // TODO: Check to see if the transaction is expired. + } + if !Self::is_deposit(allow_deposits, &tr.from, &tr.to) { if let Some(x) = self.balances.get_mut(&tr.from) { *x -= tr.asset; } } + if !tr.if_all.is_empty() { + self.pending.insert(tr.sig, tr.clone()); + } + if self.balances.contains_key(&tr.to) { if let Some(x) = self.balances.get_mut(&tr.to) { *x += tr.asset; @@ -121,10 +131,39 @@ impl Accountant { Ok(()) } + fn process_verified_sig(&mut self, _from: PublicKey, tx_sig: Signature) -> Result<()> { + if self.pending.contains_key(&tx_sig) { + if let Some(_tx) = self.pending.get_mut(&tx_sig) { + // Cancel: + // if Signature(from) is in unless_any, return funds to tx.from, and remove the tx from this map. + + // Process Multisig: + // otherwise, if "Signature(from) 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(()) + } + + fn process_verified_timestamp(&mut self, _from: PublicKey, _dt: DateTime) -> Result<()> { + // TODO: Lookup pending Transaction waiting on time, signed by a whitelisted PublicKey. + + // Expire: + // if a Timestamp after this DateTime is in unless_any, return funds to tx.from, + // and remove the tx from this map. + + // Process postponed: + // otherwise, if "Signature(from) 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(()) + } + 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), + Event::Signature { from, tx_sig, .. } => self.process_verified_sig(from, tx_sig), + Event::Timestamp { from, dt, .. } => self.process_verified_timestamp(from, dt), } } diff --git a/src/event.rs b/src/event.rs index 12a848ab5f47c8..444f21b9c82282 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,7 +1,9 @@ //! The `event` crate provides the data structures for log events. -use signature::Signature; +use signature::{PublicKey, Signature, SignatureUtil}; use transaction::Transaction; +use chrono::prelude::*; +use bincode::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 @@ -12,13 +14,26 @@ use transaction::Transaction; pub enum Event { Tick, Transaction(Transaction), + Signature { + from: PublicKey, + tx_sig: Signature, + sig: Signature, + }, + Timestamp { + from: PublicKey, + dt: DateTime, + sig: Signature, + }, } impl Event { + // TODO: Rename this to transaction_signature(). pub fn get_signature(&self) -> Option { match *self { Event::Tick => None, Event::Transaction(ref tr) => Some(tr.sig), + Event::Signature { .. } => None, + Event::Timestamp { .. } => None, } } @@ -26,6 +41,8 @@ impl Event { match *self { Event::Tick => true, Event::Transaction(ref tr) => tr.verify(), + Event::Signature { from, tx_sig, sig } => sig.verify(&from, &tx_sig), + Event::Timestamp { from, dt, sig } => sig.verify(&from, &serialize(&dt).unwrap()), } } } diff --git a/src/transaction.rs b/src/transaction.rs index 8256da28d3d003..3f2a1e99d41c59 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -8,8 +8,8 @@ use chrono::prelude::*; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub enum Condition { - DateTime(DateTime), - Cancel, + Timestamp(DateTime), + Signature(PublicKey), } #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] @@ -45,11 +45,12 @@ impl Transaction { asset: T, last_id: Hash, ) -> Self { + let from = from_keypair.pubkey(); let mut tr = Transaction { - from: from_keypair.pubkey(), + from, to, - if_all: vec![Condition::DateTime(dt)], - unless_any: vec![Condition::Cancel], + if_all: vec![Condition::Timestamp(dt)], + unless_any: vec![Condition::Signature(from)], asset, last_id, sig: Signature::default(),