@@ -162,19 +162,43 @@ enum OutboundHTLCState {
162
162
Committed ,
163
163
/// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize
164
164
/// the change (though they'll need to revoke before we fail the payment).
165
- RemoteRemoved ( Option < HTLCFailReason > ) ,
165
+ RemoteRemoved ( OutboundHTLCOutcome ) ,
166
166
/// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
167
167
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
168
168
/// can do any backwards failing. Implies AwaitingRemoteRevoke.
169
169
/// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a
170
170
/// remote revoke_and_ack on a previous state before we can do so.
171
- AwaitingRemoteRevokeToRemove ( Option < HTLCFailReason > ) ,
171
+ AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome ) ,
172
172
/// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
173
173
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
174
174
/// can do any backwards failing. Implies AwaitingRemoteRevoke.
175
175
/// We have removed this HTLC in our latest commitment_signed and are now just waiting on a
176
176
/// 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
+ }
178
202
}
179
203
180
204
struct OutboundHTLCOutput {
@@ -1289,10 +1313,10 @@ impl<Signer: Sign> Channel<Signer> {
1289
1313
} else {
1290
1314
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) ;
1291
1315
match htlc. state {
1292
- OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( None ) |OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( None ) => {
1316
+ OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( OutboundHTLCOutcome :: Success ( _ ) ) |OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( OutboundHTLCOutcome :: Success ( _ ) ) => {
1293
1317
value_to_self_msat_offset -= htlc. amount_msat as i64 ;
1294
1318
} ,
1295
- OutboundHTLCState :: RemoteRemoved ( None ) => {
1319
+ OutboundHTLCState :: RemoteRemoved ( OutboundHTLCOutcome :: Success ( _ ) ) => {
1296
1320
if !generated_by_local {
1297
1321
value_to_self_msat_offset -= htlc. amount_msat as i64 ;
1298
1322
}
@@ -2393,9 +2417,9 @@ impl<Signer: Sign> Channel<Signer> {
2393
2417
// transaction).
2394
2418
let mut removed_outbound_total_msat = 0 ;
2395
2419
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 {
2397
2421
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 {
2399
2423
removed_outbound_total_msat += htlc. amount_msat ;
2400
2424
}
2401
2425
}
@@ -2494,21 +2518,25 @@ impl<Signer: Sign> Channel<Signer> {
2494
2518
2495
2519
/// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
2496
2520
#[ 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" ) ;
2498
2523
for htlc in self . pending_outbound_htlcs . iter_mut ( ) {
2499
2524
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 ( ) ) ;
2503
2529
if payment_hash != htlc. payment_hash {
2504
2530
return Err ( ChannelError :: Close ( format ! ( "Remote tried to fulfill HTLC ({}) with an incorrect preimage" , htlc_id) ) ) ;
2505
2531
}
2532
+ OutboundHTLCOutcome :: Success ( Some ( payment_preimage) )
2533
+ }
2506
2534
} ;
2507
2535
match htlc. state {
2508
2536
OutboundHTLCState :: LocalAnnounced ( _) =>
2509
2537
return Err ( ChannelError :: Close ( format ! ( "Remote tried to fulfill/fail HTLC ({}) before it had been committed" , htlc_id) ) ) ,
2510
2538
OutboundHTLCState :: Committed => {
2511
- htlc. state = OutboundHTLCState :: RemoteRemoved ( fail_reason ) ;
2539
+ htlc. state = OutboundHTLCState :: RemoteRemoved ( outcome ) ;
2512
2540
} ,
2513
2541
OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( _) | OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( _) | OutboundHTLCState :: RemoteRemoved ( _) =>
2514
2542
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> {
2527
2555
return Err ( ChannelError :: Close ( "Peer sent update_fulfill_htlc when we needed a channel_reestablish" . to_owned ( ) ) ) ;
2528
2556
}
2529
2557
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 ) )
2532
2559
}
2533
2560
2534
2561
pub fn update_fail_htlc ( & mut self , msg : & msgs:: UpdateFailHTLC , fail_reason : HTLCFailReason ) -> Result < ( ) , ChannelError > {
@@ -2689,12 +2716,13 @@ impl<Signer: Sign> Channel<Signer> {
2689
2716
}
2690
2717
}
2691
2718
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 outcome) = & mut htlc. state {
2695
2720
log_trace ! ( logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}." ,
2696
2721
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 ( outcome, & mut reason) ;
2725
+ htlc. state = OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( reason) ;
2698
2726
need_commitment = true ;
2699
2727
}
2700
2728
}
@@ -2963,9 +2991,9 @@ impl<Signer: Sign> Channel<Signer> {
2963
2991
} else { true }
2964
2992
} ) ;
2965
2993
pending_outbound_htlcs. retain ( |htlc| {
2966
- if let & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref fail_reason ) = & htlc. state {
2994
+ if let & OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( ref outcome ) = & htlc. state {
2967
2995
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) = outcome . clone ( ) { // We really want take() here, but, again, non-mut ref :(
2969
2997
revoked_htlcs. push ( ( htlc. source . clone ( ) , htlc. payment_hash , reason) ) ;
2970
2998
} else {
2971
2999
finalized_claimed_htlcs. push ( htlc. source . clone ( ) ) ;
@@ -3019,11 +3047,12 @@ impl<Signer: Sign> Channel<Signer> {
3019
3047
log_trace ! ( logger, " ...promoting outbound LocalAnnounced {} to Committed" , log_bytes!( htlc. payment_hash. 0 ) ) ;
3020
3048
htlc. state = OutboundHTLCState :: Committed ;
3021
3049
}
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 outcome) = & mut htlc. state {
3025
3051
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 ( outcome, & mut reason) ;
3055
+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( reason) ;
3027
3056
require_commitment = true ;
3028
3057
}
3029
3058
}
@@ -4891,11 +4920,12 @@ impl<Signer: Sign> Channel<Signer> {
4891
4920
}
4892
4921
}
4893
4922
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 outcome) = & mut htlc. state {
4897
4924
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 ( outcome, & mut reason) ;
4928
+ htlc. state = OutboundHTLCState :: AwaitingRemovedRemoteRevoke ( reason) ;
4899
4929
}
4900
4930
}
4901
4931
if let Some ( ( feerate, update_state) ) = self . pending_update_fee {
@@ -5253,6 +5283,8 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
5253
5283
}
5254
5284
}
5255
5285
5286
+ let mut preimages: Vec < & Option < PaymentPreimage > > = vec ! [ ] ;
5287
+
5256
5288
( self . pending_outbound_htlcs . len ( ) as u64 ) . write ( writer) ?;
5257
5289
for htlc in self . pending_outbound_htlcs . iter ( ) {
5258
5290
htlc. htlc_id . write ( writer) ?;
@@ -5273,14 +5305,22 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
5273
5305
// resend the claim/fail on reconnect as we all (hopefully) the missing CS.
5274
5306
1u8 . write ( writer) ?;
5275
5307
} ,
5276
- & OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref fail_reason ) => {
5308
+ & OutboundHTLCState :: AwaitingRemoteRevokeToRemove ( ref outcome ) => {
5277
5309
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) => {
5281
5317
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
+ }
5284
5324
}
5285
5325
}
5286
5326
@@ -5434,6 +5474,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
5434
5474
( 9 , self . target_closing_feerate_sats_per_kw, option) ,
5435
5475
( 11 , self . monitor_pending_finalized_fulfills, vec_type) ,
5436
5476
( 13 , self . channel_creation_height, required) ,
5477
+ ( 15 , preimages, vec_type) ,
5437
5478
} ) ;
5438
5479
5439
5480
Ok ( ( ) )
@@ -5519,9 +5560,18 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
5519
5560
state : match <u8 as Readable >:: read ( reader) ? {
5520
5561
0 => OutboundHTLCState :: LocalAnnounced ( Box :: new ( Readable :: read ( reader) ?) ) ,
5521
5562
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
+ } ,
5525
5575
_ => return Err ( DecodeError :: InvalidValue ) ,
5526
5576
} ,
5527
5577
} ) ;
@@ -5675,6 +5725,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
5675
5725
// only, so we default to that if none was written.
5676
5726
let mut channel_type = Some ( ChannelTypeFeatures :: only_static_remote_key ( ) ) ;
5677
5727
let mut channel_creation_height = Some ( serialized_height) ;
5728
+ let mut preimages_opt: Option < Vec < Option < PaymentPreimage > > > = None ;
5729
+
5678
5730
read_tlv_fields ! ( reader, {
5679
5731
( 0 , announcement_sigs, option) ,
5680
5732
( 1 , minimum_depth, option) ,
@@ -5687,8 +5739,28 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
5687
5739
( 9 , target_closing_feerate_sats_per_kw, option) ,
5688
5740
( 11 , monitor_pending_finalized_fulfills, vec_type) ,
5689
5741
( 13 , channel_creation_height, option) ,
5742
+ ( 15 , preimages_opt, vec_type) ,
5690
5743
} ) ;
5691
5744
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
+
5692
5764
let chan_features = channel_type. as_ref ( ) . unwrap ( ) ;
5693
5765
if chan_features. supports_unknown_bits ( ) || chan_features. requires_unknown_bits ( ) {
5694
5766
// If the channel was written by a new version and negotiated with features we don't
0 commit comments