@@ -21,7 +21,6 @@ use lightning::events::{
2121 ClosureReason , Event as LdkEvent , FundingInfo , PaymentFailureReason , PaymentPurpose ,
2222 ReplayEvent ,
2323} ;
24- use lightning:: impl_writeable_tlv_based_enum;
2524use lightning:: ln:: channelmanager:: PaymentId ;
2625use lightning:: ln:: types:: ChannelId ;
2726use lightning:: routing:: gossip:: NodeId ;
@@ -32,6 +31,7 @@ use lightning::util::config::{
3231use lightning:: util:: errors:: APIError ;
3332use lightning:: util:: persist:: KVStore ;
3433use lightning:: util:: ser:: { Readable , ReadableArgs , Writeable , Writer } ;
34+ use lightning:: { impl_writeable_tlv_based, impl_writeable_tlv_based_enum } ;
3535use lightning_liquidity:: lsps2:: utils:: compute_opening_fee;
3636use lightning_types:: payment:: { PaymentHash , PaymentPreimage } ;
3737
@@ -61,6 +61,40 @@ use crate::{
6161 UserChannelId ,
6262} ;
6363
64+ /// Identifies the channel and counterparty that a HTLC was processed with.
65+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
66+ #[ cfg_attr( feature = "uniffi" , derive( uniffi:: Record ) ) ]
67+ pub struct HTLCLocator {
68+ /// The channel that the HTLC was sent or received on.
69+ pub channel_id : ChannelId ,
70+ /// The `user_channel_id` for the channel.
71+ ///
72+ /// Will only be `None` for events serialized with LDK Node v0.3.0 or prior, or if the
73+ /// payment was settled via an on-chain transaction.
74+ pub user_channel_id : Option < UserChannelId > ,
75+ /// The node id of the counterparty for this HTLC.
76+ ///
77+ /// This is only `None` for HTLCs received prior to LDK Node v0.5 or for events serialized by
78+ /// versions prior to v0.5.
79+ pub node_id : Option < PublicKey > ,
80+ }
81+
82+ impl_writeable_tlv_based ! ( HTLCLocator , {
83+ ( 1 , channel_id, required) ,
84+ ( 3 , user_channel_id, option) ,
85+ ( 5 , node_id, option) ,
86+ } ) ;
87+
88+ impl From < lightning:: events:: HTLCLocator > for HTLCLocator {
89+ fn from ( value : lightning:: events:: HTLCLocator ) -> Self {
90+ HTLCLocator {
91+ channel_id : value. channel_id ,
92+ user_channel_id : value. user_channel_id . map ( |u| UserChannelId ( u) ) ,
93+ node_id : value. node_id ,
94+ }
95+ }
96+ }
97+
6498/// An event emitted by [`Node`], which should be handled by the user.
6599///
66100/// [`Node`]: [`crate::Node`]
@@ -128,29 +162,14 @@ pub enum Event {
128162 } ,
129163 /// A payment has been forwarded.
130164 PaymentForwarded {
131- /// The channel id of the incoming channel between the previous node and us.
132- prev_channel_id : ChannelId ,
133- /// The channel id of the outgoing channel between the next node and us.
134- next_channel_id : ChannelId ,
135- /// The `user_channel_id` of the incoming channel between the previous node and us.
136- ///
137- /// Will only be `None` for events serialized with LDK Node v0.3.0 or prior.
138- prev_user_channel_id : Option < UserChannelId > ,
139- /// The `user_channel_id` of the outgoing channel between the next node and us.
140- ///
141- /// This will be `None` if the payment was settled via an on-chain transaction. See the
142- /// caveat described for the `total_fee_earned_msat` field.
143- next_user_channel_id : Option < UserChannelId > ,
144- /// The node id of the previous node.
145- ///
146- /// This is only `None` for HTLCs received prior to LDK Node v0.5 or for events serialized by
147- /// versions prior to v0.5.
148- prev_node_id : Option < PublicKey > ,
149- /// The node id of the next node.
150- ///
151- /// This is only `None` for HTLCs received prior to LDK Node v0.5 or for events serialized by
152- /// versions prior to v0.5.
153- next_node_id : Option < PublicKey > ,
165+ /// The set of incoming HTLCs that were forwarded to our node. Contains a single HTLC for
166+ /// source-routed payments, and may contain multiple HTLCs when we acted as a trampoline
167+ /// router.
168+ prev_htlcs : Vec < HTLCLocator > ,
169+ /// The set of outgoing HTLCs forwarded by our node. Contains a single HTLC for regular
170+ /// source-routed payments, and may contain multiple HTLCs when we acted as a trampoline
171+ /// router.
172+ next_htlcs : Vec < HTLCLocator > ,
154173 /// The total fee, in milli-satoshis, which was earned as a result of the payment.
155174 ///
156175 /// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
@@ -323,16 +342,58 @@ impl_writeable_tlv_based_enum!(Event,
323342 ( 7 , custom_records, optional_vec) ,
324343 } ,
325344 ( 7 , PaymentForwarded ) => {
326- ( 0 , prev_channel_id, required) ,
327- ( 1 , prev_node_id, option) ,
328- ( 2 , next_channel_id, required) ,
329- ( 3 , next_node_id, option) ,
330- ( 4 , prev_user_channel_id, option) ,
331- ( 6 , next_user_channel_id, option) ,
345+ // For backwards compatibility, write the first prev/next_htlc to our legacy fields. This
346+ // allows use to downgrade with some information loss about the remaining htlcs.
347+ ( 0 , prev_channel_id_legacy, ( legacy, ChannelId , |_| Ok ( ( ) ) ,
348+ |us: & Event | match us {
349+ Event :: PaymentForwarded { prev_htlcs, .. } => prev_htlcs. first( ) . map( |h| h. channel_id) ,
350+ _ => unreachable!( ) ,
351+ }
352+ ) ) ,
353+ ( 1 , prev_node_id_legacy, ( legacy, PublicKey , |_| Ok ( ( ) ) ,
354+ |us: & Event | match us {
355+ Event :: PaymentForwarded { prev_htlcs, .. } => prev_htlcs. first( ) . and_then( |h| h. node_id) ,
356+ _ => unreachable!( ) ,
357+ }
358+ ) ) ,
359+ ( 2 , next_channel_id_legacy, ( legacy, ChannelId , |_| Ok ( ( ) ) ,
360+ |us: & Event | match us {
361+ Event :: PaymentForwarded { next_htlcs, .. } => next_htlcs. first( ) . map( |h| h. channel_id) ,
362+ _ => unreachable!( ) ,
363+ }
364+ ) ) ,
365+ ( 3 , next_node_id_legacy, ( legacy, PublicKey , |_| Ok ( ( ) ) ,
366+ |us: & Event | match us {
367+ Event :: PaymentForwarded { next_htlcs, .. } => next_htlcs. first( ) . and_then( |h| h. node_id) ,
368+ _ => unreachable!( ) ,
369+ }
370+ ) ) ,
371+ ( 4 , prev_user_channel_id_legacy, ( legacy, UserChannelId , |_| Ok ( ( ) ) ,
372+ |us: & Event | match us {
373+ Event :: PaymentForwarded { prev_htlcs, .. } => prev_htlcs. first( ) . and_then( |h| h. user_channel_id) ,
374+ _ => unreachable!( ) ,
375+ }
376+ ) ) ,
377+ ( 6 , next_user_channel_id_legacy, ( legacy, UserChannelId , |_| Ok ( ( ) ) ,
378+ |us: & Event | match us {
379+ Event :: PaymentForwarded { next_htlcs, .. } => next_htlcs. first( ) . and_then( |h| h. user_channel_id) ,
380+ _ => unreachable!( ) ,
381+ }
382+ ) ) ,
332383 ( 8 , total_fee_earned_msat, option) ,
333384 ( 10 , skimmed_fee_msat, option) ,
334385 ( 12 , claim_from_onchain_tx, required) ,
335386 ( 14 , outbound_amount_forwarded_msat, option) ,
387+ ( 15 , prev_htlcs, /*(default_value, vec![HTLCLocator {
388+ channel_id: prev_channel_id_legacy.ok_or(lightning::ln::msgs::DecodeError::InvalidValue)?,
389+ user_channel_id: prev_user_channel_id_legacy,
390+ node_id: prev_node_id_legacy,
391+ }])*/ required_vec) ,
392+ ( 17 , next_htlcs, /*(default_value, vec![HTLCLocator {
393+ channel_id: next_channel_id_legacy.ok_or(lightning::ln::msgs::DecodeError::InvalidValue)?,
394+ user_channel_id: next_user_channel_id_legacy,
395+ node_id: next_node_id_legacy,
396+ }])*/ required_vec) ,
336397 } ,
337398 ( 8 , SplicePending ) => {
338399 ( 1 , channel_id, required) ,
@@ -644,7 +705,8 @@ where
644705 )
645706 . unwrap_or_else ( |e| {
646707 log_error ! ( self . logger, "Failed to force close channel after funding generation failed: {:?}" , e) ;
647- debug_assert ! ( false ,
708+ debug_assert ! (
709+ false ,
648710 "Failed to force close channel after funding generation failed"
649711 ) ;
650712 } ) ;
@@ -1306,12 +1368,8 @@ where
13061368 }
13071369 } ,
13081370 LdkEvent :: PaymentForwarded {
1309- prev_channel_id,
1310- next_channel_id,
1311- prev_user_channel_id,
1312- next_user_channel_id,
1313- prev_node_id,
1314- next_node_id,
1371+ prev_htlcs,
1372+ next_htlcs,
13151373 total_fee_earned_msat,
13161374 skimmed_fee_msat,
13171375 claim_from_onchain_tx,
@@ -1322,11 +1380,10 @@ where
13221380 let nodes = read_only_network_graph. nodes ( ) ;
13231381 let channels = self . channel_manager . list_channels ( ) ;
13241382
1325- let node_str = |channel_id : & Option < ChannelId > | {
1326- channel_id
1327- . and_then ( |channel_id| {
1328- channels. iter ( ) . find ( |c| c. channel_id == channel_id)
1329- } )
1383+ let node_str = |channel_id : & ChannelId | {
1384+ channels
1385+ . iter ( )
1386+ . find ( |c| c. channel_id == * channel_id)
13301387 . and_then ( |channel| {
13311388 nodes. get ( & NodeId :: from_pubkey ( & channel. counterparty . node_id ) )
13321389 } )
@@ -1338,21 +1395,22 @@ where
13381395 } )
13391396 } )
13401397 } ;
1341- let channel_str = |channel_id : & Option < ChannelId > | {
1342- channel_id
1343- . map ( |channel_id| format ! ( " with channel {}" , channel_id) )
1344- . unwrap_or_default ( )
1345- } ;
1346- let from_prev_str = format ! (
1347- " from {}{}" ,
1348- node_str( & prev_channel_id) ,
1349- channel_str( & prev_channel_id)
1350- ) ;
1351- let to_next_str = format ! (
1352- " to {}{}" ,
1353- node_str( & next_channel_id) ,
1354- channel_str( & next_channel_id)
1355- ) ;
1398+
1399+ let from_prev_str: String = prev_htlcs
1400+ . iter ( )
1401+ . map ( |htlc| {
1402+ format ! ( " with {} on {}" , node_str( & htlc. channel_id) , htlc. channel_id)
1403+ } )
1404+ . collect :: < Vec < _ > > ( )
1405+ . join ( "," ) ;
1406+
1407+ let to_next_str: String = next_htlcs
1408+ . iter ( )
1409+ . map ( |htlc| {
1410+ format ! ( " with {} on {}" , node_str( & htlc. channel_id) , htlc. channel_id)
1411+ } )
1412+ . collect :: < Vec < _ > > ( )
1413+ . join ( "," ) ;
13561414
13571415 let fee_earned = total_fee_earned_msat. unwrap_or ( 0 ) ;
13581416 if claim_from_onchain_tx {
@@ -1367,8 +1425,10 @@ where
13671425 } else {
13681426 log_info ! (
13691427 self . logger,
1370- "Forwarded payment{}{} of {}msat, earning {}msat in fees." ,
1428+ "Forwarded payment with {} inbound HTLC(s) ({}) and {} outbound HTLC(s) ({}) of {}msat, earning {}msat in fees." ,
1429+ prev_htlcs. len( ) ,
13711430 from_prev_str,
1431+ next_htlcs. len( ) ,
13721432 to_next_str,
13731433 outbound_amount_forwarded_msat. unwrap_or( 0 ) ,
13741434 fee_earned,
@@ -1378,18 +1438,16 @@ where
13781438
13791439 if let Some ( liquidity_source) = self . liquidity_source . as_ref ( ) {
13801440 let skimmed_fee_msat = skimmed_fee_msat. unwrap_or ( 0 ) ;
1381- liquidity_source
1382- . handle_payment_forwarded ( next_channel_id, skimmed_fee_msat)
1383- . await ;
1441+ for next_htlc in next_htlcs. iter ( ) {
1442+ liquidity_source
1443+ . handle_payment_forwarded ( Some ( next_htlc. channel_id ) , skimmed_fee_msat)
1444+ . await ;
1445+ }
13841446 }
13851447
13861448 let event = Event :: PaymentForwarded {
1387- prev_channel_id : prev_channel_id. expect ( "prev_channel_id expected for events generated by LDK versions greater than 0.0.107." ) ,
1388- next_channel_id : next_channel_id. expect ( "next_channel_id expected for events generated by LDK versions greater than 0.0.107." ) ,
1389- prev_user_channel_id : prev_user_channel_id. map ( UserChannelId ) ,
1390- next_user_channel_id : next_user_channel_id. map ( UserChannelId ) ,
1391- prev_node_id,
1392- next_node_id,
1449+ prev_htlcs : prev_htlcs. into_iter ( ) . map ( |h| h. into ( ) ) . collect ( ) ,
1450+ next_htlcs : next_htlcs. into_iter ( ) . map ( |h| h. into ( ) ) . collect ( ) ,
13931451 total_fee_earned_msat,
13941452 skimmed_fee_msat,
13951453 claim_from_onchain_tx,
0 commit comments