Better error if Bank doesn't recognize tx last_id

This commit is contained in:
Greg Fitzgerald
2018-05-29 20:48:33 -06:00
committed by Grimes
parent 290dde60a0
commit b57aecc24c

View File

@ -26,6 +26,7 @@ pub enum BankError {
AccountNotFound(PublicKey), AccountNotFound(PublicKey),
InsufficientFunds(PublicKey), InsufficientFunds(PublicKey),
InvalidTxSignature(Signature), InvalidTxSignature(Signature),
InvalidTxLastId(Hash),
InvalidTxTokens, InvalidTxTokens,
} }
@ -95,29 +96,29 @@ impl Bank {
last_item.0 last_item.0
} }
fn reserve_signature(signatures: &RwLock<HashSet<Signature>>, sig: &Signature) -> bool { fn reserve_signature(signatures: &RwLock<HashSet<Signature>>, sig: &Signature) -> Result<()> {
if signatures if signatures
.read() .read()
.expect("'signatures' read lock") .expect("'signatures' read lock")
.contains(sig) .contains(sig)
{ {
return false; return Err(BankError::InvalidTxSignature(*sig));
} }
signatures signatures
.write() .write()
.expect("'signatures' write lock") .expect("'signatures' write lock")
.insert(*sig); .insert(*sig);
true Ok(())
} }
fn forget_signature(signatures: &RwLock<HashSet<Signature>>, sig: &Signature) -> bool { fn forget_signature(signatures: &RwLock<HashSet<Signature>>, sig: &Signature) {
signatures signatures
.write() .write()
.expect("'signatures' write lock in forget_signature") .expect("'signatures' write lock in forget_signature")
.remove(sig) .remove(sig);
} }
fn forget_signature_with_last_id(&self, sig: &Signature, last_id: &Hash) -> bool { fn forget_signature_with_last_id(&self, sig: &Signature, last_id: &Hash) {
if let Some(entry) = self.last_ids if let Some(entry) = self.last_ids
.read() .read()
.expect("'last_ids' read lock in forget_signature_with_last_id") .expect("'last_ids' read lock in forget_signature_with_last_id")
@ -125,12 +126,11 @@ impl Bank {
.rev() .rev()
.find(|x| x.0 == *last_id) .find(|x| x.0 == *last_id)
{ {
return Self::forget_signature(&entry.1, sig); Self::forget_signature(&entry.1, sig);
} }
return false;
} }
fn reserve_signature_with_last_id(&self, sig: &Signature, last_id: &Hash) -> bool { fn reserve_signature_with_last_id(&self, sig: &Signature, last_id: &Hash) -> Result<()> {
if let Some(entry) = self.last_ids if let Some(entry) = self.last_ids
.read() .read()
.expect("'last_ids' read lock in reserve_signature_with_last_id") .expect("'last_ids' read lock in reserve_signature_with_last_id")
@ -140,7 +140,7 @@ impl Bank {
{ {
return Self::reserve_signature(&entry.1, sig); return Self::reserve_signature(&entry.1, sig);
} }
false Err(BankError::InvalidTxLastId(*last_id))
} }
/// Tell the bank which Entry IDs exist on the ledger. This function /// Tell the bank which Entry IDs exist on the ledger. This function
@ -175,9 +175,7 @@ impl Bank {
return Err(BankError::AccountNotFound(tx.from)); return Err(BankError::AccountNotFound(tx.from));
} }
if !self.reserve_signature_with_last_id(&tx.sig, &tx.last_id) { self.reserve_signature_with_last_id(&tx.sig, &tx.last_id)?;
return Err(BankError::InvalidTxSignature(tx.sig));
}
loop { loop {
let result = if let Instruction::NewContract(contract) = &tx.instruction { let result = if let Instruction::NewContract(contract) = &tx.instruction {
@ -544,8 +542,14 @@ mod tests {
let mint = Mint::new(1); let mint = Mint::new(1);
let bank = Bank::new(&mint); let bank = Bank::new(&mint);
let sig = Signature::default(); let sig = Signature::default();
assert!(bank.reserve_signature_with_last_id(&sig, &mint.last_id())); assert!(
assert!(!bank.reserve_signature_with_last_id(&sig, &mint.last_id())); bank.reserve_signature_with_last_id(&sig, &mint.last_id())
.is_ok()
);
assert_eq!(
bank.reserve_signature_with_last_id(&sig, &mint.last_id()),
Err(BankError::InvalidTxSignature(sig))
);
} }
#[test] #[test]
@ -553,9 +557,13 @@ mod tests {
let mint = Mint::new(1); let mint = Mint::new(1);
let bank = Bank::new(&mint); let bank = Bank::new(&mint);
let sig = Signature::default(); let sig = Signature::default();
bank.reserve_signature_with_last_id(&sig, &mint.last_id()); bank.reserve_signature_with_last_id(&sig, &mint.last_id())
assert!(bank.forget_signature_with_last_id(&sig, &mint.last_id())); .unwrap();
assert!(!bank.forget_signature_with_last_id(&sig, &mint.last_id())); bank.forget_signature_with_last_id(&sig, &mint.last_id());
assert!(
bank.reserve_signature_with_last_id(&sig, &mint.last_id())
.is_ok()
);
} }
#[test] #[test]
@ -568,7 +576,10 @@ mod tests {
bank.register_entry_id(&last_id); bank.register_entry_id(&last_id);
} }
// Assert we're no longer able to use the oldest entry ID. // Assert we're no longer able to use the oldest entry ID.
assert!(!bank.reserve_signature_with_last_id(&sig, &mint.last_id())); assert_eq!(
bank.reserve_signature_with_last_id(&sig, &mint.last_id()),
Err(BankError::InvalidTxLastId(mint.last_id()))
);
} }
#[test] #[test]