1
1
// SPDX-License-Identifier: CC0-1.0
2
2
3
- use core:: cmp:: { self , max} ;
4
3
use core:: str:: FromStr ;
5
- use core:: { fmt, hash} ;
4
+ use core:: { cmp , fmt, hash} ;
6
5
7
6
use bitcoin:: taproot:: {
8
7
LeafVersion , TaprootBuilder , TaprootSpendInfo , TAPROOT_CONTROL_BASE_SIZE ,
@@ -29,7 +28,14 @@ use crate::{
29
28
#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
30
29
pub enum TapTree < Pk : MiniscriptKey > {
31
30
/// A taproot tree structure
32
- Tree ( Arc < TapTree < Pk > > , Arc < TapTree < Pk > > ) ,
31
+ Tree {
32
+ /// Left tree branch.
33
+ left : Arc < TapTree < Pk > > ,
34
+ /// Right tree branch.
35
+ right : Arc < TapTree < Pk > > ,
36
+ /// Tree height, defined as `1 + max(left_height, right_height)`.
37
+ height : usize ,
38
+ } ,
33
39
/// A taproot leaf denoting a spending condition
34
40
// A new leaf version would require a new Context, therefore there is no point
35
41
// in adding a LeafVersion with Leaf type here. All Miniscripts right now
@@ -108,14 +114,24 @@ impl<Pk: MiniscriptKey> hash::Hash for Tr<Pk> {
108
114
}
109
115
110
116
impl < Pk : MiniscriptKey > TapTree < Pk > {
111
- // Helper function to compute height
112
- // TODO: Instead of computing this every time we add a new leaf, we should
113
- // add height as a separate field in taptree
114
- fn taptree_height ( & self ) -> usize {
117
+ /// Creates a `TapTree` by combining `left` and `right` tree nodes.
118
+ pub ( crate ) fn combine ( left : TapTree < Pk > , right : TapTree < Pk > ) -> Self {
119
+ let height = 1 + cmp:: max ( left. height ( ) , right. height ( ) ) ;
120
+ TapTree :: Tree {
121
+ left : Arc :: new ( left) ,
122
+ right : Arc :: new ( right) ,
123
+ height,
124
+ }
125
+ }
126
+
127
+ /// Returns the height of this tree.
128
+ fn height ( & self ) -> usize {
115
129
match * self {
116
- TapTree :: Tree ( ref left_tree, ref right_tree) => {
117
- 1 + max ( left_tree. taptree_height ( ) , right_tree. taptree_height ( ) )
118
- }
130
+ TapTree :: Tree {
131
+ left : _,
132
+ right : _,
133
+ height,
134
+ } => height,
119
135
TapTree :: Leaf ( ..) => 0 ,
120
136
}
121
137
}
@@ -134,12 +150,17 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
134
150
T : Translator < Pk , Q , E > ,
135
151
Q : MiniscriptKey ,
136
152
{
137
- let frag = match self {
138
- TapTree :: Tree ( l, r) => TapTree :: Tree (
139
- Arc :: new ( l. translate_helper ( t) ?) ,
140
- Arc :: new ( r. translate_helper ( t) ?) ,
141
- ) ,
142
- TapTree :: Leaf ( ms) => TapTree :: Leaf ( Arc :: new ( ms. translate_pk ( t) ?) ) ,
153
+ let frag = match * self {
154
+ TapTree :: Tree {
155
+ ref left,
156
+ ref right,
157
+ ref height,
158
+ } => TapTree :: Tree {
159
+ left : Arc :: new ( left. translate_helper ( t) ?) ,
160
+ right : Arc :: new ( right. translate_helper ( t) ?) ,
161
+ height : * height,
162
+ } ,
163
+ TapTree :: Leaf ( ref ms) => TapTree :: Leaf ( Arc :: new ( ms. translate_pk ( t) ?) ) ,
143
164
} ;
144
165
Ok ( frag)
145
166
}
@@ -148,7 +169,11 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
148
169
impl < Pk : MiniscriptKey > fmt:: Display for TapTree < Pk > {
149
170
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150
171
match self {
151
- TapTree :: Tree ( ref left, ref right) => write ! ( f, "{{{},{}}}" , * left, * right) ,
172
+ TapTree :: Tree {
173
+ ref left,
174
+ ref right,
175
+ height : _,
176
+ } => write ! ( f, "{{{},{}}}" , * left, * right) ,
152
177
TapTree :: Leaf ( ref script) => write ! ( f, "{}" , * script) ,
153
178
}
154
179
}
@@ -157,7 +182,11 @@ impl<Pk: MiniscriptKey> fmt::Display for TapTree<Pk> {
157
182
impl < Pk : MiniscriptKey > fmt:: Debug for TapTree < Pk > {
158
183
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
159
184
match self {
160
- TapTree :: Tree ( ref left, ref right) => write ! ( f, "{{{:?},{:?}}}" , * left, * right) ,
185
+ TapTree :: Tree {
186
+ ref left,
187
+ ref right,
188
+ height : _,
189
+ } => write ! ( f, "{{{:?},{:?}}}" , * left, * right) ,
161
190
TapTree :: Leaf ( ref script) => write ! ( f, "{:?}" , * script) ,
162
191
}
163
192
}
@@ -167,7 +196,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
167
196
/// Create a new [`Tr`] descriptor from internal key and [`TapTree`]
168
197
pub fn new ( internal_key : Pk , tree : Option < TapTree < Pk > > ) -> Result < Self , Error > {
169
198
Tap :: check_pk ( & internal_key) ?;
170
- let nodes = tree. as_ref ( ) . map ( |t| t. taptree_height ( ) ) . unwrap_or ( 0 ) ;
199
+ let nodes = tree. as_ref ( ) . map ( |t| t. height ( ) ) . unwrap_or ( 0 ) ;
171
200
172
201
if nodes <= TAPROOT_CONTROL_MAX_NODE_COUNT {
173
202
Ok ( Self {
@@ -186,10 +215,16 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
186
215
}
187
216
188
217
/// Obtain the [`TapTree`] of the [`Tr`] descriptor
189
- pub fn taptree ( & self ) -> & Option < TapTree < Pk > > {
218
+ pub fn tap_tree ( & self ) -> & Option < TapTree < Pk > > {
190
219
& self . tree
191
220
}
192
221
222
+ /// Obtain the [`TapTree`] of the [`Tr`] descriptor
223
+ #[ deprecated( since = "11.0.0" , note = "use tap_tree instead" ) ]
224
+ pub fn taptree ( & self ) -> & Option < TapTree < Pk > > {
225
+ self . tap_tree ( )
226
+ }
227
+
193
228
/// Iterate over all scripts in merkle tree. If there is no script path, the iterator
194
229
/// yields [`None`]
195
230
pub fn iter_scripts ( & self ) -> TapTreeIter < Pk > {
@@ -258,7 +293,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
258
293
/// # Errors
259
294
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
260
295
pub fn max_weight_to_satisfy ( & self ) -> Result < usize , Error > {
261
- let tree = match self . taptree ( ) {
296
+ let tree = match self . tap_tree ( ) {
262
297
None => {
263
298
// key spend path
264
299
// item: varint(sig+sigHash) + <sig(64)+sigHash(1)>
@@ -309,7 +344,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
309
344
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
310
345
#[ deprecated( note = "use max_weight_to_satisfy instead" ) ]
311
346
pub fn max_satisfaction_weight ( & self ) -> Result < usize , Error > {
312
- let tree = match self . taptree ( ) {
347
+ let tree = match self . tap_tree ( ) {
313
348
// key spend path:
314
349
// scriptSigLen(4) + stackLen(1) + stack[Sig]Len(1) + stack[Sig](65)
315
350
None => return Ok ( 4 + 1 + 1 + 65 ) ,
@@ -407,9 +442,13 @@ where
407
442
fn next ( & mut self ) -> Option < Self :: Item > {
408
443
while let Some ( ( depth, last) ) = self . stack . pop ( ) {
409
444
match * last {
410
- TapTree :: Tree ( ref l, ref r) => {
411
- self . stack . push ( ( depth + 1 , r) ) ;
412
- self . stack . push ( ( depth + 1 , l) ) ;
445
+ TapTree :: Tree {
446
+ ref left,
447
+ ref right,
448
+ height : _,
449
+ } => {
450
+ self . stack . push ( ( depth + 1 , right) ) ;
451
+ self . stack . push ( ( depth + 1 , left) ) ;
413
452
}
414
453
TapTree :: Leaf ( ref ms) => return Some ( ( depth, ms) ) ,
415
454
}
@@ -431,7 +470,7 @@ impl_block_str!(
431
470
expression:: Tree { name, args } if name. is_empty( ) && args. len( ) == 2 => {
432
471
let left = Self :: parse_tr_script_spend( & args[ 0 ] ) ?;
433
472
let right = Self :: parse_tr_script_spend( & args[ 1 ] ) ?;
434
- Ok ( TapTree :: Tree ( Arc :: new ( left) , Arc :: new ( right) ) )
473
+ Ok ( TapTree :: combine ( left, right) )
435
474
}
436
475
_ => Err ( Error :: Unexpected (
437
476
"unknown format for script spending paths while parsing taproot descriptor"
@@ -589,10 +628,15 @@ fn split_once(inp: &str, delim: char) -> Option<(&str, &str)> {
589
628
impl < Pk : MiniscriptKey > Liftable < Pk > for TapTree < Pk > {
590
629
fn lift ( & self ) -> Result < Policy < Pk > , Error > {
591
630
fn lift_helper < Pk : MiniscriptKey > ( s : & TapTree < Pk > ) -> Result < Policy < Pk > , Error > {
592
- match s {
593
- TapTree :: Tree ( ref l, ref r) => {
594
- Ok ( Policy :: Threshold ( 1 , vec ! [ lift_helper( l) ?, lift_helper( r) ?] ) )
595
- }
631
+ match * s {
632
+ TapTree :: Tree {
633
+ ref left,
634
+ ref right,
635
+ height : _,
636
+ } => Ok ( Policy :: Threshold (
637
+ 1 ,
638
+ vec ! [ lift_helper( left) ?, lift_helper( right) ?] ,
639
+ ) ) ,
596
640
TapTree :: Leaf ( ref leaf) => leaf. lift ( ) ,
597
641
}
598
642
}
@@ -713,10 +757,8 @@ where
713
757
#[ cfg( test) ]
714
758
mod tests {
715
759
use super :: * ;
716
- use crate :: ForEachKey ;
717
760
718
- #[ test]
719
- fn test_for_each ( ) {
761
+ fn descriptor ( ) -> String {
720
762
let desc = "tr(acc0, {
721
763
multi_a(3, acc10, acc11, acc12), {
722
764
and_v(
@@ -729,9 +771,21 @@ mod tests {
729
771
)
730
772
}
731
773
})" ;
732
- let desc = desc. replace ( & [ ' ' , '\n' ] [ ..] , "" ) ;
774
+ desc. replace ( & [ ' ' , '\n' ] [ ..] , "" )
775
+ }
776
+
777
+ #[ test]
778
+ fn for_each ( ) {
779
+ let desc = descriptor ( ) ;
733
780
let tr = Tr :: < String > :: from_str ( & desc) . unwrap ( ) ;
734
781
// Note the last ac12 only has ac and fails the predicate
735
782
assert ! ( !tr. for_each_key( |k| k. starts_with( "acc" ) ) ) ;
736
783
}
784
+
785
+ #[ test]
786
+ fn height ( ) {
787
+ let desc = descriptor ( ) ;
788
+ let tr = Tr :: < String > :: from_str ( & desc) . unwrap ( ) ;
789
+ assert_eq ! ( tr. tap_tree( ) . as_ref( ) . unwrap( ) . height( ) , 2 ) ;
790
+ }
737
791
}
0 commit comments