Skip to content

Commit

Permalink
Return valid Utxos from check::transparent_spend (#2561)
Browse files Browse the repository at this point in the history
Later PRs will use these UTXOs to check other transparent consensus rules.

Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
  • Loading branch information
teor2345 and oxarbitrage authored Aug 3, 2021
1 parent 29a658b commit 86bbafd
Showing 1 changed file with 20 additions and 15 deletions.
35 changes: 20 additions & 15 deletions zebra-state/src/service/check/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ use crate::{
},
};

/// Reject invalid spends of transparent outputs.
/// Lookup all the [`transparent::Utxo`]s spent by a [`PreparedBlock`].
/// If any of the spends are invalid, return an error.
/// Otherwise, return the looked up UTXOs.
///
/// Checks for the following kinds of invalid spends:
///
/// Double-spends:
/// - duplicate spends that are both in this block,
Expand All @@ -36,8 +40,8 @@ pub fn transparent_spend(
non_finalized_chain_unspent_utxos: &HashMap<transparent::OutPoint, transparent::Utxo>,
non_finalized_chain_spent_utxos: &HashSet<transparent::OutPoint>,
finalized_state: &FinalizedState,
) -> Result<(), ValidateContextError> {
let mut block_spends = HashSet::new();
) -> Result<HashMap<transparent::OutPoint, transparent::Utxo>, ValidateContextError> {
let mut block_spends = HashMap::new();

for (spend_tx_index_in_block, transaction) in prepared.block.transactions.iter().enumerate() {
let spends = transaction.inputs().iter().filter_map(|input| match input {
Expand All @@ -48,15 +52,6 @@ pub fn transparent_spend(
});

for spend in spends {
// see `transparent_spend_chain_order` for the consensus rule
if !block_spends.insert(*spend) {
// reject in-block duplicate spends
return Err(DuplicateTransparentSpend {
outpoint: *spend,
location: "the same block",
});
}

let utxo = transparent_spend_chain_order(
*spend,
spend_tx_index_in_block,
Expand All @@ -75,13 +70,23 @@ pub fn transparent_spend(
// We don't want to use UTXOs from invalid pending blocks,
// so we check transparent coinbase maturity and shielding
// using known valid UTXOs during non-finalized chain validation.

let spend_restriction = transaction.coinbase_spend_restriction(prepared.height);
transparent_coinbase_spend(*spend, spend_restriction, utxo)?;
let utxo = transparent_coinbase_spend(*spend, spend_restriction, utxo)?;

// 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",
});
}
}
}

Ok(())
Ok(block_spends)
}

/// Check that transparent spends occur in chain order.
Expand Down

0 comments on commit 86bbafd

Please sign in to comment.