Skip to content

Commit 150f4d6

Browse files
committed
fix: ensure the key network is updated in the KeyMap as well
Otherwise we may have inconsistencies with keys in the descriptor that have a network and keys in the keymap that are different.
1 parent 1c95ca3 commit 150f4d6

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

src/descriptor/mod.rs

+48-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use bitcoin::util::{psbt, taproot};
2121
use bitcoin::{secp256k1, PublicKey, XOnlyPublicKey};
2222
use bitcoin::{Network, TxOut};
2323

24-
use miniscript::descriptor::{DefiniteDescriptorKey, DescriptorType, InnerXKey, SinglePubKey};
24+
use miniscript::descriptor::{
25+
DefiniteDescriptorKey, DescriptorSecretKey, DescriptorType, InnerXKey, SinglePubKey,
26+
};
2527
pub use miniscript::{
2628
descriptor::DescriptorXKey, descriptor::KeyMap, descriptor::Wildcard, Descriptor,
2729
DescriptorPublicKey, Legacy, Miniscript, ScriptContext, Segwitv0,
@@ -240,14 +242,34 @@ impl IntoWalletDescriptor for DescriptorTemplateOut {
240242
);
241243
}
242244

243-
if !self.2.contains(&network) {
245+
let (desc, keymap, networks) = self;
246+
247+
if !networks.contains(&network) {
244248
return Err(DescriptorError::Key(KeyError::InvalidNetwork));
245249
}
246250

247-
// fixup the network for keys that need it
248-
let translated = self.0.translate_pk(&mut Translator { network })?;
251+
// fixup the network for keys that need it in the descriptor
252+
let translated = desc.translate_pk(&mut Translator { network })?;
253+
// ...and in the key map
254+
let fixed_keymap = keymap
255+
.into_iter()
256+
.map(|(mut k, mut v)| {
257+
match (&mut k, &mut v) {
258+
(DescriptorPublicKey::XPub(xpub), DescriptorSecretKey::XPrv(xprv)) => {
259+
xpub.xkey.network = network;
260+
xprv.xkey.network = network;
261+
}
262+
(_, DescriptorSecretKey::Single(key)) => {
263+
key.key.network = network;
264+
}
265+
_ => {}
266+
}
249267

250-
Ok((translated, self.1))
268+
(k, v)
269+
})
270+
.collect();
271+
272+
Ok((translated, fixed_keymap))
251273
}
252274
}
253275

@@ -682,23 +704,40 @@ mod test {
682704

683705
let secp = Secp256k1::new();
684706

685-
let xpub = bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap();
707+
let xprv = bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3c3gF1DUWpWNr2SG2XrG8oYPpqYh7hoWsJy9NjabErnzriJPpnGHyKz5NgdXmq1KVbqS1r4NXdCoKitWg5e86zqXHa8kxyB").unwrap();
686708
let path = bip32::DerivationPath::from_str("m/0").unwrap();
687709

688710
// here `to_descriptor_key` will set the valid networks for the key to only mainnet, since
689711
// we are using an "xpub"
690-
let key = (xpub, path).into_descriptor_key().unwrap();
712+
let key = (xprv, path.clone()).into_descriptor_key().unwrap();
691713
// override it with any. this happens in some key conversions, like bip39
692714
let key = key.override_valid_networks(any_network());
693715

694716
// make a descriptor out of it
695717
let desc = crate::descriptor!(wpkh(key)).unwrap();
696718
// this should convert the key that supports "any_network" to the right network (testnet)
697-
let (wallet_desc, _) = desc
719+
let (wallet_desc, keymap) = desc
698720
.into_wallet_descriptor(&secp, Network::Testnet)
699721
.unwrap();
700722

701-
assert_eq!(wallet_desc.to_string(), "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)#y8p7e8kk");
723+
let mut xprv_testnet = xprv;
724+
xprv_testnet.network = Network::Testnet;
725+
726+
let xpub_testnet = bip32::ExtendedPubKey::from_priv(&secp, &xprv_testnet);
727+
let desc_pubkey = DescriptorPublicKey::XPub(DescriptorXKey {
728+
xkey: xpub_testnet,
729+
origin: None,
730+
derivation_path: path,
731+
wildcard: Wildcard::Unhardened,
732+
});
733+
734+
assert_eq!(wallet_desc.to_string(), "wpkh(tpubD6NzVbkrYhZ4XtJzoDja5snUjBNQRP5B3f4Hyn1T1x6PVPxzzVjvw6nJx2D8RBCxog9GEVjZoyStfepTz7TtKoBVdkCtnc7VCJh9dD4RAU9/0/*)#a3svx0ha");
735+
assert_eq!(
736+
keymap
737+
.get(&desc_pubkey)
738+
.map(|key| key.to_public(&secp).unwrap()),
739+
Some(desc_pubkey)
740+
);
702741
}
703742

704743
// test IntoWalletDescriptor trait from &str with and without checksum appended

0 commit comments

Comments
 (0)