@@ -832,6 +832,12 @@ pub(crate) fn estimate_input_weight(prev_output: &TxOut) -> Weight {
832832 } )
833833}
834834
835+ pub ( crate ) fn get_input_weight ( witness_weight : Weight ) -> Weight {
836+ Weight :: from_wu (
837+ ( BASE_INPUT_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT ) . saturating_add ( witness_weight. to_wu ( ) ) ,
838+ )
839+ }
840+
835841pub ( crate ) fn get_output_weight ( script_pubkey : & ScriptBuf ) -> Weight {
836842 Weight :: from_wu (
837843 ( 8 /* value */ + script_pubkey. consensus_encode ( & mut sink ( ) ) . unwrap ( ) as u64 )
@@ -1949,7 +1955,7 @@ where
19491955 pub feerate_sat_per_kw : u32 ,
19501956 pub is_initiator : bool ,
19511957 pub funding_tx_locktime : AbsoluteLockTime ,
1952- pub inputs_to_contribute : Vec < ( TxIn , Transaction ) > ,
1958+ pub inputs_to_contribute : Vec < ( TxIn , Transaction , Weight ) > ,
19531959 pub shared_funding_input : Option < SharedOwnedInput > ,
19541960 pub shared_funding_output : SharedOwnedOutput ,
19551961 pub outputs_to_contribute : Vec < TxOut > ,
@@ -1989,15 +1995,15 @@ impl InteractiveTxConstructor {
19891995 ) ;
19901996
19911997 // Check for the existence of prevouts'
1992- for ( txin, tx) in inputs_to_contribute. iter ( ) {
1998+ for ( txin, tx, _ ) in inputs_to_contribute. iter ( ) {
19931999 let vout = txin. previous_output . vout as usize ;
19942000 if tx. output . get ( vout) . is_none ( ) {
19952001 return Err ( AbortReason :: PrevTxOutInvalid ) ;
19962002 }
19972003 }
19982004 let mut inputs_to_contribute: Vec < ( SerialId , InputOwned ) > = inputs_to_contribute
19992005 . into_iter ( )
2000- . map ( |( txin, tx) | {
2006+ . map ( |( txin, tx, _ ) | {
20012007 let serial_id = generate_holder_serial_id ( entropy_source, is_initiator) ;
20022008 let vout = txin. previous_output . vout as usize ;
20032009 let prev_output = tx. output . get ( vout) . unwrap ( ) . clone ( ) ; // checked above
@@ -2165,6 +2171,11 @@ impl InteractiveTxConstructor {
21652171/// given inputs and outputs, and intended contribution. Takes into account the fees and the dust
21662172/// limit.
21672173///
2174+ /// Note that since the type of change output cannot be determined at this point, this calculation
2175+ /// does not account for the weight contributed by the change output itself. The fees for the
2176+ /// weight of this change output should be subtracted from the result of this function call to get
2177+ /// the final amount for the change output (if above dust).
2178+ ///
21682179/// Three outcomes are possible:
21692180/// - Inputs are sufficient for intended contribution, fees, and a larger-than-dust change:
21702181/// `Ok(Some(change_amount))`
@@ -2247,13 +2258,14 @@ mod tests {
22472258 use crate :: util:: atomic_counter:: AtomicCounter ;
22482259 use bitcoin:: absolute:: LockTime as AbsoluteLockTime ;
22492260 use bitcoin:: amount:: Amount ;
2261+ use bitcoin:: ecdsa:: Signature ;
22502262 use bitcoin:: hashes:: Hash ;
22512263 use bitcoin:: hex:: FromHex ;
22522264 use bitcoin:: key:: { TweakedPublicKey , UntweakedPublicKey } ;
22532265 use bitcoin:: script:: Builder ;
22542266 use bitcoin:: secp256k1:: { Keypair , PublicKey , Secp256k1 , SecretKey } ;
22552267 use bitcoin:: transaction:: Version ;
2256- use bitcoin:: { opcodes, WScriptHash , Weight , XOnlyPublicKey } ;
2268+ use bitcoin:: { opcodes, WScriptHash , Weight , Witness , XOnlyPublicKey } ;
22572269 use bitcoin:: {
22582270 OutPoint , PubkeyHash , ScriptBuf , Sequence , SignedAmount , Transaction , TxIn , TxOut ,
22592271 WPubkeyHash ,
@@ -2310,12 +2322,12 @@ mod tests {
23102322
23112323 struct TestSession {
23122324 description : & ' static str ,
2313- inputs_a : Vec < ( TxIn , Transaction ) > ,
2325+ inputs_a : Vec < ( TxIn , Transaction , Weight ) > ,
23142326 a_shared_input : Option < ( OutPoint , TxOut , u64 ) > ,
23152327 /// The funding output, with the value contributed
23162328 shared_output_a : ( TxOut , u64 ) ,
23172329 outputs_a : Vec < TxOut > ,
2318- inputs_b : Vec < ( TxIn , Transaction ) > ,
2330+ inputs_b : Vec < ( TxIn , Transaction , Weight ) > ,
23192331 b_shared_input : Option < ( OutPoint , TxOut , u64 ) > ,
23202332 /// The funding output, with the value contributed
23212333 shared_output_b : ( TxOut , u64 ) ,
@@ -2585,7 +2597,7 @@ mod tests {
25852597 }
25862598 }
25872599
2588- fn generate_inputs ( outputs : & [ TestOutput ] ) -> Vec < ( TxIn , Transaction ) > {
2600+ fn generate_inputs ( outputs : & [ TestOutput ] ) -> Vec < ( TxIn , Transaction , Weight ) > {
25892601 let tx = generate_tx ( outputs) ;
25902602 let txid = tx. compute_txid ( ) ;
25912603 tx. output
@@ -2596,9 +2608,16 @@ mod tests {
25962608 previous_output : OutPoint { txid, vout : idx as u32 } ,
25972609 script_sig : Default :: default ( ) ,
25982610 sequence : Sequence :: ENABLE_RBF_NO_LOCKTIME ,
2599- witness : Default :: default ( ) ,
2611+ witness : Witness :: p2wpkh (
2612+ & Signature :: sighash_all (
2613+ bitcoin:: secp256k1:: ecdsa:: Signature :: from_der ( & <Vec < u8 > >:: from_hex ( "3044022008f4f37e2d8f74e18c1b8fde2374d5f28402fb8ab7fd1cc5b786aa40851a70cb022032b1374d1a0f125eae4f69d1bc0b7f896c964cfdba329f38a952426cf427484c" ) . unwrap ( ) [ ..] ) . unwrap ( )
2614+ )
2615+ . into ( ) ,
2616+ & PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
2617+ ) ,
26002618 } ;
2601- ( txin, tx. clone ( ) )
2619+ let witness_weight = Weight :: from_wu_usize ( txin. witness . size ( ) ) ;
2620+ ( txin, tx. clone ( ) , witness_weight)
26022621 } )
26032622 . collect ( )
26042623 }
@@ -2646,12 +2665,12 @@ mod tests {
26462665 ( generate_txout ( & TestOutput :: P2WSH ( value) ) , local_value)
26472666 }
26482667
2649- fn generate_fixed_number_of_inputs ( count : u16 ) -> Vec < ( TxIn , Transaction ) > {
2668+ fn generate_fixed_number_of_inputs ( count : u16 ) -> Vec < ( TxIn , Transaction , Weight ) > {
26502669 // Generate transactions with a total `count` number of outputs such that no transaction has a
26512670 // serialized length greater than u16::MAX.
26522671 let max_outputs_per_prevtx = 1_500 ;
26532672 let mut remaining = count;
2654- let mut inputs: Vec < ( TxIn , Transaction ) > = Vec :: with_capacity ( count as usize ) ;
2673+ let mut inputs: Vec < ( TxIn , Transaction , Weight ) > = Vec :: with_capacity ( count as usize ) ;
26552674
26562675 while remaining > 0 {
26572676 let tx_output_count = remaining. min ( max_outputs_per_prevtx) ;
@@ -2664,7 +2683,7 @@ mod tests {
26642683 ) ;
26652684 let txid = tx. compute_txid ( ) ;
26662685
2667- let mut temp: Vec < ( TxIn , Transaction ) > = tx
2686+ let mut temp: Vec < ( TxIn , Transaction , Weight ) > = tx
26682687 . output
26692688 . iter ( )
26702689 . enumerate ( )
@@ -2673,9 +2692,16 @@ mod tests {
26732692 previous_output : OutPoint { txid, vout : idx as u32 } ,
26742693 script_sig : Default :: default ( ) ,
26752694 sequence : Sequence :: ENABLE_RBF_NO_LOCKTIME ,
2676- witness : Default :: default ( ) ,
2695+ witness : Witness :: p2wpkh (
2696+ & Signature :: sighash_all (
2697+ bitcoin:: secp256k1:: ecdsa:: Signature :: from_der ( & <Vec < u8 > >:: from_hex ( "3044022008f4f37e2d8f74e18c1b8fde2374d5f28402fb8ab7fd1cc5b786aa40851a70cb022032b1374d1a0f125eae4f69d1bc0b7f896c964cfdba329f38a952426cf427484c" ) . unwrap ( ) [ ..] ) . unwrap ( )
2698+ )
2699+ . into ( ) ,
2700+ & PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
2701+ ) ,
26772702 } ;
2678- ( input, tx. clone ( ) )
2703+ let witness_weight = Weight :: from_wu_usize ( input. witness . size ( ) ) ;
2704+ ( input, tx. clone ( ) , witness_weight)
26792705 } )
26802706 . collect ( ) ;
26812707
@@ -2891,9 +2917,15 @@ mod tests {
28912917 previous_output : OutPoint { txid : tx. compute_txid ( ) , vout : 0 } ,
28922918 ..Default :: default ( )
28932919 } ;
2920+ let invalid_sequence_input_witness_weight =
2921+ Weight :: from_wu_usize ( invalid_sequence_input. witness . size ( ) ) ;
28942922 do_test_interactive_tx_constructor ( TestSession {
28952923 description : "Invalid input sequence from initiator" ,
2896- inputs_a : vec ! [ ( invalid_sequence_input, tx. clone( ) ) ] ,
2924+ inputs_a : vec ! [ (
2925+ invalid_sequence_input,
2926+ tx. clone( ) ,
2927+ invalid_sequence_input_witness_weight,
2928+ ) ] ,
28972929 a_shared_input : None ,
28982930 shared_output_a : generate_funding_txout ( 1_000_000 , 1_000_000 ) ,
28992931 outputs_a : vec ! [ ] ,
@@ -2908,9 +2940,13 @@ mod tests {
29082940 sequence : Sequence :: ENABLE_RBF_NO_LOCKTIME ,
29092941 ..Default :: default ( )
29102942 } ;
2943+ let duplicate_input_witness_weight = Weight :: from_wu_usize ( duplicate_input. witness . size ( ) ) ;
29112944 do_test_interactive_tx_constructor ( TestSession {
29122945 description : "Duplicate prevout from initiator" ,
2913- inputs_a : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) ) , ( duplicate_input, tx. clone( ) ) ] ,
2946+ inputs_a : vec ! [
2947+ ( duplicate_input. clone( ) , tx. clone( ) , duplicate_input_witness_weight) ,
2948+ ( duplicate_input, tx. clone( ) , duplicate_input_witness_weight) ,
2949+ ] ,
29142950 a_shared_input : None ,
29152951 shared_output_a : generate_funding_txout ( 1_000_000 , 1_000_000 ) ,
29162952 outputs_a : vec ! [ ] ,
@@ -2926,13 +2962,14 @@ mod tests {
29262962 sequence : Sequence :: ENABLE_RBF_NO_LOCKTIME ,
29272963 ..Default :: default ( )
29282964 } ;
2965+ let duplicate_input_witness_weight = Weight :: from_wu_usize ( duplicate_input. witness . size ( ) ) ;
29292966 do_test_interactive_tx_constructor ( TestSession {
29302967 description : "Non-initiator uses same prevout as initiator" ,
2931- inputs_a : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) ) ] ,
2968+ inputs_a : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) , duplicate_input_witness_weight ) ] ,
29322969 a_shared_input : None ,
29332970 shared_output_a : generate_funding_txout ( 1_000_000 , 905_000 ) ,
29342971 outputs_a : vec ! [ ] ,
2935- inputs_b : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) ) ] ,
2972+ inputs_b : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) , duplicate_input_witness_weight ) ] ,
29362973 b_shared_input : None ,
29372974 shared_output_b : generate_funding_txout ( 1_000_000 , 95_000 ) ,
29382975 outputs_b : vec ! [ ] ,
@@ -2943,13 +2980,14 @@ mod tests {
29432980 sequence : Sequence :: ENABLE_RBF_NO_LOCKTIME ,
29442981 ..Default :: default ( )
29452982 } ;
2983+ let duplicate_input_witness_weight = Weight :: from_wu_usize ( duplicate_input. witness . size ( ) ) ;
29462984 do_test_interactive_tx_constructor ( TestSession {
29472985 description : "Non-initiator uses same prevout as initiator" ,
2948- inputs_a : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) ) ] ,
2986+ inputs_a : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) , duplicate_input_witness_weight ) ] ,
29492987 a_shared_input : None ,
29502988 shared_output_a : generate_funding_txout ( 1_000_000 , 1_000_000 ) ,
29512989 outputs_a : vec ! [ ] ,
2952- inputs_b : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) ) ] ,
2990+ inputs_b : vec ! [ ( duplicate_input. clone( ) , tx. clone( ) , duplicate_input_witness_weight ) ] ,
29532991 b_shared_input : None ,
29542992 shared_output_b : generate_funding_txout ( 1_000_000 , 0 ) ,
29552993 outputs_b : vec ! [ ] ,
0 commit comments