Skip to content

Multi-Keychain-Redo#1

Open
110CodingP wants to merge 4 commits into
masterfrom
multi_keychain_redo
Open

Multi-Keychain-Redo#1
110CodingP wants to merge 4 commits into
masterfrom
multi_keychain_redo

Conversation

@110CodingP

@110CodingP 110CodingP commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Description

Acc to VM's suggestions.

Notes to the reviewers

Particularly need review on

  • KeyRing and its APIs
  • from_v3 and to_v3 (for backwards and forwards compatibility respectively) [tested with a db from v3, check electrum_v3 example.]
  • Merge implementation for ChangeSet.
  • schema_v2, from_sqlite and persist_to_sqlite (in changeset.rs)
  • load_from_params (in wallet/mod.rs)

Differences from bitcoindevkit#318 :

  • KeyRing is not a part of the Wallet anymore.
    Rationale:
    Most of the Wallet APIs except those required for creating or loading the Wallet does not have to do anything with the descriptors. The ones that need to are related to the indexer . Plus the indexer does contain the descriptors anyways so it is duplication. The KeyRing is now used only to validate descriptors and has a method into_params that converts it into CreateParams populated with Network and descriptors.

  • There is no KeyRing::ChangeSet. ChangeSet just contains a new descriptors field now.
    Rationale:
    If I understood correctly then a goal of this new approach by VM was to reduce the amount of public API surface. And KeyRing::ChangeSet is one such public type which is quite unecessary if the KeyRing is only used for creating the Wallet.

  • Also we donot remove descriptor and change_descriptor fields from the ChangeSet in this PR.
    Rationale:
    As VM highlighted, we need the two fields to be present because of backwards compatibility. Also providing backwards compatibility (and forwards) also forces us to handle cases when a user tries to load a v3 wallet. Since such cases only appear for KeychainKind type we need to have a separate load_from_changeset function for this type. To avoid this (kind of) I introduced from_v3 (and to_v3). Also do take a look at Merge impl for ChangeSet, changed that too.

  • KeyRing misses a lot of old APIs. Seeking feedback for the APIs I should add/bring back.

  • There is only one way to create the wallet. KeyRing ->(into_params) CreateParams ->(create_wallet_no_persist or create_from_params) Wallet/PersistedWallet. Seeking feedback on other ways we would like to introduce here.

  • KeyRing tries to actively avoid duplicate keychain or descriptor.

  • Support For Arbitrary Number (1+) of Keychains bitcoindevkit/bdk_wallet#318 introduced a new sqlite table for the descriptors and network. Here we just create a new descriptors table and still try to persist to/read from the old bdk_wallet table.
    Rationale: This makes migration easy! See electrum_v3 example.

  • We replace KeyRingError by InitError and minimise the change in v3 Wallet's error types.
    Rationale: To decrease the amount of breaking changes.

@110CodingP 110CodingP force-pushed the multi_keychain_redo branch from fa470d1 to 3b89212 Compare June 23, 2026 18:47
The KeyRing<K> struct was introduced with the following methods: new,
network, add_descriptor, add_multipath_descriptor,
add_multipath_descriptor_with_range, into_params, list_keychains.
The descriptors field within the KeyRing struct is specifically designed
for O(1) membership checks.

`KeyRing::add_descriptors` was intentionally not included because it is
difficult to provide atomicity guarantees without introducing overly
complicated logic. Also, while `KeyRing::add_multipath_with_range` is
currently internal, it should be made `pub` in the future if we can
incorporate a generic range parameter in an elegant manner.
@110CodingP 110CodingP force-pushed the multi_keychain_redo branch from 3b89212 to ce9659d Compare June 29, 2026 04:05
Introduced `InitError` to report errors at the time of `Wallet` creation
since `DescriptorError` does not report duplicate keychains case now.
Also introduced `MissingKeychain` error to report the case when address
APIs are called with an invalid keychain.
`CreateParams::multi_path_descriptor_with_range` follows the logic of
`KeyRing::add_multipath_descriptor_with_range`.

Removed `ExternalAndInternalAreTheSame` variant from `Error` in
`descriptor` in order to avoid propagating the generic to
`IntoWalletDescriptor`. Also maintaining whether keychains are the same
should be the concern of the `Wallet` level and not the descriptor
level.

The `from_v3` and `to_v3` APIs are for backwards and forward
compatibility respectively such that the `load_from_params` does not
need to deal with 2 separate types of `ChangeSets`. Users should call
these APIs appropriately. `load_from_v3`, `load_from_v3_async`,
`persist_to_v3`, and `persist_to_v3_async` have been added to
`PersistedWallet` for users convenience.

Refactor of export.rs is NOT COMPLETE.

`Utxo` and `WeightedUtxo` were primarily used in `TxBuilder` contexts so
they still use `KeychainKind`. Note we have decided that transaction
building for multi-keychain `Wallet` will only happen through
`create_psbt` API.

`Merge` implementation for `ChangeSet` does not take into account the
`descriptor` and `change_descriptor` fields because ideally `v4`
completely ignores these fields.

But `from_sqlite` and `persist_to_sqlite` still load and persist these
two fields for backwards/forwards compatibility.
The tests related to signers are yet to be fixed completely.
The new example (electrum_v3) is just for testing purposes and should be
removed from the final version of the commit.
@110CodingP 110CodingP force-pushed the multi_keychain_redo branch from ce9659d to a6160e2 Compare June 29, 2026 04:08
@thunderbiscuit

Copy link
Copy Markdown

Would you be able to do a quick write-up of the public API difference between this and bitcoindevkit#318?

I got lost a bit between all the different ideas, and it'd be great to see the rough outline of what this competing option is proposing!

@110CodingP

110CodingP commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

I added the most important differences in the description. Will keep updating the list and work on the presentation.

Edit: Done!

@110CodingP

Copy link
Copy Markdown
Owner Author

I have been adding examples here.

Added an example according to VM's suggestions that imitates Bitcoin Core's create_wallet and listdescriptors RPCs (it's very simple right now 😅 )

image

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants