You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge #72: refactor(selection)!: encapsulate Selection and fail-fast on mixed-unit locktimes
96b9f88 test(selector): cover mixed absolute-locktime-unit rejection (志宇)
5a6f34c refactor!: move locktime-unit check from create_psbt to selector (志宇)
d158cbf feat(selection): add sort/shuffle methods for inputs and outputs (志宇)
4ce801d refactor(selection)!: make fields private, add InputMut handle (志宇)
d43e81a feat: Add `fisher_yates_shuffle` method and refactor workspace (志宇)
Pull request description:
### Description
Detects mixed-unit absolute timelock requirements at `Selector::new` instead of at PSBT creation, and prevents external code from constructing or rearranging a `Selection` in ways that would bypass the check.
Closes#58
### Changes
1. **Fail-fast in the selector.** `Selector::new` now returns `SelectorError::LockTypeMismatch` when candidate inputs mix height-based and time-based absolute timelocks. The corresponding `CreatePsbtError::LockTypeMismatch` is removed and `Selection::create_psbt`'s internal locktime accumulator becomes infallible (with a `debug_assert!` guarding the upstream invariant).
2. **Encapsulate `Selection`.** `Selection.inputs` / `Selection.outputs` are now private. Access is via `inputs()` / `outputs()`. Per-input mutation goes through a new `InputMut<'_>` handle (returned by `input_mut(outpoint)` / `inputs_mut()`) which derefs to `&Input` for reads and exposes only `set_sequence`, preventing whole-input replacement that would silently break coin-selection invariants.
3. **Reorder methods.** Adds `sort_inputs_by`, `shuffle_inputs`, `sort_outputs_by`, `shuffle_outputs` on `Selection` so callers can apply BIP-69 or chain-analysis-resistant ordering without raw mutable slice access.
### Scope creep
Bundled in this PR (let me know if you'd prefer these split out):
- **Workspace refactor.** `src/utils.rs` is split into `src/afs.rs` (AFS types) and `src/no_std_rand.rs` (no-std rand helpers). `no_std_rand` is now crate-private since it has no external consumers.
- **`fisher_yates_shuffle` helper.** Added to `no_std_rand` and used to back `Selection::shuffle_inputs` / `shuffle_outputs`.
### Changelog Notice
```md
Added:
- `SelectorError::LockTypeMismatch` — raised by `Selector::new` when candidate inputs mix height-based and time-based absolute timelocks.
- `Selection::inputs` / `Selection::outputs` accessors (replacing the public fields).
- `Selection::input_mut` / `Selection::inputs_mut` returning a new `InputMut<'_>` handle that only permits `set_sequence`.
- `Selection::sort_inputs_by`, `Selection::shuffle_inputs`, `Selection::sort_outputs_by`, `Selection::shuffle_outputs` for reordering without exposing raw mutable access.
Removed:
- `CreatePsbtError::LockTypeMismatch` — superseded by `SelectorError::LockTypeMismatch`.
Changed:
- `Selection.inputs` and `Selection.outputs` are no longer public fields. External construction of `Selection` is no longer possible; obtain one from `Selector::try_finalize`.
```
### Checklist
- [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
- [x] I ran `cargo fmt` and `cargo clippy` before committing
- [x] I've added tests for the new feature
- [x] I've added docs for the new feature
- [x] I'm linking the issue being fixed by this PR
ACKs for top commit:
nymius:
ACK 96b9f88
noahjoeris:
ACK 96b9f88
Tree-SHA512: 013e0da33f2960841c74d89faa05aa4819507bdebbd279549ce09daf380abacbb6f5ec5437a9aa1893e42c30e7832e41097e160c04676b2afedfff43e513c268
0 commit comments