@@ -106,11 +106,13 @@ pub(super) enum PendingHTLCRouting {
106106 } ,
107107 Receive {
108108 payment_data : msgs:: FinalOnionHopData ,
109+ payment_metadata : Option < Vec < u8 > > ,
109110 incoming_cltv_expiry : u32 , // Used to track when we should expire pending HTLCs that go unclaimed
110111 phantom_shared_secret : Option < [ u8 ; 32 ] > ,
111112 } ,
112113 ReceiveKeysend {
113114 payment_preimage : PaymentPreimage ,
115+ payment_metadata : Option < Vec < u8 > > ,
114116 incoming_cltv_expiry : u32 , // Used to track when we should expire pending HTLCs that go unclaimed
115117 } ,
116118}
@@ -472,6 +474,7 @@ impl_writeable_tlv_based!(ClaimingPayment, {
472474
473475struct ClaimablePayment {
474476 purpose : events:: PaymentPurpose ,
477+ onion_fields : Option < RecipientOnionFields > ,
475478 htlcs : Vec < ClaimableHTLC > ,
476479}
477480
@@ -2168,7 +2171,7 @@ where
21682171 msg : "Got non final data with an HMAC of 0" ,
21692172 } ) ;
21702173 } ,
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 } => {
21722175 if payment_data. is_some ( ) && keysend_preimage. is_some ( ) {
21732176 return Err ( ReceiveError {
21742177 err_code : 0x4000 |22 ,
@@ -2178,6 +2181,7 @@ where
21782181 } else if let Some ( data) = payment_data {
21792182 PendingHTLCRouting :: Receive {
21802183 payment_data : data,
2184+ payment_metadata,
21812185 incoming_cltv_expiry : hop_data. outgoing_cltv_value ,
21822186 phantom_shared_secret,
21832187 }
@@ -2198,6 +2202,7 @@ where
21982202
21992203 PendingHTLCRouting :: ReceiveKeysend {
22002204 payment_preimage,
2205+ payment_metadata,
22012206 incoming_cltv_expiry : hop_data. outgoing_cltv_value ,
22022207 }
22032208 } else {
@@ -3284,13 +3289,19 @@ where
32843289 routing, incoming_shared_secret, payment_hash, incoming_amt_msat, outgoing_amt_msat, ..
32853290 }
32863291 } ) => {
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 } => {
32893294 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)
32913304 } ,
3292- PendingHTLCRouting :: ReceiveKeysend { payment_preimage, incoming_cltv_expiry } =>
3293- ( incoming_cltv_expiry, OnionPayload :: Spontaneous ( payment_preimage) , None , None ) ,
32943305 _ => {
32953306 panic ! ( "short_channel_id == 0 should imply any pending_forward entries are of type Receive" ) ;
32963307 }
@@ -3363,9 +3374,16 @@ where
33633374 . or_insert_with( || {
33643375 committed_to_claimable = true ;
33653376 ClaimablePayment {
3366- purpose: purpose( ) , htlcs: Vec :: new( )
3377+ purpose: purpose( ) , htlcs: Vec :: new( ) , onion_fields : None ,
33673378 }
33683379 } ) ;
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+ }
33693387 let ref mut htlcs = & mut claimable_payment. htlcs;
33703388 if htlcs. len( ) == 1 {
33713389 if let OnionPayload :: Spontaneous ( _) = htlcs[ 0 ] . onion_payload {
@@ -3471,6 +3489,7 @@ where
34713489 let purpose = events:: PaymentPurpose :: SpontaneousPayment ( preimage) ;
34723490 e. insert ( ClaimablePayment {
34733491 purpose : purpose. clone ( ) ,
3492+ onion_fields : Some ( onion_fields. clone ( ) ) ,
34743493 htlcs : vec ! [ claimable_htlc] ,
34753494 } ) ;
34763495 let prev_channel_id = prev_funding_outpoint. to_channel_id ( ) ;
@@ -6715,10 +6734,12 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
67156734 ( 0 , payment_data, required) ,
67166735 ( 1 , phantom_shared_secret, option) ,
67176736 ( 2 , incoming_cltv_expiry, required) ,
6737+ ( 3 , payment_metadata, option) ,
67186738 } ,
67196739 ( 2 , ReceiveKeysend ) => {
67206740 ( 0 , payment_preimage, required) ,
67216741 ( 2 , incoming_cltv_expiry, required) ,
6742+ ( 3 , payment_metadata, option) ,
67226743 } ,
67236744; ) ;
67246745
@@ -7051,6 +7072,7 @@ where
70517072 let pending_outbound_payments = self . pending_outbound_payments . pending_outbound_payments . lock ( ) . unwrap ( ) ;
70527073
70537074 let mut htlc_purposes: Vec < & events:: PaymentPurpose > = Vec :: new ( ) ;
7075+ let mut htlc_onion_fields: Vec < & _ > = Vec :: new ( ) ;
70547076 ( claimable_payments. claimable_payments . len ( ) as u64 ) . write ( writer) ?;
70557077 for ( payment_hash, payment) in claimable_payments. claimable_payments . iter ( ) {
70567078 payment_hash. write ( writer) ?;
@@ -7059,6 +7081,7 @@ where
70597081 htlc. write ( writer) ?;
70607082 }
70617083 htlc_purposes. push ( & payment. purpose ) ;
7084+ htlc_onion_fields. push ( & payment. onion_fields ) ;
70627085 }
70637086
70647087 let mut monitor_update_blocked_actions_per_peer = None ;
@@ -7173,6 +7196,7 @@ where
71737196 ( 7 , self . fake_scid_rand_bytes, required) ,
71747197 ( 9 , htlc_purposes, vec_type) ,
71757198 ( 11 , self . probing_cookie_secret, required) ,
7199+ ( 13 , htlc_onion_fields, optional_vec) ,
71767200 } ) ;
71777201
71787202 Ok ( ( ) )
@@ -7551,6 +7575,7 @@ where
75517575 let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
75527576 let mut probing_cookie_secret: Option < [ u8 ; 32 ] > = None ;
75537577 let mut claimable_htlc_purposes = None ;
7578+ let mut claimable_htlc_onion_fields = None ;
75547579 let mut pending_claiming_payments = Some ( HashMap :: new ( ) ) ;
75557580 let mut monitor_update_blocked_actions_per_peer = Some ( Vec :: new ( ) ) ;
75567581 read_tlv_fields ! ( reader, {
@@ -7563,6 +7588,7 @@ where
75637588 ( 7 , fake_scid_rand_bytes, option) ,
75647589 ( 9 , claimable_htlc_purposes, vec_type) ,
75657590 ( 11 , probing_cookie_secret, option) ,
7591+ ( 13 , claimable_htlc_onion_fields, optional_vec) ,
75667592 } ) ;
75677593 if fake_scid_rand_bytes. is_none ( ) {
75687594 fake_scid_rand_bytes = Some ( args. entropy_source . get_secure_random_bytes ( ) ) ;
@@ -7712,15 +7738,29 @@ where
77127738 let expanded_inbound_key = inbound_payment:: ExpandedKey :: new ( & inbound_pmt_key_material) ;
77137739
77147740 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 {
77167742 if purposes. len ( ) != claimable_htlcs_list. len ( ) {
77177743 return Err ( DecodeError :: InvalidValue ) ;
77187744 }
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+ }
77247764 }
77257765 } else {
77267766 // LDK versions prior to 0.0.107 did not write a `pending_htlc_purposes`, but do
@@ -7751,7 +7791,7 @@ where
77517791 events:: PaymentPurpose :: SpontaneousPayment ( * payment_preimage) ,
77527792 } ;
77537793 claimable_payments. insert ( payment_hash, ClaimablePayment {
7754- purpose, htlcs,
7794+ purpose, htlcs, onion_fields : None ,
77557795 } ) ;
77567796 }
77577797 }
0 commit comments