miniscript/miniscript/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! # Abstract Syntax Tree
4//!
5//! Defines a variety of data structures for describing Miniscript, a subset of
6//! Bitcoin Script which can be efficiently parsed and serialized from Script,
7//! and from which it is easy to extract data needed to construct witnesses.
8//!
9//! Users of the library in general will only need to use the structures exposed
10//! from the top level of this module; however for people wanting to do advanced
11//! things, the submodules are public as well which provide visibility into the
12//! components of the AST.
13//!
14
15use core::{fmt, hash, str};
16
17use bitcoin::hashes::hash160;
18use bitcoin::script;
19use bitcoin::taproot::{LeafVersion, TapLeafHash};
20
21use self::analyzable::ExtParams;
22pub use self::context::{BareCtx, Legacy, Segwitv0, Tap};
23use crate::iter::TreeLike;
24use crate::prelude::*;
25use crate::{script_num_size, TranslateErr};
26
27pub mod analyzable;
28pub mod astelem;
29pub(crate) mod context;
30pub mod decode;
31pub mod iter;
32pub mod lex;
33pub mod limits;
34pub mod satisfy;
35pub mod types;
36
37use core::cmp;
38
39use sync::Arc;
40
41use self::lex::{lex, TokenIter};
42pub use crate::miniscript::context::ScriptContext;
43use crate::miniscript::decode::Terminal;
44use crate::{
45    expression, plan, Error, ForEachKey, FromStrKey, MiniscriptKey, ToPublicKey, TranslatePk,
46    Translator,
47};
48#[cfg(test)]
49mod ms_tests;
50
51mod private {
52    use core::marker::PhantomData;
53
54    use super::types::{ExtData, Type};
55    pub use crate::miniscript::context::ScriptContext;
56    use crate::miniscript::types;
57    use crate::{Error, MiniscriptKey, Terminal, MAX_RECURSION_DEPTH};
58
59    /// The top-level miniscript abstract syntax tree (AST).
60    #[derive(Clone)]
61    pub struct Miniscript<Pk: MiniscriptKey, Ctx: ScriptContext> {
62        /// A node in the AST.
63        pub node: Terminal<Pk, Ctx>,
64        /// The correctness and malleability type information for the AST node.
65        pub ty: types::Type,
66        /// Additional information helpful for extra analysis.
67        pub ext: types::extra_props::ExtData,
68        /// Context PhantomData. Only accessible inside this crate
69        phantom: PhantomData<Ctx>,
70    }
71    impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
72        /// The `1` combinator.
73        pub const TRUE: Self = Miniscript {
74            node: Terminal::True,
75            ty: types::Type::TRUE,
76            ext: types::extra_props::ExtData::TRUE,
77            phantom: PhantomData,
78        };
79
80        /// The `0` combinator.
81        pub const FALSE: Self = Miniscript {
82            node: Terminal::False,
83            ty: types::Type::FALSE,
84            ext: types::extra_props::ExtData::FALSE,
85            phantom: PhantomData,
86        };
87
88        /// Add type information(Type and Extdata) to Miniscript based on
89        /// `AstElem` fragment. Dependent on display and clone because of Error
90        /// Display code of type_check.
91        pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error> {
92            let res = Miniscript {
93                ty: Type::type_check(&t)?,
94                ext: ExtData::type_check(&t)?,
95                node: t,
96                phantom: PhantomData,
97            };
98            // TODO: This recursion depth is based on segwitv0.
99            // We can relax this in tapscript, but this should be good for almost
100            // all practical cases and we can revisit this if needed.
101            // casting to u32 is safe because tree_height will never go more than u32::MAX
102            if (res.ext.tree_height as u32) > MAX_RECURSION_DEPTH {
103                return Err(Error::MaxRecursiveDepthExceeded);
104            }
105            Ctx::check_global_consensus_validity(&res)?;
106            Ok(res)
107        }
108
109        /// Create a new `Miniscript` from a `Terminal` node and a `Type` annotation
110        /// This does not check the typing rules. The user is responsible for ensuring
111        /// that the type provided is correct.
112        ///
113        /// You should almost always use `Miniscript::from_ast` instead of this function.
114        pub fn from_components_unchecked(
115            node: Terminal<Pk, Ctx>,
116            ty: types::Type,
117            ext: types::extra_props::ExtData,
118        ) -> Miniscript<Pk, Ctx> {
119            Miniscript { node, ty, ext, phantom: PhantomData }
120        }
121    }
122}
123
124pub use private::Miniscript;
125
126impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
127    /// Extracts the `AstElem` representing the root of the miniscript
128    pub fn into_inner(self) -> Terminal<Pk, Ctx> { self.node }
129
130    /// Get a reference to the inner `AstElem` representing the root of miniscript
131    pub fn as_inner(&self) -> &Terminal<Pk, Ctx> { &self.node }
132
133    /// Encode as a Bitcoin script
134    pub fn encode(&self) -> script::ScriptBuf
135    where
136        Pk: ToPublicKey,
137    {
138        self.node.encode(script::Builder::new()).into_script()
139    }
140
141    /// Size, in bytes of the script-pubkey. If this Miniscript is used outside
142    /// of segwit (e.g. in a bare or P2SH descriptor), this quantity should be
143    /// multiplied by 4 to compute the weight.
144    ///
145    /// In general, it is not recommended to use this function directly, but
146    /// to instead call the corresponding function on a `Descriptor`, which
147    /// will handle the segwit/non-segwit technicalities for you.
148    pub fn script_size(&self) -> usize {
149        use Terminal::*;
150
151        let mut len = 0;
152        for ms in self.pre_order_iter() {
153            len += match ms.node {
154                AndV(..) => 0,
155                True | False | Swap(..) | Check(..) | ZeroNotEqual(..) | AndB(..) | OrB(..) => 1,
156                Alt(..) | OrC(..) => 2,
157                DupIf(..) | AndOr(..) | OrD(..) | OrI(..) => 3,
158                NonZero(..) => 4,
159                PkH(..) | RawPkH(..) => 24,
160                Ripemd160(..) | Hash160(..) => 21 + 6,
161                Sha256(..) | Hash256(..) => 33 + 6,
162
163                Terminal::PkK(ref pk) => Ctx::pk_len(pk),
164                Terminal::After(n) => script_num_size(n.to_consensus_u32() as usize) + 1,
165                Terminal::Older(n) => script_num_size(n.to_consensus_u32() as usize) + 1,
166                Terminal::Verify(ref sub) => usize::from(!sub.ext.has_free_verify),
167                Terminal::Thresh(ref thresh) => {
168                    script_num_size(thresh.k()) // k
169                        + 1 // EQUAL
170                        + thresh.n() // ADD
171                        - 1 // no ADD on first element
172                }
173                Terminal::Multi(ref thresh) => {
174                    script_num_size(thresh.k())
175                        + 1
176                        + script_num_size(thresh.n())
177                        + thresh.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>()
178                }
179                Terminal::MultiA(ref thresh) => {
180                    script_num_size(thresh.k())
181                        + 1 // NUMEQUAL
182                        + thresh.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>() // n keys
183                        + thresh.n() // n times CHECKSIGADD
184                }
185            }
186        }
187        len
188    }
189
190    /// Maximum number of witness elements used to satisfy the Miniscript
191    /// fragment, including the witness script itself. Used to estimate
192    /// the weight of the `VarInt` that specifies this number in a serialized
193    /// transaction.
194    ///
195    /// This function may returns Error when the Miniscript is
196    /// impossible to satisfy
197    pub fn max_satisfaction_witness_elements(&self) -> Result<usize, Error> {
198        self.ext
199            .stack_elem_count_sat
200            .map(|x| x + 1)
201            .ok_or(Error::ImpossibleSatisfaction)
202    }
203
204    /// Maximum size, in bytes, of a satisfying witness. For Segwit outputs
205    /// `one_cost` should be set to 2, since the number `1` requires two
206    /// bytes to encode. For non-segwit outputs `one_cost` should be set to
207    /// 1, since `OP_1` is available in scriptSigs.
208    ///
209    /// In general, it is not recommended to use this function directly, but
210    /// to instead call the corresponding function on a `Descriptor`, which
211    /// will handle the segwit/non-segwit technicalities for you.
212    ///
213    /// All signatures are assumed to be 73 bytes in size, including the
214    /// length prefix (segwit) or push opcode (pre-segwit) and sighash
215    /// postfix.
216    pub fn max_satisfaction_size(&self) -> Result<usize, Error> {
217        Ctx::max_satisfaction_size(self).ok_or(Error::ImpossibleSatisfaction)
218    }
219
220    /// Attempt to produce non-malleable satisfying witness for the
221    /// witness script represented by the parse tree
222    pub fn satisfy<S: satisfy::Satisfier<Pk>>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error>
223    where
224        Pk: ToPublicKey,
225    {
226        // Only satisfactions for default versions (0xc0) are allowed.
227        let leaf_hash = TapLeafHash::from_script(&self.encode(), LeafVersion::TapScript);
228        let satisfaction =
229            satisfy::Satisfaction::satisfy(&self.node, &satisfier, self.ty.mall.safe, &leaf_hash);
230        self._satisfy(satisfaction)
231    }
232
233    /// Attempt to produce a malleable satisfying witness for the
234    /// witness script represented by the parse tree
235    pub fn satisfy_malleable<S: satisfy::Satisfier<Pk>>(
236        &self,
237        satisfier: S,
238    ) -> Result<Vec<Vec<u8>>, Error>
239    where
240        Pk: ToPublicKey,
241    {
242        let leaf_hash = TapLeafHash::from_script(&self.encode(), LeafVersion::TapScript);
243        let satisfaction = satisfy::Satisfaction::satisfy_mall(
244            &self.node,
245            &satisfier,
246            self.ty.mall.safe,
247            &leaf_hash,
248        );
249        self._satisfy(satisfaction)
250    }
251
252    fn _satisfy(&self, satisfaction: satisfy::Satisfaction<Vec<u8>>) -> Result<Vec<Vec<u8>>, Error>
253    where
254        Pk: ToPublicKey,
255    {
256        match satisfaction.stack {
257            satisfy::Witness::Stack(stack) => {
258                Ctx::check_witness(&stack)?;
259                Ok(stack)
260            }
261            satisfy::Witness::Unavailable | satisfy::Witness::Impossible => {
262                Err(Error::CouldNotSatisfy)
263            }
264        }
265    }
266
267    /// Attempt to produce a non-malleable witness template given the assets available
268    pub fn build_template<P: plan::AssetProvider<Pk>>(
269        &self,
270        provider: &P,
271    ) -> satisfy::Satisfaction<satisfy::Placeholder<Pk>>
272    where
273        Pk: ToPublicKey,
274    {
275        let leaf_hash = TapLeafHash::from_script(&self.encode(), LeafVersion::TapScript);
276        satisfy::Satisfaction::build_template(&self.node, provider, self.ty.mall.safe, &leaf_hash)
277    }
278
279    /// Attempt to produce a malleable witness template given the assets available
280    pub fn build_template_mall<P: plan::AssetProvider<Pk>>(
281        &self,
282        provider: &P,
283    ) -> satisfy::Satisfaction<satisfy::Placeholder<Pk>>
284    where
285        Pk: ToPublicKey,
286    {
287        let leaf_hash = TapLeafHash::from_script(&self.encode(), LeafVersion::TapScript);
288        satisfy::Satisfaction::build_template_mall(
289            &self.node,
290            provider,
291            self.ty.mall.safe,
292            &leaf_hash,
293        )
294    }
295}
296
297impl<Ctx: ScriptContext> Miniscript<Ctx::Key, Ctx> {
298    /// Attempt to parse an insane(scripts don't clear sanity checks)
299    /// script into a Miniscript representation.
300    /// Use this to parse scripts with repeated pubkeys, timelock mixing, malleable
301    /// scripts without sig or scripts that can exceed resource limits.
302    /// Some of the analysis guarantees of miniscript are lost when dealing with
303    /// insane scripts. In general, in a multi-party setting users should only
304    /// accept sane scripts.
305    pub fn parse_insane(script: &script::Script) -> Result<Miniscript<Ctx::Key, Ctx>, Error> {
306        Miniscript::parse_with_ext(script, &ExtParams::insane())
307    }
308
309    /// Attempt to parse an miniscript with extra features that not yet specified in the spec.
310    /// Users should not use this function unless they scripts can/will change in the future.
311    /// Currently, this function supports the following features:
312    ///     - Parsing all insane scripts
313    ///     - Parsing miniscripts with raw pubkey hashes
314    ///
315    /// Allowed extra features can be specified by the ext [`ExtParams`] argument.
316    pub fn parse_with_ext(
317        script: &script::Script,
318        ext: &ExtParams,
319    ) -> Result<Miniscript<Ctx::Key, Ctx>, Error> {
320        let tokens = lex(script)?;
321        let mut iter = TokenIter::new(tokens);
322
323        let top = decode::parse(&mut iter)?;
324        Ctx::check_global_validity(&top)?;
325        let type_check = types::Type::type_check(&top.node)?;
326        if type_check.corr.base != types::Base::B {
327            return Err(Error::NonTopLevel(format!("{:?}", top)));
328        };
329        if let Some(leading) = iter.next() {
330            Err(Error::Trailing(leading.to_string()))
331        } else {
332            top.ext_check(ext)?;
333            Ok(top)
334        }
335    }
336
337    /// Attempt to parse a Script into Miniscript representation.
338    ///
339    /// This function will fail parsing for scripts that do not clear the
340    /// [`Miniscript::sanity_check`] checks. Use [`Miniscript::parse_insane`] to
341    /// parse such scripts.
342    ///
343    /// ## Decode/Parse a miniscript from script hex
344    ///
345    /// ```rust
346    /// use miniscript::{Miniscript, Segwitv0, Tap};
347    /// use miniscript::bitcoin::secp256k1::XOnlyPublicKey;
348    /// use miniscript::bitcoin::hashes::hex::FromHex;
349    ///
350    /// type Segwitv0Script = Miniscript<bitcoin::PublicKey, Segwitv0>;
351    /// type TapScript = Miniscript<XOnlyPublicKey, Tap>;
352    ///
353    /// // parse x-only miniscript in Taproot context
354    /// let tapscript_ms = TapScript::parse(&bitcoin::ScriptBuf::from_hex(
355    ///     "202788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
356    /// ).expect("Even length hex"))
357    ///     .expect("Xonly keys are valid only in taproot context");
358    /// // tapscript fails decoding when we use them with compressed keys
359    /// let err = TapScript::parse(&bitcoin::ScriptBuf::from_hex(
360    ///     "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
361    /// ).expect("Even length hex"))
362    ///     .expect_err("Compressed keys cannot be used in Taproot context");
363    /// // Segwitv0 succeeds decoding with full keys.
364    /// Segwitv0Script::parse(&bitcoin::ScriptBuf::from_hex(
365    ///     "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
366    /// ).expect("Even length hex"))
367    ///     .expect("Compressed keys are allowed in Segwit context");
368    ///
369    /// ```
370    pub fn parse(script: &script::Script) -> Result<Miniscript<Ctx::Key, Ctx>, Error> {
371        let ms = Self::parse_with_ext(script, &ExtParams::sane())?;
372        Ok(ms)
373    }
374}
375
376/// `PartialOrd` of `Miniscript` must depend only on node and not the type information.
377///
378/// The type information and extra properties are implied by the AST.
379impl<Pk: MiniscriptKey, Ctx: ScriptContext> PartialOrd for Miniscript<Pk, Ctx> {
380    fn partial_cmp(&self, other: &Miniscript<Pk, Ctx>) -> Option<cmp::Ordering> {
381        Some(self.cmp(other))
382    }
383}
384
385/// `Ord` of `Miniscript` must depend only on node and not the type information.
386///
387/// The type information and extra properties are implied by the AST.
388impl<Pk: MiniscriptKey, Ctx: ScriptContext> Ord for Miniscript<Pk, Ctx> {
389    fn cmp(&self, other: &Miniscript<Pk, Ctx>) -> cmp::Ordering { self.node.cmp(&other.node) }
390}
391
392/// `PartialEq` of `Miniscript` must depend only on node and not the type information.
393///
394/// The type information and extra properties are implied by the AST.
395impl<Pk: MiniscriptKey, Ctx: ScriptContext> PartialEq for Miniscript<Pk, Ctx> {
396    fn eq(&self, other: &Miniscript<Pk, Ctx>) -> bool { self.node.eq(&other.node) }
397}
398
399/// `Eq` of `Miniscript` must depend only on node and not the type information.
400///
401/// The type information and extra properties are implied by the AST.
402impl<Pk: MiniscriptKey, Ctx: ScriptContext> Eq for Miniscript<Pk, Ctx> {}
403
404/// `Hash` of `Miniscript` must depend only on node and not the type information.
405///
406/// The type information and extra properties are implied by the AST.
407impl<Pk: MiniscriptKey, Ctx: ScriptContext> hash::Hash for Miniscript<Pk, Ctx> {
408    fn hash<H: hash::Hasher>(&self, state: &mut H) { self.node.hash(state); }
409}
410
411impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Miniscript<Pk, Ctx> {
412    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self.node) }
413}
414
415impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Miniscript<Pk, Ctx> {
416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.node) }
417}
418
419impl<Pk: MiniscriptKey, Ctx: ScriptContext> ForEachKey<Pk> for Miniscript<Pk, Ctx> {
420    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool {
421        for ms in self.pre_order_iter() {
422            match ms.node {
423                Terminal::PkK(ref p) => {
424                    if !pred(p) {
425                        return false;
426                    }
427                }
428                Terminal::PkH(ref p) => {
429                    if !pred(p) {
430                        return false;
431                    }
432                }
433                // These branches cannot be combined since technically the two `thresh`es
434                // have different types (have different maximum values).
435                Terminal::Multi(ref thresh) => {
436                    if !thresh.iter().all(&mut pred) {
437                        return false;
438                    }
439                }
440                Terminal::MultiA(ref thresh) => {
441                    if !thresh.iter().all(&mut pred) {
442                        return false;
443                    }
444                }
445                _ => {}
446            }
447        }
448        true
449    }
450}
451
452impl<Pk, Q, Ctx> TranslatePk<Pk, Q> for Miniscript<Pk, Ctx>
453where
454    Pk: MiniscriptKey,
455    Q: MiniscriptKey,
456    Ctx: ScriptContext,
457{
458    type Output = Miniscript<Q, Ctx>;
459
460    /// Translates a struct from one generic to another where the translation
461    /// for Pk is provided by [`Translator`]
462    fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
463    where
464        T: Translator<Pk, Q, E>,
465    {
466        self.translate_pk_ctx(t)
467    }
468}
469
470impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
471    pub(super) fn translate_pk_ctx<Q, CtxQ, T, FuncError>(
472        &self,
473        t: &mut T,
474    ) -> Result<Miniscript<Q, CtxQ>, TranslateErr<FuncError>>
475    where
476        Q: MiniscriptKey,
477        CtxQ: ScriptContext,
478        T: Translator<Pk, Q, FuncError>,
479    {
480        let mut translated = vec![];
481        for data in Arc::new(self.clone()).post_order_iter() {
482            let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
483
484            let new_term = match data.node.node {
485                Terminal::PkK(ref p) => Terminal::PkK(t.pk(p)?),
486                Terminal::PkH(ref p) => Terminal::PkH(t.pk(p)?),
487                Terminal::RawPkH(ref p) => Terminal::RawPkH(*p),
488                Terminal::After(n) => Terminal::After(n),
489                Terminal::Older(n) => Terminal::Older(n),
490                Terminal::Sha256(ref x) => Terminal::Sha256(t.sha256(x)?),
491                Terminal::Hash256(ref x) => Terminal::Hash256(t.hash256(x)?),
492                Terminal::Ripemd160(ref x) => Terminal::Ripemd160(t.ripemd160(x)?),
493                Terminal::Hash160(ref x) => Terminal::Hash160(t.hash160(x)?),
494                Terminal::True => Terminal::True,
495                Terminal::False => Terminal::False,
496                Terminal::Alt(..) => Terminal::Alt(child_n(0)),
497                Terminal::Swap(..) => Terminal::Swap(child_n(0)),
498                Terminal::Check(..) => Terminal::Check(child_n(0)),
499                Terminal::DupIf(..) => Terminal::DupIf(child_n(0)),
500                Terminal::Verify(..) => Terminal::Verify(child_n(0)),
501                Terminal::NonZero(..) => Terminal::NonZero(child_n(0)),
502                Terminal::ZeroNotEqual(..) => Terminal::ZeroNotEqual(child_n(0)),
503                Terminal::AndV(..) => Terminal::AndV(child_n(0), child_n(1)),
504                Terminal::AndB(..) => Terminal::AndB(child_n(0), child_n(1)),
505                Terminal::AndOr(..) => Terminal::AndOr(child_n(0), child_n(1), child_n(2)),
506                Terminal::OrB(..) => Terminal::OrB(child_n(0), child_n(1)),
507                Terminal::OrD(..) => Terminal::OrD(child_n(0), child_n(1)),
508                Terminal::OrC(..) => Terminal::OrC(child_n(0), child_n(1)),
509                Terminal::OrI(..) => Terminal::OrI(child_n(0), child_n(1)),
510                Terminal::Thresh(ref thresh) => Terminal::Thresh(
511                    thresh.map_from_post_order_iter(&data.child_indices, &translated),
512                ),
513                Terminal::Multi(ref thresh) => Terminal::Multi(thresh.translate_ref(|k| t.pk(k))?),
514                Terminal::MultiA(ref thresh) => {
515                    Terminal::MultiA(thresh.translate_ref(|k| t.pk(k))?)
516                }
517            };
518            let new_ms = Miniscript::from_ast(new_term).map_err(TranslateErr::OuterError)?;
519            translated.push(Arc::new(new_ms));
520        }
521
522        Ok(Arc::try_unwrap(translated.pop().unwrap()).unwrap())
523    }
524
525    /// Substitutes raw public keys hashes with the public keys as provided by map.
526    pub fn substitute_raw_pkh(&self, pk_map: &BTreeMap<hash160::Hash, Pk>) -> Miniscript<Pk, Ctx> {
527        let mut translated = vec![];
528        for data in Arc::new(self.clone()).post_order_iter() {
529            let new_term = if let Terminal::RawPkH(ref p) = data.node.node {
530                match pk_map.get(p) {
531                    Some(pk) => Terminal::PkH(pk.clone()),
532                    None => Terminal::RawPkH(*p),
533                }
534            } else {
535                data.node.node.clone()
536            };
537
538            let new_ms = Miniscript::from_ast(new_term).expect("typeck");
539            translated.push(Arc::new(new_ms));
540        }
541
542        Arc::try_unwrap(translated.pop().unwrap()).unwrap()
543    }
544}
545
546/// Utility function used when parsing a script from an expression tree.
547///
548/// Checks that the name of each fragment has at most one `:`, splits
549/// the name at the `:`, and implements aliases for the old `pk`/`pk_h`
550/// fragments.
551///
552/// Returns the fragment name (right of the `:`) and a list of wrappers
553/// (left of the `:`).
554fn split_expression_name(name: &str) -> Result<(&str, Cow<'_, str>), Error> {
555    let mut aliased_wrap;
556    let frag_name;
557    let frag_wrap;
558    let mut name_split = name.split(':');
559    match (name_split.next(), name_split.next(), name_split.next()) {
560        (None, _, _) => {
561            frag_name = "";
562            frag_wrap = "".into();
563        }
564        (Some(name), None, _) => {
565            if name == "pk" {
566                frag_name = "pk_k";
567                frag_wrap = "c".into();
568            } else if name == "pkh" {
569                frag_name = "pk_h";
570                frag_wrap = "c".into();
571            } else {
572                frag_name = name;
573                frag_wrap = "".into();
574            }
575        }
576        (Some(wrap), Some(name), None) => {
577            if wrap.is_empty() {
578                return Err(Error::Unexpected(name.to_owned()));
579            }
580            if name == "pk" {
581                frag_name = "pk_k";
582                aliased_wrap = wrap.to_owned();
583                aliased_wrap.push('c');
584                frag_wrap = aliased_wrap.into();
585            } else if name == "pkh" {
586                frag_name = "pk_h";
587                aliased_wrap = wrap.to_owned();
588                aliased_wrap.push('c');
589                frag_wrap = aliased_wrap.into();
590            } else {
591                frag_name = name;
592                frag_wrap = wrap.into();
593            }
594        }
595        (Some(_), Some(_), Some(_)) => {
596            return Err(Error::MultiColon(name.to_owned()));
597        }
598    }
599    Ok((frag_name, frag_wrap))
600}
601
602/// Utility function used when parsing a script from an expression tree.
603///
604/// Once a Miniscript fragment has been parsed into a terminal, apply any
605/// wrappers that were included in its name.
606fn wrap_into_miniscript<Pk, Ctx>(
607    term: Terminal<Pk, Ctx>,
608    frag_wrap: Cow<str>,
609) -> Result<Miniscript<Pk, Ctx>, Error>
610where
611    Pk: MiniscriptKey,
612    Ctx: ScriptContext,
613{
614    let mut unwrapped = term;
615    for ch in frag_wrap.chars().rev() {
616        // Check whether the wrapper is valid under the current context
617        let ms = Miniscript::from_ast(unwrapped)?;
618        Ctx::check_global_validity(&ms)?;
619        match ch {
620            'a' => unwrapped = Terminal::Alt(Arc::new(ms)),
621            's' => unwrapped = Terminal::Swap(Arc::new(ms)),
622            'c' => unwrapped = Terminal::Check(Arc::new(ms)),
623            'd' => unwrapped = Terminal::DupIf(Arc::new(ms)),
624            'v' => unwrapped = Terminal::Verify(Arc::new(ms)),
625            'j' => unwrapped = Terminal::NonZero(Arc::new(ms)),
626            'n' => unwrapped = Terminal::ZeroNotEqual(Arc::new(ms)),
627            't' => unwrapped = Terminal::AndV(Arc::new(ms), Arc::new(Miniscript::TRUE)),
628            'u' => unwrapped = Terminal::OrI(Arc::new(ms), Arc::new(Miniscript::FALSE)),
629            'l' => unwrapped = Terminal::OrI(Arc::new(Miniscript::FALSE), Arc::new(ms)),
630            x => return Err(Error::UnknownWrapper(x)),
631        }
632    }
633    // Check whether the unwrapped miniscript is valid under the current context
634    let ms = Miniscript::from_ast(unwrapped)?;
635    Ctx::check_global_validity(&ms)?;
636    Ok(ms)
637}
638
639impl<Pk: FromStrKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
640    /// Attempt to parse an insane(scripts don't clear sanity checks)
641    /// from string into a Miniscript representation.
642    /// Use this to parse scripts with repeated pubkeys, timelock mixing, malleable
643    /// scripts without sig or scripts that can exceed resource limits.
644    /// Some of the analysis guarantees of miniscript are lost when dealing with
645    /// insane scripts. In general, in a multi-party setting users should only
646    /// accept sane scripts.
647    pub fn from_str_insane(s: &str) -> Result<Miniscript<Pk, Ctx>, Error> {
648        Miniscript::from_str_ext(s, &ExtParams::insane())
649    }
650
651    /// Attempt to parse an Miniscripts that don't follow the spec.
652    /// Use this to parse scripts with repeated pubkeys, timelock mixing, malleable
653    /// scripts, raw pubkey hashes without sig or scripts that can exceed resource limits.
654    ///
655    /// Use [`ExtParams`] builder to specify the types of non-sane rules to allow while parsing.
656    pub fn from_str_ext(s: &str, ext: &ExtParams) -> Result<Miniscript<Pk, Ctx>, Error> {
657        // This checks for invalid ASCII chars
658        let top = expression::Tree::from_str(s)?;
659        let ms: Miniscript<Pk, Ctx> = expression::FromTree::from_tree(&top)?;
660        ms.ext_check(ext)?;
661
662        if ms.ty.corr.base != types::Base::B {
663            Err(Error::NonTopLevel(format!("{:?}", ms)))
664        } else {
665            Ok(ms)
666        }
667    }
668}
669
670impl<Pk: FromStrKey, Ctx: ScriptContext> crate::expression::FromTree for Arc<Miniscript<Pk, Ctx>> {
671    fn from_tree(top: &expression::Tree) -> Result<Arc<Miniscript<Pk, Ctx>>, Error> {
672        Ok(Arc::new(expression::FromTree::from_tree(top)?))
673    }
674}
675
676impl<Pk: FromStrKey, Ctx: ScriptContext> crate::expression::FromTree for Miniscript<Pk, Ctx> {
677    /// Parse an expression tree into a Miniscript. As a general rule, this
678    /// should not be called directly; rather go through the descriptor API.
679    fn from_tree(top: &expression::Tree) -> Result<Miniscript<Pk, Ctx>, Error> {
680        let inner: Terminal<Pk, Ctx> = expression::FromTree::from_tree(top)?;
681        Miniscript::from_ast(inner)
682    }
683}
684
685impl<Pk: FromStrKey, Ctx: ScriptContext> str::FromStr for Miniscript<Pk, Ctx> {
686    type Err = Error;
687    /// Parse a Miniscript from string and perform sanity checks
688    /// See [Miniscript::from_str_insane] to parse scripts from string that
689    /// do not clear the [Miniscript::sanity_check] checks.
690    fn from_str(s: &str) -> Result<Miniscript<Pk, Ctx>, Error> {
691        let ms = Self::from_str_ext(s, &ExtParams::sane())?;
692        Ok(ms)
693    }
694}
695
696serde_string_impl_pk!(Miniscript, "a miniscript", Ctx; ScriptContext);
697
698/// Provides a Double SHA256 `Hash` type that displays forwards.
699pub mod hash256 {
700    use bitcoin::hashes::{hash_newtype, sha256d};
701
702    hash_newtype! {
703        /// A hash256 of preimage.
704        #[hash_newtype(forward)]
705        pub struct Hash(sha256d::Hash);
706    }
707}
708
709#[cfg(test)]
710mod tests {
711
712    use core::str;
713    use core::str::FromStr;
714
715    use bitcoin::hashes::{hash160, sha256, Hash};
716    use bitcoin::secp256k1::XOnlyPublicKey;
717    use bitcoin::taproot::TapLeafHash;
718    use sync::Arc;
719
720    use super::{Miniscript, ScriptContext, Segwitv0, Tap};
721    use crate::miniscript::{types, Terminal};
722    use crate::policy::Liftable;
723    use crate::prelude::*;
724    use crate::test_utils::{StrKeyTranslator, StrXOnlyKeyTranslator};
725    use crate::{hex_script, Error, ExtParams, RelLockTime, Satisfier, ToPublicKey, TranslatePk};
726
727    type Segwitv0Script = Miniscript<bitcoin::PublicKey, Segwitv0>;
728    type Tapscript = Miniscript<bitcoin::secp256k1::XOnlyPublicKey, Tap>;
729
730    fn pubkeys(n: usize) -> Vec<bitcoin::PublicKey> {
731        let mut ret = Vec::with_capacity(n);
732        let secp = secp256k1::Secp256k1::new();
733        let mut sk = [0; 32];
734        for i in 1..n + 1 {
735            sk[0] = i as u8;
736            sk[1] = (i >> 8) as u8;
737            sk[2] = (i >> 16) as u8;
738
739            let pk = bitcoin::PublicKey {
740                inner: secp256k1::PublicKey::from_secret_key(
741                    &secp,
742                    &secp256k1::SecretKey::from_slice(&sk[..]).expect("secret key"),
743                ),
744                compressed: true,
745            };
746            ret.push(pk);
747        }
748        ret
749    }
750
751    fn string_rtt<Ctx: ScriptContext>(
752        script: Miniscript<bitcoin::PublicKey, Ctx>,
753        expected_debug: &str,
754        expected_display: &str,
755    ) {
756        assert_eq!(script.ty.corr.base, types::Base::B);
757        let debug = format!("{:?}", script);
758        let display = format!("{}", script);
759        if let Some(expected) = expected_debug.into() {
760            assert_eq!(debug, expected);
761        }
762        if let Some(expected) = expected_display.into() {
763            assert_eq!(display, expected);
764        }
765        let roundtrip = Miniscript::from_str(&display).expect("parse string serialization");
766        assert_eq!(roundtrip, script);
767    }
768
769    fn string_display_debug_test<Ctx: ScriptContext>(
770        script: Miniscript<bitcoin::PublicKey, Ctx>,
771        expected_debug: &str,
772        expected_display: &str,
773    ) {
774        assert_eq!(script.ty.corr.base, types::Base::B);
775        let debug = format!("{:?}", script);
776        let display = format!("{}", script);
777        if let Some(expected) = expected_debug.into() {
778            assert_eq!(debug, expected);
779        }
780        if let Some(expected) = expected_display.into() {
781            assert_eq!(display, expected);
782        }
783    }
784
785    fn dummy_string_rtt<Ctx: ScriptContext>(
786        script: Miniscript<String, Ctx>,
787        expected_debug: &str,
788        expected_display: &str,
789    ) {
790        assert_eq!(script.ty.corr.base, types::Base::B);
791        let debug = format!("{:?}", script);
792        let display = format!("{}", script);
793        if let Some(expected) = expected_debug.into() {
794            assert_eq!(debug, expected);
795        }
796        if let Some(expected) = expected_display.into() {
797            assert_eq!(display, expected);
798        }
799        let roundtrip = Miniscript::from_str(&display).expect("parse string serialization");
800        assert_eq!(roundtrip, script);
801    }
802
803    fn script_rtt<Str1: Into<Option<&'static str>>>(script: Segwitv0Script, expected_hex: Str1) {
804        assert_eq!(script.ty.corr.base, types::Base::B);
805        let bitcoin_script = script.encode();
806        assert_eq!(bitcoin_script.len(), script.script_size());
807        if let Some(expected) = expected_hex.into() {
808            assert_eq!(format!("{:x}", bitcoin_script), expected);
809        }
810        // Parse scripts with all extensions
811        let roundtrip = Segwitv0Script::parse_with_ext(&bitcoin_script, &ExtParams::allow_all())
812            .expect("parse string serialization");
813        assert_eq!(roundtrip, script);
814    }
815
816    fn roundtrip(tree: &Segwitv0Script, s: &str) {
817        assert_eq!(tree.ty.corr.base, types::Base::B);
818        let ser = tree.encode();
819        assert_eq!(ser.len(), tree.script_size());
820        assert_eq!(ser.to_string(), s);
821        let deser = Segwitv0Script::parse_insane(&ser).expect("deserialize result of serialize");
822        assert_eq!(*tree, deser);
823    }
824
825    fn ms_attributes_test(
826        ms: &str,
827        expected_hex: &str,
828        valid: bool,
829        non_mal: bool,
830        need_sig: bool,
831        ops: usize,
832        _stack: usize,
833    ) {
834        let ms: Result<Segwitv0Script, _> = Miniscript::from_str_insane(ms);
835        match (ms, valid) {
836            (Ok(ms), true) => {
837                assert_eq!(format!("{:x}", ms.encode()), expected_hex);
838                assert_eq!(ms.ty.mall.non_malleable, non_mal);
839                assert_eq!(ms.ty.mall.safe, need_sig);
840                assert_eq!(ms.ext.ops.op_count().unwrap(), ops);
841            }
842            (Err(_), false) => {}
843            _ => unreachable!(),
844        }
845    }
846
847    #[test]
848    fn all_attribute_tests() {
849        ms_attributes_test(
850            "lltvln:after(1231488000)",
851            "6300676300676300670400046749b1926869516868",
852            true,
853            true,
854            false,
855            12,
856            3,
857        );
858        ms_attributes_test("uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "6363829263522103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a21025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc52af0400046749b168670068670068", true, true, true, 14, 5);
859        ms_attributes_test("or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16))", "63522103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee872921024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae926700686b63006760b2686c9b", true, false, false, 14, 5);
860        ms_attributes_test(
861            "j:and_v(vdv:after(1567547623),older(2016))",
862            "829263766304e7e06e5db169686902e007b268",
863            true,
864            true,
865            false,
866            11,
867            1,
868        );
869        ms_attributes_test("t:and_v(vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5))", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", true, true, false, 12, 3);
870        ms_attributes_test("t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2))", "532102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975562102e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1353ae6482012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2886703010040b2696851", true, true, false, 13, 5);
871        ms_attributes_test("or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000)))", "512102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f951ae73645321022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a0121032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f2103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a53ae7c630320a107b16700689b68", true, true, false, 15, 7);
872        ms_attributes_test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", true, false, false, 16, 1);
873        ms_attributes_test("and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68))", "63522102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52103774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb52af67522103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a21025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc52af6882012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c6887", true, true, true, 11, 5);
874        ms_attributes_test("j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898)))", "82926352210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae7c6351b26703e2e440b2689a68", true, false, true, 14, 4);
875        ms_attributes_test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", true, false, false, 12, 1);
876        ms_attributes_test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", true, false, false, 16, 2);
877        ms_attributes_test("and_b(hash256(32ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac),a:and_b(hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),a:older(1)))", "82012088aa2032ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac876b82012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876b51b26c9a6c9a", true, true, false, 15, 2);
878        ms_attributes_test("thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", "522103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c721036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0052ae6b5121036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0051ae6c936b21022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ac6c935287", true, true, true, 13, 6);
879        ms_attributes_test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", true, false, false, 14, 2);
880        ms_attributes_test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", true, false, false, 15, 2);
881        ms_attributes_test("c:and_v(or_c(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764512102c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db51af682103acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeac", true, false, true, 9, 2);
882        ms_attributes_test("c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(1b0f3c404d12075c68c938f9f60ebea4f74941a0)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "5221036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a002102352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d552ae6482012088a6141b0f3c404d12075c68c938f9f60ebea4f74941a088682103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac", true, true, true, 10, 5);
883        ms_attributes_test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", true, false, false, 14, 2);
884        ms_attributes_test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", true, false, false, 20, 2);
885        ms_attributes_test("or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946))", "630320a107b1692102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", true, true, false, 10, 2);
886        ms_attributes_test("thresh(2,c:pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),s:sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),a:hash160(dd69735817e0e3f6f826a9238dc2e291184f0131))", "76a91420d637c1a6404d2227f3561fdbaff5a680dba64888ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", true, false, false, 18, 4);
887        ms_attributes_test("and_n(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),uc:and_v(v:older(144),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce)))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b2692103fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", true, false, true, 13, 3);
888        ms_attributes_test("and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))", "2103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", true, true, true, 12, 2);
889        ms_attributes_test("c:or_i(and_v(v:older(16),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729)),pk_h(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5))", "6360b26976a91420d637c1a6404d2227f3561fdbaff5a680dba648886776a9148f9dff39a81ee4abcbad2ad8bafff090415a2be88868ac", true, true, true, 12, 3);
890        ms_attributes_test("or_d(c:pk_h(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623)))", "76a9148f9dff39a81ee4abcbad2ad8bafff090415a2be888ac736421024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", true, true, false, 13, 3);
891        ms_attributes_test("c:andor(ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_v(v:hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),pk_h(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5)))", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a9148f9dff39a81ee4abcbad2ad8bafff090415a2be8886776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", true, false, true, 18, 3);
892        ms_attributes_test("c:andor(u:ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),pk_h(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5)))", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a914385defb0ed10fe95817943ed37b4984f8f4255d6886776a9148f9dff39a81ee4abcbad2ad8bafff090415a2be888686776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", true, false, true, 23, 4);
893        ms_attributes_test("c:or_i(andor(c:pk_h(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),pk_h(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "6376a9148f9dff39a81ee4abcbad2ad8bafff090415a2be888ac6476a91420d637c1a6404d2227f3561fdbaff5a680dba648886776a914385defb0ed10fe95817943ed37b4984f8f4255d68868672103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a146029755668ac", true, true, true, 17, 5);
894    }
895
896    #[test]
897    fn basic() {
898        let pk = bitcoin::PublicKey::from_str(
899            "\
900             020202020202020202020202020202020202020202020202020202020202020202\
901             ",
902        )
903        .unwrap();
904        let hash = hash160::Hash::from_byte_array([17; 20]);
905
906        let pk_node = Terminal::Check(Arc::new(
907            Miniscript::from_ast(Terminal::PkK(String::from(""))).unwrap(),
908        ));
909        let pkk_ms: Miniscript<String, Segwitv0> = Miniscript::from_ast(pk_node).unwrap();
910        dummy_string_rtt(pkk_ms, "[B/onduesm]pk(\"\")", "pk()");
911
912        let pkh_node = Terminal::Check(Arc::new(
913            Miniscript::from_ast(Terminal::PkH(String::from(""))).unwrap(),
914        ));
915        let pkh_ms: Miniscript<String, Segwitv0> = Miniscript::from_ast(pkh_node).unwrap();
916
917        let expected_debug = "[B/nduesm]pkh(\"\")";
918        let expected_display = "pkh()";
919
920        assert_eq!(pkh_ms.ty.corr.base, types::Base::B);
921        let debug = format!("{:?}", pkh_ms);
922        let display = format!("{}", pkh_ms);
923        if let Some(expected) = expected_debug.into() {
924            assert_eq!(debug, expected);
925        }
926        if let Some(expected) = expected_display.into() {
927            assert_eq!(display, expected);
928        }
929
930        let pkk_node = Terminal::Check(Arc::new(Miniscript::from_ast(Terminal::PkK(pk)).unwrap()));
931        let pkk_ms: Segwitv0Script = Miniscript::from_ast(pkk_node).unwrap();
932
933        script_rtt(
934            pkk_ms,
935            "21020202020202020202020202020202020202020202020202020202020\
936             202020202ac",
937        );
938
939        let pkh_ms: Segwitv0Script = Miniscript::from_ast(Terminal::Check(Arc::new(
940            Miniscript::from_ast(Terminal::RawPkH(hash)).unwrap(),
941        )))
942        .unwrap();
943
944        script_rtt(pkh_ms, "76a914111111111111111111111111111111111111111188ac");
945    }
946
947    #[test]
948    fn true_false() {
949        roundtrip(&ms_str!("1"), "OP_PUSHNUM_1");
950        roundtrip(&ms_str!("tv:1"), "OP_PUSHNUM_1 OP_VERIFY OP_PUSHNUM_1");
951        roundtrip(&ms_str!("0"), "OP_0");
952        roundtrip(&ms_str!("andor(0,1,0)"), "OP_0 OP_NOTIF OP_0 OP_ELSE OP_PUSHNUM_1 OP_ENDIF");
953
954        assert!(Segwitv0Script::from_str("1()").is_err());
955        assert!(Segwitv0Script::from_str("tv:1()").is_err());
956    }
957
958    #[test]
959    fn verify_parse() {
960        let ms = "and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
961        let ms: Segwitv0Script = Miniscript::from_str_insane(ms).unwrap();
962        assert_eq!(ms, Segwitv0Script::parse_insane(&ms.encode()).unwrap());
963
964        let ms = "and_v(v:sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
965        let ms: Segwitv0Script = Miniscript::from_str_insane(ms).unwrap();
966        assert_eq!(ms, Segwitv0Script::parse_insane(&ms.encode()).unwrap());
967
968        let ms = "and_v(v:ripemd160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
969        let ms: Segwitv0Script = Miniscript::from_str_insane(ms).unwrap();
970        assert_eq!(ms, Segwitv0Script::parse_insane(&ms.encode()).unwrap());
971
972        let ms = "and_v(v:hash256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
973        let ms: Segwitv0Script = Miniscript::from_str_insane(ms).unwrap();
974        assert_eq!(ms, Segwitv0Script::parse_insane(&ms.encode()).unwrap());
975    }
976
977    #[test]
978    fn pk_alias() {
979        let pubkey = pubkeys(1)[0];
980
981        let script: Segwitv0Script = ms_str!("c:pk_k({})", pubkey.to_string());
982
983        string_rtt(
984            script,
985            "[B/onduesm]pk(PublicKey { compressed: true, inner: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })",
986            "pk(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)"
987        );
988
989        let script: Segwitv0Script = ms_str!("pk({})", pubkey.to_string());
990
991        string_rtt(
992            script,
993            "[B/onduesm]pk(PublicKey { compressed: true, inner: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })",
994            "pk(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)"
995        );
996
997        let script: Segwitv0Script = ms_str!("tv:pk({})", pubkey.to_string());
998
999        string_rtt(
1000            script,
1001            "[B/onufsm]t[V/onfsm]v:[B/onduesm]pk(PublicKey { compressed: true, inner: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })",
1002            "tv:pk(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)"
1003        );
1004
1005        let script: Segwitv0Script = ms_str!("c:pk_h({})", pubkey.to_string());
1006
1007        string_display_debug_test(
1008            script,
1009            "[B/nduesm]pkh(PublicKey { compressed: true, inner: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })",
1010            "pkh(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)",
1011        );
1012
1013        let script: Segwitv0Script = ms_str!("pkh({})", pubkey.to_string());
1014
1015        string_display_debug_test(
1016            script,
1017            "[B/nduesm]pkh(PublicKey { compressed: true, inner: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })",
1018            "pkh(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)",
1019        );
1020
1021        let script: Segwitv0Script = ms_str!("tv:pkh({})", pubkey.to_string());
1022
1023        string_display_debug_test(
1024            script,
1025            "[B/nufsm]t[V/nfsm]v:[B/nduesm]pkh(PublicKey { compressed: true, inner: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })",
1026            "tv:pkh(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)",
1027        );
1028    }
1029
1030    #[test]
1031    fn serialize() {
1032        let keys = pubkeys(6);
1033
1034        let tree: &Segwitv0Script = &ms_str!("c:pk_h({})", keys[5]);
1035        assert_eq!(tree.ty.corr.base, types::Base::B);
1036        let ser = tree.encode();
1037        let s = "\
1038             OP_DUP OP_HASH160 OP_PUSHBYTES_20 \
1039             7e5a2a6a7610ca4ea78bd65a087bd75b1870e319 \
1040             OP_EQUALVERIFY OP_CHECKSIG\
1041             ";
1042        assert_eq!(ser.len(), tree.script_size());
1043        assert_eq!(ser.to_string(), s);
1044
1045        roundtrip(
1046            &ms_str!("pk({})", keys[0]),
1047            "OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa OP_CHECKSIG"
1048        );
1049        roundtrip(
1050            &ms_str!("multi(3,{},{},{},{},{})", keys[0], keys[1], keys[2], keys[3], keys[4]),
1051            "OP_PUSHNUM_3 OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 OP_PUSHBYTES_33 039729247032c0dfcf45b4841fcd72f6e9a2422631fc3466cf863e87154754dd40 OP_PUSHBYTES_33 032564fe9b5beef82d3703a607253f31ef8ea1b365772df434226aee642651b3fa OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff OP_PUSHNUM_5 OP_CHECKMULTISIG"
1052        );
1053
1054        // Liquid policy
1055        roundtrip(
1056            &ms_str!("or_d(multi(2,{},{}),and_v(v:multi(2,{},{}),older(10000)))",
1057                      keys[0].to_string(),
1058                      keys[1].to_string(),
1059                      keys[3].to_string(),
1060                      keys[4].to_string()),
1061            "OP_PUSHNUM_2 OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa \
1062                                  OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 \
1063                                  OP_PUSHNUM_2 OP_CHECKMULTISIG \
1064                     OP_IFDUP OP_NOTIF \
1065                         OP_PUSHNUM_2 OP_PUSHBYTES_33 032564fe9b5beef82d3703a607253f31ef8ea1b365772df434226aee642651b3fa \
1066                                      OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff \
1067                                      OP_PUSHNUM_2 OP_CHECKMULTISIGVERIFY \
1068                         OP_PUSHBYTES_2 1027 OP_CSV \
1069                     OP_ENDIF"
1070        );
1071
1072        let miniscript: Segwitv0Script = ms_str!(
1073            "or_d(multi(3,{},{},{}),and_v(v:multi(2,{},{}),older(10000)))",
1074            keys[0].to_string(),
1075            keys[1].to_string(),
1076            keys[2].to_string(),
1077            keys[3].to_string(),
1078            keys[4].to_string(),
1079        );
1080
1081        let mut abs = miniscript.lift().unwrap();
1082        assert_eq!(abs.n_keys(), 5);
1083        assert_eq!(abs.minimum_n_keys(), Some(2));
1084        abs = abs.at_age(RelLockTime::from_height(10000).into());
1085        assert_eq!(abs.n_keys(), 5);
1086        assert_eq!(abs.minimum_n_keys(), Some(2));
1087        abs = abs.at_age(RelLockTime::from_height(9999).into());
1088        assert_eq!(abs.n_keys(), 3);
1089        assert_eq!(abs.minimum_n_keys(), Some(3));
1090        abs = abs.at_age(RelLockTime::ZERO.into());
1091        assert_eq!(abs.n_keys(), 3);
1092        assert_eq!(abs.minimum_n_keys(), Some(3));
1093
1094        roundtrip(&ms_str!("older(921)"), "OP_PUSHBYTES_2 9903 OP_CSV");
1095
1096        roundtrip(
1097            &ms_str!("sha256({})",sha256::Hash::hash(&[])),
1098            "OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 OP_EQUAL"
1099        );
1100
1101        roundtrip(
1102            &ms_str!("multi(3,{},{},{},{},{})", keys[0], keys[1], keys[2], keys[3], keys[4]),
1103            "OP_PUSHNUM_3 \
1104             OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa \
1105             OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 \
1106             OP_PUSHBYTES_33 039729247032c0dfcf45b4841fcd72f6e9a2422631fc3466cf863e87154754dd40 \
1107             OP_PUSHBYTES_33 032564fe9b5beef82d3703a607253f31ef8ea1b365772df434226aee642651b3fa \
1108             OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff \
1109             OP_PUSHNUM_5 OP_CHECKMULTISIG",
1110        );
1111
1112        roundtrip(
1113            &ms_str!(
1114                "t:and_v(\
1115                     vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),\
1116                     v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5)\
1117                 )"),
1118            "OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY OP_PUSHNUM_1"
1119        );
1120        roundtrip(
1121            &ms_str!("and_n(pk(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))"),
1122            "OP_PUSHBYTES_33 03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729 OP_CHECKSIG OP_NOTIF OP_0 OP_ELSE OP_IF OP_0 OP_ELSE OP_PUSHBYTES_3 e2e440 OP_CSV OP_ENDIF OP_TOALTSTACK OP_PUSHNUM_16 OP_CSV OP_FROMALTSTACK OP_BOOLAND OP_ENDIF"
1123        );
1124        roundtrip(
1125            &ms_str!(
1126                "t:andor(multi(\
1127                    3,\
1128                    02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,\
1129                    03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,\
1130                    02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13\
1131                 ),\
1132                 v:older(4194305),\
1133                 v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2)\
1134                 )"),
1135            "OP_PUSHNUM_3 OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e \
1136             OP_PUSHBYTES_33 03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556 \
1137             OP_PUSHBYTES_33 02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 \
1138             OP_PUSHNUM_3 OP_CHECKMULTISIG OP_NOTIF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 \
1139             OP_PUSHBYTES_32 9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2 OP_EQUALVERIFY \
1140             OP_ELSE OP_PUSHBYTES_3 010040 OP_CSV OP_VERIFY OP_ENDIF OP_PUSHNUM_1"
1141        );
1142        roundtrip(
1143            &ms_str!(
1144                "t:and_v(\
1145                    vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),\
1146                    v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5)\
1147                 )"),
1148            "\
1149             OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL \
1150             OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY \
1151             OP_PUSHNUM_1\
1152             "
1153        );
1154
1155        // Thresh bug with equal verify roundtrip
1156        roundtrip(
1157            &ms_str!("tv:thresh(1,pk(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", ),
1158            "OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e OP_CHECKSIG OP_PUSHNUM_1 OP_EQUALVERIFY OP_PUSHNUM_1",
1159        );
1160    }
1161
1162    #[test]
1163    fn deserialize() {
1164        // Most of these came from fuzzing, hence the increasing lengths
1165        assert!(Segwitv0Script::parse_insane(&hex_script("")).is_err()); // empty
1166        assert!(Segwitv0Script::parse_insane(&hex_script("00")).is_ok()); // FALSE
1167        assert!(Segwitv0Script::parse_insane(&hex_script("51")).is_ok()); // TRUE
1168        assert!(Segwitv0Script::parse_insane(&hex_script("69")).is_err()); // VERIFY
1169        assert!(Segwitv0Script::parse_insane(&hex_script("0000")).is_err()); //and_v(FALSE,FALSE)
1170        assert!(Segwitv0Script::parse_insane(&hex_script("1001")).is_err()); // incomplete push
1171        assert!(Segwitv0Script::parse_insane(&hex_script("03990300b2")).is_err()); // non-minimal #
1172        assert!(Segwitv0Script::parse_insane(&hex_script("8559b2")).is_err()); // leading bytes
1173        assert!(Segwitv0Script::parse_insane(&hex_script("4c0169b2")).is_err()); // non-minimal push
1174        assert!(Segwitv0Script::parse_insane(&hex_script("0000af0000ae85")).is_err()); // OR not BOOLOR
1175
1176        // misc fuzzer problems
1177        assert!(Segwitv0Script::parse_insane(&hex_script("0000000000af")).is_err());
1178        assert!(Segwitv0Script::parse_insane(&hex_script("04009a2970af00")).is_err()); // giant CMS key num
1179        assert!(Segwitv0Script::parse_insane(&hex_script(
1180            "2102ffffffffffffffefefefefefefefefefefef394c0fe5b711179e124008584753ac6900"
1181        ))
1182        .is_err());
1183    }
1184
1185    #[test]
1186    fn non_ascii() {
1187        assert!(Segwitv0Script::from_str_insane("🌏")
1188            .unwrap_err()
1189            .to_string()
1190            .contains("unprintable character"));
1191    }
1192
1193    #[test]
1194    fn test_tapscript_rtt() {
1195        // Test x-only invalid under segwitc0 context
1196        Segwitv0Script::from_str_insane(
1197            "pk(2788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)",
1198        )
1199        .unwrap_err();
1200        Tapscript::from_str_insane(
1201            "pk(2788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)",
1202        )
1203        .unwrap();
1204
1205        // Now test that bitcoin::PublicKey works with Taproot context
1206        Miniscript::<bitcoin::PublicKey, Tap>::from_str_insane(
1207            "pk(022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)",
1208        )
1209        .unwrap();
1210
1211        // uncompressed keys should not be allowed
1212        Miniscript::<bitcoin::PublicKey, Tap>::from_str_insane(
1213            "pk(04eed24a081bf1b1e49e3300df4bebe04208ac7e516b6f3ea8eb6e094584267c13483f89dcf194132e12238cc5a34b6b286fc7990d68ed1db86b69ebd826c63b29)"
1214        )
1215        .unwrap_err();
1216
1217        //---------------- test script <-> miniscript ---------------
1218        // Test parsing from scripts: x-only fails decoding in segwitv0 ctx
1219        Segwitv0Script::parse_insane(&hex_script(
1220            "202788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
1221        ))
1222        .unwrap_err();
1223        // x-only succeeds in tap ctx
1224        Tapscript::parse_insane(&hex_script(
1225            "202788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
1226        ))
1227        .unwrap();
1228        // tapscript fails decoding with compressed
1229        Tapscript::parse_insane(&hex_script(
1230            "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
1231        ))
1232        .unwrap_err();
1233        // Segwitv0 succeeds decoding with tapscript.
1234        Segwitv0Script::parse_insane(&hex_script(
1235            "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
1236        ))
1237        .unwrap();
1238
1239        // multi not allowed in tapscript
1240        Tapscript::from_str_insane(
1241            "multi(1,2788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)",
1242        )
1243        .unwrap_err();
1244        // but allowed in segwit
1245        Segwitv0Script::from_str_insane(
1246            "multi(1,022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)",
1247        )
1248        .unwrap();
1249    }
1250
1251    #[test]
1252    fn multi_a_tests() {
1253        // Test from string tests
1254        type Segwitv0Ms = Miniscript<String, Segwitv0>;
1255        type TapMs = Miniscript<String, Tap>;
1256        let segwit_multi_a_ms = Segwitv0Ms::from_str_insane("multi_a(1,A,B,C)");
1257        assert_eq!(
1258            segwit_multi_a_ms.unwrap_err().to_string(),
1259            "Multi a(CHECKSIGADD) only allowed post tapscript"
1260        );
1261        let tap_multi_a_ms = TapMs::from_str_insane("multi_a(1,A,B,C)").unwrap();
1262        assert_eq!(tap_multi_a_ms.to_string(), "multi_a(1,A,B,C)");
1263
1264        // Test encode/decode and translation tests
1265        let tap_ms = tap_multi_a_ms
1266            .translate_pk(&mut StrXOnlyKeyTranslator::new())
1267            .unwrap();
1268        // script rtt test
1269        assert_eq!(
1270            Miniscript::<XOnlyPublicKey, Tap>::parse_insane(&tap_ms.encode()).unwrap(),
1271            tap_ms
1272        );
1273        assert_eq!(tap_ms.script_size(), 104);
1274        assert_eq!(tap_ms.encode().len(), tap_ms.script_size());
1275
1276        // Test satisfaction code
1277        struct SimpleSatisfier(secp256k1::schnorr::Signature);
1278
1279        // a simple satisfier that always outputs the same signature
1280        impl<Pk: ToPublicKey> Satisfier<Pk> for SimpleSatisfier {
1281            fn lookup_tap_leaf_script_sig(
1282                &self,
1283                _pk: &Pk,
1284                _h: &TapLeafHash,
1285            ) -> Option<bitcoin::taproot::Signature> {
1286                Some(bitcoin::taproot::Signature {
1287                    signature: self.0,
1288                    sighash_type: bitcoin::sighash::TapSighashType::Default,
1289                })
1290            }
1291        }
1292
1293        let schnorr_sig = secp256k1::schnorr::Signature::from_str("84526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f0784526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07").unwrap();
1294        let s = SimpleSatisfier(schnorr_sig);
1295        let template = tap_ms.build_template(&s);
1296        assert_eq!(template.absolute_timelock, None);
1297        assert_eq!(template.relative_timelock, None);
1298
1299        let wit = tap_ms.satisfy(&s).unwrap();
1300        assert_eq!(wit, vec![schnorr_sig.as_ref().to_vec(), vec![], vec![]]);
1301    }
1302
1303    #[test]
1304    fn decode_bug_cpp_review() {
1305        let ms = Miniscript::<String, Segwitv0>::from_str_insane(
1306            "and_b(1,s:and_v(v:older(9),c:pk_k(A)))",
1307        )
1308        .unwrap();
1309        let ms_trans = ms.translate_pk(&mut StrKeyTranslator::new()).unwrap();
1310        let enc = ms_trans.encode();
1311        let ms = Miniscript::<bitcoin::PublicKey, Segwitv0>::parse_insane(&enc).unwrap();
1312        assert_eq!(ms_trans.encode(), ms.encode());
1313    }
1314
1315    #[test]
1316    fn expr_features() {
1317        // test that parsing raw hash160 does not work with
1318        let hash160_str = "e9f171df53e04b270fa6271b42f66b0f4a99c5a2";
1319        let ms_str = &format!("c:expr_raw_pkh({})", hash160_str);
1320        type SegwitMs = Miniscript<bitcoin::PublicKey, Segwitv0>;
1321
1322        // Test that parsing raw hash160 from string does not work without extra features
1323        SegwitMs::from_str(ms_str).unwrap_err();
1324        SegwitMs::from_str_insane(ms_str).unwrap_err();
1325        let ms = SegwitMs::from_str_ext(ms_str, &ExtParams::allow_all()).unwrap();
1326
1327        let script = ms.encode();
1328        // The same test, but parsing from script
1329        SegwitMs::parse(&script).unwrap_err();
1330        SegwitMs::parse_insane(&script).unwrap_err();
1331        SegwitMs::parse_with_ext(&script, &ExtParams::allow_all()).unwrap();
1332    }
1333
1334    #[test]
1335    fn tr_multi_a_j_wrapper() {
1336        // Reported by darosior
1337        // `multi_a` fragment may require the top stack element to be the empty vector.
1338        // Previous version had incorrectly copied this code from multi.
1339        type TapMs = Miniscript<String, Tap>;
1340        let ms_str = TapMs::from_str_insane("j:multi_a(1,A,B,C)");
1341        assert!(ms_str.is_err());
1342    }
1343
1344    #[test]
1345    fn translate_tests() {
1346        let ms = Miniscript::<String, Segwitv0>::from_str("pk(A)").unwrap();
1347        let mut t = StrKeyTranslator::new();
1348        let uncompressed = bitcoin::PublicKey::from_str("0400232a2acfc9b43fa89f1b4f608fde335d330d7114f70ea42bfb4a41db368a3e3be6934a4097dd25728438ef73debb1f2ffdb07fec0f18049df13bdc5285dc5b").unwrap();
1349        t.pk_map.insert(String::from("A"), uncompressed);
1350        ms.translate_pk(&mut t).unwrap_err();
1351    }
1352
1353    #[test]
1354    fn template_timelocks() {
1355        use crate::{AbsLockTime, RelLockTime};
1356        let key_present = bitcoin::PublicKey::from_str(
1357            "0327a6ed0e71b451c79327aa9e4a6bb26ffb1c0056abc02c25e783f6096b79bb4f",
1358        )
1359        .unwrap();
1360        let key_missing = bitcoin::PublicKey::from_str(
1361            "03e4d788718644a59030b1d234d8bb8fff28314720b9a1a237874b74b089c638da",
1362        )
1363        .unwrap();
1364
1365        // ms, absolute_timelock, relative_timelock
1366        let test_cases = vec![
1367            (format!("t:or_c(pk({}),v:pkh({}))", key_present, key_missing), None, None),
1368            (
1369                format!("thresh(2,pk({}),s:pk({}),snl:after(1))", key_present, key_missing),
1370                Some(AbsLockTime::from_consensus(1).unwrap()),
1371                None,
1372            ),
1373            (
1374                format!("or_d(pk({}),and_v(v:pk({}),older(12960)))", key_present, key_missing),
1375                None,
1376                None,
1377            ),
1378            (
1379                format!("or_d(pk({}),and_v(v:pk({}),older(12960)))", key_missing, key_present),
1380                None,
1381                Some(RelLockTime::from_height(12960)),
1382            ),
1383            (
1384                format!(
1385                    "thresh(3,pk({}),s:pk({}),snl:older(10),snl:after(11))",
1386                    key_present, key_missing
1387                ),
1388                Some(AbsLockTime::from_consensus(11).unwrap()),
1389                Some(RelLockTime::from_height(10)),
1390            ),
1391            (
1392                format!("and_v(v:and_v(v:pk({}),older(10)),older(20))", key_present),
1393                None,
1394                Some(RelLockTime::from_height(20)),
1395            ),
1396            (
1397                format!(
1398                    "andor(pk({}),older(10),and_v(v:pk({}),older(20)))",
1399                    key_present, key_missing
1400                ),
1401                None,
1402                Some(RelLockTime::from_height(10)),
1403            ),
1404        ];
1405
1406        // Test satisfaction code
1407        struct SimpleSatisfier(secp256k1::schnorr::Signature, bitcoin::PublicKey);
1408
1409        // a simple satisfier that always outputs the same signature
1410        impl Satisfier<bitcoin::PublicKey> for SimpleSatisfier {
1411            fn lookup_tap_leaf_script_sig(
1412                &self,
1413                pk: &bitcoin::PublicKey,
1414                _h: &TapLeafHash,
1415            ) -> Option<bitcoin::taproot::Signature> {
1416                if pk == &self.1 {
1417                    Some(bitcoin::taproot::Signature {
1418                        signature: self.0,
1419                        sighash_type: bitcoin::sighash::TapSighashType::Default,
1420                    })
1421                } else {
1422                    None
1423                }
1424            }
1425
1426            fn check_older(&self, _: bitcoin::relative::LockTime) -> bool { true }
1427
1428            fn check_after(&self, _: bitcoin::absolute::LockTime) -> bool { true }
1429        }
1430
1431        let schnorr_sig = secp256k1::schnorr::Signature::from_str("84526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f0784526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07").unwrap();
1432        let s = SimpleSatisfier(schnorr_sig, key_present);
1433
1434        for (ms_str, absolute_timelock, relative_timelock) in test_cases {
1435            let ms = Miniscript::<bitcoin::PublicKey, Tap>::from_str(&ms_str).unwrap();
1436            let template = ms.build_template(&s);
1437            match template.stack {
1438                crate::miniscript::satisfy::Witness::Stack(_) => {}
1439                _ => panic!("All testcases should be possible"),
1440            }
1441            assert_eq!(template.absolute_timelock, absolute_timelock, "{}", ms_str);
1442            assert_eq!(template.relative_timelock, relative_timelock, "{}", ms_str);
1443        }
1444    }
1445
1446    #[test]
1447    fn test_dos() {
1448        let ms = "slnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn:0";
1449        matches!(
1450            Miniscript::<String, Tap>::from_str_insane(ms),
1451            Err(Error::MaxRecursiveDepthExceeded)
1452        );
1453    }
1454
1455    #[test]
1456    fn test_script_parse_dos() {
1457        let mut script = bitcoin::script::Builder::new().push_opcode(bitcoin::opcodes::OP_TRUE);
1458        for _ in 0..10000 {
1459            script = script.push_opcode(bitcoin::opcodes::all::OP_0NOTEQUAL);
1460        }
1461        Tapscript::parse_insane(&script.into_script()).unwrap_err();
1462    }
1463}
1464
1465#[cfg(bench)]
1466mod benches {
1467    use test::{black_box, Bencher};
1468
1469    use super::*;
1470
1471    #[bench]
1472    pub fn parse_segwit0(bh: &mut Bencher) {
1473        bh.iter(|| {
1474            let tree = Miniscript::<String, context::Segwitv0>::from_str_ext(
1475                "and_v(v:pk(E),thresh(2,j:and_v(v:sha256(H),t:or_i(v:sha256(H),v:pkh(A))),s:pk(B),s:pk(C),s:pk(D),sjtv:sha256(H)))",
1476                &ExtParams::sane(),
1477            ).unwrap();
1478            black_box(tree);
1479        });
1480    }
1481
1482    #[bench]
1483    pub fn parse_segwit0_deep(bh: &mut Bencher) {
1484        bh.iter(|| {
1485            let tree = Miniscript::<String, context::Segwitv0>::from_str_ext(
1486                "and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:and_v(v:pk(1),pk(2)),pk(3)),pk(4)),pk(5)),pk(6)),pk(7)),pk(8)),pk(9)),pk(10)),pk(11)),pk(12)),pk(13)),pk(14)),pk(15)),pk(16)),pk(17)),pk(18)),pk(19)),pk(20)),pk(21))",
1487                &ExtParams::sane(),
1488            ).unwrap();
1489            black_box(tree);
1490        });
1491    }
1492}