use crate::collections::BTreeMap; use crate::collections::BTreeSet; use crate::BlockId; use alloc::vec::Vec; /// Trait that "anchors" blockchain data to a specific block of height and hash. /// /// [`Anchor`] implementations must be [`Ord`] by the anchor block's [`BlockId`] first. /// /// I.e. If transaction A is anchored in block B, then if block B is in the best chain, we can /// assume that transaction A is also confirmed in the best chain. This does not necessarily mean /// that transaction A is confirmed in block B. It could also mean transaction A is confirmed in a /// parent block of B. /// /// ``` /// # use bdk_chain::local_chain::LocalChain; /// # use bdk_chain::tx_graph::TxGraph; /// # use bdk_chain::BlockId; /// # use bdk_chain::ConfirmationHeightAnchor; /// # use bdk_chain::example_utils::*; /// # use bitcoin::hashes::Hash; /// /// // Initialize the local chain with two blocks. /// let chain = LocalChain::from_blocks( /// [ /// (1, Hash::hash("first".as_bytes())), /// (2, Hash::hash("second".as_bytes())), /// ] /// .into_iter() /// .collect(), /// ); /// /// // Transaction to be inserted into `TxGraph`s with different anchor types. /// let tx = tx_from_hex(RAW_TX_1); /// /// // Insert `tx` into a `TxGraph` that uses `BlockId` as the anchor type. /// // When a transaction is anchored with `BlockId`, the anchor block and the confirmation block of /// // the transaction is the same block. /// let mut graph_a = TxGraph::::default(); /// let _ = graph_a.insert_tx(tx.clone()); /// graph_a.insert_anchor( /// tx.txid(), /// BlockId { /// height: 1, /// hash: Hash::hash("first".as_bytes()), /// }, /// ); /// /// // Insert `tx` into a `TxGraph` that uses `ConfirmationHeightAnchor` as the anchor type. /// // When a transaction is anchored with `ConfirmationHeightAnchor`, the anchor block and /// // confirmation block can be different. However, the confirmation block cannot be higher than /// // the anchor block and both blocks must be in the same chain for the anchor to be valid. /// let mut graph_b = TxGraph::::default(); /// let _ = graph_b.insert_tx(tx.clone()); /// graph_b.insert_anchor( /// tx.txid(), /// ConfirmationHeightAnchor { /// anchor_block: BlockId { /// height: 2, /// hash: Hash::hash("second".as_bytes()), /// }, /// confirmation_height: 1, /// }, /// ); /// ``` pub trait Anchor: core::fmt::Debug + Clone + Eq + PartialOrd + Ord + core::hash::Hash { /// Returns the [`BlockId`] that the associated blockchain data is "anchored" in. fn anchor_block(&self) -> BlockId; /// Get the upper bound of the chain data's confirmation height. /// /// The default definition gives a pessimistic answer. This can be overridden by the `Anchor` /// implementation for a more accurate value. fn confirmation_height_upper_bound(&self) -> u32 { self.anchor_block().height } } impl Anchor for &'static A { fn anchor_block(&self) -> BlockId { ::anchor_block(self) } } /// Trait that makes an object appendable. pub trait Append { /// Append another object of the same type onto `self`. fn append(&mut self, other: Self); /// Returns whether the structure is considered empty. fn is_empty(&self) -> bool; } impl Append for BTreeMap { fn append(&mut self, mut other: Self) { BTreeMap::append(self, &mut other) } fn is_empty(&self) -> bool { BTreeMap::is_empty(self) } } impl Append for BTreeSet { fn append(&mut self, mut other: Self) { BTreeSet::append(self, &mut other) } fn is_empty(&self) -> bool { BTreeSet::is_empty(self) } } impl Append for Vec { fn append(&mut self, mut other: Self) { Vec::append(self, &mut other) } fn is_empty(&self) -> bool { Vec::is_empty(self) } } macro_rules! impl_append_for_tuple { ($($a:ident $b:tt)*) => { impl<$($a),*> Append for ($($a,)*) where $($a: Append),* { fn append(&mut self, _other: Self) { $(Append::append(&mut self.$b, _other.$b) );* } fn is_empty(&self) -> bool { $(Append::is_empty(&self.$b) && )* true } } } } impl_append_for_tuple!(); impl_append_for_tuple!(T0 0); impl_append_for_tuple!(T0 0 T1 1); impl_append_for_tuple!(T0 0 T1 1 T2 2); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9); impl_append_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9 T10 10);