Skip to content

Commit 0ab4959

Browse files
committed
Merge commit '22ac74274d767259b5bb617e6eda0b94a39adf49' into update_2022_10
22ac742 Merge rust-bitcoin/rust-miniscript#473: Fix `max_satisfaction_weight` calculations for taproot.
2 parents b80cca3 + 22ac742 commit 0ab4959

File tree

2 files changed

+35
-25
lines changed

2 files changed

+35
-25
lines changed

examples/taproot.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ fn main() {
117117

118118
// Max Satisfaction Weight for compilation, corresponding to the script-path spend
119119
// `multi_a(2,PUBKEY_1,PUBKEY_2) at taptree depth 1, having
120-
// Max Witness Size = scriptSig len + control_block size + varint(script_size) + script_size +
121-
// varint(max satisfaction elements) + max satisfaction size
122-
// = 4 + 65 + 1 + 70 + 1 + 132
120+
// Max Witness Size = scriptSig len + witnessStack len + varint(control_block_size) +
121+
// control_block size + varint(script_size) + script_size + max_satisfaction_size
122+
// = 4 + 1 + 1 + 65 + 1 + 70 + 132 = 274
123123
let max_sat_wt = real_desc.max_satisfaction_weight().unwrap();
124-
assert_eq!(max_sat_wt, 273);
124+
assert_eq!(max_sat_wt, 274);
125125

126126
// Compute the bitcoin address and check if it matches
127127
let addr = real_desc

src/descriptor/tr.rs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -285,27 +285,37 @@ impl<Pk: MiniscriptKey, Ext: Extension> Tr<Pk, Ext> {
285285
/// # Errors
286286
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
287287
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
288-
let mut max_wieght = Some(65);
289-
for (depth, ms) in self.iter_scripts() {
290-
let script_size = ms.script_size();
291-
let max_sat_elems = match ms.max_satisfaction_witness_elements() {
292-
Ok(elem) => elem,
293-
Err(..) => continue,
294-
};
295-
let max_sat_size = match ms.max_satisfaction_size() {
296-
Ok(sz) => sz,
297-
Err(..) => continue,
298-
};
299-
let control_block_sz = control_block_len(depth);
300-
let wit_size = 4 + // scriptSig len byte
301-
control_block_sz + // first element control block
302-
varint_len(script_size) +
303-
script_size + // second element script len with prefix
304-
varint_len(max_sat_elems) +
305-
max_sat_size; // witness
306-
max_wieght = cmp::max(max_wieght, Some(wit_size));
307-
}
308-
max_wieght.ok_or(Error::ImpossibleSatisfaction)
288+
let tree = match self.taptree() {
289+
// key spend path:
290+
// scriptSigLen(4) + stackLen(1) + stack[Sig]Len(1) + stack[Sig](65)
291+
None => return Ok(4 + 1 + 1 + 65),
292+
// script path spend..
293+
Some(tree) => tree,
294+
};
295+
296+
tree.iter()
297+
.filter_map(|(depth, ms)| {
298+
let script_size = ms.script_size();
299+
let max_sat_elems = ms.max_satisfaction_witness_elements().ok()?;
300+
let max_sat_size = ms.max_satisfaction_size().ok()?;
301+
let control_block_size = control_block_len(depth);
302+
Some(
303+
// scriptSig len byte
304+
4 +
305+
// witness field stack len (+2 for control block & script)
306+
varint_len(max_sat_elems + 2) +
307+
// size of elements to satisfy script
308+
max_sat_size +
309+
// second to last element: script
310+
varint_len(script_size) +
311+
script_size +
312+
// last element: control block
313+
varint_len(control_block_size) +
314+
control_block_size,
315+
)
316+
})
317+
.max()
318+
.ok_or(Error::ImpossibleSatisfaction)
309319
}
310320
}
311321

0 commit comments

Comments
 (0)