miniscript/descriptor/tr/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use core::{cmp, fmt, hash};
4
5use bitcoin::taproot::{TAPROOT_CONTROL_BASE_SIZE, TAPROOT_CONTROL_NODE_SIZE};
6use bitcoin::{opcodes, Address, Network, ScriptBuf, Weight};
7use sync::Arc;
8
9use super::checksum;
10use crate::descriptor::DefiniteDescriptorKey;
11use crate::expression::{self, FromTree};
12use crate::miniscript::satisfy::{Placeholder, Satisfaction, SchnorrSigType, Witness};
13use crate::miniscript::Miniscript;
14use crate::plan::AssetProvider;
15use crate::policy::semantic::Policy;
16use crate::policy::Liftable;
17use crate::prelude::*;
18use crate::util::{varint_len, witness_size};
19use crate::{
20    Error, ForEachKey, FromStrKey, MiniscriptKey, ParseError, Satisfier, ScriptContext, Tap,
21    Threshold, ToPublicKey, TranslateErr, Translator,
22};
23
24mod spend_info;
25mod taptree;
26
27pub use self::spend_info::{TrSpendInfo, TrSpendInfoIter, TrSpendInfoIterItem};
28pub use self::taptree::{TapTree, TapTreeDepthError, TapTreeIter, TapTreeIterItem};
29
30/// A taproot descriptor
31pub struct Tr<Pk: MiniscriptKey> {
32    /// A taproot internal key
33    internal_key: Pk,
34    /// Optional Taproot Tree with spending conditions
35    tree: Option<TapTree<Pk>>,
36    /// Optional spending information associated with the descriptor
37    /// This will be [`None`] when the descriptor is not derived.
38    /// This information will be cached automatically when it is required
39    //
40    // The inner `Arc` here is because Rust does not allow us to return a reference
41    // to the contents of the `Option` from inside a `MutexGuard`. There is no outer
42    // `Arc` because when this structure is cloned, we create a whole new mutex.
43    spend_info: Mutex<Option<Arc<TrSpendInfo<Pk>>>>,
44}
45
46impl<Pk: MiniscriptKey> Clone for Tr<Pk> {
47    fn clone(&self) -> Self {
48        // When cloning, construct a new Mutex so that distinct clones don't
49        // cause blocking between each other. We clone only the internal `Arc`,
50        // so the clone is always cheap (in both time and space)
51        Self {
52            internal_key: self.internal_key.clone(),
53            tree: self.tree.clone(),
54            spend_info: Mutex::new(
55                self.spend_info
56                    .lock()
57                    .expect("Lock poisoned")
58                    .as_ref()
59                    .map(Arc::clone),
60            ),
61        }
62    }
63}
64
65impl<Pk: MiniscriptKey> PartialEq for Tr<Pk> {
66    fn eq(&self, other: &Self) -> bool {
67        self.internal_key == other.internal_key && self.tree == other.tree
68    }
69}
70
71impl<Pk: MiniscriptKey> Eq for Tr<Pk> {}
72
73impl<Pk: MiniscriptKey> PartialOrd for Tr<Pk> {
74    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
75}
76
77impl<Pk: MiniscriptKey> Ord for Tr<Pk> {
78    fn cmp(&self, other: &Self) -> cmp::Ordering {
79        match self.internal_key.cmp(&other.internal_key) {
80            cmp::Ordering::Equal => {}
81            ord => return ord,
82        }
83        self.tree.cmp(&other.tree)
84    }
85}
86
87impl<Pk: MiniscriptKey> hash::Hash for Tr<Pk> {
88    fn hash<H: hash::Hasher>(&self, state: &mut H) {
89        self.internal_key.hash(state);
90        self.tree.hash(state);
91    }
92}
93
94impl<Pk: MiniscriptKey> Tr<Pk> {
95    /// Create a new [`Tr`] descriptor from internal key and [`TapTree`]
96    pub fn new(internal_key: Pk, tree: Option<TapTree<Pk>>) -> Result<Self, Error> {
97        Tap::check_pk(&internal_key)?;
98        Ok(Self { internal_key, tree, spend_info: Mutex::new(None) })
99    }
100
101    /// Obtain the internal key of [`Tr`] descriptor
102    pub fn internal_key(&self) -> &Pk { &self.internal_key }
103
104    /// Obtain the [`TapTree`] of the [`Tr`] descriptor
105    pub fn tap_tree(&self) -> Option<&TapTree<Pk>> { self.tree.as_ref() }
106
107    /// Iterates over all the leaves of the tree in depth-first preorder.
108    ///
109    /// The yielded elements include the Miniscript for each leave as well as its depth
110    /// in the tree, which is the data required by PSBT (BIP 371).
111    pub fn leaves(&self) -> TapTreeIter<'_, Pk> {
112        match self.tree {
113            Some(ref t) => t.leaves(),
114            None => TapTreeIter::empty(),
115        }
116    }
117
118    /// Obtain the spending information for this [`Tr`].
119    ///
120    /// The first time this method is called, it computes the full Taproot Merkle tree of
121    /// all branches as well as the output key which appears on-chain. This is fairly
122    /// expensive since it requires hashing every branch and then doing an elliptic curve
123    /// operation. The result is cached and reused on subsequent calls.
124    ///
125    /// This data is needed to compute the Taproot output, so this method is implicitly
126    /// called through [`Self::script_pubkey`], [`Self::address`], etc. It is also needed
127    /// to compute the hash needed to sign the output.
128    pub fn spend_info(&self) -> Arc<TrSpendInfo<Pk>>
129    where
130        Pk: ToPublicKey,
131    {
132        let mut lock = self.spend_info.lock().unwrap();
133        match *lock {
134            Some(ref res) => Arc::clone(res),
135            None => {
136                let arc = Arc::new(TrSpendInfo::from_tr(self));
137                *lock = Some(Arc::clone(&arc));
138                arc
139            }
140        }
141    }
142
143    /// Checks whether the descriptor is safe.
144    pub fn sanity_check(&self) -> Result<(), Error> {
145        for leaf in self.leaves() {
146            leaf.miniscript().sanity_check()?;
147        }
148        Ok(())
149    }
150
151    /// Computes an upper bound on the difference between a non-satisfied
152    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
153    ///
154    /// Assumes all Schnorr signatures are 66 bytes, including push opcode and
155    /// sighash suffix.
156    ///
157    /// # Errors
158    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
159    pub fn max_weight_to_satisfy(&self) -> Result<Weight, Error> {
160        let tree = match self.tap_tree() {
161            None => {
162                // key spend path
163                // item: varint(sig+sigHash) + <sig(64)+sigHash(1)>
164                let item_sig_size = 1 + 65;
165                // 1 stack item
166                let stack_varint_diff = varint_len(1) - varint_len(0);
167
168                return Ok(Weight::from_wu((stack_varint_diff + item_sig_size) as u64));
169            }
170            // script path spend..
171            Some(tree) => tree,
172        };
173
174        let wu = tree
175            .leaves()
176            .filter_map(|leaf| {
177                let script_size = leaf.miniscript().script_size();
178                let max_sat_elems = leaf.miniscript().max_satisfaction_witness_elements().ok()?;
179                let max_sat_size = leaf.miniscript().max_satisfaction_size().ok()?;
180                let control_block_size = control_block_len(leaf.depth());
181
182                // stack varint difference (+1 for ctrl block, witness script already included)
183                let stack_varint_diff = varint_len(max_sat_elems + 1) - varint_len(0);
184
185                Some(
186                    stack_varint_diff +
187                    // size of elements to satisfy script
188                    max_sat_size +
189                    // second to last element: script
190                    varint_len(script_size) +
191                    script_size +
192                    // last element: control block
193                    varint_len(control_block_size) +
194                    control_block_size,
195                )
196            })
197            .max()
198            .ok_or(Error::ImpossibleSatisfaction)?;
199
200        Ok(Weight::from_wu(wu as u64))
201    }
202
203    /// Computes an upper bound on the weight of a satisfying witness to the
204    /// transaction.
205    ///
206    /// Assumes all ec-signatures are 73 bytes, including push opcode and
207    /// sighash suffix. Includes the weight of the VarInts encoding the
208    /// scriptSig and witness stack length.
209    ///
210    /// # Errors
211    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
212    #[deprecated(
213        since = "10.0.0",
214        note = "Use max_weight_to_satisfy instead. The method to count bytes was redesigned and the results will differ from max_weight_to_satisfy. For more details check rust-bitcoin/rust-miniscript#476."
215    )]
216    pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
217        let tree = match self.tap_tree() {
218            // key spend path:
219            // scriptSigLen(4) + stackLen(1) + stack[Sig]Len(1) + stack[Sig](65)
220            None => return Ok(4 + 1 + 1 + 65),
221            // script path spend..
222            Some(tree) => tree,
223        };
224
225        tree.leaves()
226            .filter_map(|leaf| {
227                let script_size = leaf.miniscript().script_size();
228                let max_sat_elems = leaf.miniscript().max_satisfaction_witness_elements().ok()?;
229                let max_sat_size = leaf.miniscript().max_satisfaction_size().ok()?;
230                let control_block_size = control_block_len(leaf.depth());
231                Some(
232                    // scriptSig len byte
233                    4 +
234                    // witness field stack len (+2 for control block & script)
235                    varint_len(max_sat_elems + 2) +
236                    // size of elements to satisfy script
237                    max_sat_size +
238                    // second to last element: script
239                    varint_len(script_size) +
240                    script_size +
241                    // last element: control block
242                    varint_len(control_block_size) +
243                    control_block_size,
244                )
245            })
246            .max()
247            .ok_or(Error::ImpossibleSatisfaction)
248    }
249
250    /// Converts keys from one type of public key to another.
251    pub fn translate_pk<T>(
252        &self,
253        translate: &mut T,
254    ) -> Result<Tr<T::TargetPk>, TranslateErr<T::Error>>
255    where
256        T: Translator<Pk>,
257    {
258        let tree = match &self.tree {
259            Some(tree) => Some(tree.translate_pk(translate)?),
260            None => None,
261        };
262        let translate_desc =
263            Tr::new(translate.pk(&self.internal_key)?, tree).map_err(TranslateErr::OuterError)?;
264        Ok(translate_desc)
265    }
266}
267
268impl<Pk: MiniscriptKey + ToPublicKey> Tr<Pk> {
269    /// Obtains the corresponding script pubkey for this descriptor.
270    pub fn script_pubkey(&self) -> ScriptBuf {
271        let output_key = self.spend_info().output_key();
272        let builder = bitcoin::blockdata::script::Builder::new();
273        builder
274            .push_opcode(opcodes::all::OP_PUSHNUM_1)
275            .push_slice(output_key.serialize())
276            .into_script()
277    }
278
279    /// Obtains the corresponding address for this descriptor.
280    pub fn address(&self, network: Network) -> Address {
281        let spend_info = self.spend_info();
282        Address::p2tr_tweaked(spend_info.output_key(), network)
283    }
284
285    /// Returns satisfying non-malleable witness and scriptSig with minimum
286    /// weight to spend an output controlled by the given descriptor if it is
287    /// possible to construct one using the `satisfier`.
288    pub fn get_satisfaction<S>(&self, satisfier: &S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
289    where
290        S: Satisfier<Pk>,
291    {
292        let satisfaction = best_tap_spend(self, satisfier, false /* allow_mall */)
293            .try_completing(satisfier)
294            .expect("the same satisfier should manage to complete the template");
295        if let Witness::Stack(stack) = satisfaction.stack {
296            Ok((stack, ScriptBuf::new()))
297        } else {
298            Err(Error::CouldNotSatisfy)
299        }
300    }
301
302    /// Returns satisfying, possibly malleable, witness and scriptSig with
303    /// minimum weight to spend an output controlled by the given descriptor if
304    /// it is possible to construct one using the `satisfier`.
305    pub fn get_satisfaction_mall<S>(
306        &self,
307        satisfier: &S,
308    ) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
309    where
310        S: Satisfier<Pk>,
311    {
312        let satisfaction = best_tap_spend(self, satisfier, true /* allow_mall */)
313            .try_completing(satisfier)
314            .expect("the same satisfier should manage to complete the template");
315        if let Witness::Stack(stack) = satisfaction.stack {
316            Ok((stack, ScriptBuf::new()))
317        } else {
318            Err(Error::CouldNotSatisfy)
319        }
320    }
321}
322
323impl Tr<DefiniteDescriptorKey> {
324    /// Returns a plan if the provided assets are sufficient to produce a non-malleable satisfaction
325    pub fn plan_satisfaction<P>(
326        &self,
327        provider: &P,
328    ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
329    where
330        P: AssetProvider<DefiniteDescriptorKey>,
331    {
332        best_tap_spend(self, provider, false /* allow_mall */)
333    }
334
335    /// Returns a plan if the provided assets are sufficient to produce a malleable satisfaction
336    pub fn plan_satisfaction_mall<P>(
337        &self,
338        provider: &P,
339    ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
340    where
341        P: AssetProvider<DefiniteDescriptorKey>,
342    {
343        best_tap_spend(self, provider, true /* allow_mall */)
344    }
345}
346
347impl<Pk: FromStrKey> core::str::FromStr for Tr<Pk> {
348    type Err = Error;
349
350    fn from_str(s: &str) -> Result<Self, Self::Err> {
351        let expr_tree = expression::Tree::from_str(s)?;
352        Self::from_tree(expr_tree.root())
353    }
354}
355
356impl<Pk: FromStrKey> crate::expression::FromTree for Tr<Pk> {
357    fn from_tree(root: expression::TreeIterItem) -> Result<Self, Error> {
358        use crate::expression::{Parens, ParseTreeError};
359
360        root.verify_toplevel("tr", 1..=2)
361            .map_err(From::from)
362            .map_err(Error::Parse)?;
363
364        let mut root_children = root.children();
365        let internal_key: Pk = root_children
366            .next()
367            .unwrap() // `verify_toplevel` above checked that first child existed
368            .verify_terminal("internal key")
369            .map_err(Error::Parse)?;
370
371        let tap_tree = match root_children.next() {
372            None => return Tr::new(internal_key, None),
373            Some(tree) => tree,
374        };
375
376        let mut tree_builder = taptree::TapTreeBuilder::new();
377        let mut tap_tree_iter = tap_tree.pre_order_iter();
378        // while let construction needed because we modify the iterator inside the loop
379        // (by calling skip_descendants to skip over the contents of the tapscripts).
380        while let Some(node) = tap_tree_iter.next() {
381            if node.parens() == Parens::Curly {
382                if !node.name().is_empty() {
383                    return Err(Error::Parse(ParseError::Tree(ParseTreeError::IncorrectName {
384                        actual: node.name().to_owned(),
385                        expected: "",
386                    })));
387                }
388                node.verify_n_children("taptree branch", 2..=2)
389                    .map_err(From::from)
390                    .map_err(Error::Parse)?;
391                tree_builder.push_inner_node()?;
392            } else {
393                let script = Miniscript::from_tree(node)?;
394                // FIXME hack for https://github.com/rust-bitcoin/rust-miniscript/issues/734
395                if script.ty.corr.base != crate::miniscript::types::Base::B {
396                    return Err(Error::NonTopLevel(format!("{:?}", script)));
397                };
398
399                tree_builder.push_leaf(script);
400                tap_tree_iter.skip_descendants();
401            }
402        }
403        Tr::new(internal_key, Some(tree_builder.finalize()))
404    }
405}
406
407impl<Pk: MiniscriptKey> fmt::Debug for Tr<Pk> {
408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409        match self.tree {
410            Some(ref s) => write!(f, "tr({:?},{:?})", self.internal_key, s),
411            None => write!(f, "tr({:?})", self.internal_key),
412        }
413    }
414}
415
416impl<Pk: MiniscriptKey> fmt::Display for Tr<Pk> {
417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418        use fmt::Write;
419        let mut wrapped_f = checksum::Formatter::new(f);
420        let key = &self.internal_key;
421        match self.tree {
422            Some(ref s) => write!(wrapped_f, "tr({},{})", key, s)?,
423            None => write!(wrapped_f, "tr({})", key)?,
424        }
425        wrapped_f.write_checksum_if_not_alt()
426    }
427}
428
429impl<Pk: MiniscriptKey> Liftable<Pk> for Tr<Pk> {
430    fn lift(&self) -> Result<Policy<Pk>, Error> {
431        match &self.tree {
432            Some(root) => Ok(Policy::Thresh(Threshold::or(
433                Arc::new(Policy::Key(self.internal_key.clone())),
434                Arc::new(root.lift()?),
435            ))),
436            None => Ok(Policy::Key(self.internal_key.clone())),
437        }
438    }
439}
440
441impl<Pk: MiniscriptKey> ForEachKey<Pk> for Tr<Pk> {
442    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool {
443        let script_keys_res = self
444            .leaves()
445            .all(|leaf| leaf.miniscript().for_each_key(&mut pred));
446        script_keys_res && pred(&self.internal_key)
447    }
448}
449
450// Helper function to compute the len of control block at a given depth
451fn control_block_len(depth: u8) -> usize {
452    TAPROOT_CONTROL_BASE_SIZE + (depth as usize) * TAPROOT_CONTROL_NODE_SIZE
453}
454
455// Helper function to get a script spend satisfaction
456// try script spend
457fn best_tap_spend<Pk, P>(
458    desc: &Tr<Pk>,
459    provider: &P,
460    allow_mall: bool,
461) -> Satisfaction<Placeholder<Pk>>
462where
463    Pk: ToPublicKey,
464    P: AssetProvider<Pk>,
465{
466    let spend_info = desc.spend_info();
467    // First try the key spend path
468    if let Some(size) = provider.provider_lookup_tap_key_spend_sig(&desc.internal_key) {
469        Satisfaction {
470            stack: Witness::Stack(vec![Placeholder::SchnorrSigPk(
471                desc.internal_key.clone(),
472                SchnorrSigType::KeySpend { merkle_root: spend_info.merkle_root() },
473                size,
474            )]),
475            has_sig: true,
476            absolute_timelock: None,
477            relative_timelock: None,
478        }
479    } else {
480        // Since we have the complete descriptor we can ignore the satisfier. We don't use the control block
481        // map (lookup_control_block) from the satisfier here.
482        let mut min_satisfaction = Satisfaction {
483            stack: Witness::Unavailable,
484            has_sig: false,
485            relative_timelock: None,
486            absolute_timelock: None,
487        };
488        let mut min_wit_len = None;
489        for leaf in spend_info.leaves() {
490            let mut satisfaction = if allow_mall {
491                match leaf.miniscript().build_template_mall(provider) {
492                    s @ Satisfaction { stack: Witness::Stack(_), .. } => s,
493                    _ => continue, // No witness for this script in tr descriptor, look for next one
494                }
495            } else {
496                match leaf.miniscript().build_template(provider) {
497                    s @ Satisfaction { stack: Witness::Stack(_), .. } => s,
498                    _ => continue, // No witness for this script in tr descriptor, look for next one
499                }
500            };
501            let wit = match satisfaction {
502                Satisfaction { stack: Witness::Stack(ref mut wit), .. } => wit,
503                _ => unreachable!(),
504            };
505
506            let script = ScriptBuf::from(leaf.script());
507            let control_block = leaf.control_block().clone();
508
509            wit.push(Placeholder::TapScript(script));
510            wit.push(Placeholder::TapControlBlock(control_block));
511
512            let wit_size = witness_size(wit);
513            if min_wit_len.is_some() && Some(wit_size) > min_wit_len {
514                continue;
515            } else {
516                min_satisfaction = satisfaction;
517                min_wit_len = Some(wit_size);
518            }
519        }
520
521        min_satisfaction
522    }
523}
524
525#[cfg(test)]
526mod tests {
527    use core::str::FromStr;
528
529    use super::*;
530
531    fn descriptor() -> String {
532        let desc = "tr(acc0, {
533            multi_a(3, acc10, acc11, acc12), {
534              and_v(
535                v:multi_a(2, acc10, acc11, acc12),
536                after(10)
537              ),
538              and_v(
539                v:multi_a(1, acc10, acc11, ac12),
540                after(100)
541              )
542            }
543         })";
544        desc.replace(&[' ', '\n'][..], "")
545    }
546
547    #[test]
548    fn for_each() {
549        let desc = descriptor();
550        let tr = Tr::<String>::from_str(&desc).unwrap();
551        // Note the last ac12 only has ac and fails the predicate
552        assert!(!tr.for_each_key(|k| k.starts_with("acc")));
553    }
554
555    #[test]
556    fn tr_maximum_depth() {
557        // Copied from integration tests
558        let descriptor128 = "tr(X!,{pk(X1!),{pk(X2!),{pk(X3!),{pk(X4!),{pk(X5!),{pk(X6!),{pk(X7!),{pk(X8!),{pk(X9!),{pk(X10!),{pk(X11!),{pk(X12!),{pk(X13!),{pk(X14!),{pk(X15!),{pk(X16!),{pk(X17!),{pk(X18!),{pk(X19!),{pk(X20!),{pk(X21!),{pk(X22!),{pk(X23!),{pk(X24!),{pk(X25!),{pk(X26!),{pk(X27!),{pk(X28!),{pk(X29!),{pk(X30!),{pk(X31!),{pk(X32!),{pk(X33!),{pk(X34!),{pk(X35!),{pk(X36!),{pk(X37!),{pk(X38!),{pk(X39!),{pk(X40!),{pk(X41!),{pk(X42!),{pk(X43!),{pk(X44!),{pk(X45!),{pk(X46!),{pk(X47!),{pk(X48!),{pk(X49!),{pk(X50!),{pk(X51!),{pk(X52!),{pk(X53!),{pk(X54!),{pk(X55!),{pk(X56!),{pk(X57!),{pk(X58!),{pk(X59!),{pk(X60!),{pk(X61!),{pk(X62!),{pk(X63!),{pk(X64!),{pk(X65!),{pk(X66!),{pk(X67!),{pk(X68!),{pk(X69!),{pk(X70!),{pk(X71!),{pk(X72!),{pk(X73!),{pk(X74!),{pk(X75!),{pk(X76!),{pk(X77!),{pk(X78!),{pk(X79!),{pk(X80!),{pk(X81!),{pk(X82!),{pk(X83!),{pk(X84!),{pk(X85!),{pk(X86!),{pk(X87!),{pk(X88!),{pk(X89!),{pk(X90!),{pk(X91!),{pk(X92!),{pk(X93!),{pk(X94!),{pk(X95!),{pk(X96!),{pk(X97!),{pk(X98!),{pk(X99!),{pk(X100!),{pk(X101!),{pk(X102!),{pk(X103!),{pk(X104!),{pk(X105!),{pk(X106!),{pk(X107!),{pk(X108!),{pk(X109!),{pk(X110!),{pk(X111!),{pk(X112!),{pk(X113!),{pk(X114!),{pk(X115!),{pk(X116!),{pk(X117!),{pk(X118!),{pk(X119!),{pk(X120!),{pk(X121!),{pk(X122!),{pk(X123!),{pk(X124!),{pk(X125!),{pk(X126!),{pk(X127!),{pk(X128!),pk(X129)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}})";
559        descriptor128.parse::<crate::Descriptor<String>>().unwrap();
560
561        // Copied from integration tests
562        let descriptor129 = "tr(X!,{pk(X1!),{pk(X2!),{pk(X3!),{pk(X4!),{pk(X5!),{pk(X6!),{pk(X7!),{pk(X8!),{pk(X9!),{pk(X10!),{pk(X11!),{pk(X12!),{pk(X13!),{pk(X14!),{pk(X15!),{pk(X16!),{pk(X17!),{pk(X18!),{pk(X19!),{pk(X20!),{pk(X21!),{pk(X22!),{pk(X23!),{pk(X24!),{pk(X25!),{pk(X26!),{pk(X27!),{pk(X28!),{pk(X29!),{pk(X30!),{pk(X31!),{pk(X32!),{pk(X33!),{pk(X34!),{pk(X35!),{pk(X36!),{pk(X37!),{pk(X38!),{pk(X39!),{pk(X40!),{pk(X41!),{pk(X42!),{pk(X43!),{pk(X44!),{pk(X45!),{pk(X46!),{pk(X47!),{pk(X48!),{pk(X49!),{pk(X50!),{pk(X51!),{pk(X52!),{pk(X53!),{pk(X54!),{pk(X55!),{pk(X56!),{pk(X57!),{pk(X58!),{pk(X59!),{pk(X60!),{pk(X61!),{pk(X62!),{pk(X63!),{pk(X64!),{pk(X65!),{pk(X66!),{pk(X67!),{pk(X68!),{pk(X69!),{pk(X70!),{pk(X71!),{pk(X72!),{pk(X73!),{pk(X74!),{pk(X75!),{pk(X76!),{pk(X77!),{pk(X78!),{pk(X79!),{pk(X80!),{pk(X81!),{pk(X82!),{pk(X83!),{pk(X84!),{pk(X85!),{pk(X86!),{pk(X87!),{pk(X88!),{pk(X89!),{pk(X90!),{pk(X91!),{pk(X92!),{pk(X93!),{pk(X94!),{pk(X95!),{pk(X96!),{pk(X97!),{pk(X98!),{pk(X99!),{pk(X100!),{pk(X101!),{pk(X102!),{pk(X103!),{pk(X104!),{pk(X105!),{pk(X106!),{pk(X107!),{pk(X108!),{pk(X109!),{pk(X110!),{pk(X111!),{pk(X112!),{pk(X113!),{pk(X114!),{pk(X115!),{pk(X116!),{pk(X117!),{pk(X118!),{pk(X119!),{pk(X120!),{pk(X121!),{pk(X122!),{pk(X123!),{pk(X124!),{pk(X125!),{pk(X126!),{pk(X127!),{pk(X128!),{pk(X129),pk(X130)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}})";
563        assert!(matches!(
564            descriptor129
565                .parse::<crate::Descriptor::<String>>()
566                .unwrap_err(),
567            crate::Error::TapTreeDepthError(TapTreeDepthError),
568        ));
569    }
570}