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

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
resolver = "2"
members = [
"wallet",
"examples/example_wallet_electrum",
"examples/example_wallet_esplora_blocking",
"examples/example_wallet_esplora_async",
"examples/example_wallet_rpc",
"examples/example_wallet_n_keychains"
# "examples/example_wallet_electrum",
# "examples/example_wallet_esplora_blocking",
# "examples/example_wallet_esplora_async",
# "examples/example_wallet_rpc",
]

[workspace.package]
Expand Down
2 changes: 1 addition & 1 deletion wallet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "bdk_wallet"
homepage = "https://bitcoindevkit.org"
version = "2.0.0-alpha.0"
version = "1.3.0-alpha.0"
repository = "https://github.com/bitcoindevkit/bdk_wallet"
documentation = "https://docs.rs/bdk_wallet"
description = "A modern, lightweight, descriptor-based wallet library"
Expand Down
23 changes: 23 additions & 0 deletions wallet/examples/n_keychains.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use bdk_wallet::{KeyRing, Wallet};
use bdk_wallet::bitcoin::Network;
use bdk_wallet::KeychainKind;

const EXTERNAL_DESC: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
const OTHER_DESC_21: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/21/*)";
const OTHER_DESC_33: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/33/*)";
const OTHER_DESC_44: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/44/*)";

fn main() -> Result<(), anyhow::Error> {
let mut keyring = KeyRing::new(EXTERNAL_DESC, Network::Testnet4);
// keyring.add_other_descriptor(OTHER_DESC_21);
// let keychains = keyring.list_keychains();
// println!("{:?}", keychains);

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(), 0).unwrap();

println!("Address {:?} at index {:?} on keychain {:?}", address_1.address, address_1.index, address_1.keychain);

Ok(())
}
36 changes: 21 additions & 15 deletions wallet/src/descriptor/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ use super::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
use crate::descriptor::DescriptorError;
use crate::keys::{DerivableKey, IntoDescriptorKey, ValidNetworks};
use crate::wallet::utils::SecpCtx;
use crate::{descriptor, KeychainKind};
use crate::descriptor;

/// Type alias for the return type of [`DescriptorTemplate`], [`descriptor!`](crate::descriptor!) and others
pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);

#[derive(Clone, Debug)]
pub enum TemplateKeychainKind {
External,
Internal,
}

/// Trait for descriptor templates that can be built into a full descriptor
///
/// Since [`IntoWalletDescriptor`] is implemented for any [`DescriptorTemplate`], they can also be
Expand Down Expand Up @@ -232,7 +238,7 @@ impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -271,7 +277,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -309,7 +315,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -348,7 +354,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -386,7 +392,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -425,7 +431,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -463,7 +469,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind);
pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -502,7 +508,7 @@ impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand All @@ -521,7 +527,7 @@ macro_rules! expand_make_bipxx {
pub(super) fn make_bipxx_private<K: DerivableKey<$ctx>>(
bip: u32,
key: K,
keychain: KeychainKind,
keychain: TemplateKeychainKind,
network: Network,
) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
let mut derivation_path = alloc::vec::Vec::with_capacity(4);
Expand All @@ -538,10 +544,10 @@ macro_rules! expand_make_bipxx {
derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);

match keychain {
KeychainKind::External => {
TemplateKeychainKind::External => {
derivation_path.push(bip32::ChildNumber::from_normal_idx(0)?)
}
KeychainKind::Internal => {
TemplateKeychainKind::Internal => {
derivation_path.push(bip32::ChildNumber::from_normal_idx(1)?)
}
};
Expand All @@ -554,12 +560,12 @@ macro_rules! expand_make_bipxx {
bip: u32,
key: K,
parent_fingerprint: bip32::Fingerprint,
keychain: KeychainKind,
keychain: TemplateKeychainKind,
network: Network,
) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
let derivation_path: bip32::DerivationPath = match keychain {
KeychainKind::External => vec![bip32::ChildNumber::from_normal_idx(0)?].into(),
KeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(),
TemplateKeychainKind::External => vec![bip32::ChildNumber::from_normal_idx(0)?].into(),
TemplateKeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(),
};

let source_path = bip32::DerivationPath::from(vec![
Expand Down
Loading