Skip to content

Creating Keys and Descriptors

BDK is a descriptor-first library. This page explores how to build them and how they interact with other standards like BIP-39 recovery phrases.

Danger

The keys and descriptors used in The Book of BDK are for illustration purposes only; UNDER NO CIRCUMSTANCES should any of the keys or descriptors containing private data be used for real money. Entropy generation should be carried out in a secure environment using cryptographically secure random number generators (CSPRNG).

Using descriptor templates

BDK offers utility constructs called descriptor templates, which allow you to build descriptors for the four most common script types (BIP 44/49/84/86) with minimal effort.

The following will build and print the full string representation of taproot (BIP-86) internal and external descriptors. We print both the public key descriptors (for HD wallet address generation only) and private key descriptors (for full wallet functionality including transaction signing).

use bdk_wallet::bitcoin::bip32::Xpriv;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::KeychainKind;
use bdk_wallet::template::{Bip86, DescriptorTemplate};
use bdk_wallet::bitcoin::secp256k1::rand;
use bdk_wallet::bitcoin::secp256k1::rand::RngCore;

fn main() -> () {
    // --8<-- [start:main]
    let mut seed: [u8; 32] = [0u8; 32];
    rand::thread_rng().fill_bytes(&mut seed);

    let network: Network = Network::Signet;
    let xprv: Xpriv = Xpriv::new_master(network, &seed).unwrap();
    println!("Generated Master Private Key:\n{}\nWarning: be very careful with private keys when using MainNet! We are logging these values for convenience only because this is an example on SigNet.\n", xprv);

    let (descriptor, key_map, _) = Bip86(xprv, KeychainKind::External)
        .build(Network::Signet)
        .expect("Failed to build external descriptor");

    let (change_descriptor, change_key_map, _) = Bip86(xprv, KeychainKind::Internal)
        .build(Network::Signet)
        .expect("Failed to build internal descriptor");

    let descriptor_string_priv = descriptor.to_string_with_secret(&key_map);
    let change_descriptor_string_priv = descriptor.to_string_with_secret(&change_key_map);
    // --8<-- [end:main]

    println!(
        "----------------  Descriptors  ------------------------------\nPrivate Key, External:\n{:?}\nPrivate Key, Internal:\n{:?}\nPublic Key, External:\n{:?}\nPublic Key, Internal:\n{:?}\n",
        descriptor_string_priv, // privkey
        change_descriptor_string_priv,
        descriptor.to_string(), // pubkey
        change_descriptor.to_string()
    );
}