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:
parent
46e8c09bd8
commit
3abe305a21
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue