Add transaction count to accountant

This commit is contained in:
Greg Fitzgerald 2018-05-14 06:49:48 -06:00
parent b132ce1944
commit 317031f455
1 changed files with 33 additions and 3 deletions

View File

@ -17,7 +17,7 @@ use std::collections::hash_map::Entry::Occupied;
use std::collections::{HashMap, HashSet, VecDeque};
use std::result;
use std::sync::RwLock;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering};
use transaction::Transaction;
pub const MAX_ENTRY_IDS: usize = 1024 * 4;
@ -59,6 +59,7 @@ pub struct Accountant {
last_ids: RwLock<VecDeque<(Hash, RwLock<HashSet<Signature>>)>>,
time_sources: RwLock<HashSet<PublicKey>>,
last_time: RwLock<DateTime<Utc>>,
transaction_count: AtomicUsize,
}
impl Accountant {
@ -72,6 +73,7 @@ impl Accountant {
last_ids: RwLock::new(VecDeque::new()),
time_sources: RwLock::new(HashSet::new()),
last_time: RwLock::new(Utc.timestamp(0, 0)),
transaction_count: AtomicUsize::new(0),
}
}
@ -188,7 +190,10 @@ impl Accountant {
);
match result {
Ok(_) => return Ok(()),
Ok(_) => {
self.transaction_count.fetch_add(1, Ordering::Relaxed);
return Ok(());
}
Err(_) => continue,
};
}
@ -387,6 +392,10 @@ impl Accountant {
.expect("'balances' read lock in get_balance");
bals.get(pubkey).map(|x| x.load(Ordering::Relaxed) as i64)
}
pub fn transaction_count(&self) -> usize {
self.transaction_count.load(Ordering::Relaxed)
}
}
#[cfg(test)]
@ -412,6 +421,7 @@ mod tests {
.transfer(500, &alice.keypair(), bob_pubkey, alice.last_id())
.unwrap();
assert_eq!(accountant.get_balance(&bob_pubkey).unwrap(), 1_500);
assert_eq!(accountant.transaction_count(), 2);
}
#[test]
@ -422,6 +432,7 @@ mod tests {
accountant.transfer(1, &KeyPair::new(), mint.pubkey(), mint.last_id()),
Err(AccountingError::AccountNotFound)
);
assert_eq!(accountant.transaction_count(), 0);
}
#[test]
@ -432,10 +443,12 @@ mod tests {
accountant
.transfer(1_000, &alice.keypair(), bob_pubkey, alice.last_id())
.unwrap();
assert_eq!(accountant.transaction_count(), 1);
assert_eq!(
accountant.transfer(10_001, &alice.keypair(), bob_pubkey, alice.last_id()),
Err(AccountingError::InsufficientFunds)
);
assert_eq!(accountant.transaction_count(), 1);
let alice_pubkey = alice.keypair().pubkey();
assert_eq!(accountant.get_balance(&alice_pubkey).unwrap(), 10_000);
@ -468,6 +481,9 @@ mod tests {
// Alice's balance will be zero because all funds are locked up.
assert_eq!(accountant.get_balance(&alice.pubkey()), Some(0));
// tx count is 1, because debits were applied.
assert_eq!(accountant.transaction_count(), 1);
// Bob's balance will be None because the funds have not been
// sent.
assert_eq!(accountant.get_balance(&bob_pubkey), None);
@ -479,6 +495,10 @@ mod tests {
.unwrap();
assert_eq!(accountant.get_balance(&bob_pubkey), Some(1));
// tx count is still 1, because we chose not to count timestamp events
// tx count.
assert_eq!(accountant.transaction_count(), 1);
accountant
.process_verified_timestamp(alice.pubkey(), dt)
.unwrap(); // <-- Attack! Attempt to process completed transaction.
@ -516,6 +536,9 @@ mod tests {
.transfer_on_date(1, &alice_keypair, bob_pubkey, dt, alice.last_id())
.unwrap();
// Assert the debit counts as a transaction.
assert_eq!(accountant.transaction_count(), 1);
// Alice's balance will be zero because all funds are locked up.
assert_eq!(accountant.get_balance(&alice.pubkey()), Some(0));
@ -530,6 +553,9 @@ mod tests {
assert_eq!(accountant.get_balance(&alice.pubkey()), Some(1));
assert_eq!(accountant.get_balance(&bob_pubkey), None);
// Assert cancel doesn't cause count to go backward.
assert_eq!(accountant.transaction_count(), 1);
accountant
.process_verified_sig(alice.pubkey(), sig)
.unwrap(); // <-- Attack! Attempt to cancel completed transaction.
@ -576,7 +602,11 @@ mod tests {
let tr0 = Transaction::new(&mint.keypair(), alice.pubkey(), 2, mint.last_id());
let tr1 = Transaction::new(&alice, mint.pubkey(), 1, mint.last_id());
let trs = vec![tr0, tr1];
assert!(accountant.process_verified_transactions(trs)[1].is_err());
let results = accountant.process_verified_transactions(trs);
assert!(results[1].is_err());
// Assert bad transactions aren't counted.
assert_eq!(accountant.transaction_count(), 1);
}
}