@@ -106,11 +106,13 @@ pub(super) enum PendingHTLCRouting {
106
106
} ,
107
107
Receive {
108
108
payment_data : msgs:: FinalOnionHopData ,
109
+ payment_metadata : Option < Vec < u8 > > ,
109
110
incoming_cltv_expiry : u32 , // Used to track when we should expire pending HTLCs that go unclaimed
110
111
phantom_shared_secret : Option < [ u8 ; 32 ] > ,
111
112
} ,
112
113
ReceiveKeysend {
113
114
payment_preimage : PaymentPreimage ,
115
+ payment_metadata : Option < Vec < u8 > > ,
114
116
incoming_cltv_expiry : u32 , // Used to track when we should expire pending HTLCs that go unclaimed
115
117
} ,
116
118
}
@@ -472,6 +474,7 @@ impl_writeable_tlv_based!(ClaimingPayment, {
472
474
473
475
struct ClaimablePayment {
474
476
purpose : events:: PaymentPurpose ,
477
+ onion_fields : Option < RecipientOnionFields > ,
475
478
htlcs : Vec < ClaimableHTLC > ,
476
479
}
477
480
@@ -2168,7 +2171,7 @@ where
2168
2171
msg : "Got non final data with an HMAC of 0" ,
2169
2172
} ) ;
2170
2173
} ,
2171
- msgs:: OnionHopDataFormat :: FinalNode { payment_data, keysend_preimage, .. } => { // TODO: expose the payment_metadata to the user
2174
+ msgs:: OnionHopDataFormat :: FinalNode { payment_data, keysend_preimage, payment_metadata } => {
2172
2175
if payment_data. is_some ( ) && keysend_preimage. is_some ( ) {
2173
2176
return Err ( ReceiveError {
2174
2177
err_code : 0x4000 |22 ,
@@ -2178,6 +2181,7 @@ where
2178
2181
} else if let Some ( data) = payment_data {
2179
2182
PendingHTLCRouting :: Receive {
2180
2183
payment_data : data,
2184
+ payment_metadata,
2181
2185
incoming_cltv_expiry : hop_data. outgoing_cltv_value ,
2182
2186
phantom_shared_secret,
2183
2187
}
@@ -2198,6 +2202,7 @@ where
2198
2202
2199
2203
PendingHTLCRouting :: ReceiveKeysend {
2200
2204
payment_preimage,
2205
+ payment_metadata,
2201
2206
incoming_cltv_expiry : hop_data. outgoing_cltv_value ,
2202
2207
}
2203
2208
} else {
@@ -3284,13 +3289,19 @@ where
3284
3289
routing, incoming_shared_secret, payment_hash, incoming_amt_msat, outgoing_amt_msat, ..
3285
3290
}
3286
3291
} ) => {
3287
- let ( cltv_expiry, onion_payload, payment_data, phantom_shared_secret) = match routing {
3288
- PendingHTLCRouting :: Receive { payment_data, incoming_cltv_expiry, phantom_shared_secret } => {
3292
+ let ( cltv_expiry, onion_payload, payment_data, phantom_shared_secret, mut onion_fields ) = match routing {
3293
+ PendingHTLCRouting :: Receive { payment_data, payment_metadata , incoming_cltv_expiry, phantom_shared_secret } => {
3289
3294
let _legacy_hop_data = Some ( payment_data. clone ( ) ) ;
3290
- ( incoming_cltv_expiry, OnionPayload :: Invoice { _legacy_hop_data } , Some ( payment_data) , phantom_shared_secret)
3295
+ let onion_fields =
3296
+ RecipientOnionFields { payment_secret : Some ( payment_data. payment_secret ) , payment_metadata } ;
3297
+ ( incoming_cltv_expiry, OnionPayload :: Invoice { _legacy_hop_data } ,
3298
+ Some ( payment_data) , phantom_shared_secret, onion_fields)
3299
+ } ,
3300
+ PendingHTLCRouting :: ReceiveKeysend { payment_preimage, payment_metadata, incoming_cltv_expiry } => {
3301
+ let onion_fields = RecipientOnionFields { payment_secret : None , payment_metadata } ;
3302
+ ( incoming_cltv_expiry, OnionPayload :: Spontaneous ( payment_preimage) ,
3303
+ None , None , onion_fields)
3291
3304
} ,
3292
- PendingHTLCRouting :: ReceiveKeysend { payment_preimage, incoming_cltv_expiry } =>
3293
- ( incoming_cltv_expiry, OnionPayload :: Spontaneous ( payment_preimage) , None , None ) ,
3294
3305
_ => {
3295
3306
panic ! ( "short_channel_id == 0 should imply any pending_forward entries are of type Receive" ) ;
3296
3307
}
@@ -3363,9 +3374,16 @@ where
3363
3374
. or_insert_with( || {
3364
3375
committed_to_claimable = true ;
3365
3376
ClaimablePayment {
3366
- purpose: purpose( ) , htlcs: Vec :: new( )
3377
+ purpose: purpose( ) , htlcs: Vec :: new( ) , onion_fields : None ,
3367
3378
}
3368
3379
} ) ;
3380
+ if let Some ( earlier_fields) = & mut claimable_payment. onion_fields {
3381
+ if earlier_fields. check_merge( & mut onion_fields) . is_err( ) {
3382
+ fail_htlc!( claimable_htlc, payment_hash) ;
3383
+ }
3384
+ } else {
3385
+ claimable_payment. onion_fields = Some ( onion_fields) ;
3386
+ }
3369
3387
let ref mut htlcs = & mut claimable_payment. htlcs;
3370
3388
if htlcs. len( ) == 1 {
3371
3389
if let OnionPayload :: Spontaneous ( _) = htlcs[ 0 ] . onion_payload {
@@ -3471,6 +3489,7 @@ where
3471
3489
let purpose = events:: PaymentPurpose :: SpontaneousPayment ( preimage) ;
3472
3490
e. insert ( ClaimablePayment {
3473
3491
purpose : purpose. clone ( ) ,
3492
+ onion_fields : Some ( onion_fields. clone ( ) ) ,
3474
3493
htlcs : vec ! [ claimable_htlc] ,
3475
3494
} ) ;
3476
3495
let prev_channel_id = prev_funding_outpoint. to_channel_id ( ) ;
@@ -6715,10 +6734,12 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
6715
6734
( 0 , payment_data, required) ,
6716
6735
( 1 , phantom_shared_secret, option) ,
6717
6736
( 2 , incoming_cltv_expiry, required) ,
6737
+ ( 3 , payment_metadata, option) ,
6718
6738
} ,
6719
6739
( 2 , ReceiveKeysend ) => {
6720
6740
( 0 , payment_preimage, required) ,
6721
6741
( 2 , incoming_cltv_expiry, required) ,
6742
+ ( 3 , payment_metadata, option) ,
6722
6743
} ,
6723
6744
; ) ;
6724
6745
@@ -7051,6 +7072,7 @@ where
7051
7072
let pending_outbound_payments = self . pending_outbound_payments . pending_outbound_payments . lock ( ) . unwrap ( ) ;
7052
7073
7053
7074
let mut htlc_purposes: Vec < & events:: PaymentPurpose > = Vec :: new ( ) ;
7075
+ let mut htlc_onion_fields: Vec < & _ > = Vec :: new ( ) ;
7054
7076
( claimable_payments. claimable_payments . len ( ) as u64 ) . write ( writer) ?;
7055
7077
for ( payment_hash, payment) in claimable_payments. claimable_payments . iter ( ) {
7056
7078
payment_hash. write ( writer) ?;
@@ -7059,6 +7081,7 @@ where
7059
7081
htlc. write ( writer) ?;
7060
7082
}
7061
7083
htlc_purposes. push ( & payment. purpose ) ;
7084
+ htlc_onion_fields. push ( & payment. onion_fields ) ;
7062
7085
}
7063
7086
7064
7087
let mut monitor_update_blocked_actions_per_peer = None ;
@@ -7173,6 +7196,7 @@ where
7173
7196
( 7 , self . fake_scid_rand_bytes, required) ,
7174
7197
( 9 , htlc_purposes, vec_type) ,
7175
7198
( 11 , self . probing_cookie_secret, required) ,
7199
+ ( 13 , htlc_onion_fields, optional_vec) ,
7176
7200
} ) ;
7177
7201
7178
7202
Ok ( ( ) )
@@ -7551,6 +7575,7 @@ where
7551
7575
let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
7552
7576
let mut probing_cookie_secret: Option < [ u8 ; 32 ] > = None ;
7553
7577
let mut claimable_htlc_purposes = None ;
7578
+ let mut claimable_htlc_onion_fields = None ;
7554
7579
let mut pending_claiming_payments = Some ( HashMap :: new ( ) ) ;
7555
7580
let mut monitor_update_blocked_actions_per_peer = Some ( Vec :: new ( ) ) ;
7556
7581
read_tlv_fields ! ( reader, {
@@ -7563,6 +7588,7 @@ where
7563
7588
( 7 , fake_scid_rand_bytes, option) ,
7564
7589
( 9 , claimable_htlc_purposes, vec_type) ,
7565
7590
( 11 , probing_cookie_secret, option) ,
7591
+ ( 13 , claimable_htlc_onion_fields, optional_vec) ,
7566
7592
} ) ;
7567
7593
if fake_scid_rand_bytes. is_none ( ) {
7568
7594
fake_scid_rand_bytes = Some ( args. entropy_source . get_secure_random_bytes ( ) ) ;
@@ -7712,15 +7738,29 @@ where
7712
7738
let expanded_inbound_key = inbound_payment:: ExpandedKey :: new ( & inbound_pmt_key_material) ;
7713
7739
7714
7740
let mut claimable_payments = HashMap :: with_capacity ( claimable_htlcs_list. len ( ) ) ;
7715
- if let Some ( mut purposes) = claimable_htlc_purposes {
7741
+ if let Some ( purposes) = claimable_htlc_purposes {
7716
7742
if purposes. len ( ) != claimable_htlcs_list. len ( ) {
7717
7743
return Err ( DecodeError :: InvalidValue ) ;
7718
7744
}
7719
- for ( purpose, ( payment_hash, htlcs) ) in purposes. drain ( ..) . zip ( claimable_htlcs_list. drain ( ..) ) {
7720
- let existing_payment = claimable_payments. insert ( payment_hash, ClaimablePayment {
7721
- purpose, htlcs,
7722
- } ) ;
7723
- if existing_payment. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
7745
+ if let Some ( onion_fields) = claimable_htlc_onion_fields {
7746
+ if onion_fields. len ( ) != claimable_htlcs_list. len ( ) {
7747
+ return Err ( DecodeError :: InvalidValue ) ;
7748
+ }
7749
+ for ( purpose, ( onion, ( payment_hash, htlcs) ) ) in
7750
+ purposes. into_iter ( ) . zip ( onion_fields. into_iter ( ) . zip ( claimable_htlcs_list. into_iter ( ) ) )
7751
+ {
7752
+ let existing_payment = claimable_payments. insert ( payment_hash, ClaimablePayment {
7753
+ purpose, htlcs, onion_fields : onion,
7754
+ } ) ;
7755
+ if existing_payment. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
7756
+ }
7757
+ } else {
7758
+ for ( purpose, ( payment_hash, htlcs) ) in purposes. into_iter ( ) . zip ( claimable_htlcs_list. into_iter ( ) ) {
7759
+ let existing_payment = claimable_payments. insert ( payment_hash, ClaimablePayment {
7760
+ purpose, htlcs, onion_fields : None ,
7761
+ } ) ;
7762
+ if existing_payment. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
7763
+ }
7724
7764
}
7725
7765
} else {
7726
7766
// LDK versions prior to 0.0.107 did not write a `pending_htlc_purposes`, but do
@@ -7751,7 +7791,7 @@ where
7751
7791
events:: PaymentPurpose :: SpontaneousPayment ( * payment_preimage) ,
7752
7792
} ;
7753
7793
claimable_payments. insert ( payment_hash, ClaimablePayment {
7754
- purpose, htlcs,
7794
+ purpose, htlcs, onion_fields : None ,
7755
7795
} ) ;
7756
7796
}
7757
7797
}
0 commit comments