Skip to content

Commit 7f2a531

Browse files
committed
Move max_satisfaction_weight out of DescriptorTrait
In preparation for removing the `DescriptorTrait` move `max_satasfication_weight` to each individual descriptor.
1 parent 8b773e6 commit 7f2a531

File tree

6 files changed

+138
-90
lines changed

6 files changed

+138
-90
lines changed

src/descriptor/bare.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ impl<Pk: MiniscriptKey> Bare<Pk> {
6767
self.ms.sanity_check()?;
6868
Ok(())
6969
}
70+
71+
/// Computes an upper bound on the weight of a satisfying witness to the
72+
/// transaction.
73+
///
74+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
75+
/// sighash suffix. Includes the weight of the VarInts encoding the
76+
/// scriptSig and witness stack length.
77+
///
78+
/// # Errors
79+
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
80+
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
81+
let scriptsig_len = self.ms.max_satisfaction_size()?;
82+
Ok(4 * (varint_len(scriptsig_len) + scriptsig_len))
83+
}
7084
}
7185

7286
impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> {
@@ -158,11 +172,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
158172
let witness = vec![];
159173
Ok((witness, script_sig))
160174
}
161-
162-
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
163-
let scriptsig_len = self.ms.max_satisfaction_size()?;
164-
Ok(4 * (varint_len(scriptsig_len) + scriptsig_len))
165-
}
166175
}
167176

168177
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Bare<Pk> {
@@ -221,6 +230,18 @@ impl<Pk: MiniscriptKey> Pkh<Pk> {
221230
}
222231
}
223232

233+
impl<Pk: MiniscriptKey> Pkh<Pk> {
234+
/// Computes an upper bound on the weight of a satisfying witness to the
235+
/// transaction.
236+
///
237+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
238+
/// sighash suffix. Includes the weight of the VarInts encoding the
239+
/// scriptSig and witness stack length.
240+
pub fn max_satisfaction_weight(&self) -> usize {
241+
4 * (1 + 73 + BareCtx::pk_len(&self.pk))
242+
}
243+
}
244+
224245
impl<Pk: MiniscriptKey + ToPublicKey> Pkh<Pk> {
225246
/// Obtains the corresponding script pubkey for this descriptor.
226247
pub fn script_pubkey(&self) -> Script {
@@ -328,10 +349,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
328349
{
329350
self.get_satisfaction(satisfier)
330351
}
331-
332-
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
333-
Ok(4 * (1 + 73 + BareCtx::pk_len(&self.pk)))
334-
}
335352
}
336353

337354
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Pkh<Pk> {

src/descriptor/mod.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,6 @@ pub trait DescriptorTrait<Pk: MiniscriptKey> {
109109
txin.script_sig = script_sig;
110110
Ok(())
111111
}
112-
113-
/// Computes an upper bound on the weight of a satisfying witness to the
114-
/// transaction. Assumes all ec-signatures are 73 bytes, including push opcode
115-
/// and sighash suffix. Includes the weight of the VarInts encoding the
116-
/// scriptSig and witness stack length.
117-
/// Returns Error when the descriptor is impossible to safisfy (ex: sh(OP_FALSE))
118-
fn max_satisfaction_weight(&self) -> Result<usize, Error>;
119112
}
120113

121114
/// Script descriptor
@@ -541,14 +534,19 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
541534
}
542535

543536
/// Computes an upper bound on the weight of a satisfying witness to the
544-
/// transaction. Assumes all signatures are 73 bytes, including push opcode
545-
/// and sighash suffix. Includes the weight of the VarInts encoding the
537+
/// transaction.
538+
///
539+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
540+
/// sighash suffix. Includes the weight of the VarInts encoding the
546541
/// scriptSig and witness stack length.
542+
///
543+
/// # Errors
544+
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
547545
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
548546
match *self {
549547
Descriptor::Bare(ref bare) => bare.max_satisfaction_weight(),
550-
Descriptor::Pkh(ref pkh) => pkh.max_satisfaction_weight(),
551-
Descriptor::Wpkh(ref wpkh) => wpkh.max_satisfaction_weight(),
548+
Descriptor::Pkh(ref pkh) => Ok(pkh.max_satisfaction_weight()),
549+
Descriptor::Wpkh(ref wpkh) => Ok(wpkh.max_satisfaction_weight()),
552550
Descriptor::Wsh(ref wsh) => wsh.max_satisfaction_weight(),
553551
Descriptor::Sh(ref sh) => sh.max_satisfaction_weight(),
554552
Descriptor::Tr(ref tr) => tr.max_satisfaction_weight(),

src/descriptor/segwitv0.rs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,35 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {
8585
}
8686
Ok(())
8787
}
88+
89+
/// Computes an upper bound on the weight of a satisfying witness to the
90+
/// transaction.
91+
///
92+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
93+
/// sighash suffix. Includes the weight of the VarInts encoding the
94+
/// scriptSig and witness stack length.
95+
///
96+
/// # Errors
97+
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
98+
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
99+
let (script_size, max_sat_elems, max_sat_size) = match self.inner {
100+
WshInner::SortedMulti(ref smv) => (
101+
smv.script_size(),
102+
smv.max_satisfaction_witness_elements(),
103+
smv.max_satisfaction_size(),
104+
),
105+
WshInner::Ms(ref ms) => (
106+
ms.script_size(),
107+
ms.max_satisfaction_witness_elements()?,
108+
ms.max_satisfaction_size()?,
109+
),
110+
};
111+
Ok(4 + // scriptSig length byte
112+
varint_len(script_size) +
113+
script_size +
114+
varint_len(max_sat_elems) +
115+
max_sat_size)
116+
}
88117
}
89118

90119
impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
@@ -224,26 +253,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wsh<Pk> {
224253
let script_sig = Script::new();
225254
Ok((witness, script_sig))
226255
}
227-
228-
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
229-
let (script_size, max_sat_elems, max_sat_size) = match self.inner {
230-
WshInner::SortedMulti(ref smv) => (
231-
smv.script_size(),
232-
smv.max_satisfaction_witness_elements(),
233-
smv.max_satisfaction_size(),
234-
),
235-
WshInner::Ms(ref ms) => (
236-
ms.script_size(),
237-
ms.max_satisfaction_witness_elements()?,
238-
ms.max_satisfaction_size()?,
239-
),
240-
};
241-
Ok(4 + // scriptSig length byte
242-
varint_len(script_size) +
243-
script_size +
244-
varint_len(max_sat_elems) +
245-
max_sat_size)
246-
}
247256
}
248257

249258
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
@@ -329,6 +338,16 @@ impl<Pk: MiniscriptKey> Wpkh<Pk> {
329338
Ok(())
330339
}
331340
}
341+
342+
/// Computes an upper bound on the weight of a satisfying witness to the
343+
/// transaction.
344+
///
345+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
346+
/// sighash suffix. Includes the weight of the VarInts encoding the
347+
/// scriptSig and witness stack length.
348+
pub fn max_satisfaction_weight(&self) -> usize {
349+
4 + 1 + 73 + Segwitv0::pk_len(&self.pk)
350+
}
332351
}
333352

334353
impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
@@ -442,10 +461,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wpkh<Pk> {
442461
{
443462
self.get_satisfaction(satisfier)
444463
}
445-
446-
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
447-
Ok(4 + 1 + 73 + Segwitv0::pk_len(&self.pk))
448-
}
449464
}
450465

451466
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {

src/descriptor/sh.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,36 @@ impl<Pk: MiniscriptKey> Sh<Pk> {
216216
}
217217
Ok(())
218218
}
219+
220+
/// Computes an upper bound on the weight of a satisfying witness to the
221+
/// transaction.
222+
///
223+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
224+
/// sighash suffix. Includes the weight of the VarInts encoding the
225+
/// scriptSig and witness stack length.
226+
///
227+
/// # Errors
228+
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
229+
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
230+
Ok(match self.inner {
231+
// add weighted script sig, len byte stays the same
232+
ShInner::Wsh(ref wsh) => 4 * 35 + wsh.max_satisfaction_weight()?,
233+
ShInner::SortedMulti(ref smv) => {
234+
let ss = smv.script_size();
235+
let ps = push_opcode_size(ss);
236+
let scriptsig_len = ps + ss + smv.max_satisfaction_size();
237+
4 * (varint_len(scriptsig_len) + scriptsig_len)
238+
}
239+
// add weighted script sig, len byte stays the same
240+
ShInner::Wpkh(ref wpkh) => 4 * 23 + wpkh.max_satisfaction_weight(),
241+
ShInner::Ms(ref ms) => {
242+
let ss = ms.script_size();
243+
let ps = push_opcode_size(ss);
244+
let scriptsig_len = ps + ss + ms.max_satisfaction_size()?;
245+
4 * (varint_len(scriptsig_len) + scriptsig_len)
246+
}
247+
})
248+
}
219249
}
220250

221251
impl<Pk: MiniscriptKey + ToPublicKey> Sh<Pk> {
@@ -352,27 +382,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Sh<Pk> {
352382
_ => self.get_satisfaction(satisfier),
353383
}
354384
}
355-
356-
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
357-
Ok(match self.inner {
358-
// add weighted script sig, len byte stays the same
359-
ShInner::Wsh(ref wsh) => 4 * 35 + wsh.max_satisfaction_weight()?,
360-
ShInner::SortedMulti(ref smv) => {
361-
let ss = smv.script_size();
362-
let ps = push_opcode_size(ss);
363-
let scriptsig_len = ps + ss + smv.max_satisfaction_size();
364-
4 * (varint_len(scriptsig_len) + scriptsig_len)
365-
}
366-
// add weighted script sig, len byte stays the same
367-
ShInner::Wpkh(ref wpkh) => 4 * 23 + wpkh.max_satisfaction_weight()?,
368-
ShInner::Ms(ref ms) => {
369-
let ss = ms.script_size();
370-
let ps = push_opcode_size(ss);
371-
let scriptsig_len = ps + ss + ms.max_satisfaction_size()?;
372-
4 * (varint_len(scriptsig_len) + scriptsig_len)
373-
}
374-
})
375-
}
376385
}
377386

378387
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Sh<Pk> {

src/descriptor/tr.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,39 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
279279
}
280280
Ok(())
281281
}
282+
283+
/// Computes an upper bound on the weight of a satisfying witness to the
284+
/// transaction.
285+
///
286+
/// Assumes all ec-signatures are 73 bytes, including push opcode and
287+
/// sighash suffix. Includes the weight of the VarInts encoding the
288+
/// scriptSig and witness stack length.
289+
///
290+
/// # Errors
291+
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
292+
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
293+
let mut max_wieght = Some(65);
294+
for (depth, ms) in self.iter_scripts() {
295+
let script_size = ms.script_size();
296+
let max_sat_elems = match ms.max_satisfaction_witness_elements() {
297+
Ok(elem) => elem,
298+
Err(..) => continue,
299+
};
300+
let max_sat_size = match ms.max_satisfaction_size() {
301+
Ok(sz) => sz,
302+
Err(..) => continue,
303+
};
304+
let control_block_sz = control_block_len(depth);
305+
let wit_size = 4 + // scriptSig len byte
306+
control_block_sz + // first element control block
307+
varint_len(script_size) +
308+
script_size + // second element script len with prefix
309+
varint_len(max_sat_elems) +
310+
max_sat_size; // witness
311+
max_wieght = cmp::max(max_wieght, Some(wit_size));
312+
}
313+
max_wieght.ok_or(Error::ImpossibleSatisfaction)
314+
}
282315
}
283316

284317
impl<Pk: MiniscriptKey + ToPublicKey> Tr<Pk> {
@@ -574,30 +607,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Tr<Pk> {
574607
{
575608
best_tap_spend(&self, satisfier, true /* allow_mall */)
576609
}
577-
578-
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
579-
let mut max_wieght = Some(65);
580-
for (depth, ms) in self.iter_scripts() {
581-
let script_size = ms.script_size();
582-
let max_sat_elems = match ms.max_satisfaction_witness_elements() {
583-
Ok(elem) => elem,
584-
Err(..) => continue,
585-
};
586-
let max_sat_size = match ms.max_satisfaction_size() {
587-
Ok(sz) => sz,
588-
Err(..) => continue,
589-
};
590-
let control_block_sz = control_block_len(depth);
591-
let wit_size = 4 + // scriptSig len byte
592-
control_block_sz + // first element control block
593-
varint_len(script_size) +
594-
script_size + // second element script len with prefix
595-
varint_len(max_sat_elems) +
596-
max_sat_size; // witness
597-
max_wieght = cmp::max(max_wieght, Some(wit_size));
598-
}
599-
max_wieght.ok_or(Error::ImpossibleSatisfaction)
600-
}
601610
}
602611

603612
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Tr<Pk> {

src/miniscript/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
254254
/// 1, since `OP_1` is available in scriptSigs.
255255
///
256256
/// In general, it is not recommended to use this function directly, but
257-
/// to instead call the corresponding function on a `Descriptor`, which
257+
/// to instead call `max_satisfaction_weight` on a descriptor, which
258258
/// will handle the segwit/non-segwit technicalities for you.
259259
///
260260
/// All signatures are assumed to be 73 bytes in size, including the

0 commit comments

Comments
 (0)