@@ -418,7 +418,7 @@ pub(super) struct ChannelHolder<Signer: Sign> {
418
418
/// Note that while this is held in the same mutex as the channels themselves, no consistency
419
419
/// guarantees are made about the channels given here actually existing anymore by the time you
420
420
/// go to read them!
421
- claimable_htlcs : HashMap < PaymentHash , Vec < ClaimableHTLC > > ,
421
+ claimable_htlcs : HashMap < PaymentHash , ( events :: PaymentPurpose , Vec < ClaimableHTLC > ) > ,
422
422
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
423
423
/// for broadcast messages, where ordering isn't as strict).
424
424
pub ( super ) pending_msg_events : Vec < MessageSendEvent > ,
@@ -3143,8 +3143,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3143
3143
macro_rules! check_total_value {
3144
3144
( $payment_data: expr, $payment_preimage: expr) => { {
3145
3145
let mut payment_received_generated = false ;
3146
- let htlcs = channel_state. claimable_htlcs. entry( payment_hash)
3147
- . or_insert( Vec :: new( ) ) ;
3146
+ let purpose = || {
3147
+ events:: PaymentPurpose :: InvoicePayment {
3148
+ payment_preimage: $payment_preimage,
3149
+ payment_secret: $payment_data. payment_secret,
3150
+ }
3151
+ } ;
3152
+ let ( _, htlcs) = channel_state. claimable_htlcs. entry( payment_hash)
3153
+ . or_insert_with( || ( purpose( ) , Vec :: new( ) ) ) ;
3148
3154
if htlcs. len( ) == 1 {
3149
3155
if let OnionPayload :: Spontaneous ( _) = htlcs[ 0 ] . onion_payload {
3150
3156
log_trace!( self . logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3175,10 +3181,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3175
3181
htlcs. push( claimable_htlc) ;
3176
3182
new_events. push( events:: Event :: PaymentReceived {
3177
3183
payment_hash,
3178
- purpose: events:: PaymentPurpose :: InvoicePayment {
3179
- payment_preimage: $payment_preimage,
3180
- payment_secret: $payment_data. payment_secret,
3181
- } ,
3184
+ purpose: purpose( ) ,
3182
3185
amt: total_value,
3183
3186
} ) ;
3184
3187
payment_received_generated = true ;
@@ -3216,11 +3219,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3216
3219
OnionPayload :: Spontaneous ( preimage) => {
3217
3220
match channel_state. claimable_htlcs . entry ( payment_hash) {
3218
3221
hash_map:: Entry :: Vacant ( e) => {
3219
- e. insert ( vec ! [ claimable_htlc] ) ;
3222
+ let purpose = events:: PaymentPurpose :: SpontaneousPayment ( preimage) ;
3223
+ e. insert ( ( purpose. clone ( ) , vec ! [ claimable_htlc] ) ) ;
3220
3224
new_events. push ( events:: Event :: PaymentReceived {
3221
3225
payment_hash,
3222
3226
amt : amt_to_forward,
3223
- purpose : events :: PaymentPurpose :: SpontaneousPayment ( preimage ) ,
3227
+ purpose,
3224
3228
} ) ;
3225
3229
} ,
3226
3230
hash_map:: Entry :: Occupied ( _) => {
@@ -3459,7 +3463,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3459
3463
true
3460
3464
} ) ;
3461
3465
3462
- channel_state. claimable_htlcs . retain ( |payment_hash, htlcs| {
3466
+ channel_state. claimable_htlcs . retain ( |payment_hash, ( _ , htlcs) | {
3463
3467
if htlcs. is_empty ( ) {
3464
3468
// This should be unreachable
3465
3469
debug_assert ! ( false ) ;
@@ -3503,7 +3507,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3503
3507
3504
3508
let mut channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ;
3505
3509
let removed_source = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( payment_hash) ;
3506
- if let Some ( mut sources) = removed_source {
3510
+ if let Some ( ( _ , mut sources) ) = removed_source {
3507
3511
for htlc in sources. drain ( ..) {
3508
3512
if channel_state. is_none ( ) { channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ; }
3509
3513
let mut htlc_msat_height_data = byte_utils:: be64_to_array ( htlc. value ) . to_vec ( ) ;
@@ -3803,7 +3807,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3803
3807
3804
3808
let mut channel_state = Some ( self . channel_state . lock ( ) . unwrap ( ) ) ;
3805
3809
let removed_source = channel_state. as_mut ( ) . unwrap ( ) . claimable_htlcs . remove ( & payment_hash) ;
3806
- if let Some ( mut sources) = removed_source {
3810
+ if let Some ( ( _ , mut sources) ) = removed_source {
3807
3811
assert ! ( !sources. is_empty( ) ) ;
3808
3812
3809
3813
// If we are claiming an MPP payment, we have to take special care to ensure that each
@@ -5540,7 +5544,7 @@ where
5540
5544
} ) ;
5541
5545
5542
5546
if let Some ( height) = height_opt {
5543
- channel_state. claimable_htlcs . retain ( |payment_hash, htlcs| {
5547
+ channel_state. claimable_htlcs . retain ( |payment_hash, ( _ , htlcs) | {
5544
5548
htlcs. retain ( |htlc| {
5545
5549
// If height is approaching the number of blocks we think it takes us to get
5546
5550
// our commitment transaction confirmed before the HTLC expires, plus the
@@ -6283,13 +6287,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
6283
6287
}
6284
6288
}
6285
6289
6290
+ let mut htlc_purposes: Vec < & events:: PaymentPurpose > = Vec :: new ( ) ;
6286
6291
( channel_state. claimable_htlcs . len ( ) as u64 ) . write ( writer) ?;
6287
- for ( payment_hash, previous_hops) in channel_state. claimable_htlcs . iter ( ) {
6292
+ for ( payment_hash, ( purpose , previous_hops) ) in channel_state. claimable_htlcs . iter ( ) {
6288
6293
payment_hash. write ( writer) ?;
6289
6294
( previous_hops. len ( ) as u64 ) . write ( writer) ?;
6290
6295
for htlc in previous_hops. iter ( ) {
6291
6296
htlc. write ( writer) ?;
6292
6297
}
6298
+ htlc_purposes. push ( purpose) ;
6293
6299
}
6294
6300
6295
6301
let per_peer_state = self . per_peer_state . write ( ) . unwrap ( ) ;
@@ -6366,6 +6372,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
6366
6372
( 3 , pending_outbound_payments, required) ,
6367
6373
( 5 , self . our_network_pubkey, required) ,
6368
6374
( 7 , self . fake_scid_rand_bytes, required) ,
6375
+ ( 9 , htlc_purposes, vec_type) ,
6369
6376
} ) ;
6370
6377
6371
6378
Ok ( ( ) )
@@ -6584,15 +6591,15 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6584
6591
}
6585
6592
6586
6593
let claimable_htlcs_count: u64 = Readable :: read ( reader) ?;
6587
- let mut claimable_htlcs = HashMap :: with_capacity ( cmp:: min ( claimable_htlcs_count as usize , 128 ) ) ;
6594
+ let mut claimable_htlcs_list = Vec :: with_capacity ( cmp:: min ( claimable_htlcs_count as usize , 128 ) ) ;
6588
6595
for _ in 0 ..claimable_htlcs_count {
6589
6596
let payment_hash = Readable :: read ( reader) ?;
6590
6597
let previous_hops_len: u64 = Readable :: read ( reader) ?;
6591
6598
let mut previous_hops = Vec :: with_capacity ( cmp:: min ( previous_hops_len as usize , MAX_ALLOC_SIZE /mem:: size_of :: < ClaimableHTLC > ( ) ) ) ;
6592
6599
for _ in 0 ..previous_hops_len {
6593
- previous_hops. push ( Readable :: read ( reader) ?) ;
6600
+ previous_hops. push ( < ClaimableHTLC as Readable > :: read ( reader) ?) ;
6594
6601
}
6595
- claimable_htlcs . insert ( payment_hash, previous_hops) ;
6602
+ claimable_htlcs_list . push ( ( payment_hash, previous_hops) ) ;
6596
6603
}
6597
6604
6598
6605
let peer_count: u64 = Readable :: read ( reader) ?;
@@ -6662,11 +6669,13 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6662
6669
let mut pending_outbound_payments = None ;
6663
6670
let mut received_network_pubkey: Option < PublicKey > = None ;
6664
6671
let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
6672
+ let mut claimable_htlc_purposes = None ;
6665
6673
read_tlv_fields ! ( reader, {
6666
6674
( 1 , pending_outbound_payments_no_retry, option) ,
6667
6675
( 3 , pending_outbound_payments, option) ,
6668
6676
( 5 , received_network_pubkey, option) ,
6669
6677
( 7 , fake_scid_rand_bytes, option) ,
6678
+ ( 9 , claimable_htlc_purposes, vec_type) ,
6670
6679
} ) ;
6671
6680
if fake_scid_rand_bytes. is_none ( ) {
6672
6681
fake_scid_rand_bytes = Some ( args. keys_manager . get_secure_random_bytes ( ) ) ;
@@ -6727,6 +6736,49 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6727
6736
}
6728
6737
}
6729
6738
6739
+ let inbound_pmt_key_material = args. keys_manager . get_inbound_payment_key_material ( ) ;
6740
+ let expanded_inbound_key = inbound_payment:: ExpandedKey :: new ( & inbound_pmt_key_material) ;
6741
+
6742
+ let mut claimable_htlcs = HashMap :: with_capacity ( claimable_htlcs_list. len ( ) ) ;
6743
+ if let Some ( mut purposes) = claimable_htlc_purposes {
6744
+ if purposes. len ( ) != claimable_htlcs_list. len ( ) {
6745
+ return Err ( DecodeError :: InvalidValue ) ;
6746
+ }
6747
+ for ( purpose, ( payment_hash, previous_hops) ) in purposes. drain ( ..) . zip ( claimable_htlcs_list. drain ( ..) ) {
6748
+ claimable_htlcs. insert ( payment_hash, ( purpose, previous_hops) ) ;
6749
+ }
6750
+ } else {
6751
+ // LDK versions prior to 0.0.107 did not write a `pending_htlc_purposes`, but do
6752
+ // include a `_legacy_hop_data` in the `OnionPayload`.
6753
+ for ( payment_hash, previous_hops) in claimable_htlcs_list. drain ( ..) {
6754
+ if previous_hops. is_empty ( ) {
6755
+ return Err ( DecodeError :: InvalidValue ) ;
6756
+ }
6757
+ let purpose = match & previous_hops[ 0 ] . onion_payload {
6758
+ OnionPayload :: Invoice { _legacy_hop_data } => {
6759
+ if let Some ( hop_data) = _legacy_hop_data {
6760
+ events:: PaymentPurpose :: InvoicePayment {
6761
+ payment_preimage : match pending_inbound_payments. get ( & payment_hash) {
6762
+ Some ( inbound_payment) => inbound_payment. payment_preimage ,
6763
+ None => match inbound_payment:: verify ( payment_hash, & hop_data, 0 , & expanded_inbound_key, & args. logger ) {
6764
+ Ok ( payment_preimage) => payment_preimage,
6765
+ Err ( ( ) ) => {
6766
+ log_error ! ( args. logger, "Failed to read claimable payment data for HTLC with payment hash {} - was not a pending inbound payment and didn't match our payment key" , log_bytes!( payment_hash. 0 ) ) ;
6767
+ return Err ( DecodeError :: InvalidValue ) ;
6768
+ }
6769
+ }
6770
+ } ,
6771
+ payment_secret : hop_data. payment_secret ,
6772
+ }
6773
+ } else { return Err ( DecodeError :: InvalidValue ) ; }
6774
+ } ,
6775
+ OnionPayload :: Spontaneous ( payment_preimage) =>
6776
+ events:: PaymentPurpose :: SpontaneousPayment ( * payment_preimage) ,
6777
+ } ;
6778
+ claimable_htlcs. insert ( payment_hash, ( purpose, previous_hops) ) ;
6779
+ }
6780
+ }
6781
+
6730
6782
let mut secp_ctx = Secp256k1 :: new ( ) ;
6731
6783
secp_ctx. seeded_randomize ( & args. keys_manager . get_secure_random_bytes ( ) ) ;
6732
6784
@@ -6772,8 +6824,6 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6772
6824
}
6773
6825
}
6774
6826
6775
- let inbound_pmt_key_material = args. keys_manager . get_inbound_payment_key_material ( ) ;
6776
- let expanded_inbound_key = inbound_payment:: ExpandedKey :: new ( & inbound_pmt_key_material) ;
6777
6827
let channel_manager = ChannelManager {
6778
6828
genesis_hash,
6779
6829
fee_estimator : args. fee_estimator ,
0 commit comments