Skip to content

Commit 24097d7

Browse files
committed
Merge bitcoindevkit/bdk#1662: fix(wallet): fix building change signers in load_with_params
b6b767f test(wallet): check keymaps can be set when loading wallet (valued mammal) 517fb53 fix(wallet): fix building change signers in `load_with_params` (valued mammal) Pull request description: This fixes an issue that prevented change signers from being built when using the `keymap` method on `LoadParams`. Now we always build a `SignersContainer` with the internal keymap whenever a change descriptor is loaded. Note, the signer may still be "empty" if neither `keymap` or `extract_keys` is used. ### Notes to the reviewers Building a `SignersContainer` now happens outside of the [match statement](https://github.com/bitcoindevkit/bdk/blob/b6b767f3fc12062d6787eec8b3e1021458283985/crates/wallet/src/wallet/mod.rs#L557) in `load_with_params` which simplifies the logic such that we can interpret this area of code as "initialize a value for `change_descriptor` and optionally extend the internal keymap, returning a `LoadMismatch` error if the changeset doesn't match the expected params." ### Changelog notice ### 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 #### Bugfixes: * [x] I've added tests to reproduce the issue which are now passing ACKs for top commit: evanlinjin: ACK b6b767f Tree-SHA512: fef2de691191e84f3e7cbe50c080cafb3b297d41e9bd493b97e45dfc1b3d77f4985c09b8fc3b398d54e22a43cf90501f6df70f8738e9b31a663efc0886f795e3
2 parents 647d285 + b6b767f commit 24097d7

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

crates/wallet/src/wallet/mod.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,9 @@ impl Wallet {
551551
}
552552
let signers = Arc::new(SignersContainer::build(external_keymap, &descriptor, &secp));
553553

554-
let (mut change_descriptor, mut change_signers) = (None, Arc::new(SignersContainer::new()));
554+
let mut change_descriptor = None;
555+
let mut internal_keymap = params.change_descriptor_keymap;
556+
555557
match (changeset.change_descriptor, params.check_change_descriptor) {
556558
// empty signer
557559
(None, None) => {}
@@ -592,17 +594,23 @@ impl Wallet {
592594
expected: Some(exp_desc),
593595
}));
594596
}
595-
let mut internal_keymap = params.change_descriptor_keymap;
596597
if params.extract_keys {
597598
internal_keymap.extend(keymap);
598599
}
599-
change_signers =
600-
Arc::new(SignersContainer::build(internal_keymap, &desc, &secp));
601600
change_descriptor = Some(desc);
602601
}
603602
},
604603
}
605604

605+
let change_signers = match change_descriptor {
606+
Some(ref change_descriptor) => Arc::new(SignersContainer::build(
607+
internal_keymap,
608+
change_descriptor,
609+
&secp,
610+
)),
611+
None => Arc::new(SignersContainer::new()),
612+
};
613+
606614
let index = create_indexer(descriptor, change_descriptor, params.lookahead)
607615
.map_err(LoadError::Descriptor)?;
608616

crates/wallet/tests/wallet.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use bitcoin::{
2626
absolute, transaction, Address, Amount, BlockHash, FeeRate, Network, OutPoint, ScriptBuf,
2727
Sequence, Transaction, TxIn, TxOut, Txid, Weight,
2828
};
29+
use miniscript::{descriptor::KeyMap, Descriptor, DescriptorPublicKey};
2930
use rand::rngs::StdRng;
3031
use rand::SeedableRng;
3132

@@ -99,6 +100,11 @@ fn insert_seen_at(wallet: &mut Wallet, txid: Txid, seen_at: u64) {
99100
.unwrap();
100101
}
101102

103+
fn parse_descriptor(s: &str) -> (Descriptor<DescriptorPublicKey>, KeyMap) {
104+
<Descriptor<DescriptorPublicKey>>::parse_descriptor(&Secp256k1::new(), s)
105+
.expect("failed to parse descriptor")
106+
}
107+
102108
// The satisfaction size of a P2WPKH is 112 WU =
103109
// 1 (elements in witness) + 1 (OP_PUSH) + 33 (pk) + 1 (OP_PUSH) + 72 (signature + sighash) + 1*4 (script len)
104110
// On the witness itself, we have to push once for the pk (33WU) and once for signature + sighash (72WU), for
@@ -251,7 +257,22 @@ fn wallet_load_checks() -> anyhow::Result<()> {
251257
))),
252258
"unexpected descriptors check result",
253259
);
254-
260+
// check setting keymaps
261+
let (_, external_keymap) = parse_descriptor(external_desc);
262+
let (_, internal_keymap) = parse_descriptor(internal_desc);
263+
let wallet = Wallet::load()
264+
.keymap(KeychainKind::External, external_keymap)
265+
.keymap(KeychainKind::Internal, internal_keymap)
266+
.load_wallet(&mut open_db(&file_path)?)
267+
.expect("db should not fail")
268+
.expect("wallet was persisted");
269+
for keychain in [KeychainKind::External, KeychainKind::Internal] {
270+
let keymap = wallet.get_signers(keychain).as_key_map(wallet.secp_ctx());
271+
assert!(
272+
!keymap.is_empty(),
273+
"load should populate keymap for keychain {keychain:?}"
274+
);
275+
}
255276
Ok(())
256277
}
257278

0 commit comments

Comments
 (0)