|
1 | 1 | // Tapscript |
2 | 2 |
|
3 | 3 | use std::cmp::{self, max}; |
4 | | -use std::str::FromStr; |
5 | 4 | use std::sync::{Arc, Mutex}; |
6 | 5 | use std::{fmt, hash}; |
7 | 6 |
|
@@ -417,7 +416,7 @@ impl_block_str!( |
417 | 416 | fn parse_tr_script_spend(tree: &expression::Tree,) -> Result<TapTree<Pk, Ext>, Error> { |
418 | 417 | match tree { |
419 | 418 | expression::Tree { name, args } if !name.is_empty() && args.is_empty() => { |
420 | | - let script = Miniscript::<Pk, Tap, Ext>::from_str(name)?; |
| 419 | + let script = Miniscript::<Pk, Tap, Ext>::from_str_insane(name)?; |
421 | 420 | Ok(TapTree::Leaf(Arc::new(script))) |
422 | 421 | } |
423 | 422 | expression::Tree { name, args } if name.is_empty() && args.len() == 2 => { |
@@ -484,6 +483,20 @@ impl_from_str!( |
484 | 483 | => Ext; Extension, |
485 | 484 | type Err = Error;, |
486 | 485 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 486 | + let res = Self::from_str_insane(s)?; |
| 487 | + if res.iter_scripts().any(|(_, ms)| ms.sanity_check().is_err()) { |
| 488 | + return Err(Error::BadDescriptor("Sanity check failed".to_string())); |
| 489 | + } |
| 490 | + Ok(res) |
| 491 | + } |
| 492 | +); |
| 493 | + |
| 494 | +#[rustfmt::skip] |
| 495 | +impl_block_str!( |
| 496 | + Tr<Pk, Ext>, |
| 497 | + => Ext; Extension, |
| 498 | + /// Parse taproot descriptors without any sanity checks |
| 499 | + pub fn from_str_insane(s: &str,) -> Result<Tr<Pk, Ext>, Error> { |
487 | 500 | let desc_str = verify_checksum(s)?; |
488 | 501 | let top = parse_tr_tree(desc_str)?; |
489 | 502 | Self::from_tree(&top) |
@@ -742,6 +755,7 @@ where |
742 | 755 | mod tests { |
743 | 756 | use super::*; |
744 | 757 | use crate::{ForEachKey, NoExt}; |
| 758 | + use core::str::FromStr; |
745 | 759 |
|
746 | 760 | #[test] |
747 | 761 | fn test_for_each() { |
|
0 commit comments