Skip to content

Commit b5db340

Browse files
committed
sortedmulti: take Thresh as input to constructors
We currently take a k value and a vector as input to the constructor to the SortedMultiVec type, and propagate this out to all the sortedmulti constructors. This means that we have to construct the threshold inside the method and then return errors outward. It's more flexible, though potentially a bit more annoying, to make the user construct the Threshold. Then they can deal with the error. This means that the descriptor constructors *only* return a validation error, which will let us tighten the Result type in a later commit.
1 parent 276cf94 commit b5db340

File tree

4 files changed

+31
-39
lines changed

4 files changed

+31
-39
lines changed

src/descriptor/mod.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ use sync::Arc;
2323

2424
use crate::expression::FromTree as _;
2525
use crate::miniscript::decode::Terminal;
26+
use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
2627
use crate::miniscript::{satisfy, Legacy, Miniscript, Segwitv0};
2728
use crate::plan::{AssetProvider, Plan};
2829
use crate::prelude::*;
2930
use crate::{
3031
expression, hash256, BareCtx, Error, ForEachKey, FromStrKey, MiniscriptKey, ParseError,
31-
Satisfier, ToPublicKey, TranslateErr, Translator,
32+
Satisfier, Threshold, ToPublicKey, TranslateErr, Translator,
3233
};
3334

3435
mod bare;
@@ -223,21 +224,27 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
223224
/// Create a new sh sortedmulti descriptor with threshold `k`
224225
/// and Vec of `pks`.
225226
/// Errors when miniscript exceeds resource limits under p2sh context
226-
pub fn new_sh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
227-
Ok(Descriptor::Sh(Sh::new_sortedmulti(k, pks)?))
227+
pub fn new_sh_sortedmulti(
228+
thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>,
229+
) -> Result<Self, Error> {
230+
Ok(Descriptor::Sh(Sh::new_sortedmulti(thresh)?))
228231
}
229232

230233
/// Create a new sh wrapped wsh sortedmulti descriptor from threshold
231234
/// `k` and Vec of `pks`
232235
/// Errors when miniscript exceeds resource limits under segwit context
233-
pub fn new_sh_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
234-
Ok(Descriptor::Sh(Sh::new_wsh_sortedmulti(k, pks)?))
236+
pub fn new_sh_wsh_sortedmulti(
237+
thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>,
238+
) -> Result<Self, Error> {
239+
Ok(Descriptor::Sh(Sh::new_wsh_sortedmulti(thresh)?))
235240
}
236241

237242
/// Create a new wsh sorted multi descriptor
238243
/// Errors when miniscript exceeds resource limits under p2sh context
239-
pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
240-
Ok(Descriptor::Wsh(Wsh::new_sortedmulti(k, pks)?))
244+
pub fn new_wsh_sortedmulti(
245+
thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>,
246+
) -> Result<Self, Error> {
247+
Ok(Descriptor::Wsh(Wsh::new_sortedmulti(thresh)?))
241248
}
242249

243250
/// Create new tr descriptor

src/descriptor/segwitv0.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ use super::SortedMultiVec;
1414
use crate::descriptor::{write_descriptor, DefiniteDescriptorKey};
1515
use crate::expression::{self, FromTree};
1616
use crate::miniscript::context::{ScriptContext, ScriptContextError};
17+
use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
1718
use crate::miniscript::satisfy::{Placeholder, Satisfaction, Witness};
1819
use crate::plan::AssetProvider;
1920
use crate::policy::{semantic, Liftable};
2021
use crate::prelude::*;
2122
use crate::util::varint_len;
2223
use crate::{
23-
Error, ForEachKey, FromStrKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, ToPublicKey,
24-
TranslateErr, Translator,
24+
Error, ForEachKey, FromStrKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, Threshold,
25+
ToPublicKey, TranslateErr, Translator,
2526
};
2627
/// A Segwitv0 wsh descriptor
2728
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
@@ -45,10 +46,10 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {
4546
}
4647

4748
/// Create a new sortedmulti wsh descriptor
48-
pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
49+
pub fn new_sortedmulti(thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>) -> Result<Self, Error> {
4950
// The context checks will be carried out inside new function for
5051
// sortedMultiVec
51-
Ok(Self { inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?) })
52+
Ok(Self { inner: WshInner::SortedMulti(SortedMultiVec::new(thresh)?) })
5253
}
5354

5455
/// Get the descriptor without the checksum

src/descriptor/sh.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ use super::{SortedMultiVec, Wpkh, Wsh};
1717
use crate::descriptor::{write_descriptor, DefiniteDescriptorKey};
1818
use crate::expression::{self, FromTree};
1919
use crate::miniscript::context::ScriptContext;
20+
use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
2021
use crate::miniscript::satisfy::{Placeholder, Satisfaction};
2122
use crate::plan::AssetProvider;
2223
use crate::policy::{semantic, Liftable};
2324
use crate::prelude::*;
2425
use crate::util::{varint_len, witness_to_scriptsig};
2526
use crate::{
2627
push_opcode_size, Error, ForEachKey, FromStrKey, Legacy, Miniscript, MiniscriptKey, Satisfier,
27-
Segwitv0, ToPublicKey, TranslateErr, Translator,
28+
Segwitv0, Threshold, ToPublicKey, TranslateErr, Translator,
2829
};
2930

3031
/// A Legacy p2sh Descriptor
@@ -125,10 +126,10 @@ impl<Pk: MiniscriptKey> Sh<Pk> {
125126

126127
/// Create a new p2sh sortedmulti descriptor with threshold `k`
127128
/// and Vec of `pks`.
128-
pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
129+
pub fn new_sortedmulti(thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>) -> Result<Self, Error> {
129130
// The context checks will be carried out inside new function for
130131
// sortedMultiVec
131-
Ok(Self { inner: ShInner::SortedMulti(SortedMultiVec::new(k, pks)?) })
132+
Ok(Self { inner: ShInner::SortedMulti(SortedMultiVec::new(thresh)?) })
132133
}
133134

134135
/// Create a new p2sh wrapped wsh descriptor with the raw miniscript
@@ -152,10 +153,12 @@ impl<Pk: MiniscriptKey> Sh<Pk> {
152153

153154
/// Create a new p2sh wrapped wsh sortedmulti descriptor from threshold
154155
/// `k` and Vec of `pks`
155-
pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
156+
pub fn new_wsh_sortedmulti(
157+
thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>,
158+
) -> Result<Self, Error> {
156159
// The context checks will be carried out inside new function for
157160
// sortedMultiVec
158-
Ok(Self { inner: ShInner::Wsh(Wsh::new_sortedmulti(k, pks)?) })
161+
Ok(Self { inner: ShInner::Wsh(Wsh::new_sortedmulti(thresh)?) })
159162
}
160163

161164
/// Create a new p2sh wrapped wpkh from `Pk`

src/descriptor/sortedmulti.rs

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
4949
/// Create a new instance of `SortedMultiVec` given a list of keys and the threshold
5050
///
5151
/// Internally checks all the applicable size limits and pubkey types limitations according to the current `Ctx`.
52-
pub fn new(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
53-
let ret =
54-
Self { inner: Threshold::new(k, pks).map_err(Error::Threshold)?, phantom: PhantomData };
52+
pub fn new(thresh: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>) -> Result<Self, Error> {
53+
let ret = Self { inner: thresh, phantom: PhantomData };
5554
ret.constructor_check()
5655
}
5756

@@ -231,24 +230,6 @@ mod tests {
231230
use super::*;
232231
use crate::miniscript::context::{Legacy, ScriptContextError};
233232

234-
#[test]
235-
fn too_many_pubkeys() {
236-
// Arbitrary 33-byte public key (34 with length prefix).
237-
let pk = PublicKey::from_str(
238-
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
239-
)
240-
.unwrap();
241-
242-
let pks = vec![pk; 1 + MAX_PUBKEYS_PER_MULTISIG];
243-
let res: Result<SortedMultiVec<PublicKey, Legacy>, Error> = SortedMultiVec::new(1, pks);
244-
let error = res.expect_err("constructor should err");
245-
246-
match error {
247-
Error::Threshold(_) => {} // ok
248-
other => panic!("unexpected error: {:?}", other),
249-
}
250-
}
251-
252233
#[test]
253234
fn too_many_pubkeys_for_p2sh() {
254235
// Arbitrary 65-byte public key (66 with length prefix).
@@ -259,8 +240,8 @@ mod tests {
259240

260241
// This is legal for CHECKMULTISIG, but the 8 keys consume the whole 520 bytes
261242
// allowed by P2SH, meaning that the full script goes over the limit.
262-
let pks = vec![pk; 8];
263-
let res: Result<SortedMultiVec<PublicKey, Legacy>, Error> = SortedMultiVec::new(2, pks);
243+
let thresh = Threshold::new(2, vec![pk; 8]).expect("the thresh is ok..");
244+
let res: Result<SortedMultiVec<PublicKey, Legacy>, Error> = SortedMultiVec::new(thresh);
264245
let error = res.expect_err("constructor should err");
265246

266247
match error {

0 commit comments

Comments
 (0)