Skip to content

Commit

Permalink
Specify that the conflict is a spend conflict
Browse files Browse the repository at this point in the history
Make the situation clearer, because there are other types of conflict.

Co-authored-by: teor <teor@riseup.net>
  • Loading branch information
jvff and teor2345 committed Sep 21, 2021
1 parent a3d7ae6 commit 17f217b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 16 deletions.
9 changes: 6 additions & 3 deletions zebrad/src/components/mempool/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ pub enum MempoolError {
#[error("transaction dropped because the queue is full")]
FullQueue,

/// The transaction conflicts with another transaction already in the mempool.
#[error("transaction rejected because it conflicts with another transaction in the mempool")]
Conflict,
/// The transaction has a spend conflict with another transaction already in the mempool.
#[error(
"transaction rejected because another transaction in the mempool has already spent some of \
its inputs"
)]
SpendConflict,
}
27 changes: 14 additions & 13 deletions zebrad/src/components/mempool/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ pub enum State {
/// An otherwise valid mempool transaction was mined into a block, therefore
/// no longer belongs in the mempool.
Confirmed(block::Hash),
/// Rejected because it conflicted with another transaction already in the mempool.
Conflict,
/// Rejected because it has a spend conflict with another transaction already in the mempool.
SpendConflict,
/// Stayed in mempool for too long without being mined.
// TODO(2021-08-20): set expiration at 2 weeks? This is what Bitcoin does.
Expired,
Expand Down Expand Up @@ -62,7 +62,7 @@ impl Storage {
State::Confirmed(block_hash) => MempoolError::InBlock(*block_hash),
State::Excess => MempoolError::Excess,
State::LowFee => MempoolError::LowFee,
State::Conflict => MempoolError::Conflict,
State::SpendConflict => MempoolError::SpendConflict,
});
}

Expand All @@ -80,7 +80,7 @@ impl Storage {
//
// TODO: Consider replacing the transaction in the mempool if the fee is higher (#2781).
if self.check_spend_conflicts(&tx) {
self.rejected.insert(tx.id, State::Conflict);
self.rejected.insert(tx.id, State::SpendConflict);
return Err(MempoolError::Rejected);
}

Expand Down Expand Up @@ -156,19 +156,20 @@ impl Storage {
.collect()
}

/// Checks if the `tx` transaction conflicts with another transaction in the mempool.
/// Checks if the `tx` transaction has spend conflicts with another transaction in the mempool.
///
/// Two transactions conflict if they spent the same UTXO or if they reveal the same nullifier.
/// Two transactions have a spend conflict if they spent the same UTXO or if they reveal the
/// same nullifier.
fn check_spend_conflicts(&self, tx: &UnminedTx) -> bool {
self.has_conflicts(tx, Transaction::spent_outpoints)
|| self.has_conflicts(tx, Transaction::sprout_nullifiers)
|| self.has_conflicts(tx, Transaction::sapling_nullifiers)
|| self.has_conflicts(tx, Transaction::orchard_nullifiers)
self.has_spend_conflicts(tx, Transaction::spent_outpoints)
|| self.has_spend_conflicts(tx, Transaction::sprout_nullifiers)
|| self.has_spend_conflicts(tx, Transaction::sapling_nullifiers)
|| self.has_spend_conflicts(tx, Transaction::orchard_nullifiers)
}

/// Checks if the `tx` transaction has any conflicts with the transactions in the mempool for
/// the provided output type obtained through the `extractor`.
fn has_conflicts<'slf, 'tx, Extractor, Outputs>(
/// Checks if the `tx` transaction has any spend conflicts with the transactions in the mempool
/// for the provided output type obtained through the `extractor`.
fn has_spend_conflicts<'slf, 'tx, Extractor, Outputs>(
&'slf self,
tx: &'tx UnminedTx,
extractor: Extractor,
Expand Down

0 comments on commit 17f217b

Please sign in to comment.