11// SPDX-License-Identifier: CC0-1.0
22
3- use core:: cmp:: { self , max} ;
43use core:: str:: FromStr ;
5- use core:: { fmt, hash} ;
4+ use core:: { cmp , fmt, hash} ;
65
76use bitcoin:: taproot:: {
87 LeafVersion , TaprootBuilder , TaprootSpendInfo , TAPROOT_CONTROL_BASE_SIZE ,
@@ -29,7 +28,14 @@ use crate::{
2928#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
3029pub enum TapTree < Pk : MiniscriptKey > {
3130 /// 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+ } ,
3339 /// A taproot leaf denoting a spending condition
3440 // A new leaf version would require a new Context, therefore there is no point
3541 // in adding a LeafVersion with Leaf type here. All Miniscripts right now
@@ -108,14 +114,24 @@ impl<Pk: MiniscriptKey> hash::Hash for Tr<Pk> {
108114}
109115
110116impl < 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 {
115129 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,
119135 TapTree :: Leaf ( ..) => 0 ,
120136 }
121137 }
@@ -134,12 +150,17 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
134150 T : Translator < Pk , Q , E > ,
135151 Q : MiniscriptKey ,
136152 {
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) ?) ) ,
143164 } ;
144165 Ok ( frag)
145166 }
@@ -148,7 +169,11 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
148169impl < Pk : MiniscriptKey > fmt:: Display for TapTree < Pk > {
149170 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150171 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) ,
152177 TapTree :: Leaf ( ref script) => write ! ( f, "{}" , * script) ,
153178 }
154179 }
@@ -157,7 +182,11 @@ impl<Pk: MiniscriptKey> fmt::Display for TapTree<Pk> {
157182impl < Pk : MiniscriptKey > fmt:: Debug for TapTree < Pk > {
158183 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
159184 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) ,
161190 TapTree :: Leaf ( ref script) => write ! ( f, "{:?}" , * script) ,
162191 }
163192 }
@@ -167,7 +196,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
167196 /// Create a new [`Tr`] descriptor from internal key and [`TapTree`]
168197 pub fn new ( internal_key : Pk , tree : Option < TapTree < Pk > > ) -> Result < Self , Error > {
169198 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 ) ;
171200
172201 if nodes <= TAPROOT_CONTROL_MAX_NODE_COUNT {
173202 Ok ( Self {
@@ -186,10 +215,16 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
186215 }
187216
188217 /// Obtain the [`TapTree`] of the [`Tr`] descriptor
189- pub fn taptree ( & self ) -> & Option < TapTree < Pk > > {
218+ pub fn tap_tree ( & self ) -> & Option < TapTree < Pk > > {
190219 & self . tree
191220 }
192221
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+
193228 /// Iterate over all scripts in merkle tree. If there is no script path, the iterator
194229 /// yields [`None`]
195230 pub fn iter_scripts ( & self ) -> TapTreeIter < Pk > {
@@ -258,7 +293,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
258293 /// # Errors
259294 /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
260295 pub fn max_weight_to_satisfy ( & self ) -> Result < usize , Error > {
261- let tree = match self . taptree ( ) {
296+ let tree = match self . tap_tree ( ) {
262297 None => {
263298 // key spend path
264299 // item: varint(sig+sigHash) + <sig(64)+sigHash(1)>
@@ -309,7 +344,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> {
309344 /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
310345 #[ deprecated( note = "use max_weight_to_satisfy instead" ) ]
311346 pub fn max_satisfaction_weight ( & self ) -> Result < usize , Error > {
312- let tree = match self . taptree ( ) {
347+ let tree = match self . tap_tree ( ) {
313348 // key spend path:
314349 // scriptSigLen(4) + stackLen(1) + stack[Sig]Len(1) + stack[Sig](65)
315350 None => return Ok ( 4 + 1 + 1 + 65 ) ,
@@ -407,9 +442,13 @@ where
407442 fn next ( & mut self ) -> Option < Self :: Item > {
408443 while let Some ( ( depth, last) ) = self . stack . pop ( ) {
409444 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) ) ;
413452 }
414453 TapTree :: Leaf ( ref ms) => return Some ( ( depth, ms) ) ,
415454 }
@@ -431,7 +470,7 @@ impl_block_str!(
431470 expression:: Tree { name, args } if name. is_empty( ) && args. len( ) == 2 => {
432471 let left = Self :: parse_tr_script_spend( & args[ 0 ] ) ?;
433472 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) )
435474 }
436475 _ => Err ( Error :: Unexpected (
437476 "unknown format for script spending paths while parsing taproot descriptor"
@@ -589,10 +628,15 @@ fn split_once(inp: &str, delim: char) -> Option<(&str, &str)> {
589628impl < Pk : MiniscriptKey > Liftable < Pk > for TapTree < Pk > {
590629 fn lift ( & self ) -> Result < Policy < Pk > , Error > {
591630 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+ ) ) ,
596640 TapTree :: Leaf ( ref leaf) => leaf. lift ( ) ,
597641 }
598642 }
@@ -713,10 +757,8 @@ where
713757#[ cfg( test) ]
714758mod tests {
715759 use super :: * ;
716- use crate :: ForEachKey ;
717760
718- #[ test]
719- fn test_for_each ( ) {
761+ fn descriptor ( ) -> String {
720762 let desc = "tr(acc0, {
721763 multi_a(3, acc10, acc11, acc12), {
722764 and_v(
@@ -729,9 +771,21 @@ mod tests {
729771 )
730772 }
731773 })" ;
732- let desc = desc. replace ( & [ ' ' , '\n' ] [ ..] , "" ) ;
774+ desc. replace ( & [ ' ' , '\n' ] [ ..] , "" )
775+ }
776+
777+ #[ test]
778+ fn for_each ( ) {
779+ let desc = descriptor ( ) ;
733780 let tr = Tr :: < String > :: from_str ( & desc) . unwrap ( ) ;
734781 // Note the last ac12 only has ac and fails the predicate
735782 assert ! ( !tr. for_each_key( |k| k. starts_with( "acc" ) ) ) ;
736783 }
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+ }
737791}
0 commit comments