Skip to content

Reachable panic in Utxo::txout #474

@ValuedMammal

Description

@ValuedMammal

Utxo::txout() returns &TxOut but contains two reachable panics for the Foreign variant:

  1. prev_tx.output[outpoint.vout as usize] — panics if the attached non_witness_utxo has fewer outputs than the outpoint.vout indicates.
  2. unreachable!("Foreign UTXOs will always have one of these set") — asserts an invariant the type does not enforce. Because Utxo::Foreign is a public enum variant with public fields, a caller can theoretically construct one with an empty psbt::Input, making this branch reachable.

The validation that guards against these states lives in TxBuilder::add_foreign_utxo_with_sequence but is bypassed by any direct construction of Utxo::Foreign.

To Reproduce

let utxo = Utxo::Foreign {
    outpoint: OutPoint::null(),
    sequence: Sequence::MAX,
    psbt_input: Box::new(psbt::Input::default()),
};
utxo.txout();

Expected behavior

txout() should not panic on a value that is constructable through the public API.

Build environment

  • BDK tag/commit: current master
  • OS+version:
  • Rust/Cargo version:
  • Rust/Cargo target:

Which backend(s) are relevant (if any)?

  • None / not backend-related

Is this blocking production use?

  • Yes
  • No

Additional context

Raised during review of #445. Three options identified:

  1. Make Utxo::Foreign wrap a type with private fields.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Discussion

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions