]> Untitled Git - bdk/commitdiff
docs: document TxUpdate temporal context requirements
authorRafael Turon <3598269+rafaelturon@users.noreply.github.com>
Thu, 5 Mar 2026 21:02:06 +0000 (18:02 -0300)
committer志宇 <hello@evanlinjin.me>
Thu, 12 Mar 2026 14:37:51 +0000 (14:37 +0000)
This introduces clear temporal context documentation to the `TxUpdate`
struct, explicitly stating that entries must have either `anchors` or
`seen_ats` to be considered canonical and contribute to wallet balances.

This fulfills the recommendation outlined in the Wizardsardine
BDK Audit Report (Q4 2024).

Signed-off-by: Rafael Turon <3598269+rafaelturon@users.noreply.github.com>
crates/chain/src/indexed_tx_graph.rs
crates/chain/src/tx_graph.rs
crates/core/src/tx_update.rs

index 9adf7ed936cc11359a9ca6e551b5c1a27119008a..693378401718a3ac37d42c2d84a9b302de9b529b 100644 (file)
@@ -178,6 +178,10 @@ where
     ///
     /// `update` is a [`tx_graph::TxUpdate<A>`] and the resultant changes is returned as
     /// [`ChangeSet`].
+    ///
+    /// **Note**: Transactions in the `update` without temporal context (anchors or seen_ats)
+    /// will be stored but will not be considered canonical. See [`tx_graph::TxUpdate`] for
+    /// more details.
     pub fn apply_update(&mut self, update: tx_graph::TxUpdate<A>) -> ChangeSet<A, I::ChangeSet> {
         let tx_graph = self.graph.apply_update(update);
         let indexer = self.index_tx_graph_changeset(&tx_graph);
index 701de335d6005c9c8d51503678ae5c417e6e137c..c2e77d34b82ac3151bcd12bbe203ad00f321dde7 100644 (file)
@@ -913,6 +913,9 @@ impl<A: Anchor> TxGraph<A> {
     ///
     /// The returned [`ChangeSet`] is the set difference between `update` and `self` (transactions
     /// that exist in `update` but not in `self`).
+    ///
+    /// **Note**: Transactions in the `update` without temporal context (anchors or seen_ats)
+    /// will be stored but will not be considered canonical. See [`TxUpdate`] for more details.
     pub fn apply_update(&mut self, update: TxUpdate<A>) -> ChangeSet<A> {
         let mut changeset = ChangeSet::<A>::default();
         for tx in update.txs {
index 4748907059157c97cd6c50f6c8f1bec7d1a22d67..f92cf3e92bc0c6f5301e32b7d31db7a07686e58f 100644 (file)
@@ -18,6 +18,13 @@ use bitcoin::{OutPoint, Transaction, TxOut, Txid};
 /// tx_update.txs.push(tx);
 /// tx_update.anchors.insert((anchor, txid));
 /// ```
+/// ## Temporal context
+/// To contribute to a wallet's balance, transactions must have an entry in either:
+/// - [`Self::anchors`]: for confirmed transactions.
+/// - [`Self::seen_ats`]: for unconfirmed transactions.
+///
+/// The built-in chain-source crates (`bdk_electrum`, `bdk_esplora`, `bdk_bitcoind_rpc`) handle this
+/// automatically. Transactions lacking temporal context are stored but ignored by canonicalization.
 #[derive(Debug, Clone)]
 #[non_exhaustive]
 pub struct TxUpdate<A = ()> {