Move reserve_signatures into accountant

Reasons Transaction signatures need to be unique:

1. guard against duplicates
2. accountant uses them as IDs to link Witness signatures to transactions via the
`pending` hash map
This commit is contained in:
Greg Fitzgerald 2018-04-02 09:36:22 -06:00
parent 46e8c09bd8
commit 3abe305a21
2 changed files with 20 additions and 23 deletions

View File

@ -39,6 +39,7 @@ pub struct Accountant {
historian: Historian,
balances: HashMap<PublicKey, i64>,
pending: HashMap<Signature, Plan>,
signatures: HashSet<Signature>,
time_sources: HashSet<PublicKey>,
last_time: DateTime<Utc>,
}
@ -61,6 +62,7 @@ impl Accountant {
historian: hist,
balances: HashMap::new(),
pending: HashMap::new(),
signatures: HashSet::new(),
time_sources: HashSet::new(),
last_time: Utc.timestamp(0, 0),
};
@ -124,13 +126,21 @@ impl Accountant {
self.log_verified_transaction(tr)
}
fn reserve_signature(&mut self, sig: &Signature) -> bool {
if self.signatures.contains(sig) {
return false;
}
self.signatures.insert(*sig);
true
}
/// Process a Transaction that has already been verified.
fn process_verified_transaction(
self: &mut Self,
tr: &Transaction,
allow_deposits: bool,
) -> Result<()> {
if !self.historian.reserve_signature(&tr.sig) {
if !self.reserve_signature(&tr.sig) {
return Err(AccountingError::InvalidTransferSignature);
}
@ -400,4 +410,13 @@ mod tests {
acc.process_verified_sig(alice.pubkey(), sig).unwrap(); // <-- Attack! Attempt to cancel completed transaction.
assert_ne!(acc.get_balance(&alice.pubkey()), Some(2));
}
#[test]
fn test_duplicate_event_signature() {
let alice = Mint::new(1);
let mut acc = Accountant::new(&alice, None);
let sig = Signature::default();
assert!(acc.reserve_signature(&sig));
assert!(!acc.reserve_signature(&sig));
}
}

View File

@ -4,8 +4,6 @@
use entry::Entry;
use hash::Hash;
use recorder::{ExitReason, Recorder, Signal};
use signature::Signature;
use std::collections::HashSet;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::thread::{spawn, JoinHandle};
use std::time::Instant;
@ -14,7 +12,6 @@ pub struct Historian {
pub sender: SyncSender<Signal>,
pub receiver: Receiver<Entry>,
pub thread_hdl: JoinHandle<ExitReason>,
pub signatures: HashSet<Signature>,
}
impl Historian {
@ -23,23 +20,13 @@ impl Historian {
let (entry_sender, receiver) = sync_channel(1000);
let thread_hdl =
Historian::create_recorder(*start_hash, ms_per_tick, event_receiver, entry_sender);
let signatures = HashSet::new();
Historian {
sender,
receiver,
thread_hdl,
signatures,
}
}
pub fn reserve_signature(&mut self, sig: &Signature) -> bool {
if self.signatures.contains(sig) {
return false;
}
self.signatures.insert(*sig);
true
}
/// A background thread that will continue tagging received Event messages and
/// sending back Entry messages until either the receiver or sender channel is closed.
fn create_recorder(
@ -110,15 +97,6 @@ mod tests {
);
}
#[test]
fn test_duplicate_event_signature() {
let zero = Hash::default();
let mut hist = Historian::new(&zero, None);
let sig = Signature::default();
assert!(hist.reserve_signature(&sig));
assert!(!hist.reserve_signature(&sig));
}
#[test]
fn test_ticking_historian() {
let zero = Hash::default();