1
1
// SPDX-License-Identifier: CC0-1.0
2
2
3
- use core:: { cmp , fmt} ;
3
+ use core:: fmt;
4
4
5
5
use bitcoin:: taproot:: { LeafVersion , TapLeafHash , TAPROOT_CONTROL_MAX_NODE_COUNT } ;
6
6
7
7
use crate :: miniscript:: context:: Tap ;
8
8
use crate :: policy:: { Liftable , Semantic } ;
9
9
use crate :: prelude:: Vec ;
10
10
use crate :: sync:: Arc ;
11
- use crate :: { Miniscript , MiniscriptKey , Threshold , ToPublicKey , TranslateErr , Translator } ;
11
+ use crate :: { Miniscript , MiniscriptKey , Threshold , ToPublicKey } ;
12
12
13
13
/// Tried to construct Taproot tree which was too deep.
14
14
#[ derive( PartialEq , Eq , Debug ) ]
@@ -25,46 +25,28 @@ impl fmt::Display for TapTreeDepthError {
25
25
impl std:: error:: Error for TapTreeDepthError { }
26
26
27
27
/// A Taproot Tree representation.
28
- // Hidden leaves are not yet supported in descriptor spec. Conceptually, it should
29
- // be simple to integrate those here, but it is best to wait on core for the exact syntax.
30
- #[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
31
- pub enum TapTree < Pk : MiniscriptKey > {
32
- /// A taproot tree structure
33
- Tree {
34
- /// Left tree branch.
35
- left : Arc < TapTree < Pk > > ,
36
- /// Right tree branch.
37
- right : Arc < TapTree < Pk > > ,
38
- /// Tree height, defined as `1 + max(left_height, right_height)`.
39
- height : usize ,
40
- } ,
41
- /// A taproot leaf denoting a spending condition
42
- // A new leaf version would require a new Context, therefore there is no point
43
- // in adding a LeafVersion with Leaf type here. All Miniscripts right now
44
- // are of Leafversion::default
45
- Leaf ( Arc < Miniscript < Pk , Tap > > ) ,
28
+ #[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
29
+ pub struct TapTree < Pk : MiniscriptKey > {
30
+ depths_leaves : Vec < ( u8 , Arc < Miniscript < Pk , Tap > > ) > ,
46
31
}
47
32
48
33
impl < Pk : MiniscriptKey > TapTree < Pk > {
49
34
/// Creates a `TapTree` leaf from a Miniscript.
50
- pub fn leaf < A : Into < Arc < Miniscript < Pk , Tap > > > > ( ms : A ) -> Self { TapTree :: Leaf ( ms. into ( ) ) }
35
+ pub fn leaf < A : Into < Arc < Miniscript < Pk , Tap > > > > ( ms : A ) -> Self {
36
+ TapTree { depths_leaves : vec ! [ ( 0 , ms. into( ) ) ] }
37
+ }
51
38
52
39
/// Creates a `TapTree` by combining `left` and `right` tree nodes.
53
40
pub fn combine ( left : TapTree < Pk > , right : TapTree < Pk > ) -> Result < Self , TapTreeDepthError > {
54
- let height = 1 + cmp:: max ( left. height ( ) , right. height ( ) ) ;
55
- if height <= TAPROOT_CONTROL_MAX_NODE_COUNT {
56
- Ok ( TapTree :: Tree { left : Arc :: new ( left) , right : Arc :: new ( right) , height } )
57
- } else {
58
- Err ( TapTreeDepthError )
59
- }
60
- }
61
-
62
- /// Returns the height of this tree.
63
- pub fn height ( & self ) -> usize {
64
- match * self {
65
- TapTree :: Tree { left : _, right : _, height } => height,
66
- TapTree :: Leaf ( ..) => 0 ,
41
+ let mut depths_leaves =
42
+ Vec :: with_capacity ( left. depths_leaves . len ( ) + right. depths_leaves . len ( ) ) ;
43
+ for ( depth, leaf) in left. depths_leaves . iter ( ) . chain ( right. depths_leaves . iter ( ) ) {
44
+ if usize:: from ( * depth) > TAPROOT_CONTROL_MAX_NODE_COUNT - 1 {
45
+ return Err ( TapTreeDepthError ) ;
46
+ }
47
+ depths_leaves. push ( ( * depth + 1 , Arc :: clone ( leaf) ) ) ;
67
48
}
49
+ Ok ( Self { depths_leaves } )
68
50
}
69
51
70
52
/// Iterates over all the leaves of the tree in depth-first preorder.
@@ -73,61 +55,73 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
73
55
/// in the tree, which is the data required by PSBT (BIP 371).
74
56
pub fn leaves ( & self ) -> TapTreeIter < Pk > { TapTreeIter :: from_tree ( self ) }
75
57
76
- // Helper function to translate keys
77
- pub ( super ) fn translate_helper < T > (
58
+ /// Converts keys from one type of public key to another.
59
+ pub fn translate_pk < T > (
78
60
& self ,
79
- t : & mut T ,
80
- ) -> Result < TapTree < T :: TargetPk > , TranslateErr < T :: Error > >
61
+ translate : & mut T ,
62
+ ) -> Result < TapTree < T :: TargetPk > , crate :: TranslateErr < T :: Error > >
81
63
where
82
- T : Translator < Pk > ,
64
+ T : crate :: Translator < Pk > ,
83
65
{
84
- let frag = match * self {
85
- TapTree :: Tree { ref left, ref right, ref height } => TapTree :: Tree {
86
- left : Arc :: new ( left. translate_helper ( t) ?) ,
87
- right : Arc :: new ( right. translate_helper ( t) ?) ,
88
- height : * height,
89
- } ,
90
- TapTree :: Leaf ( ref ms) => TapTree :: Leaf ( Arc :: new ( ms. translate_pk ( t) ?) ) ,
91
- } ;
92
- Ok ( frag)
66
+ let mut ret = TapTree { depths_leaves : Vec :: with_capacity ( self . depths_leaves . len ( ) ) } ;
67
+ for ( depth, leaf) in & self . depths_leaves {
68
+ ret. depths_leaves
69
+ . push ( ( * depth, Arc :: new ( leaf. translate_pk ( translate) ?) ) ) ;
70
+ }
71
+
72
+ Ok ( ret)
93
73
}
94
74
}
95
75
96
76
impl < Pk : MiniscriptKey > Liftable < Pk > for TapTree < Pk > {
97
77
fn lift ( & self ) -> Result < Semantic < Pk > , crate :: Error > {
98
- fn lift_helper < Pk : MiniscriptKey > ( s : & TapTree < Pk > ) -> Result < Semantic < Pk > , crate :: Error > {
99
- match * s {
100
- TapTree :: Tree { ref left, ref right, height : _ } => Ok ( Semantic :: Thresh (
101
- Threshold :: or ( Arc :: new ( lift_helper ( left) ?) , Arc :: new ( lift_helper ( right) ?) ) ,
102
- ) ) ,
103
- TapTree :: Leaf ( ref leaf) => leaf. lift ( ) ,
104
- }
78
+ let thresh_vec = self
79
+ . leaves ( )
80
+ . map ( |item| item. miniscript ( ) . lift ( ) . map ( Arc :: new) )
81
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
82
+ let thresh = Threshold :: new ( 1 , thresh_vec) . expect ( "no size limit on Semantic threshold" ) ;
83
+ Ok ( Semantic :: Thresh ( thresh) . normalized ( ) )
84
+ }
85
+ }
86
+
87
+ fn fmt_helper < Pk : MiniscriptKey > (
88
+ view : & TapTree < Pk > ,
89
+ f : & mut fmt:: Formatter ,
90
+ mut fmt_ms : impl FnMut ( & mut fmt:: Formatter , & Miniscript < Pk , Tap > ) -> fmt:: Result ,
91
+ ) -> fmt:: Result {
92
+ let mut last_depth = 0 ;
93
+ for item in view. leaves ( ) {
94
+ if last_depth > 0 {
95
+ f. write_str ( "," ) ?;
105
96
}
106
97
107
- let pol = lift_helper ( self ) ?;
108
- Ok ( pol. normalized ( ) )
98
+ while last_depth < item. depth ( ) {
99
+ f. write_str ( "{" ) ?;
100
+ last_depth += 1 ;
101
+ }
102
+ fmt_ms ( f, item. miniscript ( ) ) ?;
103
+ while last_depth > item. depth ( ) {
104
+ f. write_str ( "}" ) ?;
105
+ last_depth -= 1 ;
106
+ }
107
+ }
108
+
109
+ while last_depth > 0 {
110
+ f. write_str ( "}" ) ?;
111
+ last_depth -= 1 ;
109
112
}
113
+ Ok ( ( ) )
110
114
}
111
115
112
116
impl < Pk : MiniscriptKey > fmt:: Display for TapTree < Pk > {
113
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
114
- match self {
115
- TapTree :: Tree { ref left, ref right, height : _ } => {
116
- write ! ( f, "{{{},{}}}" , * left, * right)
117
- }
118
- TapTree :: Leaf ( ref script) => write ! ( f, "{}" , * script) ,
119
- }
117
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
118
+ fmt_helper ( self , f, |f, ms| write ! ( f, "{}" , ms) )
120
119
}
121
120
}
122
121
123
122
impl < Pk : MiniscriptKey > fmt:: Debug for TapTree < Pk > {
124
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
125
- match self {
126
- TapTree :: Tree { ref left, ref right, height : _ } => {
127
- write ! ( f, "{{{:?},{:?}}}" , * left, * right)
128
- }
129
- TapTree :: Leaf ( ref script) => write ! ( f, "{:?}" , * script) ,
130
- }
123
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
124
+ fmt_helper ( self , f, |f, ms| write ! ( f, "{:?}" , ms) )
131
125
}
132
126
}
133
127
@@ -145,35 +139,25 @@ impl<Pk: MiniscriptKey> fmt::Debug for TapTree<Pk> {
145
139
/// would yield (2, A), (2, B), (2,C), (3, D), (3, E).
146
140
///
147
141
#[ derive( Debug , Clone ) ]
148
- pub struct TapTreeIter < ' a , Pk : MiniscriptKey > {
149
- stack : Vec < ( u8 , & ' a TapTree < Pk > ) > ,
142
+ pub struct TapTreeIter < ' tr , Pk : MiniscriptKey > {
143
+ inner : core :: slice :: Iter < ' tr , ( u8 , Arc < Miniscript < Pk , Tap > > ) > ,
150
144
}
151
145
152
146
impl < ' tr , Pk : MiniscriptKey > TapTreeIter < ' tr , Pk > {
153
147
/// An empty iterator.
154
- pub fn empty ( ) -> Self { Self { stack : vec ! [ ] } }
148
+ pub fn empty ( ) -> Self { Self { inner : [ ] . iter ( ) } }
155
149
156
150
/// An iterator over a given tree.
157
- fn from_tree ( tree : & ' tr TapTree < Pk > ) -> Self { Self { stack : vec ! [ ( 0 , tree) ] } }
151
+ fn from_tree ( tree : & ' tr TapTree < Pk > ) -> Self { Self { inner : tree. depths_leaves . iter ( ) } }
158
152
}
159
153
160
- impl < ' a , Pk > Iterator for TapTreeIter < ' a , Pk >
161
- where
162
- Pk : MiniscriptKey + ' a ,
163
- {
164
- type Item = TapTreeIterItem < ' a , Pk > ;
154
+ impl < ' tr , Pk : MiniscriptKey > Iterator for TapTreeIter < ' tr , Pk > {
155
+ type Item = TapTreeIterItem < ' tr , Pk > ;
165
156
166
157
fn next ( & mut self ) -> Option < Self :: Item > {
167
- while let Some ( ( depth, last) ) = self . stack . pop ( ) {
168
- match * last {
169
- TapTree :: Tree { ref left, ref right, height : _ } => {
170
- self . stack . push ( ( depth + 1 , right) ) ;
171
- self . stack . push ( ( depth + 1 , left) ) ;
172
- }
173
- TapTree :: Leaf ( ref ms) => return Some ( TapTreeIterItem { node : ms, depth } ) ,
174
- }
175
- }
176
- None
158
+ self . inner
159
+ . next ( )
160
+ . map ( |& ( depth, ref node) | TapTreeIterItem { depth, node } )
177
161
}
178
162
}
179
163
0 commit comments