5
5
// DescriptorTrait,
6
6
// };
7
7
use bitcoin:: hashes:: _export:: _core:: fmt:: Formatter ;
8
+ use errstr;
8
9
use expression:: { self , FromTree , Tree } ;
9
10
use std:: sync:: Arc ;
10
11
use std:: { fmt, str:: FromStr } ;
11
12
use Segwitv0 ;
13
+ use MAX_RECURSION_DEPTH ;
12
14
use { miniscript:: Miniscript , Error , MiniscriptKey } ;
13
15
14
- // TODO: Update this to infer version from descriptor.
15
- const VER : u8 = 0xc0 ;
16
-
17
16
#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
18
17
pub enum TapTree < Pk : MiniscriptKey > {
19
18
Tree ( Arc < TapTree < Pk > > , Arc < TapTree < Pk > > ) ,
20
- Miniscript_ ( u8 , Arc < Miniscript < Pk , Segwitv0 > > ) ,
19
+ Miniscript_ ( Arc < Miniscript < Pk , Segwitv0 > > ) ,
21
20
}
22
21
23
22
#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
35
34
{
36
35
pub fn to_string_no_checksum ( & self ) -> String {
37
36
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( ) ) ,
40
41
}
41
42
}
42
43
}
51
52
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
52
53
let desc = self . to_string_no_checksum ( ) ;
53
54
// let checksum = desc_checksum(&desc).map_err(|_| fmt::Error)?;
54
- // write!(f, "{}", &desc)
55
+ // write!(f, "{}#{} ", &desc, &checksum )
55
56
write ! ( f, "{}" , & desc)
56
57
}
57
58
}
90
91
// Sanity checks
91
92
let script = Self :: parse_miniscript ( script) ?;
92
93
let script = Arc :: new ( script) ;
93
- Ok ( TapTree :: Miniscript_ ( VER , script) )
94
+ Ok ( TapTree :: Miniscript_ ( script) )
94
95
}
95
96
Tree { name, args } if name. len ( ) == 0 && args. len ( ) == 2 => {
96
97
// visit children
@@ -112,7 +113,7 @@ where
112
113
}
113
114
}
114
115
115
- impl < Pk > FromTree for Tr < Pk >
116
+ impl < Pk : MiniscriptKey > FromTree for Tr < Pk >
116
117
where
117
118
Pk : MiniscriptKey + FromStr ,
118
119
Pk :: Hash : FromStr ,
@@ -143,32 +144,32 @@ where
143
144
key. args. len( )
144
145
) ) ) ;
145
146
}
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) ?;
148
149
Ok ( Tr {
149
150
key_path : expression:: terminal ( key, Pk :: from_str) ?,
150
151
script_path : Some ( ret) ,
151
152
} )
152
153
}
153
154
_ => {
154
155
return Err ( Error :: Unexpected ( format ! (
155
- "{}( {} args) while parsing taproot descriptor" ,
156
+ "{}[# {} args] while parsing taproot descriptor" ,
156
157
top. name,
157
158
top. args. len( )
158
159
) ) ) ;
159
160
}
160
161
}
161
162
} else {
162
163
return Err ( Error :: Unexpected ( format ! (
163
- "{}( {} args) while parsing taproot descriptor" ,
164
+ "{}[# {} args] while parsing taproot descriptor" ,
164
165
top. name,
165
166
top. args. len( )
166
167
) ) ) ;
167
168
}
168
169
}
169
170
}
170
171
171
- impl < Pk > FromStr for Tr < Pk >
172
+ impl < Pk : MiniscriptKey > FromStr for Tr < Pk >
172
173
where
173
174
Pk : MiniscriptKey + FromStr ,
174
175
Pk :: Hash : FromStr ,
@@ -180,8 +181,10 @@ where
180
181
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
181
182
// let desc_str = verify_checksum(s)?;
182
183
// 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
185
188
}
186
189
}
187
190
@@ -193,9 +196,113 @@ where
193
196
<<Pk as MiniscriptKey >:: Hash as FromStr >:: Err : ToString ,
194
197
{
195
198
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
199
+ let key = & self . key_path ;
196
200
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) )
199
306
}
200
307
}
201
308
}
0 commit comments