Merge bitcoindevkit/bdk#2038: refactor(chain,core)!: replace `CanonicalIter` with sans-IO `CanonicalTask` + `ChainQuery` trait
555f774169ea934dbb2934f2fbe6763908e86670 fix(chain): position resolution for assumed txs (Leonardo Lima)
4f10cdef4d55139ee7f608d9cf90ff8d9c0b3037 chore(chain,example)!: remove `ChainOracle`, update docs (志宇)
a3c73e4685f3381b5b1ae799c2279009b6f7d1ea refactor(chain)!: split `canonical_view` into `canonical`,`canonical_view_task` (志宇)
22b04c33dc0b75e5a247f99087ad36f41e99a0ed refactor(chain)!: split canonicalization into two tasks with generic `Canonical<A, P>` (志宇)
a9f5ca4415af36b42cca43551414ad0644d627b8 refactor(chain)!: remove `CanonicalIter` APIs (Leonardo Lima)
bb83da8260fb167fa548f31c12710153095e9064 chore(workspace): use new `LocalChain::canonical_view` API (Leonardo Lima)
987da73fce7b7f4e015aa05cc8fa4e36deebf4df feat(core,chain): introduce `CanonicalizationTask` and `ChainQuery` (Leonardo Lima)
Pull request description:
fixes #1816
### Description
Replaces the iterator-based `CanonicalIter` with a two-phase sans-IO canonicalization pipeline, and introduces a generic `ChainQuery` trait in `bdk_core` to decouple canonicalization from chain sources.
**Old API:**
```rust
// Direct coupling between canonicalization logic and ChainOracle
let view = tx_graph.canonical_view(&chain, chain_tip, params)?;
```
**New API:**
```rust
// Option A: Two-phase (full control)
let canonical_txs = chain.canonicalize(tx_graph.canonical_task(tip, params));
let view = chain.canonicalize(canonical_txs.view_task(&tx_graph));
// Option B: Convenience method
let view = chain.canonical_view(&tx_graph, tip, params);
```
#### Phase 1: `CanonicalTask`
Determines which transactions are canonical by processing them in stages:
1. **Assumed txs** — transactions assumed canonical via `CanonicalParams`
2. **Anchored txs** — transactions anchored in the best chain (descending height)
3. **Seen txs** — unconfirmed transactions by descending last-seen time
4. **Remaining txs** — leftover anchored transactions not in the best chain
Produces a `CanonicalTxs<A>` containing each canonical transaction with its `CanonicalReason`.
#### Phase 2: `CanonicalViewTask`
Resolves `CanonicalReason`s into concrete `ChainPosition`s (confirmed height or unconfirmed with last-seen), producing the final `CanonicalView<A>`.
Both phases implement the `ChainQuery` trait, so any chain source can drive them via the same `next_query`/`resolve_query` loop.
#### Key structural changes
- **`ChainQuery` trait** added to `bdk_core` — a generic sans-IO interface (`next_query` → `resolve_query` → `finish`) for any algorithm that needs to verify blocks against a chain source.
- **`ChainOracle` trait removed** — replaced by `ChainQuery`. `LocalChain::canonicalize()` now drives any `ChainQuery` implementor.
- **`Canonical<A, P>` generic container** — `CanonicalTxs<A>` (phase 1 output) and `CanonicalView<A>` (phase 2 output) are type aliases over `Canonical<A, P>`.
- **Module split** — `canonical_view.rs` split into `canonical.rs` (types: `Canonical`, `CanonicalTx`, `CanonicalTxOut`) and `canonical_view_task.rs` (phase 2 task). `canonical_iter.rs` replaced by `canonical_task.rs`.
### Notes to the reviewers
The changes are split into multiple commits for easier review. Also depends on #2029.
### Changelog notice
```
### Added
- `bdk_core::ChainQuery` trait — generic sans-IO interface for chain verification queries
- `bdk_core::ChainRequest` / `ChainResponse` type aliases
- `CanonicalTask` — phase 1 sans-IO canonicalization (determines canonical txs)
- `CanonicalViewTask` — phase 2 sans-IO canonicalization (resolves chain positions)
- `Canonical<A, P>` generic container with `CanonicalTxs<A>` and `CanonicalView<A>` aliases
- `LocalChain::canonicalize()` — drives any `ChainQuery` implementor
- `LocalChain::canonical_view()` — convenience method for full two-phase canonicalization
### Changed
- **Breaking:** Replace `TxGraph::canonical_iter()` / `TxGraph::canonical_view()` with `TxGraph::canonical_task()`
- **Breaking:** Canonicalization now uses a two-phase sans-IO process via `ChainQuery`
- **Breaking:** `ChainQuery`, `ChainRequest`, `ChainResponse` have no generics (use `BlockId` directly)
- **Breaking:** Chain tip moved from `ChainRequest` to `ChainQuery::tip()`
### Removed
- **Breaking:** `ChainOracle` trait and all implementations
- **Breaking:** `CanonicalIter` type and `canonical_iter` module
- **Breaking:** `TxGraph::try_canonical_view()` and `TxGraph::canonical_view()` methods
- **Breaking:** `CanonicalView::new()` public constructor
```
### Checklists
#### All Submissions:
* [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
#### New Features:
* [x] I've added tests for the new feature
* [x] I've added docs for the new feature
ACKs for top commit:
evanlinjin:
ACK
555f774169ea934dbb2934f2fbe6763908e86670
Tree-SHA512: ce466a623a1f8df20dedd3e4e68460892bd369567db44e6ba391c3d9ae1d10bca6204ebdcdb7b1376a9c97f3155b89e991846af4122e200d1fa15d998deb7830