bitcoindevkit / bitcoindevkit/bdk_wallet

Reachable panic in `Utxo::txout`

Open
#474 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Rust
Stars
59
Forks
105
Avg merge
10d 9h
Merged PRs (30d)
1

Description

`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**

```rust
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)?**
- [x] None / not backend-related

**Is this blocking production use?**
- [ ] Yes
- [x] No

**Additional context**

Raised during review of #445. Three options identified:

1. ~~Make `Utxo::Foreign` wrap a type with private fields~~.
- [x] Short-term non-breaking — collapse the two `if let` arms and the `unreachable!` into a single chained `Option` with an honest `.expect("Foreign UTXOs should have one of witness_utxo, non_witness_utxo set")`. #487
- [ ] Return `Option<&TxOut>` from `txout()` (breaking).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.