fn dissatisfy_helper<Pk, Ctx, Sat, F, G>(
        term: &Terminal<Pk, Ctx>,
        stfr: &Sat,
        root_has_sig: bool,
        min_fn: &mut F,
        thresh_fn: &mut G,
    ) -> Self
    where
        Pk: MiniscriptKey + ToPublicKey,
        Ctx: ScriptContext,
        Sat: Satisfier<Pk>,
        F: FnMut(Satisfaction, Satisfaction) -> Satisfaction,
        G: FnMut(usize, &[Arc<Miniscript<Pk, Ctx>>], &Sat, bool, &mut F) -> Satisfaction,
    {
        match *term {
            Terminal::PkK(..) => Satisfaction {
                stack: Witness::push_0(),
                has_sig: false,
            },
            Terminal::PkH(ref pkh) => Satisfaction {
                stack: Witness::combine(Witness::push_0(), Witness::pkh_public_key(stfr, pkh)),
                has_sig: false,
            },
            Terminal::False => Satisfaction {
                stack: Witness::empty(),
                has_sig: false,
            },
            Terminal::True => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::Older(_) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::After(_) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::Sha256(_)
            | Terminal::Hash256(_)
            | Terminal::Ripemd160(_)
            | Terminal::Hash160(_) => Satisfaction {
                stack: Witness::hash_dissatisfaction(),
                has_sig: false,
            },
            Terminal::Alt(ref sub)
            | Terminal::Swap(ref sub)
            | Terminal::Check(ref sub)
            | Terminal::ZeroNotEqual(ref sub) => {
                Self::dissatisfy_helper(&sub.node, stfr, root_has_sig, min_fn, thresh_fn)
            }
            Terminal::DupIf(_) | Terminal::NonZero(_) => Satisfaction {
                stack: Witness::push_0(),
                has_sig: false,
            },
            Terminal::Verify(_) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::AndV(ref v, ref other) => {
                let vsat = Self::satisfy_helper(&v.node, stfr, root_has_sig, min_fn, thresh_fn);
                let odissat =
                    Self::dissatisfy_helper(&other.node, stfr, root_has_sig, min_fn, thresh_fn);
                Satisfaction {
                    stack: Witness::combine(odissat.stack, vsat.stack),
                    has_sig: vsat.has_sig || odissat.has_sig,
                }
            }
            Terminal::AndB(ref l, ref r)
            | Terminal::OrB(ref l, ref r)
            | Terminal::OrD(ref l, ref r)
            | Terminal::AndOr(ref l, _, ref r) => {
                let lnsat = Self::dissatisfy_helper(&l.node, stfr, root_has_sig, min_fn, thresh_fn);
                let rnsat = Self::dissatisfy_helper(&r.node, stfr, root_has_sig, min_fn, thresh_fn);
                Satisfaction {
                    stack: Witness::combine(rnsat.stack, lnsat.stack),
                    has_sig: rnsat.has_sig || lnsat.has_sig,
                }
            }
            Terminal::OrC(..) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::OrI(ref l, ref r) => {
                let lnsat = Self::dissatisfy_helper(&l.node, stfr, root_has_sig, min_fn, thresh_fn);
                let dissat_1 = Satisfaction {
                    stack: Witness::combine(lnsat.stack, Witness::push_1()),
                    has_sig: lnsat.has_sig,
                };

                let rnsat = Self::dissatisfy_helper(&r.node, stfr, root_has_sig, min_fn, thresh_fn);
                let dissat_2 = Satisfaction {
                    stack: Witness::combine(rnsat.stack, Witness::push_0()),
                    has_sig: rnsat.has_sig,
                };

                // Dissatisfactions don't need to non-malleable. Use minimum_mall always
                Satisfaction::minimum_mall(dissat_1, dissat_2)
            }
            Terminal::Thresh(_, ref subs) => Satisfaction {
                stack: subs.iter().fold(Witness::empty(), |acc, sub| {
                    let nsat =
                        Self::dissatisfy_helper(&sub.node, stfr, root_has_sig, min_fn, thresh_fn);
                    assert!(!nsat.has_sig);
                    Witness::combine(nsat.stack, acc)
                }),
                has_sig: false,
            },
            Terminal::Multi(k, _) => Satisfaction {
                stack: Witness::Stack(vec![vec![]; k + 1]),
                has_sig: false,
            },
            Terminal::MultiA(_, ref pks) => Satisfaction {
                stack: Witness::Stack(vec![vec![]; pks.len()]),
                has_sig: false,
            },
        }
    }
// Helper function to produce a dissatisfaction
Helper function to produce a dissatisfaction
Helper function to produce a dissatisfaction
fn dissatisfy_helper<Pk, Ctx, Sat, F, G>(
        term: &Terminal<Pk, Ctx>,
        stfr: &Sat,
        root_has_sig: bool,
        min_fn: &mut F,
        thresh_fn: &mut G,
    ) -> Self
    where
        Pk: MiniscriptKey + ToPublicKey,
        Ctx: ScriptContext,
        Sat: Satisfier<Pk>,
        F: FnMut(Satisfaction, Satisfaction) -> Satisfaction,
        G: FnMut(usize, &[Arc<Miniscript<Pk, Ctx>>], &Sat, bool, &mut F) -> Satisfaction,
    {
        match *term {
            Terminal::PkK(..) => Satisfaction {
                stack: Witness::push_0(),
                has_sig: false,
            },
            Terminal::PkH(ref pkh) => Satisfaction {
                stack: Witness::combine(Witness::push_0(), Witness::pkh_public_key(stfr, pkh)),
                has_sig: false,
            },
            Terminal::False => Satisfaction {
                stack: Witness::empty(),
                has_sig: false,
            },
            Terminal::True => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::Older(_) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::After(_) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::Sha256(_)
            | Terminal::Hash256(_)
            | Terminal::Ripemd160(_)
            | Terminal::Hash160(_) => Satisfaction {
                stack: Witness::hash_dissatisfaction(),
                has_sig: false,
            },
            Terminal::Alt(ref sub)
            | Terminal::Swap(ref sub)
            | Terminal::Check(ref sub)
            | Terminal::ZeroNotEqual(ref sub) => {
                Self::dissatisfy_helper(&sub.node, stfr, root_has_sig, min_fn, thresh_fn)
            }
            Terminal::DupIf(_) | Terminal::NonZero(_) => Satisfaction {
                stack: Witness::push_0(),
                has_sig: false,
            },
            Terminal::Verify(_) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::AndV(ref v, ref other) => {
                let vsat = Self::satisfy_helper(&v.node, stfr, root_has_sig, min_fn, thresh_fn);
                let odissat =
                    Self::dissatisfy_helper(&other.node, stfr, root_has_sig, min_fn, thresh_fn);
                Satisfaction {
                    stack: Witness::combine(odissat.stack, vsat.stack),
                    has_sig: vsat.has_sig || odissat.has_sig,
                }
            }
            Terminal::AndB(ref l, ref r)
            | Terminal::OrB(ref l, ref r)
            | Terminal::OrD(ref l, ref r)
            | Terminal::AndOr(ref l, _, ref r) => {
                let lnsat = Self::dissatisfy_helper(&l.node, stfr, root_has_sig, min_fn, thresh_fn);
                let rnsat = Self::dissatisfy_helper(&r.node, stfr, root_has_sig, min_fn, thresh_fn);
                Satisfaction {
                    stack: Witness::combine(rnsat.stack, lnsat.stack),
                    has_sig: rnsat.has_sig || lnsat.has_sig,
                }
            }
            Terminal::OrC(..) => Satisfaction {
                stack: Witness::Impossible,
                has_sig: false,
            },
            Terminal::OrI(ref l, ref r) => {
                let lnsat = Self::dissatisfy_helper(&l.node, stfr, root_has_sig, min_fn, thresh_fn);
                let dissat_1 = Satisfaction {
                    stack: Witness::combine(lnsat.stack, Witness::push_1()),
                    has_sig: lnsat.has_sig,
                };
                let rnsat = Self::dissatisfy_helper(&r.node, stfr, root_has_sig, min_fn, thresh_fn);
                let dissat_2 = Satisfaction {
                    stack: Witness::combine(rnsat.stack, Witness::push_0()),
                    has_sig: rnsat.has_sig,
                };
                // Dissatisfactions don't need to non-malleable. Use minimum_mall always
                Satisfaction::minimum_mall(dissat_1, dissat_2)
            }
            Terminal::Thresh(_, ref subs) => Satisfaction {
                stack: subs.iter().fold(Witness::empty(), |acc, sub| {
                    let nsat =
                        Self::dissatisfy_helper(&sub.node, stfr, root_has_sig, min_fn, thresh_fn);
                    assert!(!nsat.has_sig);
                    Witness::combine(nsat.stack, acc)
                }),
                has_sig: false,
            },
            Terminal::Multi(k, _) => Satisfaction {
                stack: Witness::Stack(vec![vec![]; k + 1]),
                has_sig: false,
            },
            Terminal::MultiA(_, ref pks) => Satisfaction {
                stack: Witness::Stack(vec![vec![]; pks.len()]),
                has_sig: false,
            },
        }
    }
fn dissatisfy_helper < Pk , Ctx , Sat , F , G > ( term : & Terminal < Pk , Ctx > , stfr : & Sat , root_has_sig : bool , min_fn : & mut F , thresh_fn : & mut G , ) -> Self where Pk : MiniscriptKey + ToPublicKey , Ctx : ScriptContext , Sat : Satisfier < Pk > , F : FnMut ( Satisfaction , Satisfaction ) -> Satisfaction , G : FnMut ( usize , & [ Arc < Miniscript < Pk , Ctx > > ] , & Sat , bool , & mut F ) -> Satisfaction , { match * term { Terminal :: PkK ( .. ) => Satisfaction { stack : Witness :: push_0 ( ) , has_sig : false , } , Terminal :: PkH ( ref pkh ) => Satisfaction { stack : Witness :: combine ( Witness :: push_0 ( ) , Witness :: pkh_public_key ( stfr , pkh ) ) , has_sig : false , } , Terminal :: False => Satisfaction { stack : Witness :: empty ( ) , has_sig : false , } , Terminal :: True => Satisfaction { stack : Witness :: Impossible , has_sig : false , } , Terminal :: Older ( _ ) => Satisfaction { stack : Witness :: Impossible , has_sig : false , } , Terminal :: After ( _ ) => Satisfaction { stack : Witness :: Impossible , has_sig : false , } , Terminal :: Sha256 ( _ ) | Terminal :: Hash256 ( _ ) | Terminal :: Ripemd160 ( _ ) | Terminal :: Hash160 ( _ ) => Satisfaction { stack : Witness :: hash_dissatisfaction ( ) , has_sig : false , } , Terminal :: Alt ( ref sub ) | Terminal :: Swap ( ref sub ) | Terminal :: Check ( ref sub ) | Terminal :: ZeroNotEqual ( ref sub ) => { Self :: dissatisfy_helper ( & sub . node , stfr , root_has_sig , min_fn , thresh_fn ) } Terminal :: DupIf ( _ ) | Terminal :: NonZero ( _ ) => Satisfaction { stack : Witness :: push_0 ( ) , has_sig : false , } , Terminal :: Verify ( _ ) => Satisfaction { stack : Witness :: Impossible , has_sig : false , } , Terminal :: AndV ( ref v , ref other ) => { let vsat = Self :: satisfy_helper ( & v . node , stfr , root_has_sig , min_fn , thresh_fn ) ; let odissat = Self :: dissatisfy_helper ( & other . node , stfr , root_has_sig , min_fn , thresh_fn ) ; Satisfaction { stack : Witness :: combine ( odissat . stack , vsat . stack ) , has_sig : vsat . has_sig || odissat . has_sig , } } Terminal :: AndB ( ref l , ref r ) | Terminal :: OrB ( ref l , ref r ) | Terminal :: OrD ( ref l , ref r ) | Terminal :: AndOr ( ref l , _ , ref r ) => { let lnsat = Self :: dissatisfy_helper ( & l . node , stfr , root_has_sig , min_fn , thresh_fn ) ; let rnsat = Self :: dissatisfy_helper ( & r . node , stfr , root_has_sig , min_fn , thresh_fn ) ; Satisfaction { stack : Witness :: combine ( rnsat . stack , lnsat . stack ) , has_sig : rnsat . has_sig || lnsat . has_sig , } } Terminal :: OrC ( .. ) => Satisfaction { stack : Witness :: Impossible , has_sig : false , } , Terminal :: OrI ( ref l , ref r ) => { let lnsat = Self :: dissatisfy_helper ( & l . node , stfr , root_has_sig , min_fn , thresh_fn ) ; let dissat_1 = Satisfaction { stack : Witness :: combine ( lnsat . stack , Witness :: push_1 ( ) ) , has_sig : lnsat . has_sig , } ; let rnsat = Self :: dissatisfy_helper ( & r . node , stfr , root_has_sig , min_fn , thresh_fn ) ; let dissat_2 = Satisfaction { stack : Witness :: combine ( rnsat . stack , Witness :: push_0 ( ) ) , has_sig : rnsat . has_sig , } ; // Dissatisfactions don't need to non-malleable. Use minimum_mall always Satisfaction :: minimum_mall ( dissat_1 , dissat_2 ) } Terminal :: Thresh ( _ , ref subs ) => Satisfaction { stack : subs . iter ( ) . fold ( Witness :: empty ( ) , | acc , sub | { let nsat = Self :: dissatisfy_helper ( & sub . node , stfr , root_has_sig , min_fn , thresh_fn ) ; assert ! ( nsat has_sig ) ; Witness :: combine ( nsat . stack , acc ) } ) , has_sig : false , } , Terminal :: Multi ( k , _ ) => Satisfaction { stack : Witness :: Stack ( vec ! [ vec [ ] k 1 ] ) , has_sig : false , } , Terminal :: MultiA ( _ , ref pks ) => Satisfaction { stack : Witness :: Stack ( vec ! [ vec [ ] pks len ( ) ] ) , has_sig : false , } , } }
Helper function to produce a dissatisfaction
Helper function to produce a dissatisfaction
term
&Terminal<Pk, Ctx>
stfr
&Sat
root_has_sig
bool
min_fn
&mut F
thresh_fn
&mut G
term
&Terminal<Pk, Ctx>
stfr
&Sat
root_has_sig
bool
min_fn
&mut F
thresh_fn
&mut G