@@ -200,21 +200,20 @@ pub(crate) struct ConstructedTransaction {
200
200
201
201
inputs : Vec < NegotiatedTxInput > ,
202
202
outputs : Vec < InteractiveTxOutput > ,
203
+ tx : Transaction ,
203
204
204
205
local_inputs_value_satoshis : u64 ,
205
206
local_outputs_value_satoshis : u64 ,
206
207
207
208
remote_inputs_value_satoshis : u64 ,
208
209
remote_outputs_value_satoshis : u64 ,
209
210
210
- lock_time : AbsoluteLockTime ,
211
211
shared_input_index : Option < u32 > ,
212
212
}
213
213
214
214
#[ derive( Clone , Debug , Eq , PartialEq ) ]
215
215
pub ( crate ) struct NegotiatedTxInput {
216
216
serial_id : SerialId ,
217
- txin : TxIn ,
218
217
prev_output : TxOut ,
219
218
}
220
219
@@ -230,19 +229,18 @@ impl NegotiatedTxInput {
230
229
231
230
impl_writeable_tlv_based ! ( NegotiatedTxInput , {
232
231
( 1 , serial_id, required) ,
233
- ( 3 , txin, required) ,
234
- ( 5 , prev_output, required) ,
232
+ ( 3 , prev_output, required) ,
235
233
} ) ;
236
234
237
235
impl_writeable_tlv_based ! ( ConstructedTransaction , {
238
236
( 1 , holder_is_initiator, required) ,
239
237
( 3 , inputs, required) ,
240
238
( 5 , outputs, required) ,
241
- ( 7 , local_inputs_value_satoshis , required) ,
242
- ( 9 , local_outputs_value_satoshis , required) ,
243
- ( 11 , remote_inputs_value_satoshis , required) ,
244
- ( 13 , remote_outputs_value_satoshis , required) ,
245
- ( 15 , lock_time , required) ,
239
+ ( 7 , tx , required) ,
240
+ ( 9 , local_inputs_value_satoshis , required) ,
241
+ ( 11 , local_outputs_value_satoshis , required) ,
242
+ ( 13 , remote_inputs_value_satoshis , required) ,
243
+ ( 15 , remote_outputs_value_satoshis , required) ,
246
244
( 17 , shared_input_index, option) ,
247
245
} ) ;
248
246
@@ -281,23 +279,37 @@ impl ConstructedTransaction {
281
279
value. saturating_add ( input. satisfaction_weight ( ) . to_wu ( ) )
282
280
} ) ) ;
283
281
284
- let mut inputs: Vec < NegotiatedTxInput > =
285
- context. inputs . into_values ( ) . map ( |tx_input| tx_input. into_negotiated_input ( ) ) . collect ( ) ;
282
+ let mut inputs: Vec < ( TxIn , NegotiatedTxInput ) > = context
283
+ . inputs
284
+ . into_values ( )
285
+ . map ( |input| input. into_txin_and_negotiated_input ( ) )
286
+ . collect ( ) ;
286
287
let mut outputs: Vec < InteractiveTxOutput > = context. outputs . into_values ( ) . collect ( ) ;
287
- inputs. sort_unstable_by_key ( |input| input. serial_id ) ;
288
+ inputs. sort_unstable_by_key ( |( _ , input) | input. serial_id ) ;
288
289
outputs. sort_unstable_by_key ( |output| output. serial_id ) ;
289
290
290
291
let shared_input_index =
291
292
context. shared_funding_input . as_ref ( ) . and_then ( |shared_funding_input| {
292
293
inputs
293
294
. iter ( )
294
- . position ( |input | {
295
- input . txin . previous_output == shared_funding_input. input . previous_output
295
+ . position ( |( txin , _ ) | {
296
+ txin. previous_output == shared_funding_input. input . previous_output
296
297
} )
297
298
. map ( |position| position as u32 )
298
299
} ) ;
299
300
300
- let constructed_tx = Self {
301
+ let ( input, inputs) : ( Vec < TxIn > , Vec < NegotiatedTxInput > ) = inputs. into_iter ( ) . unzip ( ) ;
302
+ let output = outputs. iter ( ) . map ( |output| output. tx_out ( ) . clone ( ) ) . collect ( ) ;
303
+
304
+ let tx =
305
+ Transaction { version : Version :: TWO , lock_time : context. tx_locktime , input, output } ;
306
+
307
+ let tx_weight = tx. weight ( ) . checked_add ( satisfaction_weight) . unwrap_or ( Weight :: MAX ) ;
308
+ if tx_weight > Weight :: from_wu ( MAX_STANDARD_TX_WEIGHT as u64 ) {
309
+ return Err ( AbortReason :: TransactionTooLarge ) ;
310
+ }
311
+
312
+ Ok ( Self {
301
313
holder_is_initiator : context. holder_is_initiator ,
302
314
303
315
local_inputs_value_satoshis,
@@ -308,39 +320,14 @@ impl ConstructedTransaction {
308
320
309
321
inputs,
310
322
outputs,
323
+ tx,
311
324
312
- lock_time : context. tx_locktime ,
313
325
shared_input_index,
314
- } ;
315
-
316
- let tx_weight = constructed_tx. weight ( satisfaction_weight) ;
317
- if tx_weight > Weight :: from_wu ( MAX_STANDARD_TX_WEIGHT as u64 ) {
318
- return Err ( AbortReason :: TransactionTooLarge ) ;
319
- }
320
-
321
- Ok ( constructed_tx)
326
+ } )
322
327
}
323
328
324
- fn weight ( & self , satisfaction_weight : Weight ) -> Weight {
325
- let inputs_weight = Weight :: from_wu ( self . inputs . len ( ) as u64 * BASE_INPUT_WEIGHT )
326
- . checked_add ( satisfaction_weight)
327
- . unwrap_or ( Weight :: MAX ) ;
328
- let outputs_weight = self . outputs . iter ( ) . fold ( Weight :: from_wu ( 0 ) , |weight, output| {
329
- weight. checked_add ( get_output_weight ( output. script_pubkey ( ) ) ) . unwrap_or ( Weight :: MAX )
330
- } ) ;
331
- Weight :: from_wu ( TX_COMMON_FIELDS_WEIGHT )
332
- . checked_add ( inputs_weight)
333
- . and_then ( |weight| weight. checked_add ( outputs_weight) )
334
- . unwrap_or ( Weight :: MAX )
335
- }
336
-
337
- pub fn build_unsigned_tx ( & self ) -> Transaction {
338
- let ConstructedTransaction { inputs, outputs, .. } = self ;
339
-
340
- let input: Vec < TxIn > = inputs. iter ( ) . map ( |input| input. txin . clone ( ) ) . collect ( ) ;
341
- let output: Vec < TxOut > = outputs. iter ( ) . map ( |output| output. tx_out ( ) . clone ( ) ) . collect ( ) ;
342
-
343
- Transaction { version : Version :: TWO , lock_time : self . lock_time , input, output }
329
+ pub fn tx ( & self ) -> & Transaction {
330
+ & self . tx
344
331
}
345
332
346
333
pub fn outputs ( & self ) -> impl Iterator < Item = & InteractiveTxOutput > {
@@ -352,23 +339,25 @@ impl ConstructedTransaction {
352
339
}
353
340
354
341
pub fn compute_txid ( & self ) -> Txid {
355
- self . build_unsigned_tx ( ) . compute_txid ( )
342
+ self . tx ( ) . compute_txid ( )
356
343
}
357
344
358
345
/// Adds provided holder witnesses to holder inputs of unsigned transaction.
359
346
///
360
347
/// Note that it is assumed that the witness count equals the holder input count.
361
348
fn add_local_witnesses ( & mut self , witnesses : Vec < Witness > ) {
362
- self . inputs
349
+ self . tx
350
+ . input
363
351
. iter_mut ( )
352
+ . zip ( self . inputs . iter ( ) )
364
353
. enumerate ( )
365
- . filter ( |( _, input) | input. is_local ( self . holder_is_initiator ) )
354
+ . filter ( |( _, ( _ , input) ) | input. is_local ( self . holder_is_initiator ) )
366
355
. filter ( |( index, _) | {
367
356
self . shared_input_index
368
357
. map ( |shared_index| * index != shared_index as usize )
369
358
. unwrap_or ( true )
370
359
} )
371
- . map ( |( _, input ) | & mut input . txin )
360
+ . map ( |( _, ( txin , _ ) ) | txin)
372
361
. zip ( witnesses)
373
362
. for_each ( |( input, witness) | input. witness = witness) ;
374
363
}
@@ -377,16 +366,18 @@ impl ConstructedTransaction {
377
366
///
378
367
/// Note that it is assumed that the witness count equals the counterparty input count.
379
368
fn add_remote_witnesses ( & mut self , witnesses : Vec < Witness > ) {
380
- self . inputs
369
+ self . tx
370
+ . input
381
371
. iter_mut ( )
372
+ . zip ( self . inputs . iter ( ) )
382
373
. enumerate ( )
383
- . filter ( |( _, input) | !input. is_local ( self . holder_is_initiator ) )
374
+ . filter ( |( _, ( _ , input) ) | !input. is_local ( self . holder_is_initiator ) )
384
375
. filter ( |( index, _) | {
385
376
self . shared_input_index
386
377
. map ( |shared_index| * index != shared_index as usize )
387
378
. unwrap_or ( true )
388
379
} )
389
- . map ( |( _, input ) | & mut input . txin )
380
+ . map ( |( _, ( txin , _ ) ) | txin)
390
381
. zip ( witnesses)
391
382
. for_each ( |( input, witness) | input. witness = witness) ;
392
383
}
@@ -594,18 +585,7 @@ impl InteractiveTxSigningSession {
594
585
}
595
586
596
587
fn finalize_funding_tx ( & mut self ) -> Transaction {
597
- let lock_time = self . unsigned_tx . lock_time ;
598
- let ConstructedTransaction { inputs, outputs, shared_input_index, .. } =
599
- & mut self . unsigned_tx ;
600
-
601
- let mut tx = Transaction {
602
- version : Version :: TWO ,
603
- lock_time,
604
- input : inputs. iter ( ) . cloned ( ) . map ( |input| input. txin ) . collect ( ) ,
605
- output : outputs. iter ( ) . cloned ( ) . map ( |output| output. into_tx_out ( ) ) . collect ( ) ,
606
- } ;
607
-
608
- if let Some ( shared_input_index) = shared_input_index {
588
+ if let Some ( shared_input_index) = self . unsigned_tx . shared_input_index {
609
589
if let Some ( holder_shared_input_sig) = self
610
590
. holder_tx_signatures
611
591
. as_ref ( )
@@ -628,7 +608,7 @@ impl InteractiveTxSigningSession {
628
608
witness. push_ecdsa_signature ( & holder_sig) ;
629
609
}
630
610
witness. push ( & shared_input_sig. witness_script ) ;
631
- tx. input [ * shared_input_index as usize ] . witness = witness;
611
+ self . unsigned_tx . tx . input [ shared_input_index as usize ] . witness = witness;
632
612
} else {
633
613
debug_assert ! ( false ) ;
634
614
}
@@ -640,19 +620,19 @@ impl InteractiveTxSigningSession {
640
620
}
641
621
}
642
622
643
- tx
623
+ self . unsigned_tx . tx . clone ( )
644
624
}
645
625
646
626
fn verify_interactive_tx_signatures < C : bitcoin:: secp256k1:: Verification > (
647
627
& self , secp_ctx : & Secp256k1 < C > , witnesses : & Vec < Witness > ,
648
628
) -> Result < ( ) , String > {
649
629
let unsigned_tx = self . unsigned_tx ( ) ;
650
- let built_tx = unsigned_tx. build_unsigned_tx ( ) ;
630
+ let built_tx = unsigned_tx. tx ( ) ;
651
631
let prev_outputs: Vec < & TxOut > =
652
632
unsigned_tx. inputs ( ) . map ( |input| input. prev_output ( ) ) . collect :: < Vec < _ > > ( ) ;
653
633
let all_prevouts = sighash:: Prevouts :: All ( & prev_outputs[ ..] ) ;
654
634
655
- let mut cache = SighashCache :: new ( & built_tx) ;
635
+ let mut cache = SighashCache :: new ( built_tx) ;
656
636
657
637
let script_pubkeys = unsigned_tx
658
638
. inputs ( )
@@ -1855,9 +1835,9 @@ impl InteractiveTxInput {
1855
1835
self . input . satisfaction_weight ( )
1856
1836
}
1857
1837
1858
- fn into_negotiated_input ( self ) -> NegotiatedTxInput {
1838
+ fn into_txin_and_negotiated_input ( self ) -> ( TxIn , NegotiatedTxInput ) {
1859
1839
let ( txin, prev_output) = self . input . into_tx_in_with_prev_output ( ) ;
1860
- NegotiatedTxInput { serial_id : self . serial_id , txin , prev_output }
1840
+ ( txin , NegotiatedTxInput { serial_id : self . serial_id , prev_output } )
1861
1841
}
1862
1842
}
1863
1843
@@ -3321,16 +3301,12 @@ mod tests {
3321
3301
fn do_verify_tx_signatures (
3322
3302
transaction : Transaction , prev_outputs : Vec < TxOut > ,
3323
3303
) -> Result < ( ) , String > {
3324
- let inputs: Vec < NegotiatedTxInput > = transaction
3325
- . input
3326
- . iter ( )
3327
- . cloned ( )
3328
- . zip ( prev_outputs. into_iter ( ) )
3304
+ let inputs: Vec < NegotiatedTxInput > = prev_outputs
3305
+ . into_iter ( )
3329
3306
. enumerate ( )
3330
- . map ( |( idx, ( txin , prev_output) ) | {
3307
+ . map ( |( idx, prev_output) | {
3331
3308
NegotiatedTxInput {
3332
3309
serial_id : idx as u64 , // even values will be holder (initiator in this test)
3333
- txin,
3334
3310
prev_output,
3335
3311
}
3336
3312
} )
@@ -3351,11 +3327,11 @@ mod tests {
3351
3327
holder_is_initiator : true ,
3352
3328
inputs,
3353
3329
outputs,
3330
+ tx : transaction. clone ( ) ,
3354
3331
local_inputs_value_satoshis : 0 , // N/A for test
3355
3332
local_outputs_value_satoshis : 0 , // N/A for test
3356
3333
remote_inputs_value_satoshis : 0 , // N/A for test
3357
3334
remote_outputs_value_satoshis : 0 , // N/A for test
3358
- lock_time : transaction. lock_time ,
3359
3335
shared_input_index : None ,
3360
3336
} ;
3361
3337
0 commit comments