Skip to content

Explorations for support of N keychains #226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

thunderbiscuit
Copy link
Member

@thunderbiscuit thunderbiscuit commented May 3, 2025

Just pushing here to show/discuss as I explore the potential for support of any number of descriptors for the Wallet type for maybe a 3.0.

Overview

The gist of my idea is a KeyRing (KeychainRing? KeychainSet?), which is basically a structure that holds a vector of keychains. You create a key ring with any number of descriptors (must have 1 default, can have 1 change, plus any number of others). The wallet constructors take this KeyRing as an argument, and from there the wallet methods need to be adjusted to work with the new paradigm.

The KeyRing has methods to add/check/query descriptors it holds, and is where the domain logic of ensuring only 1 descriptor is the default, that all descriptors use the same network, and any other requirements we have for basically this group of keychains lives. The wallet type then gets a new field key_ring, which it can use to query things like KeyRing::get_default_descriptor() or KeyRing::list_keychains().

pub enum KeychainKind {
    Default,
    Change,
    Other(DescriptorId),
}

pub type WalletKeychain = (KeychainKind, Descriptor<DescriptorPublicKey>);

pub struct KeyRing {
    keychains: Vec<WalletKeychain>,
}

Resulting API

The API is showcased in the wallet/examples/n_keychains.rs file.

// Create a keyring with a single, default descriptor (aka the KeychainKind::External from the 1.2.0 API)
let mut keyring = KeyRing::new(EXTERNAL_DESC, Network::Testnet4);

// Add 3 new custom descriptors
keyring.add_other_descriptor(OTHER_DESC_21);
keyring.add_other_descriptor(OTHER_DESC_31);
keyring.add_other_descriptor(OTHER_DESC_41);

let keychain_ids: Vec<DescriptorId> = keyring.list_keychain_ids();
println!("{:?}", keychain_ids);

// Create the wallet and peek addresses on each of the descriptors
let wallet: Wallet = Wallet::new(keyring).create_wallet_no_persist()?;
let address_1 = wallet.peek_address(KeychainKind::Default, 0).unwrap();
let address_2 = wallet.peek_address(KeychainKind::Other(keychain_ids[1]), 0).unwrap();
let address_3 = wallet.peek_address(KeychainKind::Other(keychain_ids[2]), 0).unwrap();
let address_4 = wallet.peek_address(KeychainKind::Other(keychain_ids[3]), 0).unwrap();

println!("Address 1 {:?} at index {:?} on keychain {:?}", address_1.address, address_1.index, address_1.keychain);
println!("Address 2 {:?} at index {:?} on keychain {:?}", address_2.address, address_2.index, address_2.keychain);
println!("Address 3 {:?} at index {:?} on keychain {:?}", address_3.address, address_3.index, address_3.keychain);
println!("Address 4 {:?} at index {:?} on keychain {:?}", address_4.address, address_4.index, address_4.keychain);

@thunderbiscuit
Copy link
Member Author

thunderbiscuit commented May 5, 2025

Some development notes as I go along:

  1. The CreateParams struct had 2 constructors: CreateParams::new and CreateParams::new_single. This simplifies the constructors because the KeyRing type handles all that stuff now.
  2. One sad thing is that some of the previous infallible APIs now return Results, complexifying a little bit the call-sites (Wallet::peek_address, Wallet::reveal_next_address, Wallet::next_unused_address, Wallet:mark_used, Wallet::unmark_used).

@thunderbiscuit thunderbiscuit marked this pull request as draft May 14, 2025 15:36
@thunderbiscuit thunderbiscuit force-pushed the explorations/n-keychains branch from 8751714 to 71cb992 Compare May 14, 2025 15:54
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.

1 participant