1
1
// SPDX-License-Identifier: CC0-1.0
2
2
3
+ use core:: { cmp, fmt} ;
4
+
3
5
use bitcoin:: taproot:: { LeafVersion , TapLeafHash } ;
4
6
5
- use super :: TapTree ;
6
7
use crate :: miniscript:: context:: Tap ;
7
8
use crate :: prelude:: Vec ;
8
9
use crate :: sync:: Arc ;
9
- use crate :: { Miniscript , MiniscriptKey , ToPublicKey } ;
10
+ use crate :: { Miniscript , MiniscriptKey , ToPublicKey , TranslateErr , Translator } ;
11
+
12
+ /// A Taproot Tree representation.
13
+ // Hidden leaves are not yet supported in descriptor spec. Conceptually, it should
14
+ // be simple to integrate those here, but it is best to wait on core for the exact syntax.
15
+ #[ derive( Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
16
+ pub enum TapTree < Pk : MiniscriptKey > {
17
+ /// A taproot tree structure
18
+ Tree {
19
+ /// Left tree branch.
20
+ left : Arc < TapTree < Pk > > ,
21
+ /// Right tree branch.
22
+ right : Arc < TapTree < Pk > > ,
23
+ /// Tree height, defined as `1 + max(left_height, right_height)`.
24
+ height : usize ,
25
+ } ,
26
+ /// A taproot leaf denoting a spending condition
27
+ // A new leaf version would require a new Context, therefore there is no point
28
+ // in adding a LeafVersion with Leaf type here. All Miniscripts right now
29
+ // are of Leafversion::default
30
+ Leaf ( Arc < Miniscript < Pk , Tap > > ) ,
31
+ }
32
+
33
+ impl < Pk : MiniscriptKey > TapTree < Pk > {
34
+ /// Creates a `TapTree` by combining `left` and `right` tree nodes.
35
+ pub fn combine ( left : TapTree < Pk > , right : TapTree < Pk > ) -> Self {
36
+ let height = 1 + cmp:: max ( left. height ( ) , right. height ( ) ) ;
37
+ TapTree :: Tree { left : Arc :: new ( left) , right : Arc :: new ( right) , height }
38
+ }
39
+
40
+ /// Returns the height of this tree.
41
+ pub fn height ( & self ) -> usize {
42
+ match * self {
43
+ TapTree :: Tree { left : _, right : _, height } => height,
44
+ TapTree :: Leaf ( ..) => 0 ,
45
+ }
46
+ }
47
+
48
+ /// Iterates over all miniscripts in DFS walk order compatible with the
49
+ /// PSBT requirements (BIP 371).
50
+ pub fn iter ( & self ) -> TapTreeIter < Pk > { TapTreeIter :: from_tree ( self ) }
51
+
52
+ // Helper function to translate keys
53
+ pub ( super ) fn translate_helper < T > (
54
+ & self ,
55
+ t : & mut T ,
56
+ ) -> Result < TapTree < T :: TargetPk > , TranslateErr < T :: Error > >
57
+ where
58
+ T : Translator < Pk > ,
59
+ {
60
+ let frag = match * self {
61
+ TapTree :: Tree { ref left, ref right, ref height } => TapTree :: Tree {
62
+ left : Arc :: new ( left. translate_helper ( t) ?) ,
63
+ right : Arc :: new ( right. translate_helper ( t) ?) ,
64
+ height : * height,
65
+ } ,
66
+ TapTree :: Leaf ( ref ms) => TapTree :: Leaf ( Arc :: new ( ms. translate_pk ( t) ?) ) ,
67
+ } ;
68
+ Ok ( frag)
69
+ }
70
+ }
71
+
72
+ impl < Pk : MiniscriptKey > fmt:: Display for TapTree < Pk > {
73
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
74
+ match self {
75
+ TapTree :: Tree { ref left, ref right, height : _ } => {
76
+ write ! ( f, "{{{},{}}}" , * left, * right)
77
+ }
78
+ TapTree :: Leaf ( ref script) => write ! ( f, "{}" , * script) ,
79
+ }
80
+ }
81
+ }
82
+
83
+ impl < Pk : MiniscriptKey > fmt:: Debug for TapTree < Pk > {
84
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
85
+ match self {
86
+ TapTree :: Tree { ref left, ref right, height : _ } => {
87
+ write ! ( f, "{{{:?},{:?}}}" , * left, * right)
88
+ }
89
+ TapTree :: Leaf ( ref script) => write ! ( f, "{:?}" , * script) ,
90
+ }
91
+ }
92
+ }
10
93
11
94
/// Iterator over the leaves of a Taptree.
12
95
///
@@ -31,7 +114,7 @@ impl<'tr, Pk: MiniscriptKey> TapTreeIter<'tr, Pk> {
31
114
pub fn empty ( ) -> Self { Self { stack : vec ! [ ] } }
32
115
33
116
/// An iterator over a given tree.
34
- pub ( super ) fn from_tree ( tree : & ' tr TapTree < Pk > ) -> Self { Self { stack : vec ! [ ( 0 , tree) ] } }
117
+ fn from_tree ( tree : & ' tr TapTree < Pk > ) -> Self { Self { stack : vec ! [ ( 0 , tree) ] } }
35
118
}
36
119
37
120
impl < ' a , Pk > Iterator for TapTreeIter < ' a , Pk >
0 commit comments