@@ -31,6 +31,7 @@ use bitcoin::blockdata::script::PushBytes;
31
31
use bitcoin:: blockdata:: { opcodes, script} ;
32
32
use bitcoin:: hashes:: { hash160, ripemd160, sha256, Hash } ;
33
33
use bitcoin:: { self , hashes, ScriptBuf as BtcScript } ;
34
+ use bitcoin_miniscript:: miniscript:: limits:: MAX_PUBKEYS_PER_MULTISIG ;
34
35
use bitcoin_miniscript:: TranslatePk as BtcTranslatePk ;
35
36
use elements:: secp256k1_zkp;
36
37
@@ -114,16 +115,15 @@ impl MiniscriptKey for LegacyPeginKey {
114
115
/// Legacy Pegin Descriptor
115
116
#[ derive( Clone , Ord , PartialOrd , Eq , PartialEq ) ]
116
117
pub struct LegacyPegin < Pk : MiniscriptKey > {
117
- /// The federation pks
118
- pub fed_pks : Vec < LegacyPeginKey > ,
119
118
/// The federation threshold
120
- pub fed_k : usize ,
121
- /// The emergency pks
122
- pub emer_pks : Vec < LegacyPeginKey > ,
119
+ fed : bitcoin_miniscript:: Threshold < LegacyPeginKey , MAX_PUBKEYS_PER_MULTISIG > ,
120
+
123
121
/// The emergency threshold
124
- pub emer_k : usize ,
122
+ emer : bitcoin_miniscript:: Threshold < LegacyPeginKey , MAX_PUBKEYS_PER_MULTISIG > ,
123
+
125
124
/// csv timelock
126
- pub timelock : bitcoin:: Sequence ,
125
+ timelock : bitcoin_miniscript:: RelLockTime ,
126
+
127
127
/// The elements descriptor required to redeem
128
128
///
129
129
/// TODO: Allow extension user descriptors when claiming pegins
@@ -136,30 +136,29 @@ pub struct LegacyPegin<Pk: MiniscriptKey> {
136
136
impl < Pk : MiniscriptKey > LegacyPegin < Pk > {
137
137
/// Create a new LegacyPegin descriptor
138
138
pub fn new (
139
- fed_pks : Vec < LegacyPeginKey > ,
140
- fed_k : usize ,
141
- emer_pks : Vec < LegacyPeginKey > ,
142
- emer_k : usize ,
143
- timelock : bitcoin:: Sequence ,
139
+ fed : bitcoin_miniscript:: Threshold < LegacyPeginKey , MAX_PUBKEYS_PER_MULTISIG > ,
140
+ emer : bitcoin_miniscript:: Threshold < LegacyPeginKey , MAX_PUBKEYS_PER_MULTISIG > ,
141
+ timelock : bitcoin_miniscript:: RelLockTime ,
144
142
desc : Descriptor < Pk , CovenantExt < CovExtArgs > > ,
145
143
) -> Self {
146
- let fed_ms = BtcMiniscript :: from_ast ( BtcTerminal :: Multi ( fed_k , fed_pks . clone ( ) ) )
144
+ let fed_ms = BtcMiniscript :: from_ast ( BtcTerminal :: Multi ( fed . clone ( ) ) )
147
145
. expect ( "Multi type check can't fail" ) ;
148
146
let csv = BtcMiniscript :: from_ast ( BtcTerminal :: Verify ( Arc :: new (
149
- BtcMiniscript :: from_ast ( BtcTerminal :: Older ( timelock) ) . unwrap ( ) ,
147
+ BtcMiniscript :: from_ast ( BtcTerminal :: Older (
148
+ bitcoin_miniscript:: RelLockTime :: try_from ( timelock) . expect ( "TODO" ) ,
149
+ ) )
150
+ . unwrap ( ) ,
150
151
) ) )
151
152
. unwrap ( ) ;
152
- let emer_ms = BtcMiniscript :: from_ast ( BtcTerminal :: Multi ( emer_k , emer_pks . clone ( ) ) )
153
+ let emer_ms = BtcMiniscript :: from_ast ( BtcTerminal :: Multi ( emer . clone ( ) ) )
153
154
. expect ( "Multi type check can't fail" ) ;
154
155
let emer_ms =
155
156
BtcMiniscript :: from_ast ( BtcTerminal :: AndV ( Arc :: new ( csv) , Arc :: new ( emer_ms) ) ) . unwrap ( ) ;
156
157
let ms = BtcMiniscript :: from_ast ( BtcTerminal :: OrD ( Arc :: new ( fed_ms) , Arc :: new ( emer_ms) ) )
157
158
. expect ( "Type check" ) ;
158
159
Self {
159
- fed_pks,
160
- fed_k,
161
- emer_pks,
162
- emer_k,
160
+ fed,
161
+ emer,
163
162
timelock,
164
163
desc,
165
164
ms,
@@ -175,21 +174,19 @@ impl<Pk: MiniscriptKey> LegacyPegin<Pk> {
175
174
// Miniscript is a bunch of Arc's. So, cloning is not as bad.
176
175
// Can we avoid this without NLL?
177
176
let ms_clone = ms. clone ( ) ;
178
- let ( fed_pks , fed_k , right) = if let BtcTerminal :: OrD ( ref a, ref b) = ms_clone. node {
179
- if let ( BtcTerminal :: Multi ( fed_k , fed_pks ) , right) = ( & a. node , & b. node ) {
180
- ( fed_pks , * fed_k , right)
177
+ let ( fed , right) = if let BtcTerminal :: OrD ( ref a, ref b) = ms_clone. node {
178
+ if let ( BtcTerminal :: Multi ( t ) , right) = ( & a. node , & b. node ) {
179
+ ( t . clone ( ) , right)
181
180
} else {
182
181
unreachable ! ( "Only valid pegin miniscripts" ) ;
183
182
}
184
183
} else {
185
184
unreachable ! ( "Only valid pegin miniscripts" ) ;
186
185
} ;
187
- let ( timelock, emer_pks, emer_k) = if let BtcTerminal :: AndV ( l, r) = right {
188
- if let ( BtcTerminal :: Verify ( csv) , BtcTerminal :: Multi ( emer_k, emer_pks) ) =
189
- ( & l. node , & r. node )
190
- {
186
+ let ( timelock, emer) = if let BtcTerminal :: AndV ( l, r) = right {
187
+ if let ( BtcTerminal :: Verify ( csv) , BtcTerminal :: Multi ( t) ) = ( & l. node , & r. node ) {
191
188
if let BtcTerminal :: Older ( timelock) = csv. node {
192
- ( timelock, emer_pks , * emer_k )
189
+ ( timelock, t . clone ( ) )
193
190
} else {
194
191
unreachable ! ( "Only valid pegin miniscripts" ) ;
195
192
}
@@ -200,10 +197,8 @@ impl<Pk: MiniscriptKey> LegacyPegin<Pk> {
200
197
unreachable ! ( "Only valid pegin miniscripts" ) ;
201
198
} ;
202
199
Self {
203
- fed_pks : fed_pks. to_vec ( ) ,
204
- fed_k,
205
- emer_pks : emer_pks. to_vec ( ) ,
206
- emer_k,
200
+ fed,
201
+ emer,
207
202
timelock,
208
203
desc,
209
204
ms,
@@ -222,18 +217,18 @@ impl<Pk: MiniscriptKey> LegacyPegin<Pk> {
222
217
// Hopefully, we never have to use this and dynafed is deployed
223
218
let mut builder = script:: Builder :: new ( )
224
219
. push_opcode ( opcodes:: all:: OP_DEPTH )
225
- . push_int ( self . fed_k as i64 + 1 )
220
+ . push_int ( self . fed . k ( ) as i64 + 1 )
226
221
. push_opcode ( opcodes:: all:: OP_EQUAL )
227
222
. push_opcode ( opcodes:: all:: OP_IF )
228
223
// manually serialize the left CMS branch, without the OP_CMS
229
- . push_int ( self . fed_k as i64 ) ;
224
+ . push_int ( self . fed . k ( ) as i64 ) ;
230
225
231
- for key in & self . fed_pks {
226
+ for key in self . fed . iter ( ) {
232
227
let tweaked_pk = tweak_key ( key. as_untweaked ( ) , secp, tweak. as_byte_array ( ) ) ;
233
228
builder = builder. push_key ( & tweaked_pk) ;
234
229
}
235
230
let mut nearly_done = builder
236
- . push_int ( self . fed_pks . len ( ) as i64 )
231
+ . push_int ( self . fed . n ( ) as i64 )
237
232
. push_opcode ( opcodes:: all:: OP_ELSE )
238
233
. into_script ( )
239
234
. to_bytes ( ) ;
@@ -298,6 +293,8 @@ impl<Pk: MiniscriptKey> LegacyPegin<Pk> {
298
293
. map ( |pk| LegacyPeginKey :: Functionary ( bitcoin:: PublicKey :: from_str ( pk) . unwrap ( ) ) )
299
294
. collect ( ) ;
300
295
296
+ let fed = bitcoin_miniscript:: Threshold :: new ( 22 , fed_pks) . expect ( "statically defined" ) ;
297
+
301
298
let emer_pks = "
302
299
03aab896d53a8e7d6433137bbba940f9c521e085dd07e60994579b64a6d992cf79,
303
300
0291b7d0b1b692f8f524516ed950872e5da10fb1b808b5a526dedc6fed1cf29807,
@@ -307,12 +304,12 @@ impl<Pk: MiniscriptKey> LegacyPegin<Pk> {
307
304
. map ( |pk| LegacyPeginKey :: Functionary ( bitcoin:: PublicKey :: from_str ( pk) . unwrap ( ) ) )
308
305
. collect ( ) ;
309
306
307
+ let emer = bitcoin_miniscript:: Threshold :: new ( 2 , emer_pks) . expect ( "statically defined" ) ;
308
+
310
309
Self :: new (
311
- fed_pks,
312
- 11 ,
313
- emer_pks,
314
- 2 ,
315
- bitcoin:: Sequence :: from_consensus ( 4032 ) ,
310
+ fed,
311
+ emer,
312
+ bitcoin_miniscript:: RelLockTime :: from_consensus ( 4032 ) . expect ( "statically defined" ) ,
316
313
user_desc,
317
314
)
318
315
}
@@ -473,28 +470,28 @@ impl<Pk: MiniscriptKey> LegacyPegin<Pk> {
473
470
let tweak = hashes:: sha256:: Hash :: hash ( & tweak_vec) ;
474
471
let unsigned_script_sig = self . bitcoin_unsigned_script_sig ( secp) ;
475
472
let mut sigs = vec ! [ ] ;
476
- for key in & self . fed_pks {
473
+ for key in self . fed . iter ( ) {
477
474
let tweaked_pk = tweak_key ( key. as_untweaked ( ) , secp, tweak. as_byte_array ( ) ) ;
478
475
if let Some ( sig) = satisfier. lookup_ecdsa_sig ( & tweaked_pk) {
479
476
sigs. push ( sig. to_vec ( ) ) ;
480
477
}
481
478
}
482
479
sigs. sort_by_key ( |a| a. len ( ) ) ;
483
- if sigs. len ( ) >= self . fed_k {
480
+ if sigs. len ( ) >= self . fed . k ( ) {
484
481
// Prefer using federation keys over emergency paths
485
- let mut sigs: Vec < Vec < u8 > > = sigs. into_iter ( ) . take ( self . fed_k ) . collect ( ) ;
482
+ let mut sigs: Vec < Vec < u8 > > = sigs. into_iter ( ) . take ( self . fed . k ( ) ) . collect ( ) ;
486
483
sigs. push ( vec ! [ 0 ] ) ; // CMS extra value
487
484
Ok ( ( sigs, unsigned_script_sig) )
488
485
} else {
489
486
let mut emer_sigs = vec ! [ ] ;
490
- for emer_key in & self . emer_pks {
487
+ for emer_key in self . emer . iter ( ) {
491
488
if let Some ( sig) = satisfier. lookup_ecdsa_sig ( emer_key. as_untweaked ( ) ) {
492
489
emer_sigs. push ( sig. to_vec ( ) ) ;
493
490
}
494
491
}
495
492
emer_sigs. sort_by_key ( |a| a. len ( ) ) ;
496
- if emer_sigs. len ( ) >= self . emer_k {
497
- let mut sigs: Vec < Vec < u8 > > = emer_sigs. into_iter ( ) . take ( self . emer_k ) . collect ( ) ;
493
+ if emer_sigs. len ( ) >= self . emer . k ( ) {
494
+ let mut sigs: Vec < Vec < u8 > > = emer_sigs. into_iter ( ) . take ( self . emer . k ( ) ) . collect ( ) ;
498
495
sigs. push ( vec ! [ 0 ] ) ; // CMS extra value
499
496
Ok ( ( sigs, unsigned_script_sig) )
500
497
} else {
0 commit comments