]> Untitled Git - bdk/commitdiff
test(indexed_tx_graph): Add test_get_chain_position
authorvalued mammal <valuedmammal@protonmail.com>
Mon, 3 Jun 2024 23:55:10 +0000 (19:55 -0400)
committervalued mammal <valuedmammal@protonmail.com>
Sun, 30 Jun 2024 14:08:54 +0000 (10:08 -0400)
crates/chain/tests/test_indexed_tx_graph.rs

index 4014829e225ac62ffa38fb63a50944275078c8bc..dbd7fd302b293e6a92e95b78ea516a846308811a 100644 (file)
@@ -520,3 +520,147 @@ fn test_list_owned_txouts() {
         );
     }
 }
+
+/// Given a `LocalChain`, `IndexedTxGraph`, and a `Transaction`, when we insert some anchor
+/// (possibly non-canonical) and/or a last-seen timestamp into the graph, we expect the
+/// result of `get_chain_position` in these cases:
+///
+/// - tx with no anchors or last_seen has no `ChainPosition`
+/// - tx with any last_seen will be `Unconfirmed`
+/// - tx with an anchor in best chain will be `Confirmed`
+/// - tx with an anchor not in best chain (no last_seen) has no `ChainPosition`
+#[test]
+fn test_get_chain_position() {
+    use bdk_chain::local_chain::CheckPoint;
+    use bdk_chain::BlockId;
+    use bdk_chain::SpkTxOutIndex;
+
+    struct TestCase<A> {
+        name: &'static str,
+        tx: Transaction,
+        anchor: Option<A>,
+        last_seen: Option<u64>,
+        exp_pos: Option<ChainPosition<A>>,
+    }
+
+    // addr: bcrt1qc6fweuf4xjvz4x3gx3t9e0fh4hvqyu2qw4wvxm
+    let spk = ScriptBuf::from_hex("0014c692ecf13534982a9a2834565cbd37add8027140").unwrap();
+    let mut graph = IndexedTxGraph::new({
+        let mut index = SpkTxOutIndex::default();
+        let _ = index.insert_spk(0u32, spk.clone());
+        index
+    });
+
+    // Anchors to test
+    let blocks = vec![block_id!(0, "g"), block_id!(1, "A"), block_id!(2, "B")];
+
+    let cp = CheckPoint::from_block_ids(blocks.clone()).unwrap();
+    let chain = LocalChain::from_tip(cp).unwrap();
+
+    // The test will insert a transaction into the indexed tx graph
+    // along with any anchors and timestamps, then check the value
+    // returned by `get_chain_position`.
+    fn run(
+        chain: &LocalChain,
+        graph: &mut IndexedTxGraph<BlockId, SpkTxOutIndex<u32>>,
+        test: TestCase<BlockId>,
+    ) {
+        let TestCase {
+            name,
+            tx,
+            anchor,
+            last_seen,
+            exp_pos,
+        } = test;
+
+        // add data to graph
+        let txid = tx.compute_txid();
+        let _ = graph.insert_tx(tx);
+        if let Some(anchor) = anchor {
+            let _ = graph.insert_anchor(txid, anchor);
+        }
+        if let Some(seen_at) = last_seen {
+            let _ = graph.insert_seen_at(txid, seen_at);
+        }
+
+        // check chain position
+        let res = graph
+            .graph()
+            .get_chain_position(chain, chain.tip().block_id(), txid);
+        assert_eq!(
+            res.map(ChainPosition::cloned),
+            exp_pos,
+            "failed test case: {name}"
+        );
+    }
+
+    [
+        TestCase {
+            name: "tx no anchors or last_seen - no chain pos",
+            tx: Transaction {
+                output: vec![TxOut {
+                    value: Amount::ONE_BTC,
+                    script_pubkey: spk.clone(),
+                }],
+                ..common::new_tx(0)
+            },
+            anchor: None,
+            last_seen: None,
+            exp_pos: None,
+        },
+        TestCase {
+            name: "tx last_seen - unconfirmed",
+            tx: Transaction {
+                output: vec![TxOut {
+                    value: Amount::ONE_BTC,
+                    script_pubkey: spk.clone(),
+                }],
+                ..common::new_tx(1)
+            },
+            anchor: None,
+            last_seen: Some(2),
+            exp_pos: Some(ChainPosition::Unconfirmed(2)),
+        },
+        TestCase {
+            name: "tx anchor in best chain - confirmed",
+            tx: Transaction {
+                output: vec![TxOut {
+                    value: Amount::ONE_BTC,
+                    script_pubkey: spk.clone(),
+                }],
+                ..common::new_tx(2)
+            },
+            anchor: Some(blocks[1]),
+            last_seen: None,
+            exp_pos: Some(ChainPosition::Confirmed(blocks[1])),
+        },
+        TestCase {
+            name: "tx unknown anchor with last_seen - unconfirmed",
+            tx: Transaction {
+                output: vec![TxOut {
+                    value: Amount::ONE_BTC,
+                    script_pubkey: spk.clone(),
+                }],
+                ..common::new_tx(3)
+            },
+            anchor: Some(block_id!(2, "B'")),
+            last_seen: Some(2),
+            exp_pos: Some(ChainPosition::Unconfirmed(2)),
+        },
+        TestCase {
+            name: "tx unknown anchor - no chain pos",
+            tx: Transaction {
+                output: vec![TxOut {
+                    value: Amount::ONE_BTC,
+                    script_pubkey: spk.clone(),
+                }],
+                ..common::new_tx(4)
+            },
+            anchor: Some(block_id!(2, "B'")),
+            last_seen: None,
+            exp_pos: None,
+        },
+    ]
+    .into_iter()
+    .for_each(|t| run(&chain, &mut graph, t));
+}