Skip to content

Commit f9d0bdd

Browse files
committed
refactor: remove SortedMultiVec and use Terminal::SortedMulti
- Utilize the Miniscript parsing to handle sortedmulti as a Terminal. - Deleted sortedmulti.rs (SortedMultiVec) - Refactor Wsh to only wrap a Miniscript now that SortedMultiVec isn't used. - Refactor ShInner to remove SortedMulti variant and only use the Ms variant for sortedmulti scripts
1 parent 78254b2 commit f9d0bdd

23 files changed

Lines changed: 222 additions & 458 deletions

File tree

bitcoind-tests/tests/test_cpp.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,7 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) {
147147
for i in 0..psbts.len() {
148148
let wsh_derived = desc_vec[i].derived_descriptor(&secp);
149149
let ms = if let Descriptor::Wsh(wsh) = &wsh_derived {
150-
match wsh.as_inner() {
151-
miniscript::descriptor::WshInner::Ms(ms) => ms,
152-
_ => unreachable!(),
153-
}
150+
wsh.as_inner()
154151
} else {
155152
unreachable!("Only Wsh descriptors are supported");
156153
};

bitcoind-tests/tests/test_desc.rs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -222,29 +222,15 @@ pub fn test_desc_satisfy(
222222
Descriptor::Pkh(pk) => find_sk_single_key(*pk.as_inner(), testdata),
223223
Descriptor::Wpkh(pk) => find_sk_single_key(*pk.as_inner(), testdata),
224224
Descriptor::Sh(sh) => match sh.as_inner() {
225-
miniscript::descriptor::ShInner::Wsh(wsh) => match wsh.as_inner() {
226-
miniscript::descriptor::WshInner::SortedMulti(ref smv) => {
227-
let ms = Miniscript::from_ast(smv.sorted_node()).unwrap();
228-
find_sks_ms(&ms, testdata)
229-
}
230-
miniscript::descriptor::WshInner::Ms(ref ms) => find_sks_ms(ms, testdata),
231-
},
225+
miniscript::descriptor::ShInner::Wsh(wsh) => {
226+
find_sks_ms(wsh.as_inner(), testdata)
227+
}
232228
miniscript::descriptor::ShInner::Wpkh(pk) => {
233229
find_sk_single_key(*pk.as_inner(), testdata)
234230
}
235-
miniscript::descriptor::ShInner::SortedMulti(smv) => {
236-
let ms = Miniscript::from_ast(smv.sorted_node()).unwrap();
237-
find_sks_ms(&ms, testdata)
238-
}
239231
miniscript::descriptor::ShInner::Ms(ms) => find_sks_ms(ms, testdata),
240232
},
241-
Descriptor::Wsh(wsh) => match wsh.as_inner() {
242-
miniscript::descriptor::WshInner::SortedMulti(ref smv) => {
243-
let ms = Miniscript::from_ast(smv.sorted_node()).unwrap();
244-
find_sks_ms(&ms, testdata)
245-
}
246-
miniscript::descriptor::WshInner::Ms(ref ms) => find_sks_ms(ms, testdata),
247-
},
233+
Descriptor::Wsh(wsh) => find_sks_ms(wsh.as_inner(), testdata),
248234
Descriptor::Tr(_tr) => unreachable!("Tr checked earlier"),
249235
};
250236
let msg = psbt
@@ -316,8 +302,7 @@ fn find_sks_ms<Ctx: ScriptContext>(
316302
) -> Vec<secp256k1::SecretKey> {
317303
let sks = &testdata.secretdata.sks;
318304
let pks = &testdata.pubdata.pks;
319-
let sks = ms
320-
.iter_pk()
305+
let sks = ms.iter_pk()
321306
.filter_map(|pk| {
322307
let i = pks.iter().position(|&x| x.to_public_key() == pk);
323308
i.map(|idx| sks[idx])

src/descriptor/mod.rs

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,13 @@ mod bare;
3636
mod iter;
3737
mod segwitv0;
3838
mod sh;
39-
mod sortedmulti;
4039
mod tr;
4140

4241
// Descriptor Exports
4342
pub use self::bare::{Bare, Pkh};
4443
pub use self::iter::PkIter;
45-
pub use self::segwitv0::{Wpkh, Wsh, WshInner};
44+
pub use self::segwitv0::{Wpkh, Wsh};
4645
pub use self::sh::{Sh, ShInner};
47-
pub use self::sortedmulti::SortedMultiVec;
4846
pub use self::tr::{
4947
TapTree, TapTreeDepthError, TapTreeIter, TapTreeIterItem, Tr, TrSpendInfo, TrSpendInfoIter,
5048
TrSpendInfoIterItem,
@@ -256,18 +254,31 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
256254
Descriptor::Pkh(ref pk) => PkIter::from_key(pk.as_inner().clone()),
257255
Descriptor::Wpkh(ref pk) => PkIter::from_key(pk.as_inner().clone()),
258256
Descriptor::Sh(ref sh) => match *sh.as_inner() {
259-
ShInner::Wsh(ref wsh) => match wsh.as_inner() {
260-
WshInner::SortedMulti(ref sorted) => PkIter::from_sortedmulti(sorted.pks()),
261-
WshInner::Ms(ref ms) => PkIter::from_miniscript_segwit(ms),
262-
},
257+
ShInner::Wsh(ref wsh) => {
258+
let ms = wsh.as_inner();
259+
if let Terminal::SortedMulti(ref thresh) = ms.node {
260+
PkIter::from_sortedmulti(thresh.data())
261+
} else {
262+
PkIter::from_miniscript_segwit(ms)
263+
}
264+
}
263265
ShInner::Wpkh(ref pk) => PkIter::from_key(pk.as_inner().clone()),
264-
ShInner::SortedMulti(ref sorted) => PkIter::from_sortedmulti(sorted.pks()),
265-
ShInner::Ms(ref ms) => PkIter::from_miniscript_legacy(ms),
266-
},
267-
Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
268-
WshInner::SortedMulti(ref sorted) => PkIter::from_sortedmulti(sorted.pks()),
269-
WshInner::Ms(ref ms) => PkIter::from_miniscript_segwit(ms),
266+
ShInner::Ms(ref ms) => {
267+
if let Terminal::SortedMulti(ref thresh) = ms.node {
268+
PkIter::from_sortedmulti(thresh.data())
269+
} else {
270+
PkIter::from_miniscript_legacy(ms)
271+
}
272+
}
270273
},
274+
Descriptor::Wsh(ref wsh) => {
275+
let ms = wsh.as_inner();
276+
if let Terminal::SortedMulti(ref thresh) = ms.node {
277+
PkIter::from_sortedmulti(thresh.data())
278+
} else {
279+
PkIter::from_miniscript_segwit(ms)
280+
}
281+
}
271282
Descriptor::Tr(ref tr) => PkIter::from_tr(tr),
272283
}
273284
}
@@ -313,18 +324,29 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
313324
Descriptor::Pkh(ref _pkh) => DescriptorType::Pkh,
314325
Descriptor::Wpkh(ref _wpkh) => DescriptorType::Wpkh,
315326
Descriptor::Sh(ref sh) => match sh.as_inner() {
316-
ShInner::Wsh(ref wsh) => match wsh.as_inner() {
317-
WshInner::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
318-
WshInner::Ms(ref _ms) => DescriptorType::ShWsh,
319-
},
327+
ShInner::Wsh(ref wsh) => {
328+
if let Terminal::SortedMulti(..) = wsh.as_inner().node {
329+
DescriptorType::ShWshSortedMulti
330+
} else {
331+
DescriptorType::ShWsh
332+
}
333+
}
320334
ShInner::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
321-
ShInner::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
322-
ShInner::Ms(ref _ms) => DescriptorType::Sh,
323-
},
324-
Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
325-
WshInner::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
326-
WshInner::Ms(ref _ms) => DescriptorType::Wsh,
335+
ShInner::Ms(ref ms) => {
336+
if let Terminal::SortedMulti(..) = ms.node {
337+
DescriptorType::ShSortedMulti
338+
} else {
339+
DescriptorType::Sh
340+
}
341+
}
327342
},
343+
Descriptor::Wsh(ref wsh) => {
344+
if let Terminal::SortedMulti(..) = wsh.as_inner().node {
345+
DescriptorType::WshSortedMulti
346+
} else {
347+
DescriptorType::Wsh
348+
}
349+
}
328350
Descriptor::Tr(ref _tr) => DescriptorType::Tr,
329351
}
330352
}
@@ -1121,6 +1143,7 @@ mod tests {
11211143

11221144
use super::{checksum, *};
11231145
use crate::hex_script;
1146+
use crate::miniscript::context::ScriptContextError;
11241147
#[cfg(feature = "compiler")]
11251148
use crate::policy;
11261149

@@ -1170,7 +1193,7 @@ mod tests {
11701193
StdDescriptor::from_str("sh(sortedmulti)")
11711194
.unwrap_err()
11721195
.to_string(),
1173-
"sortedmulti must have at least 1 children, but found 0"
1196+
"expected threshold, found terminal"
11741197
); //issue 202
11751198
assert_eq!(
11761199
StdDescriptor::from_str(&format!("sh(sortedmulti(2,{}))", &TEST_PK[3..69]))
@@ -2698,4 +2721,26 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
26982721
);
26992722
}
27002723
}
2724+
2725+
#[test]
2726+
fn too_many_pubkeys_for_p2sh() {
2727+
// Arbitrary 65-byte public key (66 with length prefix).
2728+
let pk = PublicKey::from_str(
2729+
"0400232a2acfc9b43fa89f1b4f608fde335d330d7114f70ea42bfb4a41db368a3e3be6934a4097dd25728438ef73debb1f2ffdb07fec0f18049df13bdc5285dc5b",
2730+
)
2731+
.unwrap();
2732+
2733+
// This is legal for CHECKMULTISIG, but the 8 keys consume the whole 520 bytes
2734+
// allowed by P2SH, meaning that the full script goes over the limit.
2735+
let thresh = Threshold::new(2, vec![pk; 8]).expect("the thresh is ok..");
2736+
let script = Miniscript::<_, Legacy>::sortedmulti(thresh).encode();
2737+
let res = Miniscript::<_, Legacy>::decode(&script);
2738+
2739+
let error = res.expect_err("decoding should err");
2740+
2741+
match error {
2742+
Error::ContextError(ScriptContextError::MaxRedeemScriptSizeExceeded { .. }) => {} // ok
2743+
other => panic!("unexpected error: {:?}", other),
2744+
}
2745+
}
27012746
}

0 commit comments

Comments
 (0)