@@ -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,9 @@ 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
+ fn height ( & self ) -> usize {
115
119
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
- }
120
+ TapTree :: Tree { left : _, right : _, ref height } => * height,
119
121
TapTree :: Leaf ( ..) => 0 ,
120
122
}
121
123
}
@@ -134,12 +136,13 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
134
136
T : Translator < Pk , Q , E > ,
135
137
Q : MiniscriptKey ,
136
138
{
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) ?) ) ,
139
+ let frag = match * self {
140
+ TapTree :: Tree { ref left, ref right, ref height } => TapTree :: Tree {
141
+ left : Arc :: new ( left. translate_helper ( t) ?) ,
142
+ right : Arc :: new ( right. translate_helper ( t) ?) ,
143
+ height : * height,
144
+ } ,
145
+ TapTree :: Leaf ( ref ms) => TapTree :: Leaf ( Arc :: new ( ms. translate_pk ( t) ?) ) ,
143
146
} ;
144
147
Ok ( frag)
145
148
}
@@ -148,7 +151,7 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
148
151
impl < Pk : MiniscriptKey > fmt:: Display for TapTree < Pk > {
149
152
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150
153
match self {
151
- TapTree :: Tree ( ref left, ref right) => write ! ( f, "{{{},{}}}" , * left, * right) ,
154
+ TapTree :: Tree { ref left, ref right, height : _ } => write ! ( f, "{{{},{}}}" , * left, * right) ,
152
155
TapTree :: Leaf ( ref script) => write ! ( f, "{}" , * script) ,
153
156
}
154
157
}
@@ -157,7 +160,7 @@ impl<Pk: MiniscriptKey> fmt::Display for TapTree<Pk> {
157
160
impl < Pk : MiniscriptKey > fmt:: Debug for TapTree < Pk > {
158
161
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
159
162
match self {
160
- TapTree :: Tree ( ref left, ref right) => write ! ( f, "{{{:?},{:?}}}" , * left, * right) ,
163
+ TapTree :: Tree { ref left, ref right, height : _ } => write ! ( f, "{{{:?},{:?}}}" , * left, * right) ,
161
164
TapTree :: Leaf ( ref script) => write ! ( f, "{:?}" , * script) ,
162
165
}
163
166
}
@@ -167,7 +170,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
167
170
/// Create a new [`Tr`] descriptor from internal key and [`TapTree`]
168
171
pub fn new ( internal_key : Pk , tree : Option < TapTree < Pk > > ) -> Result < Self , Error > {
169
172
Tap :: check_pk ( & internal_key) ?;
170
- let nodes = tree. as_ref ( ) . map ( |t| t. tap_tree_height ( ) ) . unwrap_or ( 0 ) ;
173
+ let nodes = tree. as_ref ( ) . map ( |t| t. height ( ) ) . unwrap_or ( 0 ) ;
171
174
172
175
if nodes <= TAPROOT_CONTROL_MAX_NODE_COUNT {
173
176
Ok ( Self {
@@ -407,9 +410,9 @@ where
407
410
fn next ( & mut self ) -> Option < Self :: Item > {
408
411
while let Some ( ( depth, last) ) = self . stack . pop ( ) {
409
412
match * last {
410
- TapTree :: Tree ( ref l , ref r ) => {
411
- self . stack . push ( ( depth + 1 , r ) ) ;
412
- self . stack . push ( ( depth + 1 , l ) ) ;
413
+ TapTree :: Tree { ref left , ref right , height : _ } => {
414
+ self . stack . push ( ( depth + 1 , right ) ) ;
415
+ self . stack . push ( ( depth + 1 , left ) ) ;
413
416
}
414
417
TapTree :: Leaf ( ref ms) => return Some ( ( depth, ms) ) ,
415
418
}
@@ -431,7 +434,12 @@ impl_block_str!(
431
434
expression:: Tree { name, args } if name. is_empty( ) && args. len( ) == 2 => {
432
435
let left = Self :: parse_tr_script_spend( & args[ 0 ] ) ?;
433
436
let right = Self :: parse_tr_script_spend( & args[ 1 ] ) ?;
434
- Ok ( TapTree :: Tree ( Arc :: new( left) , Arc :: new( right) ) )
437
+ let height = 1 + max( left. height( ) , right. height( ) ) ;
438
+ Ok ( TapTree :: Tree {
439
+ left: Arc :: new( left) ,
440
+ right: Arc :: new( right) ,
441
+ height,
442
+ } )
435
443
}
436
444
_ => Err ( Error :: Unexpected (
437
445
"unknown format for script spending paths while parsing taproot descriptor"
@@ -589,9 +597,9 @@ fn split_once(inp: &str, delim: char) -> Option<(&str, &str)> {
589
597
impl < Pk : MiniscriptKey > Liftable < Pk > for TapTree < Pk > {
590
598
fn lift ( & self ) -> Result < Policy < Pk > , Error > {
591
599
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 ) ?] ) )
600
+ match * s {
601
+ TapTree :: Tree { ref left , ref right , height : _ } => {
602
+ Ok ( Policy :: Threshold ( 1 , vec ! [ lift_helper( left ) ?, lift_helper( right ) ?] ) )
595
603
}
596
604
TapTree :: Leaf ( ref leaf) => leaf. lift ( ) ,
597
605
}
@@ -742,6 +750,6 @@ mod tests {
742
750
fn height ( ) {
743
751
let desc = descriptor ( ) ;
744
752
let tr = Tr :: < String > :: from_str ( & desc) . unwrap ( ) ;
745
- assert_eq ! ( tr. tap_tree( ) . as_ref( ) . unwrap( ) . tap_tree_height ( ) , 2 ) ;
753
+ assert_eq ! ( tr. tap_tree( ) . as_ref( ) . unwrap( ) . height ( ) , 2 ) ;
746
754
}
747
755
}
0 commit comments