Skip to content

Commit d858ffc

Browse files
committed
miniscript: remove recursion from script_size
As usual, we remove a method of the same name from `Terminal`, which is a breaking change.
1 parent 8c32a19 commit d858ffc

File tree

2 files changed

+51
-64
lines changed

2 files changed

+51
-64
lines changed

src/miniscript/astelem.rs

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ use crate::miniscript::ScriptContext;
2121
use crate::prelude::*;
2222
use crate::util::MsKeyBuilder;
2323
use crate::{
24-
errstr, expression, script_num_size, AbsLockTime, Error, Miniscript, MiniscriptKey, Terminal,
25-
ToPublicKey,
24+
errstr, expression, AbsLockTime, Error, Miniscript, MiniscriptKey, Terminal, ToPublicKey,
2625
};
2726

2827
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
@@ -665,64 +664,4 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
665664
}
666665
}
667666
}
668-
669-
/// Size, in bytes of the script-pubkey. If this Miniscript is used outside
670-
/// of segwit (e.g. in a bare or P2SH descriptor), this quantity should be
671-
/// multiplied by 4 to compute the weight.
672-
///
673-
/// In general, it is not recommended to use this function directly, but
674-
/// to instead call the corresponding function on a `Descriptor`, which
675-
/// will handle the segwit/non-segwit technicalities for you.
676-
pub fn script_size(&self) -> usize {
677-
match *self {
678-
Terminal::PkK(ref pk) => Ctx::pk_len(pk),
679-
Terminal::PkH(..) | Terminal::RawPkH(..) => 24,
680-
Terminal::After(n) => script_num_size(n.to_consensus_u32() as usize) + 1,
681-
Terminal::Older(n) => script_num_size(n.to_consensus_u32() as usize) + 1,
682-
Terminal::Sha256(..) => 33 + 6,
683-
Terminal::Hash256(..) => 33 + 6,
684-
Terminal::Ripemd160(..) => 21 + 6,
685-
Terminal::Hash160(..) => 21 + 6,
686-
Terminal::True => 1,
687-
Terminal::False => 1,
688-
Terminal::Alt(ref sub) => sub.node.script_size() + 2,
689-
Terminal::Swap(ref sub) => sub.node.script_size() + 1,
690-
Terminal::Check(ref sub) => sub.node.script_size() + 1,
691-
Terminal::DupIf(ref sub) => sub.node.script_size() + 3,
692-
Terminal::Verify(ref sub) => {
693-
sub.node.script_size() + usize::from(!sub.ext.has_free_verify)
694-
}
695-
Terminal::NonZero(ref sub) => sub.node.script_size() + 4,
696-
Terminal::ZeroNotEqual(ref sub) => sub.node.script_size() + 1,
697-
Terminal::AndV(ref l, ref r) => l.node.script_size() + r.node.script_size(),
698-
Terminal::AndB(ref l, ref r) => l.node.script_size() + r.node.script_size() + 1,
699-
Terminal::AndOr(ref a, ref b, ref c) => {
700-
a.node.script_size() + b.node.script_size() + c.node.script_size() + 3
701-
}
702-
Terminal::OrB(ref l, ref r) => l.node.script_size() + r.node.script_size() + 1,
703-
Terminal::OrD(ref l, ref r) => l.node.script_size() + r.node.script_size() + 3,
704-
Terminal::OrC(ref l, ref r) => l.node.script_size() + r.node.script_size() + 2,
705-
Terminal::OrI(ref l, ref r) => l.node.script_size() + r.node.script_size() + 3,
706-
Terminal::Thresh(k, ref subs) => {
707-
assert!(!subs.is_empty(), "threshold must be nonempty");
708-
script_num_size(k) // k
709-
+ 1 // EQUAL
710-
+ subs.iter().map(|s| s.node.script_size()).sum::<usize>()
711-
+ subs.len() // ADD
712-
- 1 // no ADD on first element
713-
}
714-
Terminal::Multi(k, ref pks) => {
715-
script_num_size(k)
716-
+ 1
717-
+ script_num_size(pks.len())
718-
+ pks.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>()
719-
}
720-
Terminal::MultiA(k, ref pks) => {
721-
script_num_size(k)
722-
+ 1 // NUMEQUAL
723-
+ pks.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>() // n keys
724-
+ pks.len() // n times CHECKSIGADD
725-
}
726-
}
727-
}
728667
}

src/miniscript/mod.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use self::analyzable::ExtParams;
2424
pub use self::context::{BareCtx, Legacy, Segwitv0, Tap};
2525
use crate::iter::TreeLike;
2626
use crate::prelude::*;
27-
use crate::TranslateErr;
27+
use crate::{script_num_size, TranslateErr};
2828

2929
pub mod analyzable;
3030
pub mod astelem;
@@ -259,7 +259,55 @@ where
259259
/// to instead call the corresponding function on a `Descriptor`, which
260260
/// will handle the segwit/non-segwit technicalities for you.
261261
pub fn script_size(&self) -> usize {
262-
self.node.script_size()
262+
let mut len = 0;
263+
for ms in self.pre_order_iter() {
264+
len += match ms.node {
265+
Terminal::PkK(ref pk) => Ctx::pk_len(pk),
266+
Terminal::PkH(..) | Terminal::RawPkH(..) => 24,
267+
Terminal::After(n) => script_num_size(n.to_consensus_u32() as usize) + 1,
268+
Terminal::Older(n) => script_num_size(n.to_consensus_u32() as usize) + 1,
269+
Terminal::Sha256(..) => 33 + 6,
270+
Terminal::Hash256(..) => 33 + 6,
271+
Terminal::Ripemd160(..) => 21 + 6,
272+
Terminal::Hash160(..) => 21 + 6,
273+
Terminal::True => 1,
274+
Terminal::False => 1,
275+
Terminal::Alt(..) => 2,
276+
Terminal::Swap(..) => 1,
277+
Terminal::Check(..) => 1,
278+
Terminal::DupIf(..) => 3,
279+
Terminal::Verify(ref sub) => usize::from(!sub.ext.has_free_verify),
280+
Terminal::NonZero(..) => 4,
281+
Terminal::ZeroNotEqual(..) => 1,
282+
Terminal::AndV(..) => 0,
283+
Terminal::AndB(..) => 1,
284+
Terminal::AndOr(..) => 3,
285+
Terminal::OrB(..) => 1,
286+
Terminal::OrD(..) => 3,
287+
Terminal::OrC(..) => 2,
288+
Terminal::OrI(..) => 3,
289+
Terminal::Thresh(k, ref subs) => {
290+
assert!(!subs.is_empty(), "threshold must be nonempty");
291+
script_num_size(k) // k
292+
+ 1 // EQUAL
293+
+ subs.len() // ADD
294+
- 1 // no ADD on first element
295+
}
296+
Terminal::Multi(k, ref pks) => {
297+
script_num_size(k)
298+
+ 1
299+
+ script_num_size(pks.len())
300+
+ pks.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>()
301+
}
302+
Terminal::MultiA(k, ref pks) => {
303+
script_num_size(k)
304+
+ 1 // NUMEQUAL
305+
+ pks.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>() // n keys
306+
+ pks.len() // n times CHECKSIGADD
307+
}
308+
}
309+
}
310+
len
263311
}
264312
}
265313

0 commit comments

Comments
 (0)