Skip to content

Commit ee52745

Browse files
committed
feat(core)!: Make TxUpdate non-exhaustive
If we introduce new fields to `TxUpdate`, they can be minor non-breaking updates.
1 parent 209570d commit ee52745

File tree

5 files changed

+88
-88
lines changed

5 files changed

+88
-88
lines changed

crates/chain/benches/canonicalization.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,8 @@ pub fn many_conflicting_unconfirmed(c: &mut Criterion) {
132132
}],
133133
..new_tx(i)
134134
};
135-
let update = TxUpdate {
136-
txs: vec![Arc::new(tx)],
137-
..Default::default()
138-
};
135+
let mut update = TxUpdate::default();
136+
update.txs = vec![Arc::new(tx)];
139137
let _ = tx_graph.apply_update_at(update, Some(i as u64));
140138
}
141139
}));
@@ -169,10 +167,8 @@ pub fn many_chained_unconfirmed(c: &mut Criterion) {
169167
..new_tx(i)
170168
};
171169
let txid = tx.compute_txid();
172-
let update = TxUpdate {
173-
txs: vec![Arc::new(tx)],
174-
..Default::default()
175-
};
170+
let mut update = TxUpdate::default();
171+
update.txs = vec![Arc::new(tx)];
176172
let _ = tx_graph.apply_update_at(update, Some(i as u64));
177173
// Store the next prevout.
178174
previous_output = OutPoint::new(txid, 0);

crates/chain/src/tx_graph.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,19 @@ use core::{
110110

111111
impl<A: Ord> From<TxGraph<A>> for TxUpdate<A> {
112112
fn from(graph: TxGraph<A>) -> Self {
113-
Self {
114-
txs: graph.full_txs().map(|tx_node| tx_node.tx).collect(),
115-
txouts: graph
116-
.floating_txouts()
117-
.map(|(op, txo)| (op, txo.clone()))
118-
.collect(),
119-
anchors: graph
120-
.anchors
121-
.into_iter()
122-
.flat_map(|(txid, anchors)| anchors.into_iter().map(move |a| (a, txid)))
123-
.collect(),
124-
seen_ats: graph.last_seen.into_iter().collect(),
125-
}
113+
let mut tx_update = TxUpdate::default();
114+
tx_update.txs = graph.full_txs().map(|tx_node| tx_node.tx).collect();
115+
tx_update.txouts = graph
116+
.floating_txouts()
117+
.map(|(op, txo)| (op, txo.clone()))
118+
.collect();
119+
tx_update.anchors = graph
120+
.anchors
121+
.into_iter()
122+
.flat_map(|(txid, anchors)| anchors.into_iter().map(move |a| (a, txid)))
123+
.collect();
124+
tx_update.seen_ats = graph.last_seen.into_iter().collect();
125+
tx_update
126126
}
127127
}
128128

crates/chain/tests/test_tx_graph.rs

Lines changed: 54 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,69 +1231,60 @@ fn tx_graph_update_conversion() {
12311231

12321232
let test_cases: &[TestCase] = &[
12331233
("empty_update", TxUpdate::default()),
1234-
(
1235-
"single_tx",
1236-
TxUpdate {
1237-
txs: vec![make_tx(0).into()],
1238-
..Default::default()
1239-
},
1240-
),
1241-
(
1242-
"two_txs",
1243-
TxUpdate {
1244-
txs: vec![make_tx(0).into(), make_tx(1).into()],
1245-
..Default::default()
1246-
},
1247-
),
1248-
(
1249-
"with_floating_txouts",
1250-
TxUpdate {
1251-
txs: vec![make_tx(0).into(), make_tx(1).into()],
1252-
txouts: [
1253-
(OutPoint::new(hash!("a"), 0), make_txout(0)),
1254-
(OutPoint::new(hash!("a"), 1), make_txout(1)),
1255-
(OutPoint::new(hash!("b"), 0), make_txout(2)),
1256-
]
1257-
.into(),
1258-
..Default::default()
1259-
},
1260-
),
1261-
(
1262-
"with_anchors",
1263-
TxUpdate {
1264-
txs: vec![make_tx(0).into(), make_tx(1).into()],
1265-
txouts: [
1266-
(OutPoint::new(hash!("a"), 0), make_txout(0)),
1267-
(OutPoint::new(hash!("a"), 1), make_txout(1)),
1268-
(OutPoint::new(hash!("b"), 0), make_txout(2)),
1269-
]
1270-
.into(),
1271-
anchors: [
1272-
(ConfirmationBlockTime::default(), hash!("a")),
1273-
(ConfirmationBlockTime::default(), hash!("b")),
1274-
]
1275-
.into(),
1276-
..Default::default()
1277-
},
1278-
),
1279-
(
1280-
"with_seen_ats",
1281-
TxUpdate {
1282-
txs: vec![make_tx(0).into(), make_tx(1).into()],
1283-
txouts: [
1284-
(OutPoint::new(hash!("a"), 0), make_txout(0)),
1285-
(OutPoint::new(hash!("a"), 1), make_txout(1)),
1286-
(OutPoint::new(hash!("d"), 0), make_txout(2)),
1287-
]
1288-
.into(),
1289-
anchors: [
1290-
(ConfirmationBlockTime::default(), hash!("a")),
1291-
(ConfirmationBlockTime::default(), hash!("b")),
1292-
]
1293-
.into(),
1294-
seen_ats: [(hash!("c"), 12346)].into_iter().collect(),
1295-
},
1296-
),
1234+
("single_tx", {
1235+
let mut tx_update = TxUpdate::default();
1236+
tx_update.txs = vec![make_tx(0).into()];
1237+
tx_update
1238+
}),
1239+
("two_txs", {
1240+
let mut tx_update = TxUpdate::default();
1241+
tx_update.txs = vec![make_tx(0).into(), make_tx(1).into()];
1242+
tx_update
1243+
}),
1244+
("with_floating_txouts", {
1245+
let mut tx_update = TxUpdate::default();
1246+
tx_update.txs = vec![make_tx(0).into(), make_tx(1).into()];
1247+
tx_update.txouts = [
1248+
(OutPoint::new(hash!("a"), 0), make_txout(0)),
1249+
(OutPoint::new(hash!("a"), 1), make_txout(1)),
1250+
(OutPoint::new(hash!("b"), 0), make_txout(2)),
1251+
]
1252+
.into();
1253+
tx_update
1254+
}),
1255+
("with_anchors", {
1256+
let mut tx_update = TxUpdate::default();
1257+
tx_update.txs = vec![make_tx(0).into(), make_tx(1).into()];
1258+
tx_update.txouts = [
1259+
(OutPoint::new(hash!("a"), 0), make_txout(0)),
1260+
(OutPoint::new(hash!("a"), 1), make_txout(1)),
1261+
(OutPoint::new(hash!("b"), 0), make_txout(2)),
1262+
]
1263+
.into();
1264+
tx_update.anchors = [
1265+
(ConfirmationBlockTime::default(), hash!("a")),
1266+
(ConfirmationBlockTime::default(), hash!("b")),
1267+
]
1268+
.into();
1269+
tx_update
1270+
}),
1271+
("with_seen_ats", {
1272+
let mut tx_update = TxUpdate::default();
1273+
tx_update.txs = vec![make_tx(0).into(), make_tx(1).into()];
1274+
tx_update.txouts = [
1275+
(OutPoint::new(hash!("a"), 0), make_txout(0)),
1276+
(OutPoint::new(hash!("a"), 1), make_txout(1)),
1277+
(OutPoint::new(hash!("d"), 0), make_txout(2)),
1278+
]
1279+
.into();
1280+
tx_update.anchors = [
1281+
(ConfirmationBlockTime::default(), hash!("a")),
1282+
(ConfirmationBlockTime::default(), hash!("b")),
1283+
]
1284+
.into();
1285+
tx_update.seen_ats = [(hash!("c"), 12346)].into_iter().collect();
1286+
tx_update
1287+
}),
12971288
];
12981289

12991290
for (test_name, update) in test_cases {

crates/core/src/tx_update.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,22 @@ use bitcoin::{OutPoint, Transaction, TxOut, Txid};
44

55
/// Data object used to communicate updates about relevant transactions from some chain data source
66
/// to the core model (usually a `bdk_chain::TxGraph`).
7+
///
8+
/// ```rust
9+
/// use bdk_core::TxUpdate;
10+
/// # use std::sync::Arc;
11+
/// # use bitcoin::{Transaction, transaction::Version, absolute::LockTime};
12+
/// # let version = Version::ONE;
13+
/// # let lock_time = LockTime::ZERO;
14+
/// # let tx = Arc::new(Transaction { input: vec![], output: vec![], version, lock_time });
15+
/// # let txid = tx.compute_txid();
16+
/// # let anchor = ();
17+
/// let mut tx_update = TxUpdate::default();
18+
/// tx_update.txs.push(tx);
19+
/// tx_update.anchors.insert((anchor, txid));
20+
/// ```
721
#[derive(Debug, Clone)]
22+
#[non_exhaustive]
823
pub struct TxUpdate<A = ()> {
924
/// Full transactions. These are transactions that were determined to be relevant to the wallet
1025
/// given the request.

crates/electrum/src/bdk_electrum_client.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,10 +571,8 @@ mod test {
571571
// `fetch_prev_txout` on a coinbase transaction will trigger a `fetch_tx` on a transaction
572572
// with a txid of all zeros. If `fetch_prev_txout` attempts to fetch this transaction, this
573573
// assertion will fail.
574-
let mut tx_update = TxUpdate {
575-
txs: vec![Arc::new(coinbase_tx)],
576-
..Default::default()
577-
};
574+
let mut tx_update = TxUpdate::default();
575+
tx_update.txs = vec![Arc::new(coinbase_tx)];
578576
assert!(client.fetch_prev_txout(&mut tx_update).is_ok());
579577

580578
// Ensure that the txouts are empty.

0 commit comments

Comments
 (0)