@@ -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
@@ -282,23 +280,38 @@ impl ConstructedTransaction {
282
280
. fold ( 0u64 , |value, ( _, input) | value. saturating_add ( input. satisfaction_weight ( ) . to_wu ( ) ) )
283
281
) ;
284
282
285
- let mut inputs: Vec < NegotiatedTxInput > =
286
- context. inputs . into_values ( ) . map ( |tx_input| tx_input . into_negotiated_input ( ) ) . collect ( ) ;
283
+ let mut inputs: Vec < ( TxIn , NegotiatedTxInput ) > =
284
+ context. inputs . into_values ( ) . map ( |input| input . into_txin_and_negotiated_input ( ) ) . collect ( ) ;
287
285
let mut outputs: Vec < InteractiveTxOutput > = context. outputs . into_values ( ) . collect ( ) ;
288
- inputs. sort_unstable_by_key ( |input| input. serial_id ) ;
286
+ inputs. sort_unstable_by_key ( |( _ , input) | input. serial_id ) ;
289
287
outputs. sort_unstable_by_key ( |output| output. serial_id ) ;
290
288
291
289
let shared_input_index =
292
290
context. shared_funding_input . as_ref ( ) . and_then ( |shared_funding_input| {
293
291
inputs
294
292
. iter ( )
295
- . position ( |input | {
296
- input . txin . previous_output == shared_funding_input. input . previous_output
293
+ . position ( |( txin , _ ) | {
294
+ txin. previous_output == shared_funding_input. input . previous_output
297
295
} )
298
296
. map ( |position| position as u32 )
299
297
} ) ;
300
298
301
- let constructed_tx = Self {
299
+ let ( input, inputs) : ( Vec < TxIn > , Vec < NegotiatedTxInput > ) = inputs. into_iter ( ) . unzip ( ) ;
300
+ let output = outputs. iter ( ) . map ( |output| output. tx_out ( ) . clone ( ) ) . collect ( ) ;
301
+
302
+ let tx = Transaction {
303
+ version : Version :: TWO ,
304
+ lock_time : context. tx_locktime ,
305
+ input,
306
+ output,
307
+ } ;
308
+
309
+ let tx_weight = tx. weight ( ) . checked_add ( satisfaction_weight) . unwrap_or ( Weight :: MAX ) ;
310
+ if tx_weight > Weight :: from_wu ( MAX_STANDARD_TX_WEIGHT as u64 ) {
311
+ return Err ( AbortReason :: TransactionTooLarge ) ;
312
+ }
313
+
314
+ Ok ( Self {
302
315
holder_is_initiator : context. holder_is_initiator ,
303
316
304
317
local_inputs_value_satoshis,
@@ -309,39 +322,14 @@ impl ConstructedTransaction {
309
322
310
323
inputs,
311
324
outputs,
325
+ tx,
312
326
313
- lock_time : context. tx_locktime ,
314
327
shared_input_index,
315
- } ;
316
-
317
- let tx_weight = constructed_tx. weight ( satisfaction_weight) ;
318
- if tx_weight > Weight :: from_wu ( MAX_STANDARD_TX_WEIGHT as u64 ) {
319
- return Err ( AbortReason :: TransactionTooLarge ) ;
320
- }
321
-
322
- Ok ( constructed_tx)
328
+ } )
323
329
}
324
330
325
- fn weight ( & self , satisfaction_weight : Weight ) -> Weight {
326
- let inputs_weight = Weight :: from_wu ( self . inputs . len ( ) as u64 * BASE_INPUT_WEIGHT )
327
- . checked_add ( satisfaction_weight)
328
- . unwrap_or ( Weight :: MAX ) ;
329
- let outputs_weight = self . outputs . iter ( ) . fold ( Weight :: from_wu ( 0 ) , |weight, output| {
330
- weight. checked_add ( get_output_weight ( output. script_pubkey ( ) ) ) . unwrap_or ( Weight :: MAX )
331
- } ) ;
332
- Weight :: from_wu ( TX_COMMON_FIELDS_WEIGHT )
333
- . checked_add ( inputs_weight)
334
- . and_then ( |weight| weight. checked_add ( outputs_weight) )
335
- . unwrap_or ( Weight :: MAX )
336
- }
337
-
338
- pub fn build_unsigned_tx ( & self ) -> Transaction {
339
- let ConstructedTransaction { inputs, outputs, .. } = self ;
340
-
341
- let input: Vec < TxIn > = inputs. iter ( ) . map ( |input| input. txin . clone ( ) ) . collect ( ) ;
342
- let output: Vec < TxOut > = outputs. iter ( ) . map ( |output| output. tx_out ( ) . clone ( ) ) . collect ( ) ;
343
-
344
- Transaction { version : Version :: TWO , lock_time : self . lock_time , input, output }
331
+ pub fn tx ( & self ) -> & Transaction {
332
+ & self . tx
345
333
}
346
334
347
335
pub fn outputs ( & self ) -> impl Iterator < Item = & InteractiveTxOutput > {
@@ -353,23 +341,25 @@ impl ConstructedTransaction {
353
341
}
354
342
355
343
pub fn compute_txid ( & self ) -> Txid {
356
- self . build_unsigned_tx ( ) . compute_txid ( )
344
+ self . tx ( ) . compute_txid ( )
357
345
}
358
346
359
347
/// Adds provided holder witnesses to holder inputs of unsigned transaction.
360
348
///
361
349
/// Note that it is assumed that the witness count equals the holder input count.
362
350
fn add_local_witnesses ( & mut self , witnesses : Vec < Witness > ) {
363
- self . inputs
351
+ self . tx
352
+ . input
364
353
. iter_mut ( )
354
+ . zip ( self . inputs . iter ( ) )
365
355
. enumerate ( )
366
- . filter ( |( _, input) | input. is_local ( self . holder_is_initiator ) )
356
+ . filter ( |( _, ( _ , input) ) | input. is_local ( self . holder_is_initiator ) )
367
357
. filter ( |( index, _) | {
368
358
self . shared_input_index
369
359
. map ( |shared_index| * index != shared_index as usize )
370
360
. unwrap_or ( true )
371
361
} )
372
- . map ( |( _, input ) | & mut input . txin )
362
+ . map ( |( _, ( txin , _ ) ) | txin)
373
363
. zip ( witnesses)
374
364
. for_each ( |( input, witness) | input. witness = witness) ;
375
365
}
@@ -378,16 +368,18 @@ impl ConstructedTransaction {
378
368
///
379
369
/// Note that it is assumed that the witness count equals the counterparty input count.
380
370
fn add_remote_witnesses ( & mut self , witnesses : Vec < Witness > ) {
381
- self . inputs
371
+ self . tx
372
+ . input
382
373
. iter_mut ( )
374
+ . zip ( self . inputs . iter ( ) )
383
375
. enumerate ( )
384
- . filter ( |( _, input) | !input. is_local ( self . holder_is_initiator ) )
376
+ . filter ( |( _, ( _ , input) ) | !input. is_local ( self . holder_is_initiator ) )
385
377
. filter ( |( index, _) | {
386
378
self . shared_input_index
387
379
. map ( |shared_index| * index != shared_index as usize )
388
380
. unwrap_or ( true )
389
381
} )
390
- . map ( |( _, input ) | & mut input . txin )
382
+ . map ( |( _, ( txin , _ ) ) | txin)
391
383
. zip ( witnesses)
392
384
. for_each ( |( input, witness) | input. witness = witness) ;
393
385
}
@@ -595,18 +587,7 @@ impl InteractiveTxSigningSession {
595
587
}
596
588
597
589
fn finalize_funding_tx ( & mut self ) -> Transaction {
598
- let lock_time = self . unsigned_tx . lock_time ;
599
- let ConstructedTransaction { inputs, outputs, shared_input_index, .. } =
600
- & mut self . unsigned_tx ;
601
-
602
- let mut tx = Transaction {
603
- version : Version :: TWO ,
604
- lock_time,
605
- input : inputs. iter ( ) . cloned ( ) . map ( |input| input. txin ) . collect ( ) ,
606
- output : outputs. iter ( ) . cloned ( ) . map ( |output| output. into_tx_out ( ) ) . collect ( ) ,
607
- } ;
608
-
609
- if let Some ( shared_input_index) = shared_input_index {
590
+ if let Some ( shared_input_index) = self . unsigned_tx . shared_input_index {
610
591
if let Some ( holder_shared_input_sig) = self
611
592
. holder_tx_signatures
612
593
. as_ref ( )
@@ -629,7 +610,7 @@ impl InteractiveTxSigningSession {
629
610
witness. push_ecdsa_signature ( & holder_sig) ;
630
611
}
631
612
witness. push ( & shared_input_sig. witness_script ) ;
632
- tx. input [ * shared_input_index as usize ] . witness = witness;
613
+ self . unsigned_tx . tx . input [ shared_input_index as usize ] . witness = witness;
633
614
} else {
634
615
debug_assert ! ( false ) ;
635
616
}
@@ -641,19 +622,19 @@ impl InteractiveTxSigningSession {
641
622
}
642
623
}
643
624
644
- tx
625
+ self . unsigned_tx . tx . clone ( )
645
626
}
646
627
647
628
fn verify_interactive_tx_signatures < C : bitcoin:: secp256k1:: Verification > (
648
629
& self , secp_ctx : & Secp256k1 < C > , witnesses : & Vec < Witness > ,
649
630
) -> Result < ( ) , String > {
650
631
let unsigned_tx = self . unsigned_tx ( ) ;
651
- let built_tx = unsigned_tx. build_unsigned_tx ( ) ;
632
+ let built_tx = unsigned_tx. tx ( ) ;
652
633
let prev_outputs: Vec < & TxOut > =
653
634
unsigned_tx. inputs ( ) . map ( |input| input. prev_output ( ) ) . collect :: < Vec < _ > > ( ) ;
654
635
let all_prevouts = sighash:: Prevouts :: All ( & prev_outputs[ ..] ) ;
655
636
656
- let mut cache = SighashCache :: new ( & built_tx) ;
637
+ let mut cache = SighashCache :: new ( built_tx) ;
657
638
658
639
let script_pubkeys = unsigned_tx
659
640
. inputs ( )
@@ -1848,9 +1829,9 @@ impl InteractiveTxInput {
1848
1829
self . input . satisfaction_weight ( )
1849
1830
}
1850
1831
1851
- fn into_negotiated_input ( self ) -> NegotiatedTxInput {
1832
+ fn into_txin_and_negotiated_input ( self ) -> ( TxIn , NegotiatedTxInput ) {
1852
1833
let ( txin, prev_output) = self . input . into_tx_in_with_prev_output ( ) ;
1853
- NegotiatedTxInput { serial_id : self . serial_id , txin , prev_output }
1834
+ ( txin , NegotiatedTxInput { serial_id : self . serial_id , prev_output } )
1854
1835
}
1855
1836
}
1856
1837
@@ -3310,16 +3291,12 @@ mod tests {
3310
3291
fn do_verify_tx_signatures (
3311
3292
transaction : Transaction , prev_outputs : Vec < TxOut > ,
3312
3293
) -> Result < ( ) , String > {
3313
- let inputs: Vec < NegotiatedTxInput > = transaction
3314
- . input
3315
- . iter ( )
3316
- . cloned ( )
3317
- . zip ( prev_outputs. into_iter ( ) )
3294
+ let inputs: Vec < NegotiatedTxInput > = prev_outputs
3295
+ . into_iter ( )
3318
3296
. enumerate ( )
3319
- . map ( |( idx, ( txin , prev_output) ) | {
3297
+ . map ( |( idx, prev_output) | {
3320
3298
NegotiatedTxInput {
3321
3299
serial_id : idx as u64 , // even values will be holder (initiator in this test)
3322
- txin,
3323
3300
prev_output,
3324
3301
}
3325
3302
} )
@@ -3340,11 +3317,11 @@ mod tests {
3340
3317
holder_is_initiator : true ,
3341
3318
inputs,
3342
3319
outputs,
3320
+ tx : transaction. clone ( ) ,
3343
3321
local_inputs_value_satoshis : 0 , // N/A for test
3344
3322
local_outputs_value_satoshis : 0 , // N/A for test
3345
3323
remote_inputs_value_satoshis : 0 , // N/A for test
3346
3324
remote_outputs_value_satoshis : 0 , // N/A for test
3347
- lock_time : transaction. lock_time ,
3348
3325
shared_input_index : None ,
3349
3326
} ;
3350
3327
0 commit comments