Adds new column family for [spent_out_loc] -> [spending_tx_loc] with a read method and an update to `prepare_spending_transparent_tx_ids_batch()` for maintaining it when committing blocks to the finalized state.
Adds TODOs for remaining production changes needed for issue #8837.
This commit is contained in:
parent
4f0746a613
commit
e9b39306c9
|
@ -20,6 +20,7 @@ use std::{
|
|||
};
|
||||
|
||||
use zebra_chain::{block, parallel::tree::NoteCommitmentTrees, parameters::Network};
|
||||
use zebra_db::transparent::TX_LOC_BY_SPENT_OUT_LOC;
|
||||
|
||||
use crate::{
|
||||
constants::{state_database_format_version_in_code, STATE_DATABASE_KIND},
|
||||
|
@ -77,6 +78,7 @@ pub const STATE_COLUMN_FAMILIES_IN_CODE: &[&str] = &[
|
|||
"tx_loc_by_transparent_addr_loc",
|
||||
"utxo_by_out_loc",
|
||||
"utxo_loc_by_transparent_addr_loc",
|
||||
TX_LOC_BY_SPENT_OUT_LOC,
|
||||
// Sprout
|
||||
"sprout_nullifiers",
|
||||
"sprout_anchors",
|
||||
|
|
|
@ -355,6 +355,10 @@ impl ZebraDb {
|
|||
.iter()
|
||||
.map(|(outpoint, _output_loc, utxo)| (*outpoint, utxo.clone()))
|
||||
.collect();
|
||||
let out_loc_by_outpoint: HashMap<transparent::OutPoint, OutputLocation> = spent_utxos
|
||||
.iter()
|
||||
.map(|(outpoint, out_loc, _utxo)| (*outpoint, *out_loc))
|
||||
.collect();
|
||||
let spent_utxos_by_out_loc: BTreeMap<OutputLocation, transparent::Utxo> = spent_utxos
|
||||
.into_iter()
|
||||
.map(|(_outpoint, out_loc, utxo)| (out_loc, utxo))
|
||||
|
@ -392,6 +396,7 @@ impl ZebraDb {
|
|||
new_outputs_by_out_loc,
|
||||
spent_utxos_by_outpoint,
|
||||
spent_utxos_by_out_loc,
|
||||
out_loc_by_outpoint,
|
||||
address_balances,
|
||||
self.finalized_value_pool(),
|
||||
prev_note_commitment_trees,
|
||||
|
@ -448,6 +453,7 @@ impl DiskWriteBatch {
|
|||
new_outputs_by_out_loc: BTreeMap<OutputLocation, transparent::Utxo>,
|
||||
spent_utxos_by_outpoint: HashMap<transparent::OutPoint, transparent::Utxo>,
|
||||
spent_utxos_by_out_loc: BTreeMap<OutputLocation, transparent::Utxo>,
|
||||
out_loc_by_outpoint: HashMap<transparent::OutPoint, OutputLocation>,
|
||||
address_balances: HashMap<transparent::Address, AddressBalanceLocation>,
|
||||
value_pool: ValueBalance<NonNegative>,
|
||||
prev_note_commitment_trees: Option<NoteCommitmentTrees>,
|
||||
|
@ -479,12 +485,13 @@ impl DiskWriteBatch {
|
|||
if !finalized.height.is_min() {
|
||||
// Commit transaction indexes
|
||||
self.prepare_transparent_transaction_batch(
|
||||
db,
|
||||
zebra_db,
|
||||
network,
|
||||
finalized,
|
||||
&new_outputs_by_out_loc,
|
||||
&spent_utxos_by_outpoint,
|
||||
&spent_utxos_by_out_loc,
|
||||
&out_loc_by_outpoint,
|
||||
address_balances,
|
||||
)?;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Provides high-level access to database:
|
||||
//! - unspent [`transparent::Output`]s (UTXOs), and
|
||||
//! - unspent [`transparent::Output`]s (UTXOs),
|
||||
//! - spent [`transparent::Output`]s, and
|
||||
//! - transparent address indexes.
|
||||
//!
|
||||
//! This module makes sure that:
|
||||
|
@ -37,12 +38,44 @@ use crate::{
|
|||
},
|
||||
zebra_db::ZebraDb,
|
||||
},
|
||||
BoxError,
|
||||
BoxError, TypedColumnFamily,
|
||||
};
|
||||
|
||||
/// The name of the transaction hash by spent outpoints column family.
|
||||
///
|
||||
/// This constant should be used so the compiler can detect typos.
|
||||
pub const TX_LOC_BY_SPENT_OUT_LOC: &str = "tx_loc_by_spent_out_loc";
|
||||
|
||||
/// The type for reading value pools from the database.
|
||||
///
|
||||
/// This constant should be used so the compiler can detect incorrectly typed accesses to the
|
||||
/// column family.
|
||||
pub type TransactionLocationBySpentOutputLocationCf<'cf> =
|
||||
TypedColumnFamily<'cf, OutputLocation, TransactionLocation>;
|
||||
|
||||
impl ZebraDb {
|
||||
// Column family convenience methods
|
||||
|
||||
/// Returns a typed handle to the transaction location by spent output location column family.
|
||||
pub(crate) fn tx_loc_by_spent_output_loc_cf(
|
||||
&self,
|
||||
) -> TransactionLocationBySpentOutputLocationCf {
|
||||
TransactionLocationBySpentOutputLocationCf::new(&self.db, TX_LOC_BY_SPENT_OUT_LOC)
|
||||
.expect("column family was created when database was created")
|
||||
}
|
||||
|
||||
// Read transparent methods
|
||||
|
||||
/// 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(
|
||||
&self,
|
||||
output_location: &OutputLocation,
|
||||
) -> Option<TransactionLocation> {
|
||||
self.tx_loc_by_spent_output_loc_cf().zs_get(output_location)
|
||||
}
|
||||
|
||||
/// Returns the [`AddressBalanceLocation`] for a [`transparent::Address`],
|
||||
/// if it is in the finalized state.
|
||||
#[allow(clippy::unwrap_in_result)]
|
||||
|
@ -342,14 +375,16 @@ impl DiskWriteBatch {
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn prepare_transparent_transaction_batch(
|
||||
&mut self,
|
||||
db: &DiskDb,
|
||||
zebra_db: &ZebraDb,
|
||||
network: &Network,
|
||||
finalized: &FinalizedBlock,
|
||||
new_outputs_by_out_loc: &BTreeMap<OutputLocation, transparent::Utxo>,
|
||||
spent_utxos_by_outpoint: &HashMap<transparent::OutPoint, transparent::Utxo>,
|
||||
spent_utxos_by_out_loc: &BTreeMap<OutputLocation, transparent::Utxo>,
|
||||
out_loc_by_outpoint: &HashMap<transparent::OutPoint, OutputLocation>,
|
||||
mut address_balances: HashMap<transparent::Address, AddressBalanceLocation>,
|
||||
) -> Result<(), BoxError> {
|
||||
let db = &zebra_db.db;
|
||||
let FinalizedBlock { block, height, .. } = finalized;
|
||||
|
||||
// Update created and spent transparent outputs
|
||||
|
@ -371,11 +406,12 @@ impl DiskWriteBatch {
|
|||
let spending_tx_location = TransactionLocation::from_usize(*height, tx_index);
|
||||
|
||||
self.prepare_spending_transparent_tx_ids_batch(
|
||||
db,
|
||||
zebra_db,
|
||||
network,
|
||||
spending_tx_location,
|
||||
transaction,
|
||||
spent_utxos_by_outpoint,
|
||||
out_loc_by_outpoint,
|
||||
&address_balances,
|
||||
)?;
|
||||
}
|
||||
|
@ -531,16 +567,18 @@ impl DiskWriteBatch {
|
|||
/// # Errors
|
||||
///
|
||||
/// - This method doesn't currently return any errors, but it might in future
|
||||
#[allow(clippy::unwrap_in_result)]
|
||||
#[allow(clippy::unwrap_in_result, clippy::too_many_arguments)]
|
||||
pub fn prepare_spending_transparent_tx_ids_batch(
|
||||
&mut self,
|
||||
db: &DiskDb,
|
||||
zebra_db: &ZebraDb,
|
||||
network: &Network,
|
||||
spending_tx_location: TransactionLocation,
|
||||
transaction: &Transaction,
|
||||
spent_utxos_by_outpoint: &HashMap<transparent::OutPoint, transparent::Utxo>,
|
||||
out_loc_by_outpoint: &HashMap<transparent::OutPoint, OutputLocation>,
|
||||
address_balances: &HashMap<transparent::Address, AddressBalanceLocation>,
|
||||
) -> Result<(), BoxError> {
|
||||
let db = &zebra_db.db;
|
||||
let tx_loc_by_transparent_addr_loc =
|
||||
db.cf_handle("tx_loc_by_transparent_addr_loc").unwrap();
|
||||
|
||||
|
@ -569,6 +607,15 @@ impl DiskWriteBatch {
|
|||
AddressTransaction::new(sending_address_location, spending_tx_location);
|
||||
self.zs_insert(&tx_loc_by_transparent_addr_loc, address_transaction, ());
|
||||
}
|
||||
|
||||
let spent_output_location = out_loc_by_outpoint
|
||||
.get(&spent_outpoint)
|
||||
.expect("spent outpoints must already have output locations");
|
||||
|
||||
let _ = zebra_db
|
||||
.tx_loc_by_spent_output_loc_cf()
|
||||
.with_batch_for_writing(self)
|
||||
.zs_insert(spent_output_location, &spending_tx_location);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -94,6 +94,15 @@ pub struct ChainInner {
|
|||
/// including those created by earlier transactions or blocks in the chain.
|
||||
pub(crate) spent_utxos: HashSet<transparent::OutPoint>,
|
||||
|
||||
// TODO:
|
||||
// - Add a field for tracking spending tx ids by spent outpoint
|
||||
// - Update the field when committing blocks to non-finalized chain
|
||||
// - Add a read fn for querying tx ids by spent outpoint
|
||||
// - Add a db format upgrade for indexing spending tx ids (transaction locations) by
|
||||
// spent outpoints (output locations) in the finalized state
|
||||
// - Add ReadRequest & ReadResponse variants for querying spending tx ids by
|
||||
// spent outpoints and handle them in the ReadStateService
|
||||
|
||||
// Note commitment trees
|
||||
//
|
||||
/// The Sprout note commitment tree for each anchor.
|
||||
|
|
Loading…
Reference in New Issue