]> Untitled Git - bdk/commitdiff
[bdk_chain_redesign] Add test for `insert_relevant_txs`
author志宇 <hello@evanlinjin.me>
Fri, 21 Apr 2023 06:39:13 +0000 (14:39 +0800)
committer志宇 <hello@evanlinjin.me>
Fri, 21 Apr 2023 06:55:30 +0000 (14:55 +0800)
Ensure `insert_relevant_txs` does not require transactions to be in
topological order.

Other changes: Rm `try_list_owned_txs` as it is useless

crates/chain/src/indexed_tx_graph.rs
crates/chain/tests/test_indexed_tx_graph.rs [new file with mode: 0644]

index f44b7847489e4fdda3f472808d8ca0aa01565e31..60a6c646b0fe32f93706a626f17ff7ffaf311d5a 100644 (file)
@@ -1,11 +1,11 @@
 use core::convert::Infallible;
 
 use alloc::vec::Vec;
-use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid};
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
 
 use crate::{
     keychain::Balance,
-    tx_graph::{Additions, CanonicalTx, TxGraph},
+    tx_graph::{Additions, TxGraph},
     Anchor, Append, BlockId, ChainOracle, FullTxOut, ObservedAs,
 };
 
@@ -153,36 +153,6 @@ where
 }
 
 impl<A: Anchor, I: OwnedIndexer> IndexedTxGraph<A, I> {
-    pub fn try_list_owned_txs<'a, C: ChainOracle + 'a>(
-        &'a self,
-        chain: &'a C,
-        chain_tip: BlockId,
-    ) -> impl Iterator<Item = Result<CanonicalTx<'a, Transaction, A>, C::Error>> {
-        self.graph
-            .full_txs()
-            .filter(|node| tx_alters_owned_utxo_set(&self.graph, &self.index, node.txid, node.tx))
-            .filter_map(move |tx_node| {
-                self.graph
-                    .try_get_chain_position(chain, chain_tip, tx_node.txid)
-                    .map(|v| {
-                        v.map(|observed_as| CanonicalTx {
-                            observed_as,
-                            node: tx_node,
-                        })
-                    })
-                    .transpose()
-            })
-    }
-
-    pub fn list_owned_txs<'a, C: ChainOracle<Error = Infallible> + 'a>(
-        &'a self,
-        chain: &'a C,
-        chain_tip: BlockId,
-    ) -> impl Iterator<Item = CanonicalTx<'a, Transaction, A>> {
-        self.try_list_owned_txs(chain, chain_tip)
-            .map(|r| r.expect("chain oracle is infallible"))
-    }
-
     pub fn try_list_owned_txouts<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
@@ -356,21 +326,3 @@ pub trait OwnedIndexer: Indexer {
     /// Determines whether a given script pubkey (`spk`) is owned.
     fn is_spk_owned(&self, spk: &Script) -> bool;
 }
-
-fn tx_alters_owned_utxo_set<A, I>(
-    graph: &TxGraph<A>,
-    index: &I,
-    txid: Txid,
-    tx: &Transaction,
-) -> bool
-where
-    A: Anchor,
-    I: OwnedIndexer,
-{
-    let prev_spends = (0..tx.input.len() as u32)
-        .map(|vout| OutPoint { txid, vout })
-        .filter_map(|op| graph.get_txout(op));
-    prev_spends
-        .chain(&tx.output)
-        .any(|txout| index.is_spk_owned(&txout.script_pubkey))
-}
diff --git a/crates/chain/tests/test_indexed_tx_graph.rs b/crates/chain/tests/test_indexed_tx_graph.rs
new file mode 100644 (file)
index 0000000..e85d424
--- /dev/null
@@ -0,0 +1,69 @@
+mod common;
+
+use bdk_chain::{
+    indexed_tx_graph::{IndexedAdditions, IndexedTxGraph},
+    tx_graph::Additions,
+    BlockId, SpkTxOutIndex,
+};
+use bitcoin::{hashes::hex::FromHex, OutPoint, Script, Transaction, TxIn, TxOut};
+
+/// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented
+/// in topological order.
+///
+/// Given 3 transactions (A, B, C), where A has 2 owned outputs. B and C spends an output each of A.
+/// Typically, we would only know whether B and C are relevant if we have indexed A (A's outpoints
+/// are associated with owned spks in the index). Ensure insertion and indexing is topological-
+/// agnostic.
+#[test]
+fn insert_relevant_txs() {
+    let mut graph = IndexedTxGraph::<BlockId, SpkTxOutIndex<u32>>::default();
+
+    // insert some spks
+    let spk_0 = Script::from_hex("0014034f9515cace31713707dff8194b8f550eb6d336").unwrap();
+    let spk_1 = Script::from_hex("0014beaa39ab2b4f47995c77107d8c3f481d3bd33941").unwrap();
+    graph.index.insert_spk(0, spk_0.clone());
+    graph.index.insert_spk(1, spk_1.clone());
+
+    let tx_a = Transaction {
+        output: vec![
+            TxOut {
+                value: 10_000,
+                script_pubkey: spk_0,
+            },
+            TxOut {
+                value: 20_000,
+                script_pubkey: spk_1,
+            },
+        ],
+        ..common::new_tx(0)
+    };
+
+    let tx_b = Transaction {
+        input: vec![TxIn {
+            previous_output: OutPoint::new(tx_a.txid(), 0),
+            ..Default::default()
+        }],
+        ..common::new_tx(1)
+    };
+
+    let tx_c = Transaction {
+        input: vec![TxIn {
+            previous_output: OutPoint::new(tx_a.txid(), 1),
+            ..Default::default()
+        }],
+        ..common::new_tx(2)
+    };
+
+    let txs = [tx_c, tx_b, tx_a];
+
+    assert_eq!(
+        graph.insert_relevant_txs(&txs, None, None),
+        IndexedAdditions {
+            graph_additions: Additions {
+                tx: txs.into(),
+                ..Default::default()
+            },
+            ..Default::default()
+        }
+    )
+}