Skip to content

Commit 8d65899

Browse files
fix(chain): Tx assumed to be canonical will not be forced unconfimred
Previously there was a bug where txs added in `CanonicalizationParams::assume_canonical` were forced to always be unconfirmed (even if it's anchored in the best chain). This commit fixes this. `test_assumed_canonical_with_anchor_is_confirmed` is added to ensure expected behavior. Co-authored-by: AayushGupta56 <aayushgupt56@gmail.com>
1 parent 2ee48d7 commit 8d65899

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

crates/chain/src/tx_graph.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,8 +1028,8 @@ impl<A: Anchor> TxGraph<A> {
10281028
res.map(|(txid, _, canonical_reason)| {
10291029
let tx_node = self.get_tx_node(txid).expect("must contain tx");
10301030
let chain_position = match canonical_reason {
1031-
CanonicalReason::Assumed { descendant } => match descendant {
1032-
Some(_) => match find_direct_anchor(&tx_node, chain, chain_tip)? {
1031+
CanonicalReason::Assumed { .. } => {
1032+
match find_direct_anchor(&tx_node, chain, chain_tip)? {
10331033
Some(anchor) => ChainPosition::Confirmed {
10341034
anchor,
10351035
transitively: None,
@@ -1038,12 +1038,8 @@ impl<A: Anchor> TxGraph<A> {
10381038
first_seen: tx_node.first_seen,
10391039
last_seen: tx_node.last_seen,
10401040
},
1041-
},
1042-
None => ChainPosition::Unconfirmed {
1043-
first_seen: tx_node.first_seen,
1044-
last_seen: tx_node.last_seen,
1045-
},
1046-
},
1041+
}
1042+
}
10471043
CanonicalReason::Anchor { anchor, descendant } => match descendant {
10481044
Some(_) => match find_direct_anchor(&tx_node, chain, chain_tip)? {
10491045
Some(anchor) => ChainPosition::Confirmed {

crates/chain/tests/test_tx_graph.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,58 @@ fn test_get_first_seen_of_a_tx() {
15451545
assert_eq!(first_seen, Some(seen_at));
15461546
}
15471547

1548+
#[test]
1549+
fn test_assumed_canonical_with_anchor_is_confirmed() {
1550+
use bdk_chain::ChainPosition;
1551+
1552+
let chain = LocalChain::from_blocks(
1553+
[(0, hash!("genesis")), (2, hash!("b2"))]
1554+
.into_iter()
1555+
.collect(),
1556+
)
1557+
.unwrap();
1558+
1559+
// Create an anchored transaction that will be assumed canonical via `CanonicalizationParams`.
1560+
let tx = Transaction {
1561+
input: vec![TxIn {
1562+
previous_output: OutPoint::new(hash!("parent"), 0),
1563+
..Default::default()
1564+
}],
1565+
output: vec![TxOut {
1566+
value: Amount::from_sat(50_000),
1567+
script_pubkey: ScriptBuf::new(),
1568+
}],
1569+
..new_tx(1)
1570+
};
1571+
let txid = tx.compute_txid();
1572+
1573+
let mut tx_graph = TxGraph::default();
1574+
let _ = tx_graph.insert_tx(tx);
1575+
let _ = tx_graph.insert_anchor(
1576+
txid,
1577+
ConfirmationBlockTime {
1578+
block_id: chain.get(2).unwrap().block_id(),
1579+
confirmation_time: 123456,
1580+
},
1581+
);
1582+
1583+
let canonical_tx = tx_graph
1584+
.list_canonical_txs(
1585+
&chain,
1586+
chain.tip().block_id(),
1587+
CanonicalizationParams {
1588+
assume_canonical: vec![txid],
1589+
},
1590+
)
1591+
.find(|c_tx| c_tx.tx_node.txid == txid)
1592+
.expect("tx must exist");
1593+
1594+
assert!(
1595+
matches!(canonical_tx.chain_position, ChainPosition::Confirmed { .. }),
1596+
"tx that is assumed canonical and has a direct anchor should have ChainPosition::Confirmed"
1597+
);
1598+
}
1599+
15481600
/// A helper structure to constructs multiple [`TxGraph`] scenarios, used in
15491601
/// `test_list_ordered_canonical_txs`.
15501602
struct Scenario<'a> {

0 commit comments

Comments
 (0)