@@ -248,6 +248,10 @@ impl_writeable_tlv_based!(ConstructedTransaction, {
248248
249249impl ConstructedTransaction {
250250 fn new ( context : NegotiationContext ) -> Result < Self , AbortReason > {
251+ let remote_inputs_value = context. remote_inputs_value ( ) ;
252+ let remote_outputs_value = context. remote_outputs_value ( ) ;
253+ let remote_weight_contributed = context. remote_weight_contributed ( ) ;
254+
251255 let satisfaction_weight =
252256 Weight :: from_wu ( context. inputs . iter ( ) . fold ( 0u64 , |value, ( _, input) | {
253257 value. saturating_add ( input. satisfaction_weight ( ) . to_wu ( ) )
@@ -284,6 +288,29 @@ impl ConstructedTransaction {
284288 shared_input_index,
285289 } ;
286290
291+ // The receiving node:
292+ // MUST fail the negotiation if:
293+ // - the peer's total input satoshis is less than their outputs
294+ if remote_inputs_value < remote_outputs_value {
295+ return Err ( AbortReason :: OutputsValueExceedsInputsValue ) ;
296+ }
297+
298+ // - the peer's paid feerate does not meet or exceed the agreed feerate (based on the minimum fee).
299+ let remote_fees_contributed = remote_inputs_value. saturating_sub ( remote_outputs_value) ;
300+ let required_remote_contribution_fee =
301+ fee_for_weight ( context. feerate_sat_per_kw , remote_weight_contributed) ;
302+ if remote_fees_contributed < required_remote_contribution_fee {
303+ return Err ( AbortReason :: InsufficientFees ) ;
304+ }
305+
306+ // - there are more than 252 inputs
307+ // - there are more than 252 outputs
308+ if tx. tx . input . len ( ) > MAX_INPUTS_OUTPUTS_COUNT
309+ || tx. tx . output . len ( ) > MAX_INPUTS_OUTPUTS_COUNT
310+ {
311+ return Err ( AbortReason :: ExceededNumberOfInputsOrOutputs ) ;
312+ }
313+
287314 if context. shared_funding_input . is_some ( ) && tx. shared_input_index . is_none ( ) {
288315 return Err ( AbortReason :: MissingFundingInput ) ;
289316 }
@@ -886,6 +913,18 @@ impl NegotiationContext {
886913 )
887914 }
888915
916+ fn remote_weight_contributed ( & self ) -> u64 {
917+ self . remote_inputs_weight ( )
918+ . to_wu ( )
919+ . saturating_add ( self . remote_outputs_weight ( ) . to_wu ( ) )
920+ // The receiving node:
921+ // - MUST fail the negotiation if
922+ // - if is the non-initiator:
923+ // - the initiator's fees do not cover the common fields (version, segwit marker + flag,
924+ // input count, output count, locktime)
925+ . saturating_add ( if !self . holder_is_initiator { TX_COMMON_FIELDS_WEIGHT } else { 0 } )
926+ }
927+
889928 fn remote_outputs_weight ( & self ) -> Weight {
890929 Weight :: from_wu (
891930 self . outputs
@@ -1188,52 +1227,6 @@ impl NegotiationContext {
11881227 self . outputs . remove ( & msg. serial_id ) ;
11891228 Ok ( ( ) )
11901229 }
1191-
1192- fn check_counterparty_fees (
1193- & self , counterparty_fees_contributed : u64 ,
1194- ) -> Result < ( ) , AbortReason > {
1195- let mut counterparty_weight_contributed = self
1196- . remote_inputs_weight ( )
1197- . to_wu ( )
1198- . saturating_add ( self . remote_outputs_weight ( ) . to_wu ( ) ) ;
1199- if !self . holder_is_initiator {
1200- // if is the non-initiator:
1201- // - the initiator's fees do not cover the common fields (version, segwit marker + flag,
1202- // input count, output count, locktime)
1203- counterparty_weight_contributed += TX_COMMON_FIELDS_WEIGHT ;
1204- }
1205- let required_counterparty_contribution_fee =
1206- fee_for_weight ( self . feerate_sat_per_kw , counterparty_weight_contributed) ;
1207- if counterparty_fees_contributed < required_counterparty_contribution_fee {
1208- return Err ( AbortReason :: InsufficientFees ) ;
1209- }
1210- Ok ( ( ) )
1211- }
1212-
1213- fn validate_tx ( self ) -> Result < ConstructedTransaction , AbortReason > {
1214- // The receiving node:
1215- // MUST fail the negotiation if:
1216-
1217- // - the peer's total input satoshis is less than their outputs
1218- let remote_inputs_value = self . remote_inputs_value ( ) ;
1219- let remote_outputs_value = self . remote_outputs_value ( ) ;
1220- if remote_inputs_value < remote_outputs_value {
1221- return Err ( AbortReason :: OutputsValueExceedsInputsValue ) ;
1222- }
1223-
1224- // - there are more than 252 inputs
1225- // - there are more than 252 outputs
1226- if self . inputs . len ( ) > MAX_INPUTS_OUTPUTS_COUNT
1227- || self . outputs . len ( ) > MAX_INPUTS_OUTPUTS_COUNT
1228- {
1229- return Err ( AbortReason :: ExceededNumberOfInputsOrOutputs ) ;
1230- }
1231-
1232- // - the peer's paid feerate does not meet or exceed the agreed feerate (based on the minimum fee).
1233- self . check_counterparty_fees ( remote_inputs_value. saturating_sub ( remote_outputs_value) ) ?;
1234-
1235- ConstructedTransaction :: new ( self )
1236- }
12371230}
12381231
12391232// The interactive transaction construction protocol allows two peers to collaboratively build a
@@ -1372,7 +1365,7 @@ macro_rules! define_state_transitions {
13721365 let holder_node_id = context. holder_node_id;
13731366 let counterparty_node_id = context. counterparty_node_id;
13741367
1375- let tx = context . validate_tx ( ) ?;
1368+ let tx = ConstructedTransaction :: new ( context ) ?;
13761369
13771370 // Strict ordering prevents deadlocks during tx_signatures exchange
13781371 let local_contributed_input_value = tx. local_contributed_input_value( ) ;
0 commit comments