Skip to content

Instantly share code, notes, and snippets.

@110CodingP
Last active November 2, 2025 06:57
Show Gist options
  • Save 110CodingP/234608b3175f2cb055058ae5d3427349 to your computer and use it in GitHub Desktop.
Save 110CodingP/234608b3175f2cb055058ae5d3427349 to your computer and use it in GitHub Desktop.

Bringing multi-keychain wallets to BDK!

Background

Currently the Wallet controls

  1. Keychains (Internal and External)
  2. Network
  3. Interacting with chain sources (IndexedTxGraph, LocalChain)
  4. Transaction creation
  5. Signing

We want the wallet to hold multiple keychains instead which will help advanced users and also lead to feature parity with Bitcoin Core wallet. Also the transaction creation and signing logic are being moved out of the Wallet (independent of the multi-keychain work).

Proposed Changes

First an awesome summary by thunderbiscuit.

Note

Some details like visibility might be omitted for brevity.

The heart of the changes is the type KeyRing:

struct KeyRing<K>  {
    descriptors: BTreeMap<K, Descriptor<DescriptorPublicKey>>,
    default_keychain: K,
    network: Network,
    secp: Secp256k1<All>,
}

The new Wallet holds a KeyRing instead of Network and the descriptors, also all fields related to signing have been removed.

struct Wallet<K> {
    keyring: KeyRing<K>,
    tx_graph: IndexedTxGraph<ConfirmationBlockTime, KeychainTxOutIndex<K>>,
    chain: LocalChain,
    stage: ChangeSet<K>,
}

Achieving parity with the current bdk_wallet and new APIs leveraging multi-keychains are the two major types of changes.

Grouping the changes according to parts of the wallet affected:

Descriptors and Network

  • APIs for creating wallet take in KeyRing now!
  • Address/spk/outputs APIs take in a keychain now, also each of these APIs gets a version which calls the default keychain. Keeping this in mind.
  • TBD: Should we have CreateParams and LoadParams?
  • Calculation of fee etc. APIs are easily supportable.
  • Balance API with this in mind. (TBD: should we have balance per keychain?)

Interacting with Chain sources

  • Syncing APIs (as in here)
  • APIs for block-by-block syncing (as in here)

Persistence

  • Implement persist and load functions for the KeyRing::ChangeSet holding keychains of a general type keeping in mind the migration users would need to do.
  • Modify PersistedWallet impls accordingly.

Transaction Creation and Signing

The changes of this category would be clearer when the this and this are merged.

New Features

  • Importing Bitcoin Core (issue) and Caravan format (as done in bdk_wallet).
  • APIs to add descriptors to wallet's keyring after wallet has been created.
  • (Needs discussion) Using bdk_tx be able to spend from certain keychains (with certain priority maybe) and get change from certain keychain such that changescript is same as output script.

Misc

  • Modify/Add tests accordingly.
  • Checks to ensure the 1 to 1 mapping between keychains and descriptors.
  • Add new features to multi_keychain_wallet as they are being added to bdk_wallet like user-facing events.
  • Add a check_descriptor to KeyRing::new and KeyRing::add_descriptor.

Previously work has been done here:#966, #1539 Currently, the work was being explored here and here. Final changes going on here.

Notes

These changes will be done in a breaking way for better maintainability.

Implications of Wallet controlling multiple keychains

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