@@ -21,8 +21,8 @@ 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 ;
25+ use lightning:: ln:: msgs:: DecodeError ;
2626use lightning:: ln:: types:: ChannelId ;
2727use lightning:: routing:: gossip:: NodeId ;
2828use lightning:: sign:: EntropySource ;
@@ -31,7 +31,10 @@ use lightning::util::config::{
3131} ;
3232use lightning:: util:: errors:: APIError ;
3333use lightning:: util:: persist:: KVStore ;
34- use lightning:: util:: ser:: { Readable , ReadableArgs , Writeable , Writer } ;
34+ use lightning:: util:: ser:: {
35+ CollectionLength , MaybeReadable , Readable , ReadableArgs , Writeable , Writer ,
36+ } ;
37+ use lightning:: { impl_writeable_tlv_based, impl_writeable_tlv_based_enum} ;
3538use lightning_liquidity:: lsps2:: utils:: compute_opening_fee;
3639use lightning_types:: payment:: { PaymentHash , PaymentPreimage } ;
3740
@@ -61,6 +64,70 @@ use crate::{
6164 UserChannelId ,
6265} ;
6366
67+ /// A set of multiple htlcs all associated with same forward.
68+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
69+ pub struct HTLCSet ( pub Vec < HTLCLocator > ) ;
70+
71+ impl Writeable for HTLCSet {
72+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , lightning:: io:: Error > {
73+ lightning:: util:: ser:: CollectionLength ( self . 0 . len ( ) as u64 ) . write ( w) ?;
74+ for elem in self . 0 . iter ( ) {
75+ elem. write ( w) ?;
76+ }
77+ Ok ( ( ) )
78+ }
79+ }
80+
81+ impl Readable for HTLCSet {
82+ fn read < R : lightning:: io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
83+ let len: CollectionLength = Readable :: read ( r) ?;
84+ let mut ret = Vec :: with_capacity ( std:: cmp:: min (
85+ len. 0 as usize ,
86+ lightning:: util:: ser:: MAX_BUF_SIZE / core:: mem:: size_of :: < HTLCLocator > ( ) ,
87+ ) ) ;
88+ for _ in 0 ..len. 0 {
89+ if let Some ( val) = MaybeReadable :: read ( r) ? {
90+ ret. push ( val) ;
91+ }
92+ }
93+ Ok ( HTLCSet ( ret) )
94+ }
95+ }
96+
97+ /// Identifies the channel and counterparty that a HTLC was processed with.
98+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
99+ #[ cfg_attr( feature = "uniffi" , derive( uniffi:: Record ) ) ]
100+ pub struct HTLCLocator {
101+ /// The channel that the HTLC was sent or received on.
102+ pub channel_id : ChannelId ,
103+ /// The `user_channel_id` for the channel.
104+ ///
105+ /// Will only be `None` for events serialized with LDK Node v0.3.0 or prior, or if the
106+ /// payment was settled via an on-chain transaction.
107+ pub user_channel_id : Option < UserChannelId > ,
108+ /// The node id of the counterparty for this HTLC.
109+ ///
110+ /// This is only `None` for HTLCs received prior to LDK Node v0.5 or for events serialized by
111+ /// versions prior to v0.5.
112+ pub node_id : Option < PublicKey > ,
113+ }
114+
115+ impl_writeable_tlv_based ! ( HTLCLocator , {
116+ ( 1 , channel_id, required) ,
117+ ( 3 , user_channel_id, option) ,
118+ ( 5 , node_id, option) ,
119+ } ) ;
120+
121+ impl From < lightning:: events:: HTLCLocator > for HTLCLocator {
122+ fn from ( value : lightning:: events:: HTLCLocator ) -> Self {
123+ HTLCLocator {
124+ channel_id : value. channel_id ,
125+ user_channel_id : value. user_channel_id . map ( |u| UserChannelId ( u) ) ,
126+ node_id : value. node_id ,
127+ }
128+ }
129+ }
130+
64131/// An event emitted by [`Node`], which should be handled by the user.
65132///
66133/// [`Node`]: [`crate::Node`]
@@ -128,29 +195,14 @@ pub enum Event {
128195 } ,
129196 /// A payment has been forwarded.
130197 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 > ,
198+ /// The set of incoming HTLCs that were forwarded to our node. Contains a single HTLC for
199+ /// source-routed payments, and may contain multiple HTLCs when we acted as a trampoline
200+ /// router.
201+ prev_htlcs : HTLCSet ,
202+ /// The set of outgoing HTLCs forwarded by our node. Contains a single HTLC for regular
203+ /// source-routed payments, and may contain multiple HTLCs when we acted as a trampoline
204+ /// router.
205+ next_htlcs : HTLCSet ,
154206 /// The total fee, in milli-satoshis, which was earned as a result of the payment.
155207 ///
156208 /// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
@@ -323,16 +375,58 @@ impl_writeable_tlv_based_enum!(Event,
323375 ( 7 , custom_records, optional_vec) ,
324376 } ,
325377 ( 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) ,
378+ // For backwards compatibility, write the first prev/next_htlc to our legacy fields. This
379+ // allows use to downgrade with some information loss about the remaining htlcs.
380+ ( 0 , prev_channel_id_legacy, ( legacy, ChannelId , |_| Ok ( ( ) ) ,
381+ |us: & Event | match us {
382+ Event :: PaymentForwarded { prev_htlcs, .. } => prev_htlcs. 0 . first( ) . map( |h| h. channel_id) ,
383+ _ => unreachable!( ) ,
384+ }
385+ ) ) ,
386+ ( 1 , prev_node_id_legacy, ( legacy, PublicKey , |_| Ok ( ( ) ) ,
387+ |us: & Event | match us {
388+ Event :: PaymentForwarded { prev_htlcs, .. } => prev_htlcs. 0 . first( ) . and_then( |h| h. node_id) ,
389+ _ => unreachable!( ) ,
390+ }
391+ ) ) ,
392+ ( 2 , next_channel_id_legacy, ( legacy, ChannelId , |_| Ok ( ( ) ) ,
393+ |us: & Event | match us {
394+ Event :: PaymentForwarded { next_htlcs, .. } => next_htlcs. 0 . first( ) . map( |h| h. channel_id) ,
395+ _ => unreachable!( ) ,
396+ }
397+ ) ) ,
398+ ( 3 , next_node_id_legacy, ( legacy, PublicKey , |_| Ok ( ( ) ) ,
399+ |us: & Event | match us {
400+ Event :: PaymentForwarded { next_htlcs, .. } => next_htlcs. 0 . first( ) . and_then( |h| h. node_id) ,
401+ _ => unreachable!( ) ,
402+ }
403+ ) ) ,
404+ ( 4 , prev_user_channel_id_legacy, ( legacy, UserChannelId , |_| Ok ( ( ) ) ,
405+ |us: & Event | match us {
406+ Event :: PaymentForwarded { prev_htlcs, .. } => prev_htlcs. 0 . first( ) . and_then( |h| h. user_channel_id) ,
407+ _ => unreachable!( ) ,
408+ }
409+ ) ) ,
410+ ( 6 , next_user_channel_id_legacy, ( legacy, UserChannelId , |_| Ok ( ( ) ) ,
411+ |us: & Event | match us {
412+ Event :: PaymentForwarded { next_htlcs, .. } => next_htlcs. 0 . first( ) . and_then( |h| h. user_channel_id) ,
413+ _ => unreachable!( ) ,
414+ }
415+ ) ) ,
332416 ( 8 , total_fee_earned_msat, option) ,
333417 ( 10 , skimmed_fee_msat, option) ,
334418 ( 12 , claim_from_onchain_tx, required) ,
335419 ( 14 , outbound_amount_forwarded_msat, option) ,
420+ ( 15 , prev_htlcs, ( default_value, HTLCSet ( vec![ HTLCLocator {
421+ channel_id: prev_channel_id_legacy. ok_or( lightning:: ln:: msgs:: DecodeError :: InvalidValue ) ?,
422+ user_channel_id: prev_user_channel_id_legacy,
423+ node_id: prev_node_id_legacy,
424+ } ] ) ) ) ,
425+ ( 17 , next_htlcs, ( default_value, HTLCSet ( vec![ HTLCLocator {
426+ channel_id: next_channel_id_legacy. ok_or( lightning:: ln:: msgs:: DecodeError :: InvalidValue ) ?,
427+ user_channel_id: next_user_channel_id_legacy,
428+ node_id: next_node_id_legacy,
429+ } ] ) ) ) ,
336430 } ,
337431 ( 8 , SplicePending ) => {
338432 ( 1 , channel_id, required) ,
@@ -644,7 +738,8 @@ where
644738 )
645739 . unwrap_or_else ( |e| {
646740 log_error ! ( self . logger, "Failed to force close channel after funding generation failed: {:?}" , e) ;
647- debug_assert ! ( false ,
741+ debug_assert ! (
742+ false ,
648743 "Failed to force close channel after funding generation failed"
649744 ) ;
650745 } ) ;
@@ -1306,12 +1401,8 @@ where
13061401 }
13071402 } ,
13081403 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,
1404+ prev_htlcs,
1405+ next_htlcs,
13151406 total_fee_earned_msat,
13161407 skimmed_fee_msat,
13171408 claim_from_onchain_tx,
@@ -1322,11 +1413,10 @@ where
13221413 let nodes = read_only_network_graph. nodes ( ) ;
13231414 let channels = self . channel_manager . list_channels ( ) ;
13241415
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- } )
1416+ let node_str = |channel_id : & ChannelId | {
1417+ channels
1418+ . iter ( )
1419+ . find ( |c| c. channel_id == * channel_id)
13301420 . and_then ( |channel| {
13311421 nodes. get ( & NodeId :: from_pubkey ( & channel. counterparty . node_id ) )
13321422 } )
@@ -1338,21 +1428,22 @@ where
13381428 } )
13391429 } )
13401430 } ;
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- ) ;
1431+
1432+ let from_prev_str: String = prev_htlcs
1433+ . iter ( )
1434+ . map ( |htlc| {
1435+ format ! ( "with {} on {}" , node_str( & htlc. channel_id) , htlc. channel_id)
1436+ } )
1437+ . collect :: < Vec < _ > > ( )
1438+ . join ( ", " ) ;
1439+
1440+ let to_next_str: String = next_htlcs
1441+ . iter ( )
1442+ . map ( |htlc| {
1443+ format ! ( "with {} on {}" , node_str( & htlc. channel_id) , htlc. channel_id)
1444+ } )
1445+ . collect :: < Vec < _ > > ( )
1446+ . join ( ", " ) ;
13561447
13571448 let fee_earned = total_fee_earned_msat. unwrap_or ( 0 ) ;
13581449 if claim_from_onchain_tx {
@@ -1367,8 +1458,10 @@ where
13671458 } else {
13681459 log_info ! (
13691460 self . logger,
1370- "Forwarded payment{}{} of {}msat, earning {}msat in fees." ,
1461+ "Forwarded payment with {} inbound HTLC(s) ({}) and {} outbound HTLC(s) ({}) of {}msat, earning {}msat in fees." ,
1462+ prev_htlcs. len( ) ,
13711463 from_prev_str,
1464+ next_htlcs. len( ) ,
13721465 to_next_str,
13731466 outbound_amount_forwarded_msat. unwrap_or( 0 ) ,
13741467 fee_earned,
@@ -1378,18 +1471,16 @@ where
13781471
13791472 if let Some ( liquidity_source) = self . liquidity_source . as_ref ( ) {
13801473 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 ;
1474+ for next_htlc in next_htlcs. iter ( ) {
1475+ liquidity_source
1476+ . handle_payment_forwarded ( Some ( next_htlc. channel_id ) , skimmed_fee_msat)
1477+ . await ;
1478+ }
13841479 }
13851480
13861481 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,
1482+ prev_htlcs : HTLCSet ( prev_htlcs. into_iter ( ) . map ( |h| h. into ( ) ) . collect ( ) ) ,
1483+ next_htlcs : HTLCSet ( next_htlcs. into_iter ( ) . map ( |h| h. into ( ) ) . collect ( ) ) ,
13931484 total_fee_earned_msat,
13941485 skimmed_fee_msat,
13951486 claim_from_onchain_tx,
0 commit comments