From 445a929efb2f2b8221dbbdc32215d545f2768d7d Mon Sep 17 00:00:00 2001 From: Arya Date: Thu, 26 Sep 2024 21:59:37 -0400 Subject: [PATCH] adds a `spending_transaction_hash()` read fn for the new column family --- .../finalized_state/zebra_db/transparent.rs | 12 ++++++++++-- .../src/service/non_finalized_state/chain.rs | 12 ++++++++---- zebra-state/src/service/read.rs | 3 ++- zebra-state/src/service/read/block.rs | 16 ++++++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/zebra-state/src/service/finalized_state/zebra_db/transparent.rs b/zebra-state/src/service/finalized_state/zebra_db/transparent.rs index e9957c1aa..f10e5d8af 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/transparent.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/transparent.rs @@ -68,8 +68,7 @@ impl ZebraDb { /// Returns the [`TransactionLocation`] for a transaction that spent the output /// at the provided [`OutputLocation`], if it is in the finalized state. - #[allow(clippy::unwrap_in_result)] - pub fn tx_loc_by_spent_output_loc( + pub fn tx_location_by_spent_output_location( &self, output_location: &OutputLocation, ) -> Option { @@ -123,6 +122,15 @@ impl ZebraDb { self.utxo_by_location(output_location) } + /// Returns the [`transaction::Hash`] of the transaction that spent the given + /// [`transparent::OutPoint`], if it is unspent in the finalized state. + pub fn spending_tx_id(&self, outpoint: &transparent::OutPoint) -> Option { + let output_location = self.output_location(outpoint)?; + let spending_tx_location = self.tx_location_by_spent_output_location(&output_location)?; + + self.transaction_hash(spending_tx_location) + } + /// Returns the transparent output for an [`OutputLocation`], /// if it is unspent in the finalized state. #[allow(clippy::unwrap_in_result)] diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index 351a7b7cc..0f8612c81 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -1256,11 +1256,15 @@ impl Chain { /// /// UTXOs are returned regardless of whether they have been spent. pub fn created_utxo(&self, outpoint: &transparent::OutPoint) -> Option { - if let Some(utxo) = self.created_utxos.get(outpoint) { - return Some(utxo.utxo.clone()); - } + self.created_utxos + .get(outpoint) + .map(|utxo| utxo.utxo.clone()) + } - None + /// Returns the [`transaction::Hash`] of the transaction that spent the given + /// [`transparent::OutPoint`], if it was spent by this chain. + pub fn spending_tx_id(&self, outpoint: &transparent::OutPoint) -> Option { + self.spent_utxos.get(outpoint).cloned() } // Address index queries diff --git a/zebra-state/src/service/read.rs b/zebra-state/src/service/read.rs index 0188ca1bf..b364400fa 100644 --- a/zebra-state/src/service/read.rs +++ b/zebra-state/src/service/read.rs @@ -31,7 +31,8 @@ pub use address::{ utxo::{address_utxos, AddressUtxos}, }; pub use block::{ - any_utxo, block, block_header, mined_transaction, transaction_hashes_for_block, unspent_utxo, + any_utxo, block, block_header, mined_transaction, spending_transaction_hash, + transaction_hashes_for_block, unspent_utxo, }; pub use find::{ best_tip, block_locator, depth, finalized_state_contains_block_hash, find_chain_hashes, diff --git a/zebra-state/src/service/read/block.rs b/zebra-state/src/service/read/block.rs index ba527f74a..9d9add205 100644 --- a/zebra-state/src/service/read/block.rs +++ b/zebra-state/src/service/read/block.rs @@ -181,6 +181,22 @@ where } } +/// Returns the [`Hash`](transaction::Hash) of the transaction that spent an output at +/// the provided [`transparent::OutPoint`], if it exists and is spent in the non-finalized +/// `chain` or finalized `db`. +pub fn spending_transaction_hash( + chain: Option, + db: &ZebraDb, + outpoint: transparent::OutPoint, +) -> Option +where + C: AsRef, +{ + chain + .and_then(|chain| chain.as_ref().spending_tx_id(&outpoint)) + .or_else(|| db.spending_tx_id(&outpoint)) +} + /// Returns the [`Utxo`] for [`transparent::OutPoint`], if it exists in any chain /// in the `non_finalized_state`, or in the finalized `db`. ///