diff --git a/crates/chain/src/sparse_chain.rs b/crates/chain/src/sparse_chain.rs index 55121695..b9c1e24b 100644 --- a/crates/chain/src/sparse_chain.rs +++ b/crates/chain/src/sparse_chain.rs @@ -456,7 +456,7 @@ impl core::fmt::Display for UpdateError

{ #[cfg(feature = "std")] impl std::error::Error for UpdateError

{} -impl

SparseChain

{ +impl SparseChain

{ /// Creates a new chain from a list of block hashes and heights. The caller must guarantee they /// are in the same chain. pub fn from_checkpoints(checkpoints: C) -> Self @@ -487,6 +487,13 @@ impl

SparseChain

{ .map(|&hash| BlockId { height, hash }) } + /// Return the [`ChainPosition`] of a `txid`. + /// + /// This returns [`None`] if the transaction does not exist. + pub fn tx_position(&self, txid: Txid) -> Option<&P> { + self.txid_to_pos.get(&txid) + } + /// Return a [`BTreeMap`] of all checkpoints (block hashes by height). pub fn checkpoints(&self) -> &BTreeMap { &self.checkpoints @@ -502,47 +509,6 @@ impl

SparseChain

{ .map(|(&height, &hash)| BlockId { height, hash }) } - /// Returns the value set as the checkpoint limit. - /// - /// Refer to [`set_checkpoint_limit`]. - /// - /// [`set_checkpoint_limit`]: Self::set_checkpoint_limit - pub fn checkpoint_limit(&self) -> Option { - self.checkpoint_limit - } - - /// Set the checkpoint limit. - /// - /// The checkpoint limit restricts the number of checkpoints that can be stored in [`Self`]. - /// Oldest checkpoints are pruned first. - pub fn set_checkpoint_limit(&mut self, limit: Option) { - self.checkpoint_limit = limit; - self.prune_checkpoints(); - } - - fn prune_checkpoints(&mut self) -> Option> { - let limit = self.checkpoint_limit?; - - // find the last height to be pruned - let last_height = *self.checkpoints.keys().rev().nth(limit)?; - // first height to be kept - let keep_height = last_height + 1; - - let mut split = self.checkpoints.split_off(&keep_height); - core::mem::swap(&mut self.checkpoints, &mut split); - - Some(split) - } -} - -impl SparseChain

{ - /// Return the [`ChainPosition`] of a `txid`. - /// - /// This returns [`None`] if the transaction does not exist. - pub fn tx_position(&self, txid: Txid) -> Option<&P> { - self.txid_to_pos.get(&txid) - } - /// Preview changes of updating [`Self`] with another chain that connects to it. /// /// If the `update` wishes to introduce confirmed transactions, it must contain a checkpoint @@ -933,7 +899,7 @@ impl SparseChain

{ /// Attempt to retrieve a [`FullTxOut`] of the given `outpoint`. /// /// This will return `Some` only if the output's transaction is in both `self` and `graph`. - pub fn full_txout(&self, graph: &TxGraph, outpoint: OutPoint) -> Option> { + pub fn full_txout(&self, graph: &TxGraph, outpoint: OutPoint) -> Option> { let chain_pos = self.tx_position(outpoint.txid)?; let tx = graph.get_tx(outpoint.txid)?; @@ -953,6 +919,24 @@ impl SparseChain

{ }) } + /// Returns the value set as the checkpoint limit. + /// + /// Refer to [`set_checkpoint_limit`]. + /// + /// [`set_checkpoint_limit`]: Self::set_checkpoint_limit + pub fn checkpoint_limit(&self) -> Option { + self.checkpoint_limit + } + + /// Set the checkpoint limit. + /// + /// The checkpoint limit restricts the number of checkpoints that can be stored in [`Self`]. + /// Oldest checkpoints are pruned first. + pub fn set_checkpoint_limit(&mut self, limit: Option) { + self.checkpoint_limit = limit; + self.prune_checkpoints(); + } + /// Return [`Txid`]s that would be added to the sparse chain if this `changeset` was applied. pub fn changeset_additions<'a>( &'a self, @@ -968,15 +952,29 @@ impl SparseChain

{ .map(|(&txid, _)| txid) } + fn prune_checkpoints(&mut self) -> Option> { + let limit = self.checkpoint_limit?; + + // find the last height to be pruned + let last_height = *self.checkpoints.keys().rev().nth(limit)?; + // first height to be kept + let keep_height = last_height + 1; + + let mut split = self.checkpoints.split_off(&keep_height); + core::mem::swap(&mut self.checkpoints, &mut split); + + Some(split) + } + /// Finds the transaction in the chain that spends `outpoint`. /// /// [`TxGraph`] is used to provide the spend relationships. /// /// Note that the transaction including `outpoint` does not need to be in the `graph` or the /// `chain` for this to return `Some`. - pub fn spent_by(&self, graph: &TxGraph, outpoint: OutPoint) -> Option<(&P, Txid)> { + pub fn spent_by(&self, graph: &TxGraph, outpoint: OutPoint) -> Option<(&P, Txid)> { graph - .output_spends(outpoint) + .outspends(outpoint) .iter() .find_map(|&txid| Some((self.tx_position(txid)?, txid))) } diff --git a/crates/chain/src/tx_graph.rs b/crates/chain/src/tx_graph.rs index 07e4680e..c7c496ef 100644 --- a/crates/chain/src/tx_graph.rs +++ b/crates/chain/src/tx_graph.rs @@ -282,7 +282,7 @@ impl TxGraph { /// /// `TxGraph` allows conflicting transactions within the graph. Obviously the transactions in /// the returned set will never be in the same active-chain. - pub fn output_spends(&self, outpoint: OutPoint) -> &HashSet { + pub fn outspends(&self, outpoint: OutPoint) -> &HashSet { self.spends.get(&outpoint).unwrap_or(&self.empty_outspends) } diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index 20b3e27f..c74a2e99 100644 --- a/crates/chain/tests/test_tx_graph.rs +++ b/crates/chain/tests/test_tx_graph.rs @@ -202,7 +202,7 @@ fn insert_tx_graph_doesnt_count_coinbase_as_spent() { let mut graph = TxGraph::<()>::default(); let _ = graph.insert_tx(tx); - assert!(graph.output_spends(OutPoint::null()).is_empty()); + assert!(graph.outspends(OutPoint::null()).is_empty()); assert!(graph.tx_spends(Txid::all_zeros()).next().is_none()); } @@ -241,10 +241,10 @@ fn insert_tx_graph_keeps_track_of_spend() { let _ = graph2.insert_tx(tx1); assert_eq!( - graph1.output_spends(op), + graph1.outspends(op), &iter::once(tx2.txid()).collect::>() ); - assert_eq!(graph2.output_spends(op), graph1.output_spends(op)); + assert_eq!(graph2.outspends(op), graph1.outspends(op)); } #[test]