Skip to content

reduce binary bloat by removing generic param from type_check #584

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/miniscript/astelem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("[")?;
if let Ok(type_map) = types::Type::type_check(self, |_| None) {
if let Ok(type_map) = types::Type::type_check(self) {
f.write_str(match type_map.corr.base {
types::Base::B => "B",
types::Base::K => "K",
Expand Down
20 changes: 8 additions & 12 deletions src/miniscript/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ use crate::prelude::*;
use crate::Descriptor;
use crate::{bitcoin, hash256, AbsLockTime, Error, Miniscript, MiniscriptKey, ToPublicKey};

fn return_none<T>(_: usize) -> Option<T> {
None
}

/// Trait for parsing keys from byte slices
pub trait ParseableKey: Sized + ToPublicKey + private::Sealed {
/// Parse a key from slice
Expand Down Expand Up @@ -223,8 +219,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> TerminalStack<Pk, Ctx> {

///reduce, type check and push a 0-arg node
fn reduce0(&mut self, ms: Terminal<Pk, Ctx>) -> Result<(), Error> {
let ty = Type::type_check(&ms, return_none)?;
let ext = ExtData::type_check(&ms, return_none)?;
let ty = Type::type_check(&ms)?;
let ext = ExtData::type_check(&ms)?;
let ms = Miniscript {
node: ms,
ty,
Expand All @@ -244,8 +240,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> TerminalStack<Pk, Ctx> {
let top = self.pop().unwrap();
let wrapped_ms = wrap(Arc::new(top));

let ty = Type::type_check(&wrapped_ms, return_none)?;
let ext = ExtData::type_check(&wrapped_ms, return_none)?;
let ty = Type::type_check(&wrapped_ms)?;
let ext = ExtData::type_check(&wrapped_ms)?;
let ms = Miniscript {
node: wrapped_ms,
ty,
Expand All @@ -267,8 +263,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> TerminalStack<Pk, Ctx> {

let wrapped_ms = wrap(Arc::new(left), Arc::new(right));

let ty = Type::type_check(&wrapped_ms, return_none)?;
let ext = ExtData::type_check(&wrapped_ms, return_none)?;
let ty = Type::type_check(&wrapped_ms)?;
let ext = ExtData::type_check(&wrapped_ms)?;
let ms = Miniscript {
node: wrapped_ms,
ty,
Expand Down Expand Up @@ -556,8 +552,8 @@ pub fn parse<Ctx: ScriptContext>(
let c = term.pop().unwrap();
let wrapped_ms = Terminal::AndOr(Arc::new(a), Arc::new(c), Arc::new(b));

let ty = Type::type_check(&wrapped_ms, return_none)?;
let ext = ExtData::type_check(&wrapped_ms, return_none)?;
let ty = Type::type_check(&wrapped_ms)?;
let ext = ExtData::type_check(&wrapped_ms)?;

term.0.push(Miniscript {
node: wrapped_ms,
Expand Down
6 changes: 3 additions & 3 deletions src/miniscript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
/// Display code of type_check.
pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error> {
let res = Miniscript {
ty: Type::type_check(&t, |_| None)?,
ext: ExtData::type_check(&t, |_| None)?,
ty: Type::type_check(&t)?,
ext: ExtData::type_check(&t)?,
node: t,
phantom: PhantomData,
};
Expand Down Expand Up @@ -269,7 +269,7 @@ impl<Ctx: ScriptContext> Miniscript<Ctx::Key, Ctx> {

let top = decode::parse(&mut iter)?;
Ctx::check_global_validity(&top)?;
let type_check = types::Type::type_check(&top.node, |_| None)?;
let type_check = types::Type::type_check(&top.node)?;
if type_check.corr.base != types::Base::B {
return Err(Error::NonTopLevel(format!("{:?}", top)));
};
Expand Down
18 changes: 13 additions & 5 deletions src/miniscript/types/extra_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,14 +888,22 @@ impl Property for ExtData {
})
}

fn type_check_with_child<Pk, Ctx, C>(
_fragment: &Terminal<Pk, Ctx>,
mut _child: C,
) -> Result<Self, Error<Pk, Ctx>>
where
C: FnMut(usize) -> Self,
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
unreachable!()
}

/// Compute the type of a fragment assuming all the children of
/// Miniscript have been computed already.
fn type_check<Pk, Ctx, C>(
fragment: &Terminal<Pk, Ctx>,
_child: C,
) -> Result<Self, Error<Pk, Ctx>>
fn type_check<Pk, Ctx>(fragment: &Terminal<Pk, Ctx>) -> Result<Self, Error<Pk, Ctx>>
where
C: FnMut(usize) -> Option<Self>,
Ctx: ScriptContext,
Pk: MiniscriptKey,
{
Expand Down
61 changes: 41 additions & 20 deletions src/miniscript/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ pub use self::malleability::{Dissat, Malleability};
use super::ScriptContext;
use crate::{MiniscriptKey, Terminal};

/// None-returning function to help type inference when we need a
/// closure that simply returns `None`
fn return_none<T>(_: usize) -> Option<T> {
None
}

/// Detailed type of a typechecker error
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum ErrorKind {
Expand Down Expand Up @@ -374,20 +368,15 @@ pub trait Property: Sized {
/// Compute the type of a fragment, given a function to look up
/// the types of its children, if available and relevant for the
/// given fragment
fn type_check<Pk, Ctx, C>(
fragment: &Terminal<Pk, Ctx>,
mut child: C,
fn type_check_common<'a, Pk, Ctx, C>(
fragment: &'a Terminal<Pk, Ctx>,
mut get_child: C,
) -> Result<Self, Error<Pk, Ctx>>
where
C: FnMut(usize) -> Option<Self>,
C: FnMut(&'a Terminal<Pk, Ctx>, usize) -> Result<Self, Error<Pk, Ctx>>,
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
let mut get_child = |sub, n| {
child(n)
.map(Ok)
.unwrap_or_else(|| Self::type_check(sub, return_none))
};
let wrap_err = |result: Result<Self, ErrorKind>| {
result.map_err(|kind| Error {
fragment: fragment.clone(),
Expand Down Expand Up @@ -523,6 +512,30 @@ pub trait Property: Sized {
}
ret
}

/// Compute the type of a fragment, given a function to look up
/// the types of its children.
fn type_check_with_child<Pk, Ctx, C>(
fragment: &Terminal<Pk, Ctx>,
mut child: C,
) -> Result<Self, Error<Pk, Ctx>>
where
C: FnMut(usize) -> Self,
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
let get_child = |_sub, n| Ok(child(n));
Self::type_check_common(fragment, get_child)
}

/// Compute the type of a fragment.
fn type_check<Pk, Ctx>(fragment: &Terminal<Pk, Ctx>) -> Result<Self, Error<Pk, Ctx>>
where
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
Self::type_check_common(fragment, |sub, _n| Self::type_check(sub))
}
}

impl Property for Type {
Expand Down Expand Up @@ -767,14 +780,22 @@ impl Property for Type {
})
}

fn type_check_with_child<Pk, Ctx, C>(
_fragment: &Terminal<Pk, Ctx>,
mut _child: C,
) -> Result<Self, Error<Pk, Ctx>>
where
C: FnMut(usize) -> Self,
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
unreachable!()
}

/// Compute the type of a fragment assuming all the children of
/// Miniscript have been computed already.
fn type_check<Pk, Ctx, C>(
fragment: &Terminal<Pk, Ctx>,
_child: C,
) -> Result<Self, Error<Pk, Ctx>>
fn type_check<Pk, Ctx>(fragment: &Terminal<Pk, Ctx>) -> Result<Self, Error<Pk, Ctx>>
where
C: FnMut(usize) -> Option<Self>,
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
Expand Down
24 changes: 12 additions & 12 deletions src/policy/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
fn terminal(ast: Terminal<Pk, Ctx>) -> AstElemExt<Pk, Ctx> {
AstElemExt {
comp_ext_data: CompilerExtData::type_check(&ast, |_| None).unwrap(),
comp_ext_data: CompilerExtData::type_check(&ast).unwrap(),
ms: Arc::new(Miniscript::from_ast(ast).expect("Terminal creation must always succeed")),
}
}
Expand All @@ -491,15 +491,15 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
r: &AstElemExt<Pk, Ctx>,
) -> Result<AstElemExt<Pk, Ctx>, types::Error<Pk, Ctx>> {
let lookup_ext = |n| match n {
0 => Some(l.comp_ext_data),
1 => Some(r.comp_ext_data),
0 => l.comp_ext_data,
1 => r.comp_ext_data,
_ => unreachable!(),
};
//Types and ExtData are already cached and stored in children. So, we can
//type_check without cache. For Compiler extra data, we supply a cache.
let ty = types::Type::type_check(&ast, |_| None)?;
let ext = types::ExtData::type_check(&ast, |_| None)?;
let comp_ext_data = CompilerExtData::type_check(&ast, lookup_ext)?;
let ty = types::Type::type_check(&ast)?;
let ext = types::ExtData::type_check(&ast)?;
let comp_ext_data = CompilerExtData::type_check_with_child(&ast, lookup_ext)?;
Ok(AstElemExt {
ms: Arc::new(Miniscript::from_components_unchecked(ast, ty, ext)),
comp_ext_data,
Expand All @@ -513,16 +513,16 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
c: &AstElemExt<Pk, Ctx>,
) -> Result<AstElemExt<Pk, Ctx>, types::Error<Pk, Ctx>> {
let lookup_ext = |n| match n {
0 => Some(a.comp_ext_data),
1 => Some(b.comp_ext_data),
2 => Some(c.comp_ext_data),
0 => a.comp_ext_data,
1 => b.comp_ext_data,
2 => c.comp_ext_data,
_ => unreachable!(),
};
//Types and ExtData are already cached and stored in children. So, we can
//type_check without cache. For Compiler extra data, we supply a cache.
let ty = types::Type::type_check(&ast, |_| None)?;
let ext = types::ExtData::type_check(&ast, |_| None)?;
let comp_ext_data = CompilerExtData::type_check(&ast, lookup_ext)?;
let ty = types::Type::type_check(&ast)?;
let ext = types::ExtData::type_check(&ast)?;
let comp_ext_data = CompilerExtData::type_check_with_child(&ast, lookup_ext)?;
Ok(AstElemExt {
ms: Arc::new(Miniscript::from_components_unchecked(ast, ty, ext)),
comp_ext_data,
Expand Down