2021-03-03 13:22:05 -08:00
|
|
|
// Bitcoin Dev Kit
|
|
|
|
// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
|
2020-08-31 11:26:36 +02:00
|
|
|
//
|
2021-03-03 13:22:05 -08:00
|
|
|
// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
|
2020-08-31 11:26:36 +02:00
|
|
|
//
|
2021-03-03 13:22:05 -08:00
|
|
|
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
|
|
|
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
|
|
|
|
// You may not use this file except in accordance with one or both of these
|
|
|
|
// licenses.
|
2020-08-31 11:26:36 +02:00
|
|
|
|
2024-02-06 08:56:31 -06:00
|
|
|
extern crate bdk_wallet;
|
2020-04-29 11:52:45 +02:00
|
|
|
extern crate bitcoin;
|
|
|
|
extern crate miniscript;
|
|
|
|
extern crate serde_json;
|
|
|
|
|
2021-02-02 20:06:40 -05:00
|
|
|
use std::error::Error;
|
2020-04-29 11:52:45 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
use bitcoin::Network;
|
|
|
|
use miniscript::policy::Concrete;
|
|
|
|
use miniscript::Descriptor;
|
|
|
|
|
2024-02-06 08:56:31 -06:00
|
|
|
use bdk_wallet::{KeychainKind, Wallet};
|
2020-04-29 11:52:45 +02:00
|
|
|
|
2022-08-21 17:43:14 +05:30
|
|
|
/// Miniscript policy is a high level abstraction of spending conditions. Defined in the
|
2023-01-19 15:03:37 -05:00
|
|
|
/// rust-miniscript library here https://docs.rs/miniscript/7.0.0/miniscript/policy/index.html
|
2022-08-21 17:43:14 +05:30
|
|
|
/// rust-miniscript provides a `compile()` function that can be used to compile any miniscript policy
|
|
|
|
/// into a descriptor. This descriptor then in turn can be used in bdk a fully functioning wallet
|
|
|
|
/// can be derived from the policy.
|
|
|
|
///
|
|
|
|
/// This example demonstrates the interaction between a bdk wallet and miniscript policy.
|
|
|
|
|
2021-02-02 20:06:40 -05:00
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
2024-03-26 21:57:10 -04:00
|
|
|
// We start with a miniscript policy string
|
|
|
|
let policy_str = "or(
|
|
|
|
10@thresh(4,
|
|
|
|
pk(029ffbe722b147f3035c87cb1c60b9a5947dd49c774cc31e94773478711a929ac0),pk(025f05815e3a1a8a83bfbb03ce016c9a2ee31066b98f567f6227df1d76ec4bd143),pk(025625f41e4a065efc06d5019cbbd56fe8c07595af1231e7cbc03fafb87ebb71ec),pk(02a27c8b850a00f67da3499b60562673dcf5fdfb82b7e17652a7ac54416812aefd),pk(03e618ec5f384d6e19ca9ebdb8e2119e5bef978285076828ce054e55c4daf473e2)
|
|
|
|
),1@and(
|
|
|
|
older(4209713),
|
|
|
|
thresh(2,
|
|
|
|
pk(03deae92101c790b12653231439f27b8897264125ecb2f46f48278603102573165),pk(033841045a531e1adf9910a6ec279589a90b3b8a904ee64ffd692bd08a8996c1aa),pk(02aebf2d10b040eb936a6f02f44ee82f8b34f5c1ccb20ff3949c2b28206b7c1068)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)"
|
|
|
|
.replace(&[' ', '\n', '\t'][..], "");
|
|
|
|
|
2023-11-11 13:02:02 -06:00
|
|
|
println!("Compiling policy: \n{}", policy_str);
|
2020-04-29 11:52:45 +02:00
|
|
|
|
2022-08-21 17:43:14 +05:30
|
|
|
// Parse the string as a [`Concrete`] type miniscript policy.
|
2024-03-26 21:57:10 -04:00
|
|
|
let policy = Concrete::<String>::from_str(&policy_str)?;
|
2020-04-29 11:52:45 +02:00
|
|
|
|
2022-08-21 17:43:14 +05:30
|
|
|
// Create a `wsh` type descriptor from the policy.
|
|
|
|
// `policy.compile()` returns the resulting miniscript from the policy.
|
2024-03-26 21:57:10 -04:00
|
|
|
let descriptor = Descriptor::new_wsh(policy.compile()?)?.to_string();
|
|
|
|
|
|
|
|
println!("Compiled into Descriptor: \n{}", descriptor);
|
|
|
|
|
|
|
|
// Do the same for another (internal) keychain
|
|
|
|
let policy_str = "or(
|
|
|
|
10@thresh(2,
|
|
|
|
pk(029ffbe722b147f3035c87cb1c60b9a5947dd49c774cc31e94773478711a929ac0),pk(025f05815e3a1a8a83bfbb03ce016c9a2ee31066b98f567f6227df1d76ec4bd143),pk(025625f41e4a065efc06d5019cbbd56fe8c07595af1231e7cbc03fafb87ebb71ec)
|
|
|
|
),1@and(
|
|
|
|
pk(03deae92101c790b12653231439f27b8897264125ecb2f46f48278603102573165),
|
|
|
|
older(12960)
|
|
|
|
)
|
|
|
|
)"
|
|
|
|
.replace(&[' ', '\n', '\t'][..], "");
|
2020-04-29 11:52:45 +02:00
|
|
|
|
2024-03-26 21:57:10 -04:00
|
|
|
println!("Compiling internal policy: \n{}", policy_str);
|
|
|
|
|
|
|
|
let policy = Concrete::<String>::from_str(&policy_str)?;
|
|
|
|
let internal_descriptor = Descriptor::new_wsh(policy.compile()?)?.to_string();
|
|
|
|
println!(
|
|
|
|
"Compiled into internal Descriptor: \n{}",
|
|
|
|
internal_descriptor
|
|
|
|
);
|
2020-04-29 11:52:45 +02:00
|
|
|
|
2024-03-26 21:57:10 -04:00
|
|
|
// Create a new wallet from descriptors
|
2024-06-01 00:06:20 -05:00
|
|
|
let mut wallet = Wallet::new(&descriptor, &internal_descriptor, Network::Regtest)?;
|
2022-08-21 17:43:14 +05:30
|
|
|
|
2023-11-11 13:02:02 -06:00
|
|
|
println!(
|
2022-08-21 17:43:14 +05:30
|
|
|
"First derived address from the descriptor: \n{}",
|
2024-06-01 00:06:20 -05:00
|
|
|
wallet.next_unused_address(KeychainKind::External),
|
2022-08-21 17:43:14 +05:30
|
|
|
);
|
|
|
|
|
|
|
|
// BDK also has it's own `Policy` structure to represent the spending condition in a more
|
|
|
|
// human readable json format.
|
|
|
|
let spending_policy = wallet.policies(KeychainKind::External)?;
|
2023-11-11 13:02:02 -06:00
|
|
|
println!(
|
2022-08-21 17:43:14 +05:30
|
|
|
"The BDK spending policy: \n{}",
|
|
|
|
serde_json::to_string_pretty(&spending_policy)?
|
|
|
|
);
|
2021-02-02 20:06:40 -05:00
|
|
|
|
|
|
|
Ok(())
|
2020-04-29 11:52:45 +02:00
|
|
|
}
|