• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bitcoindevkit / bdk / 10528192619

23 Aug 2024 03:19PM UTC coverage: 82.01% (+0.2%) from 81.848%
10528192619

Pull #1569

github

web-flow
Merge a3e5dfc38 into 9e6ac72a6
Pull Request #1569: `bdk_core` WIP WIP WIP

379 of 439 new or added lines in 13 files covered. (86.33%)

5 existing lines in 4 files now uncovered.

11214 of 13674 relevant lines covered (82.01%)

12930.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.16
/crates/chain/src/tx_data_traits.rs
1
use crate::collections::BTreeMap;
2
use crate::collections::BTreeSet;
3
use crate::BlockId;
4
use alloc::vec::Vec;
5
use bdk_core::ConfirmationBlockTime;
6

7
/// Trait that "anchors" blockchain data to a specific block of height and hash.
8
///
9
/// If transaction A is anchored in block B, and block B is in the best chain, we can
10
/// assume that transaction A is also confirmed in the best chain. This does not necessarily mean
11
/// that transaction A is confirmed in block B. It could also mean transaction A is confirmed in a
12
/// parent block of B.
13
///
14
/// Every [`Anchor`] implementation must contain a [`BlockId`] parameter, and must implement
15
/// [`Ord`]. When implementing [`Ord`], the anchors' [`BlockId`]s should take precedence
16
/// over other elements inside the [`Anchor`]s for comparison purposes, i.e., you should first
17
/// compare the anchors' [`BlockId`]s and then care about the rest.
18
///
19
/// The example shows different types of anchors:
20
/// ```
21
/// # use bdk_chain::local_chain::LocalChain;
22
/// # use bdk_chain::tx_graph::TxGraph;
23
/// # use bdk_chain::BlockId;
24
/// # use bdk_chain::ConfirmationBlockTime;
25
/// # use bdk_chain::example_utils::*;
26
/// # use bitcoin::hashes::Hash;
27
/// // Initialize the local chain with two blocks.
28
/// let chain = LocalChain::from_blocks(
29
///     [
30
///         (1, Hash::hash("first".as_bytes())),
31
///         (2, Hash::hash("second".as_bytes())),
32
///     ]
33
///     .into_iter()
34
///     .collect(),
35
/// );
36
///
37
/// // Transaction to be inserted into `TxGraph`s with different anchor types.
38
/// let tx = tx_from_hex(RAW_TX_1);
39
///
40
/// // Insert `tx` into a `TxGraph` that uses `BlockId` as the anchor type.
41
/// // When a transaction is anchored with `BlockId`, the anchor block and the confirmation block of
42
/// // the transaction is the same block.
43
/// let mut graph_a = TxGraph::<BlockId>::default();
44
/// let _ = graph_a.insert_tx(tx.clone());
45
/// graph_a.insert_anchor(
46
///     tx.compute_txid(),
47
///     BlockId {
48
///         height: 1,
49
///         hash: Hash::hash("first".as_bytes()),
50
///     },
51
/// );
52
///
53
/// // Insert `tx` into a `TxGraph` that uses `ConfirmationBlockTime` as the anchor type.
54
/// // This anchor records the anchor block and the confirmation time of the transaction. When a
55
/// // transaction is anchored with `ConfirmationBlockTime`, the anchor block and confirmation block
56
/// // of the transaction is the same block.
57
/// let mut graph_c = TxGraph::<ConfirmationBlockTime>::default();
58
/// let _ = graph_c.insert_tx(tx.clone());
59
/// graph_c.insert_anchor(
60
///     tx.compute_txid(),
61
///     ConfirmationBlockTime {
62
///         block_id: BlockId {
63
///             height: 2,
64
///             hash: Hash::hash("third".as_bytes()),
65
///         },
66
///         confirmation_time: 123,
67
///     },
68
/// );
69
/// ```
70
pub trait Anchor: core::fmt::Debug + Clone + Eq + PartialOrd + Ord + core::hash::Hash {
71
    /// Returns the [`BlockId`] that the associated blockchain data is "anchored" in.
72
    fn anchor_block(&self) -> BlockId;
73

74
    /// Get the upper bound of the chain data's confirmation height.
75
    ///
76
    /// The default definition gives a pessimistic answer. This can be overridden by the `Anchor`
77
    /// implementation for a more accurate value.
78
    fn confirmation_height_upper_bound(&self) -> u32 {
71✔
79
        self.anchor_block().height
71✔
80
    }
71✔
81
}
82

83
impl<'a, A: Anchor> Anchor for &'a A {
84
    fn anchor_block(&self) -> BlockId {
×
85
        <A as Anchor>::anchor_block(self)
×
86
    }
×
87
}
88

89
impl Anchor for BlockId {
90
    fn anchor_block(&self) -> Self {
16,632✔
91
        *self
16,632✔
92
    }
16,632✔
93
}
94

95
impl Anchor for ConfirmationBlockTime {
96
    fn anchor_block(&self) -> BlockId {
32,529✔
97
        self.block_id
32,529✔
98
    }
32,529✔
99

100
    fn confirmation_height_upper_bound(&self) -> u32 {
1,260✔
101
        self.block_id.height
1,260✔
102
    }
1,260✔
103
}
104

105
/// An [`Anchor`] that can be constructed from a given block, block height and transaction position
106
/// within the block.
107
pub trait AnchorFromBlockPosition: Anchor {
108
    /// Construct the anchor from a given `block`, block height and `tx_pos` within the block.
109
    fn from_block_position(block: &bitcoin::Block, block_id: BlockId, tx_pos: usize) -> Self;
110
}
111

112
impl AnchorFromBlockPosition for BlockId {
113
    fn from_block_position(_block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
4,053✔
114
        block_id
4,053✔
115
    }
4,053✔
116
}
117

118
impl AnchorFromBlockPosition for ConfirmationBlockTime {
NEW
119
    fn from_block_position(block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
×
NEW
120
        Self {
×
NEW
121
            block_id,
×
NEW
122
            confirmation_time: block.header.time as _,
×
NEW
123
        }
×
NEW
124
    }
×
125
}
126

127
/// Trait that makes an object mergeable.
128
pub trait Merge: Default {
129
    /// Merge another object of the same type onto `self`.
130
    fn merge(&mut self, other: Self);
131

132
    /// Returns whether the structure is considered empty.
133
    fn is_empty(&self) -> bool;
134

135
    /// Take the value, replacing it with the default value.
136
    fn take(&mut self) -> Option<Self> {
80✔
137
        if self.is_empty() {
80✔
138
            None
×
139
        } else {
140
            Some(core::mem::take(self))
80✔
141
        }
142
    }
80✔
143
}
144

145
impl<K: Ord, V> Merge for BTreeMap<K, V> {
146
    fn merge(&mut self, other: Self) {
46,221✔
147
        // We use `extend` instead of `BTreeMap::append` due to performance issues with `append`.
46,221✔
148
        // Refer to https://github.com/rust-lang/rust/issues/34666#issuecomment-675658420
46,221✔
149
        BTreeMap::extend(self, other)
46,221✔
150
    }
46,221✔
151

152
    fn is_empty(&self) -> bool {
×
153
        BTreeMap::is_empty(self)
×
154
    }
×
155
}
156

157
impl<T: Ord> Merge for BTreeSet<T> {
158
    fn merge(&mut self, other: Self) {
450✔
159
        // We use `extend` instead of `BTreeMap::append` due to performance issues with `append`.
450✔
160
        // Refer to https://github.com/rust-lang/rust/issues/34666#issuecomment-675658420
450✔
161
        BTreeSet::extend(self, other)
450✔
162
    }
450✔
163

164
    fn is_empty(&self) -> bool {
437✔
165
        BTreeSet::is_empty(self)
437✔
166
    }
437✔
167
}
168

169
impl<T> Merge for Vec<T> {
170
    fn merge(&mut self, mut other: Self) {
×
171
        Vec::append(self, &mut other)
×
172
    }
×
173

174
    fn is_empty(&self) -> bool {
×
175
        Vec::is_empty(self)
×
176
    }
×
177
}
178

179
macro_rules! impl_merge_for_tuple {
180
    ($($a:ident $b:tt)*) => {
181
        impl<$($a),*> Merge for ($($a,)*) where $($a: Merge),* {
182

183
            fn merge(&mut self, _other: Self) {
6,762✔
184
                $(Merge::merge(&mut self.$b, _other.$b) );*
6,762✔
185
            }
6,762✔
186

187
            fn is_empty(&self) -> bool {
×
188
                $(Merge::is_empty(&self.$b) && )* true
×
189
            }
2,142✔
190
        }
191
    }
192
}
193

194
impl_merge_for_tuple!();
195
impl_merge_for_tuple!(T0 0);
196
impl_merge_for_tuple!(T0 0 T1 1);
197
impl_merge_for_tuple!(T0 0 T1 1 T2 2);
198
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3);
199
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4);
200
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5);
201
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6);
202
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7);
203
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8);
204
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9);
205
impl_merge_for_tuple!(T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9 T10 10);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc