@@ -111,34 +111,24 @@ struct ForwardHTLCsAction(ChannelId, Vec<InterceptedHTLC>);
111
111
112
112
#[ derive( Debug , Clone ) ]
113
113
enum TrustModel {
114
- ClientTrustsLsp {
115
- funding_tx_broadcast_safe : bool ,
116
- payment_claimed : bool ,
117
- funding_tx : Option < Transaction > ,
118
- } ,
114
+ ClientTrustsLsp { funding_tx_broadcast_safe : bool , funding_tx : Option < Transaction > } ,
119
115
LspTrustsClient ,
120
116
}
121
117
122
118
impl TrustModel {
123
- fn should_manually_broadcast ( & self ) -> bool {
119
+ fn should_manually_broadcast ( & self , state_is_payment_forward : bool ) -> bool {
124
120
match self {
125
- TrustModel :: ClientTrustsLsp {
126
- funding_tx_broadcast_safe,
127
- payment_claimed,
128
- funding_tx,
129
- } => * funding_tx_broadcast_safe && * payment_claimed && funding_tx. is_some ( ) ,
121
+ TrustModel :: ClientTrustsLsp { funding_tx_broadcast_safe, funding_tx } => {
122
+ * funding_tx_broadcast_safe && state_is_payment_forward && funding_tx. is_some ( )
123
+ } ,
130
124
// in lsp-trusts-client, the broadcast is automatic, so we never need to manually broadcast.
131
125
TrustModel :: LspTrustsClient => false ,
132
126
}
133
127
}
134
128
135
129
fn new ( client_trusts_lsp : bool ) -> Self {
136
130
if client_trusts_lsp {
137
- TrustModel :: ClientTrustsLsp {
138
- funding_tx_broadcast_safe : false ,
139
- payment_claimed : false ,
140
- funding_tx : None ,
141
- }
131
+ TrustModel :: ClientTrustsLsp { funding_tx_broadcast_safe : false , funding_tx : None }
142
132
} else {
143
133
TrustModel :: LspTrustsClient
144
134
}
@@ -166,17 +156,6 @@ impl TrustModel {
166
156
}
167
157
}
168
158
169
- fn set_payment_claimed ( & mut self , payment_claimed : bool ) {
170
- match self {
171
- TrustModel :: ClientTrustsLsp { payment_claimed : claimed, .. } => {
172
- * claimed = payment_claimed;
173
- } ,
174
- TrustModel :: LspTrustsClient => {
175
- // No-op
176
- } ,
177
- }
178
- }
179
-
180
159
fn get_funding_tx ( & self ) -> Option < Transaction > {
181
160
match self {
182
161
TrustModel :: ClientTrustsLsp { funding_tx, .. } => funding_tx. clone ( ) ,
@@ -435,15 +414,44 @@ impl OutboundJITChannelState {
435
414
}
436
415
}
437
416
438
- fn payment_forwarded ( & mut self ) -> Result < Option < ForwardHTLCsAction > , ChannelStateError > {
417
+ fn payment_forwarded (
418
+ & mut self , skimmed_fee_msat : Option < u64 > , client_trusts_lsp : bool ,
419
+ ) -> Result < Option < ForwardHTLCsAction > , ChannelStateError > {
439
420
match self {
440
421
OutboundJITChannelState :: PendingPaymentForward {
441
- payment_queue, channel_id, ..
422
+ payment_queue,
423
+ channel_id,
424
+ opening_fee_msat,
442
425
} => {
443
- let mut payment_queue = core:: mem:: take ( payment_queue) ;
444
- let forward_htlcs = ForwardHTLCsAction ( * channel_id, payment_queue. clear ( ) ) ;
445
- * self = OutboundJITChannelState :: PaymentForwarded { channel_id : * channel_id } ;
446
- Ok ( Some ( forward_htlcs) )
426
+ if !client_trusts_lsp {
427
+ let mut pq = core:: mem:: take ( payment_queue) ;
428
+ let forward_htlcs = ForwardHTLCsAction ( * channel_id, pq. clear ( ) ) ;
429
+ * self = OutboundJITChannelState :: PaymentForwarded { channel_id : * channel_id } ;
430
+ return Ok ( Some ( forward_htlcs) ) ;
431
+ }
432
+
433
+ if skimmed_fee_msat. is_none ( ) {
434
+ * self = OutboundJITChannelState :: PendingPaymentForward {
435
+ payment_queue : core:: mem:: take ( payment_queue) ,
436
+ opening_fee_msat : * opening_fee_msat,
437
+ channel_id : * channel_id,
438
+ } ;
439
+ return Ok ( None ) ;
440
+ }
441
+
442
+ if skimmed_fee_msat. unwrap ( ) >= * opening_fee_msat {
443
+ let mut pq = core:: mem:: take ( payment_queue) ;
444
+ let forward_htlcs = ForwardHTLCsAction ( * channel_id, pq. clear ( ) ) ;
445
+ * self = OutboundJITChannelState :: PaymentForwarded { channel_id : * channel_id } ;
446
+ Ok ( Some ( forward_htlcs) )
447
+ } else {
448
+ * self = OutboundJITChannelState :: PendingPaymentForward {
449
+ payment_queue : core:: mem:: take ( payment_queue) ,
450
+ opening_fee_msat : * opening_fee_msat,
451
+ channel_id : * channel_id,
452
+ } ;
453
+ Ok ( None )
454
+ }
447
455
} ,
448
456
OutboundJITChannelState :: PaymentForwarded { channel_id } => {
449
457
* self = OutboundJITChannelState :: PaymentForwarded { channel_id : * channel_id } ;
@@ -499,11 +507,10 @@ impl OutboundJITChannel {
499
507
Ok ( action)
500
508
}
501
509
502
- fn payment_forwarded ( & mut self ) -> Result < Option < ForwardHTLCsAction > , LightningError > {
503
- let action = self . state . payment_forwarded ( ) ?;
504
- if action. is_some ( ) {
505
- self . trust_model . set_payment_claimed ( true ) ;
506
- }
510
+ fn payment_forwarded (
511
+ & mut self , skimmed_fee_msat : Option < u64 > ,
512
+ ) -> Result < Option < ForwardHTLCsAction > , LightningError > {
513
+ let action = self . state . payment_forwarded ( skimmed_fee_msat, self . is_client_trusts_lsp ( ) ) ?;
507
514
Ok ( action)
508
515
}
509
516
@@ -527,14 +534,17 @@ impl OutboundJITChannel {
527
534
}
528
535
529
536
fn should_broadcast_funding_transaction ( & self ) -> bool {
530
- self . trust_model . should_manually_broadcast ( )
537
+ self . trust_model . should_manually_broadcast ( matches ! (
538
+ self . state,
539
+ OutboundJITChannelState :: PaymentForwarded { .. }
540
+ ) )
531
541
}
532
542
533
543
fn get_funding_tx ( & self ) -> Option < Transaction > {
534
544
self . trust_model . get_funding_tx ( )
535
545
}
536
546
537
- fn client_trusts_lsp ( & self ) -> bool {
547
+ fn is_client_trusts_lsp ( & self ) -> bool {
538
548
self . trust_model . is_client_trusts_lsp ( )
539
549
}
540
550
}
@@ -1004,15 +1014,22 @@ where
1004
1014
/// Forward [`Event::PaymentForwarded`] event parameter into this function.
1005
1015
///
1006
1016
/// Will register the forwarded payment as having paid the JIT channel fee, and forward any held
1007
- /// and future HTLCs for the SCID of the initial invoice. In the future, this will verify the
1008
- /// `skimmed_fee_msat` in [`Event::PaymentForwarded`].
1017
+ /// and future HTLCs for the SCID of the initial invoice.
1018
+ ///
1019
+ /// If client_trusts_lsp=true, this method will verify the `skimmed_fee_msat` in [`Event::PaymentForwarded`].
1020
+ /// If the skimmed_fee_msat covers the opening_fee_msat, that means that the client has claimed the funds and
1021
+ /// paid the promised fee, so the funding transaction becomes eligible for broadcast, and the
1022
+ /// [`Event::BroadcastFundingTransaction`] is emitted.
1009
1023
///
1010
1024
/// Note that `next_channel_id` is required to be provided. Therefore, the corresponding
1011
1025
/// [`Event::PaymentForwarded`] events need to be generated and serialized by LDK versions
1012
1026
/// greater or equal to 0.0.107.
1013
1027
///
1014
1028
/// [`Event::PaymentForwarded`]: lightning::events::Event::PaymentForwarded
1015
- pub fn payment_forwarded ( & self , next_channel_id : ChannelId ) -> Result < ( ) , APIError > {
1029
+ /// [`Event::BroadcastFundingTransaction`]: crate::lsps2::event::LSPS2ServiceEvent::BroadcastFundingTransaction
1030
+ pub fn payment_forwarded (
1031
+ & self , next_channel_id : ChannelId , skimmed_fee_msat : Option < u64 > ,
1032
+ ) -> Result < ( ) , APIError > {
1016
1033
if let Some ( counterparty_node_id) =
1017
1034
self . peer_by_channel_id . read ( ) . unwrap ( ) . get ( & next_channel_id)
1018
1035
{
@@ -1026,7 +1043,7 @@ where
1026
1043
if let Some ( jit_channel) =
1027
1044
peer_state. outbound_channels_by_intercept_scid . get_mut ( & intercept_scid)
1028
1045
{
1029
- match jit_channel. payment_forwarded ( ) {
1046
+ match jit_channel. payment_forwarded ( skimmed_fee_msat ) {
1030
1047
Ok ( Some ( ForwardHTLCsAction ( channel_id, htlcs) ) ) => {
1031
1048
for htlc in htlcs {
1032
1049
self . channel_manager . get_cm ( ) . forward_intercepted_htlc (
@@ -1569,7 +1586,7 @@ where
1569
1586
) ,
1570
1587
} ) ?;
1571
1588
1572
- Ok ( jit_channel. client_trusts_lsp ( ) )
1589
+ Ok ( jit_channel. is_client_trusts_lsp ( ) )
1573
1590
}
1574
1591
1575
1592
/// Called to store the funding transaction for a JIT channel.
@@ -1751,6 +1768,7 @@ mod tests {
1751
1768
1752
1769
use proptest:: prelude:: * ;
1753
1770
1771
+ use bitcoin:: { absolute:: LockTime , transaction:: Version } ;
1754
1772
use core:: str:: FromStr ;
1755
1773
1756
1774
const MAX_VALUE_MSAT : u64 = 21_000_000_0000_0000_000 ;
@@ -1987,7 +2005,7 @@ mod tests {
1987
2005
}
1988
2006
// Payment completes, queued payments get forwarded.
1989
2007
{
1990
- let action = state. payment_forwarded ( ) . unwrap ( ) ;
2008
+ let action = state. payment_forwarded ( None , false ) . unwrap ( ) ;
1991
2009
assert ! ( matches!( state, OutboundJITChannelState :: PaymentForwarded { .. } ) ) ;
1992
2010
match action {
1993
2011
Some ( ForwardHTLCsAction ( channel_id, htlcs) ) => {
@@ -2122,7 +2140,7 @@ mod tests {
2122
2140
}
2123
2141
// Payment completes, queued payments get forwarded.
2124
2142
{
2125
- let action = state. payment_forwarded ( ) . unwrap ( ) ;
2143
+ let action = state. payment_forwarded ( None , false ) . unwrap ( ) ;
2126
2144
assert ! ( matches!( state, OutboundJITChannelState :: PaymentForwarded { .. } ) ) ;
2127
2145
match action {
2128
2146
Some ( ForwardHTLCsAction ( channel_id, htlcs) ) => {
@@ -2158,4 +2176,105 @@ mod tests {
2158
2176
) ;
2159
2177
}
2160
2178
}
2179
+
2180
+ #[ test]
2181
+ fn broadcast_not_allowed_after_non_paying_fee_payment_claimed ( ) {
2182
+ let min_fee_msat: u64 = 12345 ;
2183
+ let opening_fee_params = LSPS2OpeningFeeParams {
2184
+ min_fee_msat,
2185
+ proportional : 0 ,
2186
+ valid_until : LSPSDateTime :: from_str ( "2035-05-20T08:30:45Z" ) . unwrap ( ) ,
2187
+ min_lifetime : 144 ,
2188
+ max_client_to_self_delay : 128 ,
2189
+ min_payment_size_msat : 1 ,
2190
+ max_payment_size_msat : 10_000_000_000 ,
2191
+ promise : "ignore" . to_string ( ) ,
2192
+ } ;
2193
+
2194
+ let payment_size_msat = Some ( 1_000_000 ) ;
2195
+ let user_channel_id = 4242u128 ;
2196
+ let mut jit_channel = OutboundJITChannel :: new (
2197
+ payment_size_msat,
2198
+ opening_fee_params. clone ( ) ,
2199
+ user_channel_id,
2200
+ true ,
2201
+ ) ;
2202
+
2203
+ let opening_payment_hash = PaymentHash ( [ 42 ; 32 ] ) ;
2204
+ let htlcs_for_opening = [
2205
+ InterceptedHTLC {
2206
+ intercept_id : InterceptId ( [ 0 ; 32 ] ) ,
2207
+ expected_outbound_amount_msat : 400_000 ,
2208
+ payment_hash : opening_payment_hash,
2209
+ } ,
2210
+ InterceptedHTLC {
2211
+ intercept_id : InterceptId ( [ 1 ; 32 ] ) ,
2212
+ expected_outbound_amount_msat : 600_000 ,
2213
+ payment_hash : opening_payment_hash,
2214
+ } ,
2215
+ ] ;
2216
+
2217
+ assert ! ( jit_channel. htlc_intercepted( htlcs_for_opening[ 0 ] . clone( ) ) . unwrap( ) . is_none( ) ) ;
2218
+ let action = jit_channel. htlc_intercepted ( htlcs_for_opening[ 1 ] . clone ( ) ) . unwrap ( ) ;
2219
+ match action {
2220
+ Some ( HTLCInterceptedAction :: OpenChannel ( _) ) => { } ,
2221
+ other => panic ! ( "Expected OpenChannel action, got {:?}" , other) ,
2222
+ }
2223
+
2224
+ let channel_id = ChannelId ( [ 7 ; 32 ] ) ;
2225
+ let ForwardPaymentAction ( _, fee_payment) = jit_channel. channel_ready ( channel_id) . unwrap ( ) ;
2226
+ assert_eq ! ( fee_payment. opening_fee_msat, min_fee_msat) ;
2227
+
2228
+ let followup = jit_channel. htlc_handling_failed ( ) . unwrap ( ) ;
2229
+ assert ! ( followup. is_none( ) ) ;
2230
+
2231
+ let dummy_tx = Transaction {
2232
+ version : Version ( 2 ) ,
2233
+ lock_time : LockTime :: ZERO ,
2234
+ input : vec ! [ ] ,
2235
+ output : vec ! [ ] ,
2236
+ } ;
2237
+ jit_channel. set_funding_tx ( dummy_tx) ;
2238
+ jit_channel. set_funding_tx_broadcast_safe ( true ) ;
2239
+ assert ! (
2240
+ !jit_channel. should_broadcast_funding_transaction( ) ,
2241
+ "Should not broadcast before any successful payment is claimed"
2242
+ ) ;
2243
+
2244
+ let second_payment_hash = PaymentHash ( [ 99 ; 32 ] ) ;
2245
+ let second_htlc = InterceptedHTLC {
2246
+ intercept_id : InterceptId ( [ 2 ; 32 ] ) ,
2247
+ expected_outbound_amount_msat : min_fee_msat,
2248
+ payment_hash : second_payment_hash,
2249
+ } ;
2250
+ let action2 = jit_channel. htlc_intercepted ( second_htlc) . unwrap ( ) ;
2251
+ let ( forwarded_channel_id, fee_payment2) = match action2 {
2252
+ Some ( HTLCInterceptedAction :: ForwardPayment ( cid, fp) ) => ( cid, fp) ,
2253
+ other => panic ! ( "Expected ForwardPayment for second HTLC, got {:?}" , other) ,
2254
+ } ;
2255
+ assert_eq ! ( forwarded_channel_id, channel_id) ;
2256
+ assert_eq ! ( fee_payment2. opening_fee_msat, min_fee_msat) ;
2257
+
2258
+ assert ! (
2259
+ !jit_channel. should_broadcast_funding_transaction( ) ,
2260
+ "Should not broadcast before any successful payment is claimed"
2261
+ ) ;
2262
+
2263
+ // Forward a payment that is not enough to cover the fees
2264
+ let _ = jit_channel. payment_forwarded ( Some ( min_fee_msat - 1 ) ) . unwrap ( ) ;
2265
+
2266
+ assert ! (
2267
+ !jit_channel. should_broadcast_funding_transaction( ) ,
2268
+ "Should not broadcast before all the fees are collected"
2269
+ ) ;
2270
+
2271
+ let _ = jit_channel. payment_forwarded ( Some ( min_fee_msat) ) . unwrap ( ) ;
2272
+
2273
+ let broadcast_allowed = jit_channel. should_broadcast_funding_transaction ( ) ;
2274
+
2275
+ assert ! (
2276
+ broadcast_allowed,
2277
+ "Broadcast was not allowed even though all the skimmed fees were collected"
2278
+ ) ;
2279
+ }
2161
2280
}
0 commit comments