Skip to content

Commit c5f7903

Browse files
committed
Use Threshold type in concrete::Policy::Thresh
Use the `Threshold` type in `policy::concrete::Policy::Thresh` to help maintain invariants on n and k.
1 parent e153ef3 commit c5f7903

File tree

4 files changed

+90
-71
lines changed

4 files changed

+90
-71
lines changed

src/iter/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl<'a, Pk: MiniscriptKey> TreeLike for &'a policy::Concrete<Pk> {
7777
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
7878
And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
7979
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| p.as_ref()).collect()),
80-
Thresh(_, ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
80+
Thresh(thresh) => Tree::Nary(thresh.iter().map(Arc::as_ref).collect()),
8181
}
8282
}
8383
}
@@ -90,7 +90,7 @@ impl<'a, Pk: MiniscriptKey> TreeLike for Arc<policy::Concrete<Pk>> {
9090
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
9191
And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
9292
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
93-
Thresh(_, ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
93+
Thresh(thresh) => Tree::Nary(thresh.iter().map(Arc::clone).collect()),
9494
}
9595
}
9696
}

src/policy/compiler.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -920,8 +920,9 @@ where
920920
compile_binary!(&mut l_comp[3], &mut r_comp[2], [lw, rw], Terminal::OrI);
921921
compile_binary!(&mut r_comp[3], &mut l_comp[2], [rw, lw], Terminal::OrI);
922922
}
923-
Concrete::Thresh(k, ref subs) => {
924-
let n = subs.len();
923+
Concrete::Thresh(ref thresh) => {
924+
let k = thresh.k();
925+
let n = thresh.n();
925926
let k_over_n = k as f64 / n as f64;
926927

927928
let mut sub_ast = Vec::with_capacity(n);
@@ -931,7 +932,7 @@ where
931932
let mut best_ws = Vec::with_capacity(n);
932933

933934
let mut min_value = (0, f64::INFINITY);
934-
for (i, ast) in subs.iter().enumerate() {
935+
for (i, ast) in thresh.iter().enumerate() {
935936
let sp = sat_prob * k_over_n;
936937
//Expressions must be dissatisfiable
937938
let dp = Some(dissat_prob.unwrap_or(0 as f64) + (1.0 - k_over_n) * sat_prob);
@@ -949,7 +950,7 @@ where
949950
}
950951
sub_ext_data.push(best_es[min_value.0].0);
951952
sub_ast.push(Arc::clone(&best_es[min_value.0].1.ms));
952-
for (i, _ast) in subs.iter().enumerate() {
953+
for (i, _ast) in thresh.iter().enumerate() {
953954
if i != min_value.0 {
954955
sub_ext_data.push(best_ws[i].0);
955956
sub_ast.push(Arc::clone(&best_ws[i].1.ms));
@@ -966,7 +967,7 @@ where
966967
insert_wrap!(ast_ext);
967968
}
968969

969-
let key_vec: Vec<Pk> = subs
970+
let key_vec: Vec<Pk> = thresh
970971
.iter()
971972
.filter_map(|s| {
972973
if let Concrete::Key(ref pk) = s.as_ref() {
@@ -978,16 +979,16 @@ where
978979
.collect();
979980

980981
match Ctx::sig_type() {
981-
SigType::Schnorr if key_vec.len() == subs.len() => {
982+
SigType::Schnorr if key_vec.len() == thresh.n() => {
982983
insert_wrap!(AstElemExt::terminal(Terminal::MultiA(k, key_vec)))
983984
}
984985
SigType::Ecdsa
985-
if key_vec.len() == subs.len() && subs.len() <= MAX_PUBKEYS_PER_MULTISIG =>
986+
if key_vec.len() == thresh.n() && thresh.n() <= MAX_PUBKEYS_PER_MULTISIG =>
986987
{
987988
insert_wrap!(AstElemExt::terminal(Terminal::Multi(k, key_vec)))
988989
}
989-
_ if k == subs.len() => {
990-
let mut it = subs.iter();
990+
_ if k == thresh.n() => {
991+
let mut it = thresh.iter();
991992
let mut policy = it.next().expect("No sub policy in thresh() ?").clone();
992993
policy =
993994
it.fold(policy, |acc, pol| Concrete::And(vec![acc, pol.clone()]).into());
@@ -1157,6 +1158,7 @@ mod tests {
11571158
use super::*;
11581159
use crate::miniscript::{Legacy, Segwitv0, Tap};
11591160
use crate::policy::Liftable;
1161+
use crate::threshold::Threshold;
11601162
use crate::{script_num_size, ToPublicKey};
11611163

11621164
type SPolicy = Concrete<String>;
@@ -1301,19 +1303,19 @@ mod tests {
13011303
let policy: BPolicy = Concrete::Or(vec![
13021304
(
13031305
127,
1304-
Arc::new(Concrete::Thresh(
1306+
Arc::new(Concrete::Thresh(Threshold::new_unchecked(
13051307
3,
13061308
key_pol[0..5].iter().map(|p| (p.clone()).into()).collect(),
1307-
)),
1309+
))),
13081310
),
13091311
(
13101312
1,
13111313
Arc::new(Concrete::And(vec![
13121314
Arc::new(Concrete::Older(Sequence::from_height(10000))),
1313-
Arc::new(Concrete::Thresh(
1315+
Arc::new(Concrete::Thresh(Threshold::new_unchecked(
13141316
2,
13151317
key_pol[5..8].iter().map(|p| (p.clone()).into()).collect(),
1316-
)),
1318+
))),
13171319
])),
13181320
),
13191321
]);
@@ -1430,7 +1432,7 @@ mod tests {
14301432
.iter()
14311433
.map(|pubkey| Arc::new(Concrete::Key(*pubkey)))
14321434
.collect();
1433-
let big_thresh = Concrete::Thresh(*k, pubkeys);
1435+
let big_thresh = Concrete::Thresh(Threshold::new_unchecked(*k, pubkeys));
14341436
let big_thresh_ms: SegwitMiniScript = big_thresh.compile().unwrap();
14351437
if *k == 21 {
14361438
// N * (PUSH + pubkey + CHECKSIGVERIFY)
@@ -1466,8 +1468,8 @@ mod tests {
14661468
.collect();
14671469

14681470
let thresh_res: Result<SegwitMiniScript, _> = Concrete::Or(vec![
1469-
(1, Arc::new(Concrete::Thresh(keys_a.len(), keys_a))),
1470-
(1, Arc::new(Concrete::Thresh(keys_b.len(), keys_b))),
1471+
(1, Arc::new(Concrete::Thresh(Threshold::new_unchecked(keys_a.len(), keys_a)))),
1472+
(1, Arc::new(Concrete::Thresh(Threshold::new_unchecked(keys_b.len(), keys_b)))),
14711473
])
14721474
.compile();
14731475
let script_size = thresh_res.clone().and_then(|m| Ok(m.script_size()));
@@ -1484,7 +1486,8 @@ mod tests {
14841486
.iter()
14851487
.map(|pubkey| Arc::new(Concrete::Key(*pubkey)))
14861488
.collect();
1487-
let thresh_res: Result<SegwitMiniScript, _> = Concrete::Thresh(keys.len(), keys).compile();
1489+
let thresh_res: Result<SegwitMiniScript, _> =
1490+
Concrete::Thresh(Threshold::new_unchecked(keys.len(), keys)).compile();
14881491
let n_elements = thresh_res
14891492
.clone()
14901493
.and_then(|m| Ok(m.max_satisfaction_witness_elements()));
@@ -1505,7 +1508,7 @@ mod tests {
15051508
.map(|pubkey| Arc::new(Concrete::Key(*pubkey)))
15061509
.collect();
15071510
let thresh_res: Result<SegwitMiniScript, _> =
1508-
Concrete::Thresh(keys.len() - 1, keys).compile();
1511+
Concrete::Thresh(Threshold::new_unchecked(keys.len() - 1, keys)).compile();
15091512
let ops_count = thresh_res.clone().and_then(|m| Ok(m.ext.ops.op_count()));
15101513
assert_eq!(
15111514
thresh_res,
@@ -1519,7 +1522,8 @@ mod tests {
15191522
.iter()
15201523
.map(|pubkey| Arc::new(Concrete::Key(*pubkey)))
15211524
.collect();
1522-
let thresh_res = Concrete::Thresh(keys.len() - 1, keys).compile::<Legacy>();
1525+
let thresh_res =
1526+
Concrete::Thresh(Threshold::new_unchecked(keys.len() - 1, keys)).compile::<Legacy>();
15231527
let ops_count = thresh_res.clone().and_then(|m| Ok(m.ext.ops.op_count()));
15241528
assert_eq!(
15251529
thresh_res,

0 commit comments

Comments
 (0)