@@ -107,19 +107,19 @@ enum OutboundHTLCState {
107107 Committed ,
108108 /// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize
109109 /// the change (though they'll need to revoke before we fail the payment).
110- RemoteRemoved ,
110+ RemoteRemoved ( Option < HTLCFailReason > ) ,
111111 /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
112112 /// the remote side hasn't yet revoked their previous state, which we need them to do before we
113113 /// can do any backwards failing. Implies AwaitingRemoteRevoke.
114114 /// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a
115115 /// remote revoke_and_ack on a previous state before we can do so.
116- AwaitingRemoteRevokeToRemove ,
116+ AwaitingRemoteRevokeToRemove ( Option < HTLCFailReason > ) ,
117117 /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
118118 /// the remote side hasn't yet revoked their previous state, which we need them to do before we
119119 /// can do any backwards failing. Implies AwaitingRemoteRevoke.
120120 /// We have removed this HTLC in our latest commitment_signed and are now just waiting on a
121121 /// revoke_and_ack to drop completely.
122- AwaitingRemovedRemoteRevoke ,
122+ AwaitingRemovedRemoteRevoke ( Option < HTLCFailReason > ) ,
123123}
124124
125125struct OutboundHTLCOutput {
@@ -129,8 +129,6 @@ struct OutboundHTLCOutput {
129129 payment_hash : PaymentHash ,
130130 state : OutboundHTLCState ,
131131 source : HTLCSource ,
132- /// If we're in a removed state, set if they failed, otherwise None
133- fail_reason : Option < HTLCFailReason > ,
134132}
135133
136134/// See AwaitingRemoteRevoke ChannelState for more info
@@ -859,9 +857,9 @@ impl Channel {
859857 let ( include, state_name) = match htlc. state {
860858 OutboundHTLCState :: LocalAnnounced ( _) => ( generated_by_local, "LocalAnnounced" ) ,
861859 OutboundHTLCState :: Committed => ( true , "Committed" ) ,
862- OutboundHTLCState :: RemoteRemoved => ( generated_by_local, "RemoteRemoved" ) ,
863- OutboundHTLCState :: AwaitingRemoteRevokeToRemove => ( generated_by_local, "AwaitingRemoteRevokeToRemove" ) ,
864- OutboundHTLCState :: AwaitingRemovedRemoteRevoke => ( false , "AwaitingRemovedRemoteRevoke" ) ,
860+ OutboundHTLCState :: RemoteRemoved ( _ ) => ( generated_by_local, "RemoteRemoved" ) ,
861+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( _ ) => ( generated_by_local, "AwaitingRemoteRevokeToRemove" ) ,
862+ OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( _ ) => ( false , "AwaitingRemovedRemoteRevoke" ) ,
865863 } ;
866864
867865 if include {
@@ -870,13 +868,11 @@ impl Channel {
870868 } else {
871869 log_trace ! ( self , " ...not including outbound HTLC {} (hash {}) with value {} due to state ({})" , htlc. htlc_id, log_bytes!( htlc. payment_hash. 0 ) , htlc. amount_msat, state_name) ;
872870 match htlc. state {
873- OutboundHTLCState :: AwaitingRemoteRevokeToRemove |OutboundHTLCState :: AwaitingRemovedRemoteRevoke => {
874- if htlc. fail_reason . is_none ( ) {
875- value_to_self_msat_offset -= htlc. amount_msat as i64 ;
876- }
871+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( None ) |OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( None ) => {
872+ value_to_self_msat_offset -= htlc. amount_msat as i64 ;
877873 } ,
878- OutboundHTLCState :: RemoteRemoved => {
879- if !generated_by_local && htlc . fail_reason . is_none ( ) {
874+ OutboundHTLCState :: RemoteRemoved ( None ) => {
875+ if !generated_by_local {
880876 value_to_self_msat_offset -= htlc. amount_msat as i64 ;
881877 }
882878 } ,
@@ -1645,10 +1641,9 @@ impl Channel {
16451641 OutboundHTLCState :: LocalAnnounced ( _) =>
16461642 return Err ( ChannelError :: Close ( "Remote tried to fulfill/fail HTLC before it had been committed" ) ) ,
16471643 OutboundHTLCState :: Committed => {
1648- htlc. state = OutboundHTLCState :: RemoteRemoved ;
1649- htlc. fail_reason = fail_reason;
1644+ htlc. state = OutboundHTLCState :: RemoteRemoved ( fail_reason) ;
16501645 } ,
1651- OutboundHTLCState :: AwaitingRemoteRevokeToRemove | OutboundHTLCState :: AwaitingRemovedRemoteRevoke | OutboundHTLCState :: RemoteRemoved =>
1646+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( _ ) | OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( _ ) | OutboundHTLCState :: RemoteRemoved ( _ ) =>
16521647 return Err ( ChannelError :: Close ( "Remote tried to fulfill/fail HTLC that they'd already fulfilled/failed" ) ) ,
16531648 }
16541649 return Ok ( & htlc. source ) ;
@@ -1801,8 +1796,10 @@ impl Channel {
18011796 }
18021797 }
18031798 for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
1804- if let OutboundHTLCState :: RemoteRemoved = htlc. state {
1805- htlc. state = OutboundHTLCState :: AwaitingRemoteRevokeToRemove ;
1799+ if let Some ( fail_reason) = if let & mut OutboundHTLCState :: RemoteRemoved ( ref mut fail_reason) = & mut htlc. state {
1800+ Some ( fail_reason. take ( ) )
1801+ } else { None } {
1802+ htlc. state = OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( fail_reason) ;
18061803 need_our_commitment = true ;
18071804 }
18081805 }
@@ -1855,6 +1852,8 @@ impl Channel {
18551852 fn free_holding_cell_htlcs ( & mut self ) -> Result < Option < ( msgs:: CommitmentUpdate , ChannelMonitor ) > , ChannelError > {
18561853 assert_eq ! ( self . channel_state & ChannelState :: MonitorUpdateFailed as u32 , 0 ) ;
18571854 if self . holding_cell_htlc_updates . len ( ) != 0 || self . holding_cell_update_fee . is_some ( ) {
1855+ log_trace ! ( self , "Freeing holding cell with {} HTLC updates{}" , self . holding_cell_htlc_updates. len( ) , if self . holding_cell_update_fee. is_some( ) { " and a fee update" } else { "" } ) ;
1856+
18581857 let mut htlc_updates = Vec :: new ( ) ;
18591858 mem:: swap ( & mut htlc_updates, & mut self . holding_cell_htlc_updates ) ;
18601859 let mut update_add_htlcs = Vec :: with_capacity ( htlc_updates. len ( ) ) ;
@@ -2020,9 +2019,9 @@ impl Channel {
20202019 } else { true }
20212020 } ) ;
20222021 pending_outbound_htlcs. retain ( |htlc| {
2023- if let OutboundHTLCState :: AwaitingRemovedRemoteRevoke = htlc. state {
2022+ if let & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref fail_reason ) = & htlc. state {
20242023 log_trace ! ( logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}" , log_bytes!( htlc. payment_hash. 0 ) ) ;
2025- if let Some ( reason) = htlc . fail_reason . clone ( ) { // We really want take() here, but, again, non-mut ref :(
2024+ if let Some ( reason) = fail_reason. clone ( ) { // We really want take() here, but, again, non-mut ref :(
20262025 revoked_htlcs. push ( ( htlc. source . clone ( ) , htlc. payment_hash , reason) ) ;
20272026 } else {
20282027 // They fulfilled, so we sent them money
@@ -2073,9 +2072,12 @@ impl Channel {
20732072 if let OutboundHTLCState :: LocalAnnounced ( _) = htlc. state {
20742073 log_trace ! ( logger, " ...promoting outbound LocalAnnounced {} to Committed" , log_bytes!( htlc. payment_hash. 0 ) ) ;
20752074 htlc. state = OutboundHTLCState :: Committed ;
2076- } else if let OutboundHTLCState :: AwaitingRemoteRevokeToRemove = htlc. state {
2075+ }
2076+ if let Some ( fail_reason) = if let & mut OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref mut fail_reason) = & mut htlc. state {
2077+ Some ( fail_reason. take ( ) )
2078+ } else { None } {
20772079 log_trace ! ( logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke" , log_bytes!( htlc. payment_hash. 0 ) ) ;
2078- htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ;
2080+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( fail_reason ) ;
20792081 require_commitment = true ;
20802082 }
20812083 }
@@ -2231,7 +2233,7 @@ impl Channel {
22312233 self . next_remote_htlc_id -= inbound_drop_count;
22322234
22332235 for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
2234- if let OutboundHTLCState :: RemoteRemoved = htlc. state {
2236+ if let OutboundHTLCState :: RemoteRemoved ( _ ) = htlc. state {
22352237 // They sent us an update to remove this but haven't yet sent the corresponding
22362238 // commitment_signed, we need to move it back to Committed and they can re-send
22372239 // the update upon reconnection.
@@ -3249,7 +3251,6 @@ impl Channel {
32493251 cltv_expiry : cltv_expiry,
32503252 state : OutboundHTLCState :: LocalAnnounced ( Box :: new ( onion_routing_packet. clone ( ) ) ) ,
32513253 source,
3252- fail_reason : None ,
32533254 } ) ;
32543255
32553256 let res = msgs:: UpdateAddHTLC {
@@ -3314,8 +3315,10 @@ impl Channel {
33143315 }
33153316 }
33163317 for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
3317- if let OutboundHTLCState :: AwaitingRemoteRevokeToRemove = htlc. state {
3318- htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ;
3318+ if let Some ( fail_reason) = if let & mut OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref mut fail_reason) = & mut htlc. state {
3319+ Some ( fail_reason. take ( ) )
3320+ } else { None } {
3321+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( fail_reason) ;
33193322 }
33203323 }
33213324
@@ -3581,7 +3584,6 @@ impl Writeable for Channel {
35813584 htlc. cltv_expiry . write ( writer) ?;
35823585 htlc. payment_hash . write ( writer) ?;
35833586 htlc. source . write ( writer) ?;
3584- write_option ! ( htlc. fail_reason) ;
35853587 match & htlc. state {
35863588 & OutboundHTLCState :: LocalAnnounced ( ref onion_packet) => {
35873589 0u8 . write ( writer) ?;
@@ -3590,14 +3592,17 @@ impl Writeable for Channel {
35903592 & OutboundHTLCState :: Committed => {
35913593 1u8 . write ( writer) ?;
35923594 } ,
3593- & OutboundHTLCState :: RemoteRemoved => {
3595+ & OutboundHTLCState :: RemoteRemoved ( ref fail_reason ) => {
35943596 2u8 . write ( writer) ?;
3597+ write_option ! ( * fail_reason) ;
35953598 } ,
3596- & OutboundHTLCState :: AwaitingRemoteRevokeToRemove => {
3599+ & OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref fail_reason ) => {
35973600 3u8 . write ( writer) ?;
3601+ write_option ! ( * fail_reason) ;
35983602 } ,
3599- & OutboundHTLCState :: AwaitingRemovedRemoteRevoke => {
3603+ & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref fail_reason ) => {
36003604 4u8 . write ( writer) ?;
3605+ write_option ! ( * fail_reason) ;
36013606 } ,
36023607 }
36033608 }
@@ -3760,13 +3765,12 @@ impl<R : ::std::io::Read> ReadableArgs<R, Arc<Logger>> for Channel {
37603765 cltv_expiry : Readable :: read ( reader) ?,
37613766 payment_hash : Readable :: read ( reader) ?,
37623767 source : Readable :: read ( reader) ?,
3763- fail_reason : Readable :: read ( reader) ?,
37643768 state : match <u8 as Readable < R > >:: read ( reader) ? {
37653769 0 => OutboundHTLCState :: LocalAnnounced ( Box :: new ( Readable :: read ( reader) ?) ) ,
37663770 1 => OutboundHTLCState :: Committed ,
3767- 2 => OutboundHTLCState :: RemoteRemoved ,
3768- 3 => OutboundHTLCState :: AwaitingRemoteRevokeToRemove ,
3769- 4 => OutboundHTLCState :: AwaitingRemovedRemoteRevoke ,
3771+ 2 => OutboundHTLCState :: RemoteRemoved ( Readable :: read ( reader ) ? ) ,
3772+ 3 => OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( Readable :: read ( reader ) ? ) ,
3773+ 4 => OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( Readable :: read ( reader ) ? ) ,
37703774 _ => return Err ( DecodeError :: InvalidValue ) ,
37713775 } ,
37723776 } ) ;
@@ -4161,7 +4165,6 @@ mod tests {
41614165 payment_hash : PaymentHash ( [ 0 ; 32 ] ) ,
41624166 state : OutboundHTLCState :: Committed ,
41634167 source : HTLCSource :: dummy ( ) ,
4164- fail_reason : None ,
41654168 } ;
41664169 out. payment_hash . 0 = Sha256 :: hash ( & hex:: decode ( "0202020202020202020202020202020202020202020202020202020202020202" ) . unwrap ( ) ) . into_inner ( ) ;
41674170 out
@@ -4174,7 +4177,6 @@ mod tests {
41744177 payment_hash : PaymentHash ( [ 0 ; 32 ] ) ,
41754178 state : OutboundHTLCState :: Committed ,
41764179 source : HTLCSource :: dummy ( ) ,
4177- fail_reason : None ,
41784180 } ;
41794181 out. payment_hash . 0 = Sha256 :: hash ( & hex:: decode ( "0303030303030303030303030303030303030303030303030303030303030303" ) . unwrap ( ) ) . into_inner ( ) ;
41804182 out
0 commit comments