Skip to content

refactor(chain): add CanonicalView topological ordering#2219

Draft
oleonardolima wants to merge 8 commits into
bitcoindevkit:masterfrom
oleonardolima:refactor/add-canonical-view-topological-ordering
Draft

refactor(chain): add CanonicalView topological ordering#2219
oleonardolima wants to merge 8 commits into
bitcoindevkit:masterfrom
oleonardolima:refactor/add-canonical-view-topological-ordering

Conversation

@oleonardolima
Copy link
Copy Markdown
Collaborator

depends on #2038

Description

Notes to the reviewers

Changelog notice

Checklists

All Submissions:

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature

Bugfixes:

  • This pull request breaks the existing API
  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

oleonardolima and others added 8 commits June 2, 2026 17:39
It introduces the new `CanonicalizationTask` that's implements the
canonicalization algorithm through a request/response pattern.

Also, it introduces the new `ChainQuery` trait in `bdk_core`, which
provides an interface for blockchain source/oracle query-based operations.
Allowing sans-IO patterns for algorithm that needs a blockchain oracle,
without the need for directly implement/handle I/O.

Adds new API methods into `LocalChain`: `canonicalize` and `canonical_view`,
adding same features as the existing `CanonicalIter` and it's APIs.

Co-Authored-By: Claude <noreply@anthropic.com>
Updates the codebase to use the new convenience
`LocalChain::canonical_view` method in order to generate the
`CanonicalView`. Internally the convenience method follows the `sans-IO` approach,
separating the canonicalization algorithm from i/o operations, and it's
used as follows:

1. Create a new `CanonicalizationTask` with a `TxGraph`, by calling:
   `graph.canonicalization_task(params)`
2. Execute the canonicalization process with a chain oracle (e.g
   `LocalChain`, which implements `ChainOracle` trait), by calling:
   `chain.canonicalize(task, chain_tip)`
The codebase has been updated to the new `LocalChain::canonical_view`
method. It's now safe to remove the `CanonicalIter` it's the old APIs
relying on it, eg. `try_canonical_view`.
…`Canonical<A, P>`

Separate concerns by splitting `CanonicalizationTask` into two phases:

1. `CanonicalTask` determines which transactions are canonical and why
   (`CanonicalReason`), outputting `CanonicalTxs<A>`.
2. `CanonicalViewTask` resolves reasons into `ChainPosition`s (confirmed
   vs unconfirmed), outputting `CanonicalView<A>`.

Make `Canonical<A, P>`, `CanonicalTx<P>`, and `FullTxOut<P>` generic over
the position type so the same structs serve both phases. Add
`LocalChain::canonical_view()` convenience method for the common two-step
pipeline.

Renames:

- `CanonicalizationTask` -> `CanonicalTask`
- `CanonicalizationParams` -> `CanonicalParams`
- `canonicalization_task()` -> `canonical_task()`
- `FullTxOut::chain_position` -> `FullTxOut::pos`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…view_task`

It moves the shared types: `CanonicalTx`, `Canonical`, `CanonicalView`,
`CanonicalTxs` and other convenience methods into `canonical.rs`.

Keep the phase-2 task (`CanonicalViewTask` in `canonical_view_task.rs`.

Also, rename `FullTxOut` to `CanonicalTxOut`, and move it to
`canonical.rs`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- add new `test_canonical_view_task.rs` to handle different scenarios
  of chain position resolution.
- fixes the assumed canonical txs chain position resolution, especially for transitively
  assumed canonical transactions, where there's an anchored/confirmed descendant.
- add `sort_topologically` to `CanonicalViewTask::finish()` using
  Kahn's algorithm, ensuring `CanonicalView` returns `Txid`s in
  topological order (parents before children)
- add `test_list_ordered_canonical_txs` with scenarios covering
  various transaction graph shapes
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 4, 2026

Codecov Report

❌ Patch coverage is 89.73881% with 55 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.76%. Comparing base (47556ab) to head (5969a64).

Files with missing lines Patch % Lines
crates/chain/src/canonical.rs 80.18% 19 Missing and 2 partials ⚠️
crates/chain/src/canonical_task.rs 94.71% 9 Missing and 3 partials ⚠️
crates/chain/src/canonical_view_task.rs 93.37% 6 Missing and 4 partials ⚠️
crates/chain/src/indexed_tx_graph.rs 0.00% 8 Missing ⚠️
crates/chain/src/local_chain.rs 88.88% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2219      +/-   ##
==========================================
+ Coverage   77.69%   78.76%   +1.07%     
==========================================
  Files          29       30       +1     
  Lines        5801     5938     +137     
  Branches      271      283      +12     
==========================================
+ Hits         4507     4677     +170     
+ Misses       1223     1185      -38     
- Partials       71       76       +5     
Flag Coverage Δ
rust 78.76% <89.73%> (+1.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants