@@ -162,19 +162,43 @@ enum OutboundHTLCState {
162162 Committed ,
163163 /// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize
164164 /// the change (though they'll need to revoke before we fail the payment).
165- RemoteRemoved ( Option < HTLCFailReason > ) ,
165+ RemoteRemoved ( OutboundHTLCOutcome ) ,
166166 /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
167167 /// the remote side hasn't yet revoked their previous state, which we need them to do before we
168168 /// can do any backwards failing. Implies AwaitingRemoteRevoke.
169169 /// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a
170170 /// remote revoke_and_ack on a previous state before we can do so.
171- AwaitingRemoteRevokeToRemove ( Option < HTLCFailReason > ) ,
171+ AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome ) ,
172172 /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
173173 /// the remote side hasn't yet revoked their previous state, which we need them to do before we
174174 /// can do any backwards failing. Implies AwaitingRemoteRevoke.
175175 /// We have removed this HTLC in our latest commitment_signed and are now just waiting on a
176176 /// revoke_and_ack to drop completely.
177- AwaitingRemovedRemoteRevoke ( Option < HTLCFailReason > ) ,
177+ AwaitingRemovedRemoteRevoke ( OutboundHTLCOutcome ) ,
178+ }
179+
180+ #[ derive( Clone ) ]
181+ enum OutboundHTLCOutcome {
182+ Success ( Option < PaymentPreimage > ) ,
183+ Failure ( HTLCFailReason ) ,
184+ }
185+
186+ impl From < Option < HTLCFailReason > > for OutboundHTLCOutcome {
187+ fn from ( o : Option < HTLCFailReason > ) -> Self {
188+ match o {
189+ None => OutboundHTLCOutcome :: Success ( None ) ,
190+ Some ( r) => OutboundHTLCOutcome :: Failure ( r)
191+ }
192+ }
193+ }
194+
195+ impl < ' a > Into < Option < & ' a HTLCFailReason > > for & ' a OutboundHTLCOutcome {
196+ fn into ( self ) -> Option < & ' a HTLCFailReason > {
197+ match self {
198+ OutboundHTLCOutcome :: Success ( _) => None ,
199+ OutboundHTLCOutcome :: Failure ( ref r) => Some ( r)
200+ }
201+ }
178202}
179203
180204struct OutboundHTLCOutput {
@@ -1289,10 +1313,10 @@ impl<Signer: Sign> Channel<Signer> {
12891313 } else {
12901314 log_trace ! ( logger, " ...not including outbound HTLC {} (hash {}) with value {} due to state ({})" , htlc. htlc_id, log_bytes!( htlc. payment_hash. 0 ) , htlc. amount_msat, state_name) ;
12911315 match htlc. state {
1292- OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( None ) |OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( None ) => {
1316+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome :: Success ( _ ) ) |OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( OutboundHTLCOutcome :: Success ( _ ) ) => {
12931317 value_to_self_msat_offset -= htlc. amount_msat as i64 ;
12941318 } ,
1295- OutboundHTLCState :: RemoteRemoved ( None ) => {
1319+ OutboundHTLCState :: RemoteRemoved ( OutboundHTLCOutcome :: Success ( _ ) ) => {
12961320 if !generated_by_local {
12971321 value_to_self_msat_offset -= htlc. amount_msat as i64 ;
12981322 }
@@ -2393,9 +2417,9 @@ impl<Signer: Sign> Channel<Signer> {
23932417 // transaction).
23942418 let mut removed_outbound_total_msat = 0 ;
23952419 for ref htlc in self . pending_outbound_htlcs . iter ( ) {
2396- if let OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( None ) = htlc. state {
2420+ if let OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome :: Success ( _ ) ) = htlc. state {
23972421 removed_outbound_total_msat += htlc. amount_msat ;
2398- } else if let OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( None ) = htlc. state {
2422+ } else if let OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( OutboundHTLCOutcome :: Success ( _ ) ) = htlc. state {
23992423 removed_outbound_total_msat += htlc. amount_msat ;
24002424 }
24012425 }
@@ -2494,21 +2518,25 @@ impl<Signer: Sign> Channel<Signer> {
24942518
24952519 /// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
24962520 #[ inline]
2497- fn mark_outbound_htlc_removed ( & mut self , htlc_id : u64 , check_preimage : Option < PaymentHash > , fail_reason : Option < HTLCFailReason > ) -> Result < & OutboundHTLCOutput , ChannelError > {
2521+ fn mark_outbound_htlc_removed ( & mut self , htlc_id : u64 , check_preimage : Option < PaymentPreimage > , fail_reason : Option < HTLCFailReason > ) -> Result < & OutboundHTLCOutput , ChannelError > {
2522+ assert ! ( !( check_preimage. is_some( ) && fail_reason. is_some( ) ) , "cannot fail while we have a preimage" ) ;
24982523 for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
24992524 if htlc. htlc_id == htlc_id {
2500- match check_preimage {
2501- None => { } ,
2502- Some ( payment_hash) =>
2525+ let outcome = match check_preimage {
2526+ None => fail_reason. into ( ) ,
2527+ Some ( payment_preimage) => {
2528+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 [ ..] ) . into_inner ( ) ) ;
25032529 if payment_hash != htlc. payment_hash {
25042530 return Err ( ChannelError :: Close ( format ! ( "Remote tried to fulfill HTLC ({}) with an incorrect preimage" , htlc_id) ) ) ;
25052531 }
2532+ OutboundHTLCOutcome :: Success ( Some ( payment_preimage) )
2533+ }
25062534 } ;
25072535 match htlc. state {
25082536 OutboundHTLCState :: LocalAnnounced ( _) =>
25092537 return Err ( ChannelError :: Close ( format ! ( "Remote tried to fulfill/fail HTLC ({}) before it had been committed" , htlc_id) ) ) ,
25102538 OutboundHTLCState :: Committed => {
2511- htlc. state = OutboundHTLCState :: RemoteRemoved ( fail_reason ) ;
2539+ htlc. state = OutboundHTLCState :: RemoteRemoved ( outcome ) ;
25122540 } ,
25132541 OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( _) | OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( _) | OutboundHTLCState :: RemoteRemoved ( _) =>
25142542 return Err ( ChannelError :: Close ( format ! ( "Remote tried to fulfill/fail HTLC ({}) that they'd already fulfilled/failed" , htlc_id) ) ) ,
@@ -2527,8 +2555,7 @@ impl<Signer: Sign> Channel<Signer> {
25272555 return Err ( ChannelError :: Close ( "Peer sent update_fulfill_htlc when we needed a channel_reestablish" . to_owned ( ) ) ) ;
25282556 }
25292557
2530- let payment_hash = PaymentHash ( Sha256 :: hash ( & msg. payment_preimage . 0 [ ..] ) . into_inner ( ) ) ;
2531- self . mark_outbound_htlc_removed ( msg. htlc_id , Some ( payment_hash) , None ) . map ( |htlc| ( htlc. source . clone ( ) , htlc. amount_msat ) )
2558+ self . mark_outbound_htlc_removed ( msg. htlc_id , Some ( msg. payment_preimage ) , None ) . map ( |htlc| ( htlc. source . clone ( ) , htlc. amount_msat ) )
25322559 }
25332560
25342561 pub fn update_fail_htlc ( & mut self , msg : & msgs:: UpdateFailHTLC , fail_reason : HTLCFailReason ) -> Result < ( ) , ChannelError > {
@@ -2689,12 +2716,13 @@ impl<Signer: Sign> Channel<Signer> {
26892716 }
26902717 }
26912718 for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
2692- if let Some ( fail_reason) = if let & mut OutboundHTLCState :: RemoteRemoved ( ref mut fail_reason) = & mut htlc. state {
2693- Some ( fail_reason. take ( ) )
2694- } else { None } {
2719+ if let & mut OutboundHTLCState :: RemoteRemoved ( ref mut fail_reason) = & mut htlc. state {
26952720 log_trace ! ( logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}." ,
26962721 log_bytes!( htlc. payment_hash. 0 ) , log_bytes!( self . channel_id) ) ;
2697- htlc. state = OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( fail_reason) ;
2722+ // Grab the preimage, if it exists, instead of cloning
2723+ let mut reason = OutboundHTLCOutcome :: Success ( None ) ;
2724+ mem:: swap ( fail_reason, & mut reason) ;
2725+ htlc. state = OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( reason) ;
26982726 need_commitment = true ;
26992727 }
27002728 }
@@ -2965,7 +2993,7 @@ impl<Signer: Sign> Channel<Signer> {
29652993 pending_outbound_htlcs. retain ( |htlc| {
29662994 if let & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref fail_reason) = & htlc. state {
29672995 log_trace ! ( logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}" , log_bytes!( htlc. payment_hash. 0 ) ) ;
2968- if let Some ( reason) = fail_reason. clone ( ) { // We really want take() here, but, again, non-mut ref :(
2996+ if let OutboundHTLCOutcome :: Failure ( reason) = fail_reason. clone ( ) { // We really want take() here, but, again, non-mut ref :(
29692997 revoked_htlcs. push ( ( htlc. source . clone ( ) , htlc. payment_hash , reason) ) ;
29702998 } else {
29712999 finalized_claimed_htlcs. push ( htlc. source . clone ( ) ) ;
@@ -3019,11 +3047,12 @@ impl<Signer: Sign> Channel<Signer> {
30193047 log_trace ! ( logger, " ...promoting outbound LocalAnnounced {} to Committed" , log_bytes!( htlc. payment_hash. 0 ) ) ;
30203048 htlc. state = OutboundHTLCState :: Committed ;
30213049 }
3022- if let Some ( fail_reason) = if let & mut OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref mut fail_reason) = & mut htlc. state {
3023- Some ( fail_reason. take ( ) )
3024- } else { None } {
3050+ if let & mut OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref mut fail_reason) = & mut htlc. state {
30253051 log_trace ! ( logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke" , log_bytes!( htlc. payment_hash. 0 ) ) ;
3026- htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( fail_reason) ;
3052+ // Grab the preimage, if it exists, instead of cloning
3053+ let mut reason = OutboundHTLCOutcome :: Success ( None ) ;
3054+ mem:: swap ( fail_reason, & mut reason) ;
3055+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( reason) ;
30273056 require_commitment = true ;
30283057 }
30293058 }
@@ -4891,11 +4920,12 @@ impl<Signer: Sign> Channel<Signer> {
48914920 }
48924921 }
48934922 for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
4894- if let Some ( fail_reason) = if let & mut OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref mut fail_reason) = & mut htlc. state {
4895- Some ( fail_reason. take ( ) )
4896- } else { None } {
4923+ if let & mut OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref mut fail_reason) = & mut htlc. state {
48974924 log_trace ! ( logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke" , log_bytes!( htlc. payment_hash. 0 ) ) ;
4898- htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( fail_reason) ;
4925+ // Grab the preimage, if it exists, instead of cloning
4926+ let mut reason = OutboundHTLCOutcome :: Success ( None ) ;
4927+ mem:: swap ( fail_reason, & mut reason) ;
4928+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( reason) ;
48994929 }
49004930 }
49014931 if let Some ( ( feerate, update_state) ) = self . pending_update_fee {
@@ -5253,6 +5283,8 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
52535283 }
52545284 }
52555285
5286+ let mut preimages: Vec < & Option < PaymentPreimage > > = vec ! [ ] ;
5287+
52565288 ( self . pending_outbound_htlcs . len ( ) as u64 ) . write ( writer) ?;
52575289 for htlc in self . pending_outbound_htlcs . iter ( ) {
52585290 htlc. htlc_id . write ( writer) ?;
@@ -5273,14 +5305,22 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
52735305 // resend the claim/fail on reconnect as we all (hopefully) the missing CS.
52745306 1u8 . write ( writer) ?;
52755307 } ,
5276- & OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref fail_reason ) => {
5308+ & OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref outcome ) => {
52775309 3u8 . write ( writer) ?;
5278- fail_reason. write ( writer) ?;
5279- } ,
5280- & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref fail_reason) => {
5310+ if let OutboundHTLCOutcome :: Success ( preimage) = outcome {
5311+ preimages. push ( preimage) ;
5312+ }
5313+ let reason: Option < & HTLCFailReason > = outcome. into ( ) ;
5314+ reason. write ( writer) ?;
5315+ }
5316+ & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref outcome) => {
52815317 4u8 . write ( writer) ?;
5282- fail_reason. write ( writer) ?;
5283- } ,
5318+ if let OutboundHTLCOutcome :: Success ( preimage) = outcome {
5319+ preimages. push ( preimage) ;
5320+ }
5321+ let reason: Option < & HTLCFailReason > = outcome. into ( ) ;
5322+ reason. write ( writer) ?;
5323+ }
52845324 }
52855325 }
52865326
@@ -5434,6 +5474,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
54345474 ( 9 , self . target_closing_feerate_sats_per_kw, option) ,
54355475 ( 11 , self . monitor_pending_finalized_fulfills, vec_type) ,
54365476 ( 13 , self . channel_creation_height, required) ,
5477+ ( 15 , preimages, vec_type) ,
54375478 } ) ;
54385479
54395480 Ok ( ( ) )
@@ -5519,9 +5560,18 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
55195560 state : match <u8 as Readable >:: read ( reader) ? {
55205561 0 => OutboundHTLCState :: LocalAnnounced ( Box :: new ( Readable :: read ( reader) ?) ) ,
55215562 1 => OutboundHTLCState :: Committed ,
5522- 2 => OutboundHTLCState :: RemoteRemoved ( Readable :: read ( reader) ?) ,
5523- 3 => OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( Readable :: read ( reader) ?) ,
5524- 4 => OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( Readable :: read ( reader) ?) ,
5563+ 2 => {
5564+ let option: Option < HTLCFailReason > = Readable :: read ( reader) ?;
5565+ OutboundHTLCState :: RemoteRemoved ( option. into ( ) )
5566+ } ,
5567+ 3 => {
5568+ let option: Option < HTLCFailReason > = Readable :: read ( reader) ?;
5569+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( option. into ( ) )
5570+ } ,
5571+ 4 => {
5572+ let option: Option < HTLCFailReason > = Readable :: read ( reader) ?;
5573+ OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( option. into ( ) )
5574+ } ,
55255575 _ => return Err ( DecodeError :: InvalidValue ) ,
55265576 } ,
55275577 } ) ;
@@ -5675,6 +5725,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
56755725 // only, so we default to that if none was written.
56765726 let mut channel_type = Some ( ChannelTypeFeatures :: only_static_remote_key ( ) ) ;
56775727 let mut channel_creation_height = Some ( serialized_height) ;
5728+ let mut preimages_opt: Option < Vec < Option < PaymentPreimage > > > = None ;
5729+
56785730 read_tlv_fields ! ( reader, {
56795731 ( 0 , announcement_sigs, option) ,
56805732 ( 1 , minimum_depth, option) ,
@@ -5687,8 +5739,28 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
56875739 ( 9 , target_closing_feerate_sats_per_kw, option) ,
56885740 ( 11 , monitor_pending_finalized_fulfills, vec_type) ,
56895741 ( 13 , channel_creation_height, option) ,
5742+ ( 15 , preimages_opt, vec_type) ,
56905743 } ) ;
56915744
5745+ if let Some ( preimages) = preimages_opt {
5746+ let mut iter = preimages. into_iter ( ) ;
5747+ for htlc in pending_outbound_htlcs. iter_mut ( ) {
5748+ match & htlc. state {
5749+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome :: Success ( None ) ) => {
5750+ htlc. state = OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome :: Success ( iter. next ( ) . ok_or ( DecodeError :: InvalidValue ) ?) ) ;
5751+ }
5752+ OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( OutboundHTLCOutcome :: Success ( None ) ) => {
5753+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( OutboundHTLCOutcome :: Success ( iter. next ( ) . ok_or ( DecodeError :: InvalidValue ) ?) ) ;
5754+ }
5755+ _ => { }
5756+ }
5757+ }
5758+ // We expect all preimages to be consumed above
5759+ if iter. next ( ) . is_some ( ) {
5760+ return Err ( DecodeError :: InvalidValue ) ;
5761+ }
5762+ }
5763+
56925764 let chan_features = channel_type. as_ref ( ) . unwrap ( ) ;
56935765 if chan_features. supports_unknown_bits ( ) || chan_features. requires_unknown_bits ( ) {
56945766 // If the channel was written by a new version and negotiated with features we don't
0 commit comments