Skip to content

Commit ef53556

Browse files
authored
Merge pull request #97 from Foundation-Devices/SFT-6045
SFT-6045: Don't use multipath keys on multisig.
2 parents 2c136b6 + aa2ba34 commit ef53556

File tree

3 files changed

+60
-33
lines changed

3 files changed

+60
-33
lines changed

src/psbt.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,11 +505,15 @@ where
505505
if let Some(witness_script) = input.witness_script.as_ref() {
506506
if witness_script.is_multisig() {
507507
let required_signers = multisig::disassemble(witness_script).unwrap();
508-
descriptors.insert(p2wsh::multisig_descriptor(
508+
let multisig_descriptors = p2wsh::multisig_descriptor(
509509
required_signers,
510510
&psbt.xpub,
511511
&input.bip32_derivation,
512-
)?);
512+
)?;
513+
514+
for descriptor in multisig_descriptors {
515+
descriptors.insert(descriptor);
516+
}
513517
} else {
514518
return Err(Error::Unimplemented);
515519
}
@@ -542,11 +546,15 @@ where
542546
if let Some(witness_script) = input.witness_script.as_ref() {
543547
if witness_script.is_multisig() {
544548
let required_signers = multisig::disassemble(witness_script).unwrap();
545-
descriptors.insert(p2sh::wsh_multisig_descriptor(
549+
let multisig_descriptors = p2sh::wsh_multisig_descriptor(
546550
required_signers,
547551
&psbt.xpub,
548552
&input.bip32_derivation,
549-
)?);
553+
)?;
554+
555+
for descriptor in multisig_descriptors {
556+
descriptors.insert(descriptor);
557+
}
550558
} else {
551559
return Err(Error::Unimplemented);
552560
}

src/psbt/p2sh.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use bdk_wallet::bitcoin::secp256k1::{PublicKey, Secp256k1, Signing};
88
use bdk_wallet::bitcoin::{Address, CompressedPublicKey, Network, TxOut};
99
use bdk_wallet::descriptor::{Descriptor, ExtendedDescriptor, Segwitv0};
1010
use bdk_wallet::keys::DescriptorPublicKey;
11-
use bdk_wallet::miniscript::descriptor::{DerivPaths, DescriptorMultiXKey, Wildcard};
11+
use bdk_wallet::miniscript::descriptor::{DescriptorXKey, Wildcard};
1212
use bdk_wallet::miniscript::descriptor::{Sh, Wpkh};
1313
use bdk_wallet::miniscript::{ForEachKey, Miniscript};
1414
use bdk_wallet::template::{Bip49Public, DescriptorTemplate};
@@ -187,7 +187,7 @@ pub fn wsh_multisig_descriptor(
187187
required_signers: u8,
188188
global_xpubs: &BTreeMap<Xpub, KeySource>,
189189
bip32_derivations: &BTreeMap<PublicKey, KeySource>,
190-
) -> Result<ExtendedDescriptor, Error> {
190+
) -> Result<[ExtendedDescriptor; 2], Error> {
191191
// Find the account Xpubs in the global Xpub map of the PSBT.
192192
let xpubs = bip32_derivations
193193
.iter()
@@ -201,26 +201,35 @@ pub fn wsh_multisig_descriptor(
201201
.ok_or_else(|| Error::MissingGlobalXpub(subpath.clone()))
202202
});
203203

204-
let mut descriptor_pubkeys = Vec::new();
204+
let mut external_keys = Vec::new();
205+
let mut internal_keys = Vec::new();
205206
for maybe_xpub in xpubs {
206207
let (xpub, source) = maybe_xpub?;
207208

208-
let descriptor_pubkey = DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
209+
let external_key = DescriptorPublicKey::XPub(DescriptorXKey {
209210
origin: Some(source.clone()),
210211
xkey: *xpub,
211-
derivation_paths: DerivPaths::new(vec![
212-
DerivationPath::from(vec![ChildNumber::Normal { index: 0 }]),
213-
DerivationPath::from(vec![ChildNumber::Normal { index: 1 }]),
214-
])
215-
.expect("the vector passed should not be empty"),
212+
derivation_path: DerivationPath::from(vec![ChildNumber::Normal { index: 0 }]),
216213
wildcard: Wildcard::Unhardened,
217214
});
218-
descriptor_pubkeys.push(descriptor_pubkey);
215+
216+
let internal_key = DescriptorPublicKey::XPub(DescriptorXKey {
217+
origin: Some(source.clone()),
218+
xkey: *xpub,
219+
derivation_path: DerivationPath::from(vec![ChildNumber::Normal { index: 1 }]),
220+
wildcard: Wildcard::Unhardened,
221+
});
222+
223+
external_keys.push(external_key);
224+
internal_keys.push(internal_key);
219225
}
220226

221-
Ok(ExtendedDescriptor::new_sh_wsh_sortedmulti(
222-
usize::from(required_signers),
223-
descriptor_pubkeys,
224-
)
225-
.unwrap())
227+
let external_descriptor =
228+
ExtendedDescriptor::new_sh_wsh_sortedmulti(usize::from(required_signers), external_keys)
229+
.unwrap();
230+
let internal_descriptor =
231+
ExtendedDescriptor::new_sh_wsh_sortedmulti(usize::from(required_signers), internal_keys)
232+
.unwrap();
233+
234+
Ok([external_descriptor, internal_descriptor])
226235
}

src/psbt/p2wsh.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bdk_wallet::bitcoin::secp256k1::PublicKey;
66
use bdk_wallet::bitcoin::{Network, TxOut};
77
use bdk_wallet::descriptor::{Descriptor, ExtendedDescriptor, Segwitv0};
88
use bdk_wallet::keys::DescriptorPublicKey;
9-
use bdk_wallet::miniscript::descriptor::{DerivPaths, DescriptorMultiXKey, Wildcard, Wsh};
9+
use bdk_wallet::miniscript::descriptor::{DescriptorXKey, Wildcard, Wsh};
1010
use bdk_wallet::miniscript::{ForEachKey, Miniscript};
1111
use std::collections::BTreeMap;
1212

@@ -103,7 +103,7 @@ pub fn multisig_descriptor(
103103
required_signers: u8,
104104
global_xpubs: &BTreeMap<Xpub, KeySource>,
105105
bip32_derivations: &BTreeMap<PublicKey, KeySource>,
106-
) -> Result<ExtendedDescriptor, Error> {
106+
) -> Result<[ExtendedDescriptor; 2], Error> {
107107
// Find the account Xpubs in the global Xpub map of the PSBT.
108108
let xpubs = bip32_derivations
109109
.iter()
@@ -117,25 +117,35 @@ pub fn multisig_descriptor(
117117
.ok_or_else(|| Error::MissingGlobalXpub(subpath.clone()))
118118
});
119119

120-
let mut descriptor_pubkeys = Vec::new();
120+
let mut external_keys = Vec::new();
121+
let mut internal_keys = Vec::new();
121122
for maybe_xpub in xpubs {
122123
let (xpub, source) = maybe_xpub?;
123124

124-
let descriptor_pubkey = DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
125+
let external_key = DescriptorPublicKey::XPub(DescriptorXKey {
125126
origin: Some(source.clone()),
126127
xkey: *xpub,
127-
derivation_paths: DerivPaths::new(vec![
128-
DerivationPath::from(vec![ChildNumber::Normal { index: 0 }]),
129-
DerivationPath::from(vec![ChildNumber::Normal { index: 1 }]),
130-
])
131-
.expect("the vector passed should not be empty"),
128+
derivation_path: DerivationPath::from(vec![ChildNumber::Normal { index: 0 }]),
132129
wildcard: Wildcard::Unhardened,
133130
});
134-
descriptor_pubkeys.push(descriptor_pubkey);
131+
132+
let internal_key = DescriptorPublicKey::XPub(DescriptorXKey {
133+
origin: Some(source.clone()),
134+
xkey: *xpub,
135+
derivation_path: DerivationPath::from(vec![ChildNumber::Normal { index: 1 }]),
136+
wildcard: Wildcard::Unhardened,
137+
});
138+
139+
external_keys.push(external_key);
140+
internal_keys.push(internal_key);
135141
}
136142

137-
Ok(
138-
ExtendedDescriptor::new_wsh_sortedmulti(usize::from(required_signers), descriptor_pubkeys)
139-
.unwrap(),
140-
)
143+
let external_descriptor =
144+
ExtendedDescriptor::new_wsh_sortedmulti(usize::from(required_signers), external_keys)
145+
.unwrap();
146+
let internal_descriptor =
147+
ExtendedDescriptor::new_wsh_sortedmulti(usize::from(required_signers), internal_keys)
148+
.unwrap();
149+
150+
Ok([external_descriptor, internal_descriptor])
141151
}

0 commit comments

Comments
 (0)