1
+ use core:: fmt;
2
+ use core:: marker:: PhantomData ;
3
+ use core:: str:: FromStr ;
4
+
5
+ use bitcoin:: script;
6
+
7
+ use crate :: miniscript:: context:: ScriptContext ;
8
+ use crate :: miniscript:: decode:: Terminal ;
9
+ use crate :: miniscript:: limits:: MAX_PUBKEYS_PER_MULTISIG ;
10
+ use crate :: miniscript:: satisfy:: { Placeholder , Satisfaction } ;
11
+ use crate :: plan:: AssetProvider ;
12
+ use crate :: prelude:: * ;
13
+ use crate :: {
14
+ errstr, expression, Error , ForEachKey , Miniscript , MiniscriptKey ,
15
+ Satisfier , ToPublicKey , TranslateErr , Translator ,
16
+ } ;
17
+
18
+ /// Contents of a "sortedmultiA" descriptor
19
+ #[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
20
+ pub struct SortedMultiAVec < Pk : MiniscriptKey , Ctx : ScriptContext > {
21
+ /// signatures required
22
+ pub k : usize ,
23
+ /// public keys inside sorted Multi
24
+ pub pks : Vec < Pk > ,
25
+ /// The current ScriptContext for sortedmultiA
26
+ pub ( crate ) phantom : PhantomData < Ctx > ,
27
+ }
28
+
29
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiAVec < Pk , Ctx > {
30
+ /// Create a new instance of `SortedMultiVecA` given a list of keys and the threshold
31
+ pub fn new ( k : usize , pks : Vec < Pk > ) -> Result < Self , Error > {
32
+ if pks. len ( ) > MAX_PUBKEYS_PER_MULTISIG {
33
+ return Err ( Error :: BadDescriptor ( "Too many public keys" . to_string ( ) ) ) ;
34
+ }
35
+
36
+ let term: Terminal < Pk , Ctx > = Terminal :: MultiA ( k, pks. clone ( ) ) ;
37
+ let ms = Miniscript :: from_ast ( term) ?;
38
+
39
+ Ctx :: check_local_validity ( & ms) ?;
40
+
41
+ Ok ( Self { k, pks, phantom : PhantomData } )
42
+ }
43
+
44
+ /// Parse an expression tree into a SortedMultiVec
45
+ #[ allow( dead_code) ]
46
+ pub fn from_tree ( tree : & expression:: Tree ) -> Result < Self , Error >
47
+ where
48
+ Pk : FromStr ,
49
+ <Pk as FromStr >:: Err : ToString ,
50
+ {
51
+ if tree. args . is_empty ( ) {
52
+ return Err ( errstr ( "no arguments given for sortedmulti_a" ) ) ;
53
+ }
54
+ let k = expression:: parse_num ( tree. args [ 0 ] . name ) ?;
55
+ if k > ( tree. args . len ( ) - 1 ) as u32 {
56
+ return Err ( errstr ( "higher threshold than there were keys in sortedmulti_a" ) ) ;
57
+ }
58
+ let pks: Result < Vec < Pk > , _ > = tree. args [ 1 ..]
59
+ . iter ( )
60
+ . map ( |sub| expression:: terminal ( sub, Pk :: from_str) )
61
+ . collect ( ) ;
62
+
63
+ pks. map ( |pks| SortedMultiAVec :: new ( k as usize , pks) ) ?
64
+ }
65
+
66
+ #[ allow( dead_code) ]
67
+ pub fn translate_pk < T , Q , FuncError > (
68
+ & self ,
69
+ t : & mut T ,
70
+ ) -> Result < SortedMultiAVec < Q , Ctx > , TranslateErr < FuncError > >
71
+ where
72
+ T : Translator < Pk , Q , FuncError > ,
73
+ Q : MiniscriptKey ,
74
+ {
75
+ let pks: Result < Vec < Q > , _ > = self . pks . iter ( ) . map ( |pk| t. pk ( pk) ) . collect ( ) ;
76
+ let res = SortedMultiAVec :: new ( self . k , pks?) . map_err ( TranslateErr :: OuterError ) ?;
77
+ Ok ( res)
78
+ }
79
+ }
80
+
81
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > ForEachKey < Pk > for SortedMultiAVec < Pk , Ctx > {
82
+ fn for_each_key < ' a , F : FnMut ( & ' a Pk ) -> bool > ( & ' a self , pred : F ) -> bool {
83
+ self . pks . iter ( ) . all ( pred)
84
+ }
85
+ }
86
+
87
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiAVec < Pk , Ctx > {
88
+ /// utility function to sanity a sorted multi vec
89
+ #[ allow( dead_code) ]
90
+ pub fn sanity_check ( & self ) -> Result < ( ) , Error > {
91
+ let ms: Miniscript < Pk , Ctx > =
92
+ Miniscript :: from_ast ( Terminal :: MultiA ( self . k , self . pks . clone ( ) ) )
93
+ . expect ( "Must typecheck" ) ;
94
+ // '?' for doing From conversion
95
+ ms. sanity_check ( ) ?;
96
+ Ok ( ( ) )
97
+ }
98
+ }
99
+
100
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiAVec < Pk , Ctx > {
101
+ /// Create Terminal::Multi containing sorted pubkeys
102
+ #[ allow( dead_code) ]
103
+ pub fn sorted_node ( & self ) -> Terminal < Pk , Ctx >
104
+ where
105
+ Pk : ToPublicKey ,
106
+ {
107
+ let mut pks = self . pks . clone ( ) ;
108
+ pks. sort_by ( |a, b| {
109
+ a. to_public_key ( )
110
+ . inner
111
+ . serialize ( )
112
+ . partial_cmp ( & b. to_public_key ( ) . inner . serialize ( ) )
113
+ . unwrap ( )
114
+ } ) ;
115
+ Terminal :: MultiA ( self . k , pks)
116
+ }
117
+
118
+ /// Encode as a Bitcoin script
119
+ #[ allow( dead_code) ]
120
+ pub fn encode ( & self ) -> script:: ScriptBuf
121
+ where
122
+ Pk : ToPublicKey ,
123
+ {
124
+ self . sorted_node ( )
125
+ . encode ( script:: Builder :: new ( ) )
126
+ . into_script ( )
127
+ }
128
+
129
+ #[ allow( dead_code) ]
130
+ pub fn satisfy < S > ( & self , satisfier : S ) -> Result < Vec < Vec < u8 > > , Error >
131
+ where
132
+ Pk : ToPublicKey ,
133
+ S : Satisfier < Pk > ,
134
+ {
135
+ todo ! ( "Unimplemented" )
136
+ }
137
+
138
+ #[ allow( dead_code) ]
139
+ pub fn build_template < P > ( & self , provider : & P ) -> Satisfaction < Placeholder < Pk > >
140
+ where
141
+ Pk : ToPublicKey ,
142
+ P : AssetProvider < Pk > ,
143
+ {
144
+ todo ! ( "Unimplemented" )
145
+ }
146
+
147
+ #[ allow( dead_code) ]
148
+ pub fn script_size ( & self ) -> usize {
149
+ todo ! ( "Unimplemented" )
150
+ }
151
+
152
+ #[ allow( dead_code) ]
153
+ pub fn max_satisfaction_witness_elements ( & self ) -> usize { self . pks . len ( ) }
154
+
155
+ #[ allow( dead_code) ]
156
+ pub fn max_satisfaction_size ( & self ) -> usize { ( 1 + 65 ) * self . k + ( self . pks . len ( ) - self . k ) }
157
+ }
158
+
159
+
160
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > fmt:: Debug for SortedMultiAVec < Pk , Ctx > {
161
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result { fmt:: Display :: fmt ( self , f) }
162
+ }
163
+
164
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > fmt:: Display for SortedMultiAVec < Pk , Ctx > {
165
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
166
+ write ! ( f, "sortedmulti_a({}" , self . k) ?;
167
+ for k in & self . pks {
168
+ write ! ( f, ",{}" , k) ?;
169
+ }
170
+ f. write_str ( ")" )
171
+ }
172
+ }
0 commit comments