From 01326936e606ac72a0917012b525f5e3f72e4e0f Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Thu, 5 Apr 2018 10:26:43 -0600 Subject: [PATCH] Expire all transactions after some amount of time Reject old transactions so that we can calculate an upper bound for memory usage, and therefore ensure the server won't slow down over time to crash due to memory exhaustion. --- src/accountant.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 153ba8786d..efe80df37e 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -15,6 +15,8 @@ use std::result; use std::sync::RwLock; use transaction::Transaction; +const MAX_ENTRY_IDS: usize = 1024 * 4; + #[derive(Debug, PartialEq, Eq)] pub enum AccountingError { InsufficientFunds, @@ -93,8 +95,11 @@ impl Accountant { /// the oldest ones once its internal cache is full. Once boot, the /// accountant will reject transactions using that `last_id`. pub fn register_entry_id(&self, last_id: &Hash) { - let sigs = RwLock::new(HashSet::new()); - self.last_ids.write().unwrap().push_back((*last_id, sigs)); + let mut last_ids = self.last_ids.write().unwrap(); + if last_ids.len() >= MAX_ENTRY_IDS { + last_ids.pop_front(); + } + last_ids.push_back((*last_id, RwLock::new(HashSet::new()))); } /// Process a Transaction that has already been verified. @@ -222,6 +227,8 @@ impl Accountant { mod tests { use super::*; use signature::KeyPairUtil; + use hash::hash; + use bincode::serialize; #[test] fn test_accountant() { @@ -342,6 +349,19 @@ mod tests { assert!(acc.reserve_signature_with_last_id(&sig, &alice.last_id())); assert!(!acc.reserve_signature_with_last_id(&sig, &alice.last_id())); } + + #[test] + fn test_max_entry_ids() { + let alice = Mint::new(1); + let acc = Accountant::new(&alice); + let sig = Signature::default(); + for i in 0..MAX_ENTRY_IDS { + let last_id = hash(&serialize(&i).unwrap()); // Unique hash + acc.register_entry_id(&last_id); + } + // Assert we're no longer able to use the oldest entry ID. + assert!(!acc.reserve_signature_with_last_id(&sig, &alice.last_id())); + } } #[cfg(all(feature = "unstable", test))]