@@ -29,7 +29,14 @@ use crate::{
29
29
#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
30
30
pub enum TapTree < Pk : MiniscriptKey > {
31
31
/// A taproot tree structure
32
- Tree ( Arc < TapTree < Pk > > , Arc < TapTree < Pk > > ) ,
32
+ Tree {
33
+ /// Left tree branch.
34
+ left : Arc < TapTree < Pk > > ,
35
+ /// Right tree branch.
36
+ right : Arc < TapTree < Pk > > ,
37
+ /// Tree height, defined as `1 + max(left_height, right_height)`.
38
+ height : usize ,
39
+ } ,
33
40
/// A taproot leaf denoting a spending condition
34
41
// A new leaf version would require a new Context, therefore there is no point
35
42
// in adding a LeafVersion with Leaf type here. All Miniscripts right now
@@ -108,14 +115,24 @@ impl<Pk: MiniscriptKey> hash::Hash for Tr<Pk> {
108
115
}
109
116
110
117
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 tap tree
114
- fn tap_tree_height ( & self ) -> usize {
118
+ /// Combine `left` and `right` leaves into a tree.
119
+ pub ( crate ) fn combine ( left : TapTree < Pk > , right : TapTree < Pk > ) -> Self {
120
+ let height = 1 + max ( left. height ( ) , right. height ( ) ) ;
121
+ TapTree :: Tree {
122
+ left : Arc :: new ( left) ,
123
+ right : Arc :: new ( right) ,
124
+ height,
125
+ }
126
+ }
127
+
128
+ /// Returns the height of this tree (leaves are defined as height 0).
129
+ fn height ( & self ) -> usize {
115
130
match * self {
116
- TapTree :: Tree ( ref left_tree, ref right_tree) => {
117
- 1 + max ( left_tree. tap_tree_height ( ) , right_tree. tap_tree_height ( ) )
118
- }
131
+ TapTree :: Tree {
132
+ left : _,
133
+ right : _,
134
+ ref height,
135
+ } => * height,
119
136
TapTree :: Leaf ( ..) => 0 ,
120
137
}
121
138
}
@@ -134,12 +151,17 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
134
151
T : Translator < Pk , Q , E > ,
135
152
Q : MiniscriptKey ,
136
153
{
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) ?) ) ,
154
+ let frag = match * self {
155
+ TapTree :: Tree {
156
+ ref left,
157
+ ref right,
158
+ ref height,
159
+ } => TapTree :: Tree {
160
+ left : Arc :: new ( left. translate_helper ( t) ?) ,
161
+ right : Arc :: new ( right. translate_helper ( t) ?) ,
162
+ height : * height,
163
+ } ,
164
+ TapTree :: Leaf ( ref ms) => TapTree :: Leaf ( Arc :: new ( ms. translate_pk ( t) ?) ) ,
143
165
} ;
144
166
Ok ( frag)
145
167
}
@@ -148,7 +170,11 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
148
170
impl < Pk : MiniscriptKey > fmt:: Display for TapTree < Pk > {
149
171
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150
172
match self {
151
- TapTree :: Tree ( ref left, ref right) => write ! ( f, "{{{},{}}}" , * left, * right) ,
173
+ TapTree :: Tree {
174
+ ref left,
175
+ ref right,
176
+ height : _,
177
+ } => write ! ( f, "{{{},{}}}" , * left, * right) ,
152
178
TapTree :: Leaf ( ref script) => write ! ( f, "{}" , * script) ,
153
179
}
154
180
}
@@ -157,7 +183,11 @@ impl<Pk: MiniscriptKey> fmt::Display for TapTree<Pk> {
157
183
impl < Pk : MiniscriptKey > fmt:: Debug for TapTree < Pk > {
158
184
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
159
185
match self {
160
- TapTree :: Tree ( ref left, ref right) => write ! ( f, "{{{:?},{:?}}}" , * left, * right) ,
186
+ TapTree :: Tree {
187
+ ref left,
188
+ ref right,
189
+ height : _,
190
+ } => write ! ( f, "{{{:?},{:?}}}" , * left, * right) ,
161
191
TapTree :: Leaf ( ref script) => write ! ( f, "{:?}" , * script) ,
162
192
}
163
193
}
@@ -167,7 +197,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
167
197
/// Create a new [`Tr`] descriptor from internal key and [`TapTree`]
168
198
pub fn new ( internal_key : Pk , tree : Option < TapTree < Pk > > ) -> Result < Self , Error > {
169
199
Tap :: check_pk ( & internal_key) ?;
170
- let nodes = tree. as_ref ( ) . map ( |t| t. tap_tree_height ( ) ) . unwrap_or ( 0 ) ;
200
+ let nodes = tree. as_ref ( ) . map ( |t| t. height ( ) ) . unwrap_or ( 0 ) ;
171
201
172
202
if nodes <= TAPROOT_CONTROL_MAX_NODE_COUNT {
173
203
Ok ( Self {
@@ -407,9 +437,13 @@ where
407
437
fn next ( & mut self ) -> Option < Self :: Item > {
408
438
while let Some ( ( depth, last) ) = self . stack . pop ( ) {
409
439
match * last {
410
- TapTree :: Tree ( ref l, ref r) => {
411
- self . stack . push ( ( depth + 1 , r) ) ;
412
- self . stack . push ( ( depth + 1 , l) ) ;
440
+ TapTree :: Tree {
441
+ ref left,
442
+ ref right,
443
+ height : _,
444
+ } => {
445
+ self . stack . push ( ( depth + 1 , right) ) ;
446
+ self . stack . push ( ( depth + 1 , left) ) ;
413
447
}
414
448
TapTree :: Leaf ( ref ms) => return Some ( ( depth, ms) ) ,
415
449
}
@@ -431,7 +465,7 @@ impl_block_str!(
431
465
expression:: Tree { name, args } if name. is_empty( ) && args. len( ) == 2 => {
432
466
let left = Self :: parse_tr_script_spend( & args[ 0 ] ) ?;
433
467
let right = Self :: parse_tr_script_spend( & args[ 1 ] ) ?;
434
- Ok ( TapTree :: Tree ( Arc :: new ( left) , Arc :: new ( right) ) )
468
+ Ok ( TapTree :: combine ( left, right) )
435
469
}
436
470
_ => Err ( Error :: Unexpected (
437
471
"unknown format for script spending paths while parsing taproot descriptor"
@@ -589,10 +623,15 @@ fn split_once(inp: &str, delim: char) -> Option<(&str, &str)> {
589
623
impl < Pk : MiniscriptKey > Liftable < Pk > for TapTree < Pk > {
590
624
fn lift ( & self ) -> Result < Policy < Pk > , Error > {
591
625
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
- }
626
+ match * s {
627
+ TapTree :: Tree {
628
+ ref left,
629
+ ref right,
630
+ height : _,
631
+ } => Ok ( Policy :: Threshold (
632
+ 1 ,
633
+ vec ! [ lift_helper( left) ?, lift_helper( right) ?] ,
634
+ ) ) ,
596
635
TapTree :: Leaf ( ref leaf) => leaf. lift ( ) ,
597
636
}
598
637
}
@@ -742,6 +781,6 @@ mod tests {
742
781
fn height ( ) {
743
782
let desc = descriptor ( ) ;
744
783
let tr = Tr :: < String > :: from_str ( & desc) . unwrap ( ) ;
745
- assert_eq ! ( tr. tap_tree( ) . as_ref( ) . unwrap( ) . tap_tree_height ( ) , 2 ) ;
784
+ assert_eq ! ( tr. tap_tree( ) . as_ref( ) . unwrap( ) . height ( ) , 2 ) ;
746
785
}
747
786
}
0 commit comments