Don't allow same transaction to be received multiple times (#2124)
* don't allow same transaction to be received multiple times * issues in other tests uncovered and fixed * allow tx_hex update function to operate without an account being specified, to allow finalize_tx function to work without an account being specified * rustfmt * fix to retrieve_txs * rustfmt
This commit is contained in:
@@ -425,7 +425,7 @@ where
|
||||
|
||||
let res = Ok((
|
||||
validated,
|
||||
updater::retrieve_txs(&mut *w, tx_id, tx_slate_id, &parent_key_id)?,
|
||||
updater::retrieve_txs(&mut *w, tx_id, tx_slate_id, Some(&parent_key_id))?,
|
||||
));
|
||||
|
||||
w.close()?;
|
||||
@@ -832,6 +832,11 @@ where
|
||||
}
|
||||
None => w.parent_key_id(),
|
||||
};
|
||||
// Don't do this multiple times
|
||||
let tx = updater::retrieve_txs(&mut *w, None, Some(slate.id), Some(&parent_key_id))?;
|
||||
if tx.len() > 0 {
|
||||
return Err(ErrorKind::TransactionAlreadyReceived(slate.id.to_string()).into());
|
||||
}
|
||||
let res = tx::receive_tx(&mut *w, slate, &parent_key_id, false, message);
|
||||
w.close()?;
|
||||
|
||||
|
||||
@@ -167,6 +167,10 @@ pub enum ErrorKind {
|
||||
#[fail(display = "Transaction already confirmed error")]
|
||||
TransactionAlreadyConfirmed,
|
||||
|
||||
/// Transaction has already been received
|
||||
#[fail(display = "Transaction {} has already been received", _0)]
|
||||
TransactionAlreadyReceived(String),
|
||||
|
||||
/// Attempt to repost a transaction that's not completed and stored
|
||||
#[fail(display = "Transaction building not completed: {}", _0)]
|
||||
TransactionBuildingNotCompleted(u32),
|
||||
|
||||
@@ -169,7 +169,7 @@ where
|
||||
} else if let Some(tx_slate_id) = tx_slate_id {
|
||||
tx_id_string = tx_slate_id.to_string();
|
||||
}
|
||||
let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, &parent_key_id)?;
|
||||
let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, Some(&parent_key_id))?;
|
||||
if tx_vec.len() != 1 {
|
||||
return Err(ErrorKind::TransactionDoesntExist(tx_id_string))?;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ where
|
||||
C: NodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), None, parent_key_id)?;
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), None, Some(parent_key_id))?;
|
||||
if tx_vec.len() != 1 {
|
||||
return Err(ErrorKind::TransactionDoesntExist(tx_id.to_string()))?;
|
||||
}
|
||||
@@ -219,7 +219,9 @@ where
|
||||
K: Keychain,
|
||||
{
|
||||
let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap());
|
||||
let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), parent_key_id)?;
|
||||
// This will ignore the parent key, so no need to specify account on the
|
||||
// finalise command
|
||||
let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), None)?;
|
||||
if tx_vec.len() != 1 {
|
||||
return Err(ErrorKind::TransactionDoesntExist(slate.id.to_string()))?;
|
||||
}
|
||||
|
||||
@@ -80,11 +80,12 @@ where
|
||||
}
|
||||
|
||||
/// Retrieve all of the transaction entries, or a particular entry
|
||||
/// if `parent_key_id` is set, only return entries from that key
|
||||
pub fn retrieve_txs<T: ?Sized, C, K>(
|
||||
wallet: &mut T,
|
||||
tx_id: Option<u32>,
|
||||
tx_slate_id: Option<Uuid>,
|
||||
parent_key_id: &Identifier,
|
||||
parent_key_id: Option<&Identifier>,
|
||||
) -> Result<Vec<TxLogEntry>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
@@ -93,9 +94,7 @@ where
|
||||
{
|
||||
// just read the wallet here, no need for a write lock
|
||||
let mut txs = if let Some(id) = tx_id {
|
||||
let tx = wallet
|
||||
.tx_log_iter()
|
||||
.find(|t| t.id == id && t.parent_key_id == *parent_key_id);
|
||||
let tx = wallet.tx_log_iter().find(|t| t.id == id);
|
||||
if let Some(t) = tx {
|
||||
vec![t]
|
||||
} else {
|
||||
@@ -109,14 +108,19 @@ where
|
||||
vec![]
|
||||
}
|
||||
} else {
|
||||
wallet
|
||||
.tx_log_iter()
|
||||
.filter(|t| t.parent_key_id == *parent_key_id)
|
||||
.collect::<Vec<_>>()
|
||||
wallet.tx_log_iter().collect::<Vec<_>>()
|
||||
};
|
||||
if let Some(k) = parent_key_id {
|
||||
txs = txs
|
||||
.iter()
|
||||
.filter(|t| t.parent_key_id == *k)
|
||||
.map(|t| t.clone())
|
||||
.collect();
|
||||
}
|
||||
txs.sort_by_key(|tx| tx.creation_ts);
|
||||
Ok(txs)
|
||||
}
|
||||
|
||||
/// Refreshes the outputs in a wallet with the latest information
|
||||
/// from a node
|
||||
pub fn refresh_outputs<T: ?Sized, C, K>(
|
||||
|
||||
Reference in New Issue
Block a user