[bdk_chain_redesign] Revert changes to SparseChain
This commit is contained in:
parent
34a7bf5afe
commit
03c128311a
@ -456,7 +456,7 @@ impl<P: core::fmt::Debug> core::fmt::Display for UpdateError<P> {
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<P: core::fmt::Debug> std::error::Error for UpdateError<P> {}
|
impl<P: core::fmt::Debug> std::error::Error for UpdateError<P> {}
|
||||||
|
|
||||||
impl<P> SparseChain<P> {
|
impl<P: ChainPosition> SparseChain<P> {
|
||||||
/// Creates a new chain from a list of block hashes and heights. The caller must guarantee they
|
/// Creates a new chain from a list of block hashes and heights. The caller must guarantee they
|
||||||
/// are in the same chain.
|
/// are in the same chain.
|
||||||
pub fn from_checkpoints<C>(checkpoints: C) -> Self
|
pub fn from_checkpoints<C>(checkpoints: C) -> Self
|
||||||
@ -487,6 +487,13 @@ impl<P> SparseChain<P> {
|
|||||||
.map(|&hash| BlockId { height, hash })
|
.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).
|
/// Return a [`BTreeMap`] of all checkpoints (block hashes by height).
|
||||||
pub fn checkpoints(&self) -> &BTreeMap<u32, BlockHash> {
|
pub fn checkpoints(&self) -> &BTreeMap<u32, BlockHash> {
|
||||||
&self.checkpoints
|
&self.checkpoints
|
||||||
@ -502,47 +509,6 @@ impl<P> SparseChain<P> {
|
|||||||
.map(|(&height, &hash)| BlockId { height, hash })
|
.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<usize> {
|
|
||||||
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<usize>) {
|
|
||||||
self.checkpoint_limit = limit;
|
|
||||||
self.prune_checkpoints();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prune_checkpoints(&mut self) -> Option<BTreeMap<u32, BlockHash>> {
|
|
||||||
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<P: ChainPosition> SparseChain<P> {
|
|
||||||
/// 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.
|
/// 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
|
/// If the `update` wishes to introduce confirmed transactions, it must contain a checkpoint
|
||||||
@ -933,7 +899,7 @@ impl<P: ChainPosition> SparseChain<P> {
|
|||||||
/// Attempt to retrieve a [`FullTxOut`] of the given `outpoint`.
|
/// 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`.
|
/// This will return `Some` only if the output's transaction is in both `self` and `graph`.
|
||||||
pub fn full_txout<A>(&self, graph: &TxGraph<A>, outpoint: OutPoint) -> Option<FullTxOut<P>> {
|
pub fn full_txout(&self, graph: &TxGraph, outpoint: OutPoint) -> Option<FullTxOut<P>> {
|
||||||
let chain_pos = self.tx_position(outpoint.txid)?;
|
let chain_pos = self.tx_position(outpoint.txid)?;
|
||||||
|
|
||||||
let tx = graph.get_tx(outpoint.txid)?;
|
let tx = graph.get_tx(outpoint.txid)?;
|
||||||
@ -953,6 +919,24 @@ impl<P: ChainPosition> SparseChain<P> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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<usize> {
|
||||||
|
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<usize>) {
|
||||||
|
self.checkpoint_limit = limit;
|
||||||
|
self.prune_checkpoints();
|
||||||
|
}
|
||||||
|
|
||||||
/// Return [`Txid`]s that would be added to the sparse chain if this `changeset` was applied.
|
/// Return [`Txid`]s that would be added to the sparse chain if this `changeset` was applied.
|
||||||
pub fn changeset_additions<'a>(
|
pub fn changeset_additions<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
@ -968,15 +952,29 @@ impl<P: ChainPosition> SparseChain<P> {
|
|||||||
.map(|(&txid, _)| txid)
|
.map(|(&txid, _)| txid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prune_checkpoints(&mut self) -> Option<BTreeMap<u32, BlockHash>> {
|
||||||
|
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`.
|
/// Finds the transaction in the chain that spends `outpoint`.
|
||||||
///
|
///
|
||||||
/// [`TxGraph`] is used to provide the spend relationships.
|
/// [`TxGraph`] is used to provide the spend relationships.
|
||||||
///
|
///
|
||||||
/// Note that the transaction including `outpoint` does not need to be in the `graph` or the
|
/// Note that the transaction including `outpoint` does not need to be in the `graph` or the
|
||||||
/// `chain` for this to return `Some`.
|
/// `chain` for this to return `Some`.
|
||||||
pub fn spent_by<A>(&self, graph: &TxGraph<A>, outpoint: OutPoint) -> Option<(&P, Txid)> {
|
pub fn spent_by(&self, graph: &TxGraph, outpoint: OutPoint) -> Option<(&P, Txid)> {
|
||||||
graph
|
graph
|
||||||
.output_spends(outpoint)
|
.outspends(outpoint)
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|&txid| Some((self.tx_position(txid)?, txid)))
|
.find_map(|&txid| Some((self.tx_position(txid)?, txid)))
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ impl<A> TxGraph<A> {
|
|||||||
///
|
///
|
||||||
/// `TxGraph` allows conflicting transactions within the graph. Obviously the transactions in
|
/// `TxGraph` allows conflicting transactions within the graph. Obviously the transactions in
|
||||||
/// the returned set will never be in the same active-chain.
|
/// the returned set will never be in the same active-chain.
|
||||||
pub fn output_spends(&self, outpoint: OutPoint) -> &HashSet<Txid> {
|
pub fn outspends(&self, outpoint: OutPoint) -> &HashSet<Txid> {
|
||||||
self.spends.get(&outpoint).unwrap_or(&self.empty_outspends)
|
self.spends.get(&outpoint).unwrap_or(&self.empty_outspends)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ fn insert_tx_graph_doesnt_count_coinbase_as_spent() {
|
|||||||
|
|
||||||
let mut graph = TxGraph::<()>::default();
|
let mut graph = TxGraph::<()>::default();
|
||||||
let _ = graph.insert_tx(tx);
|
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());
|
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);
|
let _ = graph2.insert_tx(tx1);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph1.output_spends(op),
|
graph1.outspends(op),
|
||||||
&iter::once(tx2.txid()).collect::<HashSet<_>>()
|
&iter::once(tx2.txid()).collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(graph2.output_spends(op), graph1.output_spends(op));
|
assert_eq!(graph2.outspends(op), graph1.outspends(op));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user