Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject duplicate UTXO spends and nullifier reveals within the same mempool transaction #2787

Closed
Tracked by #2309
teor2345 opened this issue Sep 21, 2021 · 1 comment · Fixed by #2843
Closed
Tracked by #2309
Assignees

Comments

@teor2345
Copy link
Contributor

teor2345 commented Sep 21, 2021

Motivation

Mempools typically require a consistent set of transactions, which could all be mined into a single block.

In order to support this restriction, Zebra should reject transactions that:

  • spend the same output more than once
  • reveal the same nullifier more than once

Specifications

This consensus rule applies to both block and mempool transactions, so we might want to implement it in transaction::Verifier.

Design

zebra-state already checks for double-spends within the same block transaction.
We can move this check to transaction::Verifier.

// We don't delete the UTXOs until the block is committed,
// so we need to check for duplicate spends within the same block.
//
// See `transparent_spend_chain_order` for the relevant consensus rule.
if block_spends.insert(*spend, utxo).is_some() {
return Err(DuplicateTransparentSpend {
outpoint: *spend,
location: "the same block",
});
}

The mempool already checks for double-spends between transactions in check_spend_conflicts:

/// Checks if the `tx` transaction has spend conflicts with another transaction in the mempool.
///
/// 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_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)
}

@teor2345 teor2345 mentioned this issue Sep 21, 2021
59 tasks
@teor2345 teor2345 added this to the 2021 Sprint 20 milestone Sep 21, 2021
@mpguerra
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants