Skip to content

CanonicalReason::Assumed should map to ChainPosition::Confirmed if a direct anchor exists #2088

@ValuedMammal

Description

@ValuedMammal

Describe the bug

I tried to pass a Txid to CanonicalizationParams::assume_canonical, which I expected to be confirmed by a direct anchor, but in the set of canonical txs that is returned the chain position of the assumed tx appeared as ChainPosition::Unconfirmed. This later caused unexpected results at the time of doing coin selection.

Currently when a txid is assumed to be canonical, returning a chain position of ChainPosition::Confirmed is only possible if the CanonicalReason's descendant has some value.

CanonicalReason::Assumed { descendant } => match descendant {
Some(_) => match find_direct_anchor(&tx_node, chain, chain_tip)? {
Some(anchor) => ChainPosition::Confirmed {
anchor,
transitively: None,
},

Expected behavior

CanonicalReason::Assumed should map to ChainPosition::Confirmed if a direct anchor exists.

  • If the reason carries a descendant txid that is confirmed by a direct anchor, I would expect a chain position that is transitively confirmed by the descendant.
  • If the assumed tx is confirmed by a direct anchor and is not accompanied by a descendant, I would expect a chain position that is confirmed by the direct anchor and a transitively of None.
  • If neither the assumed tx nor a descendant are confirmed by a direct anchor, I would expect ChainPosition::Unconfirmed.

To Reproduce

I added this test case to demonstrate what I think is the expected behavior. Notice B is both assumed and confirmed.

test_tx_graph_conflicts.rs

Scenario {
    name: "B and C are confirmed, C1 spends C, all are assume-canonical",
    tx_templates: &[
        TxTemplate {
            tx_name: "B",
            inputs: &[TxInTemplate::Bogus],
            outputs: &[TxOutTemplate::new(10_000, Some(0))],
            anchors: &[block_id!(1, "B")],
            last_seen: None,
            assume_canonical: true,
        },
        TxTemplate {
            tx_name: "C",
            inputs: &[TxInTemplate::Bogus],
            outputs: &[TxOutTemplate::new(8_000, Some(0))],
            anchors: &[block_id!(2, "C")],
            last_seen: None,
            assume_canonical: true,
        },
        TxTemplate {
            tx_name: "C1",
            inputs: &[TxInTemplate::PrevTx("C", 0)],
            outputs: &[TxOutTemplate::new(6_000, Some(0))],
            assume_canonical: true,
            ..Default::default()
        }
    ],
    exp_chain_txs: HashSet::from(["B", "C", "C1"]),
    exp_chain_txouts: HashSet::from([("B", 0), ("C", 0), ("C1", 0)]),
    exp_unspents: HashSet::from([("B", 0), ("C1", 0)]),
    exp_balance: Balance {
        immature: Amount::ZERO,
        trusted_pending: Amount::from_sat(6_000),
        untrusted_pending: Amount::ZERO,
        confirmed: Amount::from_sat(10_000),
    }
}

Build environment

  • BDK tag/commit: 09ddfb2
  • Rust/Cargo version: 1.88.0

Is this blocking production use?

  • Yes
  • No

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions