Skip to content

Commit 76aec62

Browse files
committed
Merge #1533: [wallet] Enable support for single descriptor wallets
13e7008 doc(wallet): clarify docs for `Wallet::load` (valued mammal) 3951110 fix(wallet)!: Change method `LoadParams::descriptors` (valued mammal) b802714 example(wallet): simplify miniscript compiler example (valued mammal) 2ca8b6f test(wallet): Add tests for single descriptor wallet (valued mammal) 31f1c2d fix(wallet): Change FromSql type to `Option<_>` (valued mammal) 75155b7 feat(wallet): Add method `Wallet::create_single` (valued mammal) Pull request description: The change descriptor is made optional, making this an effective reversion of #1390 and enables creating wallets with a single descriptor. fixes #1511 ### Notes to the reviewers PR 1390 also removed an error case [`ChangePolicyDescriptor`](https://github.com/bitcoindevkit/bdk/blob/8eef350bd08057acc39b6fc50b1217db5e29b968/crates/wallet/src/wallet/mod.rs#L1529-L1533) and this can possibly be added back. In the case the wallet only has a single descriptor we allow any utxos to fund a tx that aren't specifically marked unspendable regardless of the change spend policy. ### Changelog notice * Added method `Wallet::create_single` that expects a single `D: IntoWalletDescriptor` as input and enables building a wallet with no internal keychain. ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] This pull request breaks the existing API * [x] I've added tests for the new feature * [x] I've added docs for the new feature ACKs for top commit: evanlinjin: ACK 13e7008 Tree-SHA512: 3e6fe5d9165d62332ac1863ec769c4bc5c7cd3c7f3fbdb8f505906bcdc681fa73b3fef2571adb0e52e9a23d4257f66a6145838b90ec68596b5f4c64054a047fa
2 parents 74b24d3 + 13e7008 commit 76aec62

File tree

12 files changed

+417
-151
lines changed

12 files changed

+417
-151
lines changed

crates/chain/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ pub type KeychainIndexed<K, T> = ((K, u32), T);
113113
/// A wrapper that we use to impl remote traits for types in our crate or dependency crates.
114114
pub struct Impl<T>(pub T);
115115

116+
impl<T> Impl<T> {
117+
/// Returns the inner `T`.
118+
pub fn into_inner(self) -> T {
119+
self.0
120+
}
121+
}
122+
116123
impl<T> From<T> for Impl<T> {
117124
fn from(value: T) -> Self {
118125
Self(value)

crates/wallet/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ let network = Network::Testnet;
7979
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
8080
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
8181
let wallet_opt = Wallet::load()
82-
.descriptors(descriptor, change_descriptor)
8382
.network(network)
83+
.descriptor(KeychainKind::External, Some(descriptor))
84+
.descriptor(KeychainKind::Internal, Some(change_descriptor))
85+
.extract_keys()
8486
.load_wallet(&mut db)
8587
.expect("wallet");
8688
let mut wallet = match wallet_opt {

crates/wallet/examples/compiler.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,28 +56,8 @@ fn main() -> Result<(), Box<dyn Error>> {
5656

5757
println!("Compiled into Descriptor: \n{}", descriptor);
5858

59-
// Do the same for another (internal) keychain
60-
let policy_str = "or(
61-
10@thresh(2,
62-
pk(029ffbe722b147f3035c87cb1c60b9a5947dd49c774cc31e94773478711a929ac0),pk(025f05815e3a1a8a83bfbb03ce016c9a2ee31066b98f567f6227df1d76ec4bd143),pk(025625f41e4a065efc06d5019cbbd56fe8c07595af1231e7cbc03fafb87ebb71ec)
63-
),1@and(
64-
pk(03deae92101c790b12653231439f27b8897264125ecb2f46f48278603102573165),
65-
older(12960)
66-
)
67-
)"
68-
.replace(&[' ', '\n', '\t'][..], "");
69-
70-
println!("Compiling internal policy: \n{}", policy_str);
71-
72-
let policy = Concrete::<String>::from_str(&policy_str)?;
73-
let internal_descriptor = Descriptor::new_wsh(policy.compile()?)?.to_string();
74-
println!(
75-
"Compiled into internal Descriptor: \n{}",
76-
internal_descriptor
77-
);
78-
7959
// Create a new wallet from descriptors
80-
let mut wallet = Wallet::create(descriptor, internal_descriptor)
60+
let mut wallet = Wallet::create_single(descriptor)
8161
.network(Network::Regtest)
8262
.create_wallet_no_persist()?;
8363

crates/wallet/src/wallet/changeset.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,18 @@ impl ChangeSet {
103103
let row = wallet_statement
104104
.query_row([], |row| {
105105
Ok((
106-
row.get::<_, Impl<Descriptor<DescriptorPublicKey>>>("descriptor")?,
107-
row.get::<_, Impl<Descriptor<DescriptorPublicKey>>>("change_descriptor")?,
108-
row.get::<_, Impl<bitcoin::Network>>("network")?,
106+
row.get::<_, Option<Impl<Descriptor<DescriptorPublicKey>>>>("descriptor")?,
107+
row.get::<_, Option<Impl<Descriptor<DescriptorPublicKey>>>>(
108+
"change_descriptor",
109+
)?,
110+
row.get::<_, Option<Impl<bitcoin::Network>>>("network")?,
109111
))
110112
})
111113
.optional()?;
112-
if let Some((Impl(desc), Impl(change_desc), Impl(network))) = row {
113-
changeset.descriptor = Some(desc);
114-
changeset.change_descriptor = Some(change_desc);
115-
changeset.network = Some(network);
114+
if let Some((desc, change_desc, network)) = row {
115+
changeset.descriptor = desc.map(Impl::into_inner);
116+
changeset.change_descriptor = change_desc.map(Impl::into_inner);
117+
changeset.network = network.map(Impl::into_inner);
116118
}
117119

118120
changeset.local_chain = local_chain::ChangeSet::from_sqlite(db_tx)?;

0 commit comments

Comments
 (0)