@@ -748,7 +748,7 @@ impl Channel {
748
748
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
749
749
/// which peer generated this transaction and "to whom" this transaction flows.
750
750
#[ inline]
751
- fn build_commitment_transaction ( & self , commitment_number : u64 , keys : & TxCreationKeys , local : bool , generated_by_local : bool , feerate_per_kw : u64 ) -> ( Transaction , Vec < HTLCOutputInCommitment > , Vec < ( PaymentHash , & HTLCSource , Option < u32 > ) > ) {
751
+ fn build_commitment_transaction ( & self , commitment_number : u64 , keys : & TxCreationKeys , local : bool , generated_by_local : bool , feerate_per_kw : u64 ) -> ( Transaction , usize , Vec < ( HTLCOutputInCommitment , Option < & HTLCSource > ) > ) {
752
752
let obscured_commitment_transaction_number = self . get_commitment_transaction_number_obscure_factor ( ) ^ ( INITIAL_COMMITMENT_NUMBER - commitment_number) ;
753
753
754
754
let txins = {
@@ -915,30 +915,23 @@ impl Channel {
915
915
transaction_utils:: sort_outputs ( & mut txouts) ;
916
916
917
917
let mut outputs: Vec < TxOut > = Vec :: with_capacity ( txouts. len ( ) ) ;
918
- let mut htlcs_included: Vec < HTLCOutputInCommitment > = Vec :: with_capacity ( txouts. len ( ) ) ;
919
- let mut htlc_sources: Vec < ( PaymentHash , & HTLCSource , Option < u32 > ) > = Vec :: with_capacity ( txouts. len ( ) + unincluded_htlc_sources. len ( ) ) ;
920
- for ( idx, out) in txouts. drain ( ..) . enumerate ( ) {
918
+ let mut htlcs_included: Vec < ( HTLCOutputInCommitment , Option < & HTLCSource > ) > = Vec :: with_capacity ( txouts. len ( ) + unincluded_htlc_sources. len ( ) ) ;
919
+ for ( idx, mut out) in txouts. drain ( ..) . enumerate ( ) {
921
920
outputs. push ( out. 0 ) ;
922
- if let Some ( ( mut htlc, source_option) ) = out. 1 {
921
+ if let Some ( ( mut htlc, source_option) ) = out. 1 . take ( ) {
923
922
htlc. transaction_output_index = Some ( idx as u32 ) ;
924
- if let Some ( source) = source_option {
925
- htlc_sources. push ( ( htlc. payment_hash , source, Some ( idx as u32 ) ) ) ;
926
- }
927
- htlcs_included. push ( htlc) ;
928
- }
929
- }
930
- for ( htlc, source_option) in unincluded_htlc_sources. drain ( ..) {
931
- if let Some ( source) = source_option {
932
- htlc_sources. push ( ( htlc. payment_hash , source, None ) ) ;
923
+ htlcs_included. push ( ( htlc, source_option) ) ;
933
924
}
934
925
}
926
+ let non_dust_htlc_count = htlcs_included. len ( ) ;
927
+ htlcs_included. append ( & mut unincluded_htlc_sources) ;
935
928
936
929
( Transaction {
937
930
version : 2 ,
938
931
lock_time : ( ( 0x20 as u32 ) << 8 * 3 ) | ( ( obscured_commitment_transaction_number & 0xffffffu64 ) as u32 ) ,
939
932
input : txins,
940
933
output : outputs,
941
- } , htlcs_included , htlc_sources )
934
+ } , non_dust_htlc_count , htlcs_included )
942
935
}
943
936
944
937
#[ inline]
@@ -1451,9 +1444,9 @@ impl Channel {
1451
1444
1452
1445
// Now that we're past error-generating stuff, update our local state:
1453
1446
1454
- self . channel_monitor . provide_latest_remote_commitment_tx_info ( & remote_initial_commitment_tx, Vec :: new ( ) , Vec :: new ( ) , self . cur_remote_commitment_transaction_number , self . their_cur_commitment_point . unwrap ( ) ) ;
1447
+ self . channel_monitor . provide_latest_remote_commitment_tx_info ( & remote_initial_commitment_tx, Vec :: new ( ) , self . cur_remote_commitment_transaction_number , self . their_cur_commitment_point . unwrap ( ) ) ;
1455
1448
self . last_local_commitment_txn = vec ! [ local_initial_commitment_tx. clone( ) ] ;
1456
- self . channel_monitor . provide_latest_local_commitment_tx_info ( local_initial_commitment_tx, local_keys, self . feerate_per_kw , Vec :: new ( ) , Vec :: new ( ) ) ;
1449
+ self . channel_monitor . provide_latest_local_commitment_tx_info ( local_initial_commitment_tx, local_keys, self . feerate_per_kw , Vec :: new ( ) ) ;
1457
1450
self . channel_state = ChannelState :: FundingSent as u32 ;
1458
1451
self . channel_id = funding_txo. to_channel_id ( ) ;
1459
1452
self . cur_remote_commitment_transaction_number -= 1 ;
@@ -1490,7 +1483,7 @@ impl Channel {
1490
1483
secp_check ! ( self . secp_ctx. verify( & local_sighash, & msg. signature, & self . their_funding_pubkey. unwrap( ) ) , "Invalid funding_signed signature from peer" ) ;
1491
1484
1492
1485
self . sign_commitment_transaction ( & mut local_initial_commitment_tx, & msg. signature ) ;
1493
- self . channel_monitor . provide_latest_local_commitment_tx_info ( local_initial_commitment_tx. clone ( ) , local_keys, self . feerate_per_kw , Vec :: new ( ) , Vec :: new ( ) ) ;
1486
+ self . channel_monitor . provide_latest_local_commitment_tx_info ( local_initial_commitment_tx. clone ( ) , local_keys, self . feerate_per_kw , Vec :: new ( ) ) ;
1494
1487
self . last_local_commitment_txn = vec ! [ local_initial_commitment_tx] ;
1495
1488
self . channel_state = ChannelState :: FundingSent as u32 ;
1496
1489
self . cur_local_commitment_transaction_number -= 1 ;
@@ -1693,7 +1686,7 @@ impl Channel {
1693
1686
1694
1687
let mut local_commitment_tx = {
1695
1688
let mut commitment_tx = self . build_commitment_transaction ( self . cur_local_commitment_transaction_number , & local_keys, true , false , feerate_per_kw) ;
1696
- let htlcs_cloned: Vec < _ > = commitment_tx. 2 . drain ( ..) . map ( |htlc_source | ( htlc_source . 0 , htlc_source . 1 . clone ( ) , htlc_source . 2 ) ) . collect ( ) ;
1689
+ let htlcs_cloned: Vec < _ > = commitment_tx. 2 . drain ( ..) . map ( |htlc | ( htlc . 0 , htlc . 1 . map ( |h| h . clone ( ) ) ) ) . collect ( ) ;
1697
1690
( commitment_tx. 0 , commitment_tx. 1 , htlcs_cloned)
1698
1691
} ;
1699
1692
let local_commitment_txid = local_commitment_tx. 0 . txid ( ) ;
@@ -1702,24 +1695,24 @@ impl Channel {
1702
1695
1703
1696
//If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
1704
1697
if update_fee {
1705
- let num_htlcs = local_commitment_tx. 1 . len ( ) ;
1698
+ let num_htlcs = local_commitment_tx. 1 ;
1706
1699
let total_fee: u64 = feerate_per_kw as u64 * ( COMMITMENT_TX_BASE_WEIGHT + ( num_htlcs as u64 ) * COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ;
1707
1700
1708
1701
if self . channel_value_satoshis - self . value_to_self_msat / 1000 < total_fee + self . their_channel_reserve_satoshis {
1709
1702
return Err ( ChannelError :: Close ( "Funding remote cannot afford proposed new fee" ) ) ;
1710
1703
}
1711
1704
}
1712
1705
1713
- if msg. htlc_signatures . len ( ) != local_commitment_tx. 1 . len ( ) {
1706
+ if msg. htlc_signatures . len ( ) != local_commitment_tx. 1 {
1714
1707
return Err ( ChannelError :: Close ( "Got wrong number of HTLC signatures from remote" ) ) ;
1715
1708
}
1716
1709
1717
- let mut new_local_commitment_txn = Vec :: with_capacity ( local_commitment_tx. 1 . len ( ) + 1 ) ;
1710
+ let mut new_local_commitment_txn = Vec :: with_capacity ( local_commitment_tx. 1 + 1 ) ;
1718
1711
self . sign_commitment_transaction ( & mut local_commitment_tx. 0 , & msg. signature ) ;
1719
1712
new_local_commitment_txn. push ( local_commitment_tx. 0 . clone ( ) ) ;
1720
1713
1721
- let mut htlcs_and_sigs = Vec :: with_capacity ( local_commitment_tx. 1 . len ( ) ) ;
1722
- for ( idx, htlc) in local_commitment_tx. 1 . drain ( ..) . enumerate ( ) {
1714
+ let mut htlcs_and_sigs = Vec :: with_capacity ( local_commitment_tx. 2 . len ( ) ) ;
1715
+ for ( idx, ( htlc, source ) ) in local_commitment_tx. 2 . drain ( ..) . enumerate ( ) {
1723
1716
if let Some ( _) = htlc. transaction_output_index {
1724
1717
let mut htlc_tx = self . build_htlc_transaction ( & local_commitment_txid, & htlc, true , & local_keys, feerate_per_kw) ;
1725
1718
let htlc_redeemscript = chan_utils:: get_htlc_redeemscript ( & htlc, & local_keys) ;
@@ -1732,7 +1725,9 @@ impl Channel {
1732
1725
} else {
1733
1726
self . create_htlc_tx_signature ( & htlc_tx, & htlc, & local_keys) ?. 1
1734
1727
} ;
1735
- htlcs_and_sigs. push ( ( htlc, msg. htlc_signatures [ idx] , htlc_sig) ) ;
1728
+ htlcs_and_sigs. push ( ( htlc, Some ( ( msg. htlc_signatures [ idx] , htlc_sig) ) , source) ) ;
1729
+ } else {
1730
+ htlcs_and_sigs. push ( ( htlc, None , source) ) ;
1736
1731
}
1737
1732
}
1738
1733
@@ -1760,7 +1755,7 @@ impl Channel {
1760
1755
self . monitor_pending_order = None ;
1761
1756
}
1762
1757
1763
- self . channel_monitor . provide_latest_local_commitment_tx_info ( local_commitment_tx. 0 , local_keys, self . feerate_per_kw , htlcs_and_sigs, local_commitment_tx . 2 ) ;
1758
+ self . channel_monitor . provide_latest_local_commitment_tx_info ( local_commitment_tx. 0 , local_keys, self . feerate_per_kw , htlcs_and_sigs) ;
1764
1759
1765
1760
for htlc in self . pending_inbound_htlcs . iter_mut ( ) {
1766
1761
let new_forward = if let & InboundHTLCState :: RemoteAnnounced ( ref forward_info) = & htlc. state {
@@ -3030,7 +3025,7 @@ impl Channel {
3030
3025
let temporary_channel_id = self . channel_id ;
3031
3026
3032
3027
// Now that we're past error-generating stuff, update our local state:
3033
- self . channel_monitor . provide_latest_remote_commitment_tx_info ( & commitment_tx, Vec :: new ( ) , Vec :: new ( ) , self . cur_remote_commitment_transaction_number , self . their_cur_commitment_point . unwrap ( ) ) ;
3028
+ self . channel_monitor . provide_latest_remote_commitment_tx_info ( & commitment_tx, Vec :: new ( ) , self . cur_remote_commitment_transaction_number , self . their_cur_commitment_point . unwrap ( ) ) ;
3034
3029
self . channel_state = ChannelState :: FundingCreated as u32 ;
3035
3030
self . channel_id = funding_txo. to_channel_id ( ) ;
3036
3031
self . cur_remote_commitment_transaction_number -= 1 ;
@@ -3262,23 +3257,23 @@ impl Channel {
3262
3257
}
3263
3258
}
3264
3259
3265
- let ( res, remote_commitment_tx, htlcs, htlc_sources ) = match self . send_commitment_no_state_update ( ) {
3266
- Ok ( ( res, ( remote_commitment_tx, htlcs , mut htlc_sources ) ) ) => {
3260
+ let ( res, remote_commitment_tx, htlcs) = match self . send_commitment_no_state_update ( ) {
3261
+ Ok ( ( res, ( remote_commitment_tx, mut htlcs ) ) ) => {
3267
3262
// Update state now that we've passed all the can-fail calls...
3268
- let htlc_sources_no_ref = htlc_sources . drain ( ..) . map ( |htlc_source| ( htlc_source . 0 , htlc_source. 1 . clone ( ) , htlc_source . 2 ) ) . collect ( ) ;
3269
- ( res, remote_commitment_tx, htlcs , htlc_sources_no_ref )
3263
+ let htlcs_no_ref = htlcs . drain ( ..) . map ( |( htlc , htlc_source) | ( htlc , htlc_source. map ( |source_ref| Box :: new ( source_ref . clone ( ) ) ) ) ) . collect ( ) ;
3264
+ ( res, remote_commitment_tx, htlcs_no_ref )
3270
3265
} ,
3271
3266
Err ( e) => return Err ( e) ,
3272
3267
} ;
3273
3268
3274
- self . channel_monitor . provide_latest_remote_commitment_tx_info ( & remote_commitment_tx, htlcs, htlc_sources , self . cur_remote_commitment_transaction_number , self . their_cur_commitment_point . unwrap ( ) ) ;
3269
+ self . channel_monitor . provide_latest_remote_commitment_tx_info ( & remote_commitment_tx, htlcs, self . cur_remote_commitment_transaction_number , self . their_cur_commitment_point . unwrap ( ) ) ;
3275
3270
self . channel_state |= ChannelState :: AwaitingRemoteRevoke as u32 ;
3276
3271
Ok ( ( res, self . channel_monitor . clone ( ) ) )
3277
3272
}
3278
3273
3279
3274
/// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
3280
3275
/// when we shouldn't change HTLC/channel state.
3281
- fn send_commitment_no_state_update ( & self ) -> Result < ( msgs:: CommitmentSigned , ( Transaction , Vec < HTLCOutputInCommitment > , Vec < ( PaymentHash , & HTLCSource , Option < u32 > ) > ) ) , ChannelError > {
3276
+ fn send_commitment_no_state_update ( & self ) -> Result < ( msgs:: CommitmentSigned , ( Transaction , Vec < ( HTLCOutputInCommitment , Option < & HTLCSource > ) > ) ) , ChannelError > {
3282
3277
let funding_script = self . get_funding_redeemscript ( ) ;
3283
3278
3284
3279
let mut feerate_per_kw = self . feerate_per_kw ;
@@ -3294,9 +3289,8 @@ impl Channel {
3294
3289
let remote_sighash = Message :: from_slice ( & bip143:: SighashComponents :: new ( & remote_commitment_tx. 0 ) . sighash_all ( & remote_commitment_tx. 0 . input [ 0 ] , & funding_script, self . channel_value_satoshis ) [ ..] ) . unwrap ( ) ;
3295
3290
let our_sig = self . secp_ctx . sign ( & remote_sighash, & self . local_keys . funding_key ) ;
3296
3291
3297
- let mut htlc_sigs = Vec :: new ( ) ;
3298
-
3299
- for ref htlc in remote_commitment_tx. 1 . iter ( ) {
3292
+ let mut htlc_sigs = Vec :: with_capacity ( remote_commitment_tx. 1 ) ;
3293
+ for & ( ref htlc, _) in remote_commitment_tx. 2 . iter ( ) {
3300
3294
if let Some ( _) = htlc. transaction_output_index {
3301
3295
let htlc_tx = self . build_htlc_transaction ( & remote_commitment_txid, htlc, false , & remote_keys, feerate_per_kw) ;
3302
3296
let htlc_redeemscript = chan_utils:: get_htlc_redeemscript ( & htlc, & remote_keys) ;
@@ -3310,7 +3304,7 @@ impl Channel {
3310
3304
channel_id : self . channel_id ,
3311
3305
signature : our_sig,
3312
3306
htlc_signatures : htlc_sigs,
3313
- } , remote_commitment_tx) )
3307
+ } , ( remote_commitment_tx. 0 , remote_commitment_tx . 2 ) ) )
3314
3308
}
3315
3309
3316
3310
/// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
@@ -4024,8 +4018,11 @@ mod tests {
4024
4018
macro_rules! test_commitment {
4025
4019
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
4026
4020
unsigned_tx = {
4027
- let res = chan. build_commitment_transaction( 0xffffffffffff - 42 , & keys, true , false , chan. feerate_per_kw) ;
4028
- ( res. 0 , res. 1 )
4021
+ let mut res = chan. build_commitment_transaction( 0xffffffffffff - 42 , & keys, true , false , chan. feerate_per_kw) ;
4022
+ let htlcs = res. 2 . drain( ..)
4023
+ . filter_map( |( htlc, _) | if htlc. transaction_output_index. is_some( ) { Some ( htlc) } else { None } )
4024
+ . collect( ) ;
4025
+ ( res. 0 , htlcs)
4029
4026
} ;
4030
4027
let their_signature = Signature :: from_der( & secp_ctx, & hex:: decode( $their_sig_hex) . unwrap( ) [ ..] ) . unwrap( ) ;
4031
4028
let sighash = Message :: from_slice( & bip143:: SighashComponents :: new( & unsigned_tx. 0 ) . sighash_all( & unsigned_tx. 0 . input[ 0 ] , & chan. get_funding_redeemscript( ) , chan. channel_value_satoshis) [ ..] ) . unwrap( ) ;
0 commit comments