@@ -200,21 +200,20 @@ pub(crate) struct ConstructedTransaction {
200200
201201 inputs : Vec < NegotiatedTxInput > ,
202202 outputs : Vec < InteractiveTxOutput > ,
203+ tx : Transaction ,
203204
204205 local_inputs_value_satoshis : u64 ,
205206 local_outputs_value_satoshis : u64 ,
206207
207208 remote_inputs_value_satoshis : u64 ,
208209 remote_outputs_value_satoshis : u64 ,
209210
210- lock_time : AbsoluteLockTime ,
211211 shared_input_index : Option < u32 > ,
212212}
213213
214214#[ derive( Clone , Debug , Eq , PartialEq ) ]
215215pub ( crate ) struct NegotiatedTxInput {
216216 serial_id : SerialId ,
217- txin : TxIn ,
218217 prev_output : TxOut ,
219218}
220219
@@ -230,19 +229,18 @@ impl NegotiatedTxInput {
230229
231230impl_writeable_tlv_based ! ( NegotiatedTxInput , {
232231 ( 1 , serial_id, required) ,
233- ( 3 , txin, required) ,
234- ( 5 , prev_output, required) ,
232+ ( 3 , prev_output, required) ,
235233} ) ;
236234
237235impl_writeable_tlv_based ! ( ConstructedTransaction , {
238236 ( 1 , holder_is_initiator, required) ,
239237 ( 3 , inputs, required) ,
240238 ( 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) ,
246244 ( 17 , shared_input_index, option) ,
247245} ) ;
248246
@@ -281,23 +279,37 @@ impl ConstructedTransaction {
281279 value. saturating_add ( input. satisfaction_weight ( ) . to_wu ( ) )
282280 } ) ) ;
283281
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 ( ) ;
286287 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 ) ;
288289 outputs. sort_unstable_by_key ( |output| output. serial_id ) ;
289290
290291 let shared_input_index =
291292 context. shared_funding_input . as_ref ( ) . and_then ( |shared_funding_input| {
292293 inputs
293294 . 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
296297 } )
297298 . map ( |position| position as u32 )
298299 } ) ;
299300
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 {
301313 holder_is_initiator : context. holder_is_initiator ,
302314
303315 local_inputs_value_satoshis,
@@ -308,39 +320,14 @@ impl ConstructedTransaction {
308320
309321 inputs,
310322 outputs,
323+ tx,
311324
312- lock_time : context. tx_locktime ,
313325 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+ } )
322327 }
323328
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
344331 }
345332
346333 pub fn outputs ( & self ) -> impl Iterator < Item = & InteractiveTxOutput > {
@@ -352,23 +339,25 @@ impl ConstructedTransaction {
352339 }
353340
354341 pub fn compute_txid ( & self ) -> Txid {
355- self . build_unsigned_tx ( ) . compute_txid ( )
342+ self . tx ( ) . compute_txid ( )
356343 }
357344
358345 /// Adds provided holder witnesses to holder inputs of unsigned transaction.
359346 ///
360347 /// Note that it is assumed that the witness count equals the holder input count.
361348 fn add_local_witnesses ( & mut self , witnesses : Vec < Witness > ) {
362- self . inputs
349+ self . tx
350+ . input
363351 . iter_mut ( )
352+ . zip ( self . inputs . iter ( ) )
364353 . enumerate ( )
365- . filter ( |( _, input) | input. is_local ( self . holder_is_initiator ) )
354+ . filter ( |( _, ( _ , input) ) | input. is_local ( self . holder_is_initiator ) )
366355 . filter ( |( index, _) | {
367356 self . shared_input_index
368357 . map ( |shared_index| * index != shared_index as usize )
369358 . unwrap_or ( true )
370359 } )
371- . map ( |( _, input ) | & mut input . txin )
360+ . map ( |( _, ( txin , _ ) ) | txin)
372361 . zip ( witnesses)
373362 . for_each ( |( input, witness) | input. witness = witness) ;
374363 }
@@ -377,16 +366,18 @@ impl ConstructedTransaction {
377366 ///
378367 /// Note that it is assumed that the witness count equals the counterparty input count.
379368 fn add_remote_witnesses ( & mut self , witnesses : Vec < Witness > ) {
380- self . inputs
369+ self . tx
370+ . input
381371 . iter_mut ( )
372+ . zip ( self . inputs . iter ( ) )
382373 . enumerate ( )
383- . filter ( |( _, input) | !input. is_local ( self . holder_is_initiator ) )
374+ . filter ( |( _, ( _ , input) ) | !input. is_local ( self . holder_is_initiator ) )
384375 . filter ( |( index, _) | {
385376 self . shared_input_index
386377 . map ( |shared_index| * index != shared_index as usize )
387378 . unwrap_or ( true )
388379 } )
389- . map ( |( _, input ) | & mut input . txin )
380+ . map ( |( _, ( txin , _ ) ) | txin)
390381 . zip ( witnesses)
391382 . for_each ( |( input, witness) | input. witness = witness) ;
392383 }
@@ -594,18 +585,7 @@ impl InteractiveTxSigningSession {
594585 }
595586
596587 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 {
609589 if let Some ( holder_shared_input_sig) = self
610590 . holder_tx_signatures
611591 . as_ref ( )
@@ -628,7 +608,7 @@ impl InteractiveTxSigningSession {
628608 witness. push_ecdsa_signature ( & holder_sig) ;
629609 }
630610 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;
632612 } else {
633613 debug_assert ! ( false ) ;
634614 }
@@ -640,19 +620,19 @@ impl InteractiveTxSigningSession {
640620 }
641621 }
642622
643- tx
623+ self . unsigned_tx . tx . clone ( )
644624 }
645625
646626 fn verify_interactive_tx_signatures < C : bitcoin:: secp256k1:: Verification > (
647627 & self , secp_ctx : & Secp256k1 < C > , witnesses : & Vec < Witness > ,
648628 ) -> Result < ( ) , String > {
649629 let unsigned_tx = self . unsigned_tx ( ) ;
650- let built_tx = unsigned_tx. build_unsigned_tx ( ) ;
630+ let built_tx = unsigned_tx. tx ( ) ;
651631 let prev_outputs: Vec < & TxOut > =
652632 unsigned_tx. inputs ( ) . map ( |input| input. prev_output ( ) ) . collect :: < Vec < _ > > ( ) ;
653633 let all_prevouts = sighash:: Prevouts :: All ( & prev_outputs[ ..] ) ;
654634
655- let mut cache = SighashCache :: new ( & built_tx) ;
635+ let mut cache = SighashCache :: new ( built_tx) ;
656636
657637 let script_pubkeys = unsigned_tx
658638 . inputs ( )
@@ -1855,9 +1835,9 @@ impl InteractiveTxInput {
18551835 self . input . satisfaction_weight ( )
18561836 }
18571837
1858- fn into_negotiated_input ( self ) -> NegotiatedTxInput {
1838+ fn into_txin_and_negotiated_input ( self ) -> ( TxIn , NegotiatedTxInput ) {
18591839 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 } )
18611841 }
18621842}
18631843
@@ -3321,16 +3301,12 @@ mod tests {
33213301 fn do_verify_tx_signatures (
33223302 transaction : Transaction , prev_outputs : Vec < TxOut > ,
33233303 ) -> 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 ( )
33293306 . enumerate ( )
3330- . map ( |( idx, ( txin , prev_output) ) | {
3307+ . map ( |( idx, prev_output) | {
33313308 NegotiatedTxInput {
33323309 serial_id : idx as u64 , // even values will be holder (initiator in this test)
3333- txin,
33343310 prev_output,
33353311 }
33363312 } )
@@ -3351,11 +3327,11 @@ mod tests {
33513327 holder_is_initiator : true ,
33523328 inputs,
33533329 outputs,
3330+ tx : transaction. clone ( ) ,
33543331 local_inputs_value_satoshis : 0 , // N/A for test
33553332 local_outputs_value_satoshis : 0 , // N/A for test
33563333 remote_inputs_value_satoshis : 0 , // N/A for test
33573334 remote_outputs_value_satoshis : 0 , // N/A for test
3358- lock_time : transaction. lock_time ,
33593335 shared_input_index : None ,
33603336 } ;
33613337
0 commit comments