55// DescriptorTrait,
66// };
77use bitcoin:: hashes:: _export:: _core:: fmt:: Formatter ;
8+ use errstr;
89use expression:: { self , FromTree , Tree } ;
910use std:: sync:: Arc ;
1011use std:: { fmt, str:: FromStr } ;
1112use Segwitv0 ;
13+ use MAX_RECURSION_DEPTH ;
1214use { miniscript:: Miniscript , Error , MiniscriptKey } ;
1315
14- // TODO: Update this to infer version from descriptor.
15- const VER : u8 = 0xc0 ;
16-
1716#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
1817pub enum TapTree < Pk : MiniscriptKey > {
1918 Tree ( Arc < TapTree < Pk > > , Arc < TapTree < Pk > > ) ,
20- Miniscript_ ( u8 , Arc < Miniscript < Pk , Segwitv0 > > ) ,
19+ Miniscript_ ( Arc < Miniscript < Pk , Segwitv0 > > ) ,
2120}
2221
2322#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
3534{
3635 pub fn to_string_no_checksum ( & self ) -> String {
3736 match self {
38- TapTree :: Tree ( ref left, ref right) => format ! ( "{{{},{}}}" , * left, * right) ,
39- TapTree :: Miniscript_ ( _, ref miniscript) => format ! ( "{}" , * miniscript) ,
37+ TapTree :: Tree ( ref left, ref right) => {
38+ format ! ( "{{{},{}}}" , * left. clone( ) , * right. clone( ) )
39+ }
40+ TapTree :: Miniscript_ ( ref script) => format ! ( "{}" , * script. clone( ) ) ,
4041 }
4142 }
4243}
5152 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
5253 let desc = self . to_string_no_checksum ( ) ;
5354 // let checksum = desc_checksum(&desc).map_err(|_| fmt::Error)?;
54- // write!(f, "{}", &desc)
55+ // write!(f, "{}#{} ", &desc, &checksum )
5556 write ! ( f, "{}" , & desc)
5657 }
5758}
9091 // Sanity checks
9192 let script = Self :: parse_miniscript ( script) ?;
9293 let script = Arc :: new ( script) ;
93- Ok ( TapTree :: Miniscript_ ( VER , script) )
94+ Ok ( TapTree :: Miniscript_ ( script) )
9495 }
9596 Tree { name, args } if name. len ( ) == 0 && args. len ( ) == 2 => {
9697 // visit children
@@ -112,7 +113,7 @@ where
112113 }
113114}
114115
115- impl < Pk > FromTree for Tr < Pk >
116+ impl < Pk : MiniscriptKey > FromTree for Tr < Pk >
116117where
117118 Pk : MiniscriptKey + FromStr ,
118119 Pk :: Hash : FromStr ,
@@ -143,32 +144,32 @@ where
143144 key. args. len( )
144145 ) ) ) ;
145146 }
146- let ref tree = top. args [ 1 ] ; // Tree name should be a valid miniscript except the base case
147- let ret = Tr :: tr_script_path ( & tree) ?;
147+ let ref tree = top. args [ 1 ] ;
148+ let ret = Tr :: tr_script_path ( tree) ?;
148149 Ok ( Tr {
149150 key_path : expression:: terminal ( key, Pk :: from_str) ?,
150151 script_path : Some ( ret) ,
151152 } )
152153 }
153154 _ => {
154155 return Err ( Error :: Unexpected ( format ! (
155- "{}( {} args) while parsing taproot descriptor" ,
156+ "{}[# {} args] while parsing taproot descriptor" ,
156157 top. name,
157158 top. args. len( )
158159 ) ) ) ;
159160 }
160161 }
161162 } else {
162163 return Err ( Error :: Unexpected ( format ! (
163- "{}( {} args) while parsing taproot descriptor" ,
164+ "{}[# {} args] while parsing taproot descriptor" ,
164165 top. name,
165166 top. args. len( )
166167 ) ) ) ;
167168 }
168169 }
169170}
170171
171- impl < Pk > FromStr for Tr < Pk >
172+ impl < Pk : MiniscriptKey > FromStr for Tr < Pk >
172173where
173174 Pk : MiniscriptKey + FromStr ,
174175 Pk :: Hash : FromStr ,
@@ -180,8 +181,10 @@ where
180181 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
181182 // let desc_str = verify_checksum(s)?;
182183 // let top = expression::Tree::from_str(desc_str)?;
183- let top = expression:: Tree :: from_str ( s) ?;
184- Self :: from_tree ( & top)
184+
185+ // Pass the TapTree then
186+ let top = parse_tr ( s) ?;
187+ Self :: from_tree ( & top) // parse taptree and tapscript differently
185188 }
186189}
187190
@@ -193,9 +196,113 @@ where
193196 <<Pk as MiniscriptKey >:: Hash as FromStr >:: Err : ToString ,
194197{
195198 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
199+ let key = & self . key_path ;
196200 match self . script_path {
197- Some ( ref s) => write ! ( f, "tr({},{})" , self . key_path, s) ,
198- None => write ! ( f, "tr({})" , self . key_path) ,
201+ Some ( ref s) => write ! ( f, "tr({},{})" , key, s) ,
202+ None => write ! ( f, "tr({})" , key) ,
203+ }
204+ }
205+ }
206+
207+ /// TODO: Refactor to make from_str more generic in `expression.rs`?
208+ fn parse_tr < ' a > ( s : & ' a str ) -> Result < Tree < ' a > , Error > {
209+ for ch in s. bytes ( ) {
210+ if ch > 0x7f {
211+ return Err ( Error :: Unprintable ( ch) ) ;
212+ }
213+ }
214+
215+ let ( top, rem) = parse_tr_helper ( s, 0 ) ?;
216+ if rem. is_empty ( ) {
217+ Ok ( top)
218+ } else {
219+ Err ( errstr ( rem) )
220+ }
221+ }
222+
223+ /// Helper function to parse Taproot Descriptor into key_path and TapTree
224+ fn parse_tr_helper < ' a > ( mut sl : & ' a str , depth : u32 ) -> Result < ( Tree < ' a > , & ' a str ) , Error > {
225+ if depth >= MAX_RECURSION_DEPTH {
226+ return Err ( Error :: MaxRecursiveDepthExceeded ) ;
227+ }
228+
229+ enum Found {
230+ Nothing ,
231+ Lparen ( usize ) ,
232+ Comma ( usize ) ,
233+ Rparen ( usize ) ,
234+ }
235+
236+ let mut found = Found :: Nothing ;
237+ for ( n, ch) in sl. char_indices ( ) {
238+ match ch {
239+ '(' => {
240+ found = Found :: Lparen ( n) ;
241+ break ;
242+ }
243+ ',' => {
244+ found = Found :: Comma ( n) ;
245+ break ;
246+ }
247+ ')' => {
248+ found = Found :: Rparen ( n) ;
249+ break ;
250+ }
251+ _ => { }
252+ }
253+ }
254+
255+ match found {
256+ // String-ending terminal
257+ Found :: Nothing => Ok ( (
258+ Tree {
259+ name : & sl[ ..] ,
260+ args : vec ! [ ] ,
261+ } ,
262+ "" ,
263+ ) ) ,
264+ // Terminal
265+ Found :: Comma ( n) | Found :: Rparen ( n) => Ok ( (
266+ Tree {
267+ name : & sl[ ..n] ,
268+ args : vec ! [ ] ,
269+ } ,
270+ & sl[ n..] ,
271+ ) ) ,
272+ // Function call
273+ Found :: Lparen ( n) => {
274+ let mut ret = Tree {
275+ name : & sl[ ..n] ,
276+ args : vec ! [ ] ,
277+ } ;
278+
279+ sl = & sl[ n + 1 ..] ;
280+ let mut prev_sl: & str = "" ;
281+ let mut prev_arg: Tree ;
282+ loop {
283+ if prev_sl. contains ( "{" ) {
284+ let ( arg, new_sl) = expression:: Tree :: from_slice_helper_curly ( sl, depth + 1 ) ?;
285+ prev_arg = arg;
286+ prev_sl = new_sl;
287+ } else {
288+ let ( arg, new_sl) = parse_tr_helper ( sl, depth + 1 ) ?;
289+ prev_arg = arg;
290+ prev_sl = new_sl;
291+ }
292+ ret. args . push ( prev_arg) ;
293+
294+ if prev_sl. is_empty ( ) {
295+ return Err ( Error :: ExpectedChar ( ')' ) ) ;
296+ }
297+
298+ sl = & prev_sl[ 1 ..] ;
299+ match prev_sl. as_bytes ( ) [ 0 ] {
300+ b',' => { }
301+ b')' => break ,
302+ _ => return Err ( Error :: ExpectedChar ( ')' ) ) ,
303+ }
304+ }
305+ Ok ( ( ret, sl) )
199306 }
200307 }
201308}
0 commit comments