@@ -44,6 +44,17 @@ pub struct ChannelKeys {
44
44
pub commitment_seed : [ u8 ; 32 ] ,
45
45
}
46
46
47
+ #[ cfg( test) ]
48
+ pub struct ChannelValueStat {
49
+ pub value_to_self_msat : u64 ,
50
+ pub channel_value_msat : u64 ,
51
+ pub channel_reserve_msat : u64 ,
52
+ pub pending_outbound_htlcs_amount_msat : u64 ,
53
+ pub pending_inbound_htlcs_amount_msat : u64 ,
54
+ pub holding_cell_outbound_amount_msat : u64 ,
55
+ pub their_max_htlc_value_in_flight_msat : u64 , // outgoing
56
+ }
57
+
47
58
impl ChannelKeys {
48
59
pub fn new_from_seed ( seed : & [ u8 ; 32 ] ) -> Result < ChannelKeys , secp256k1:: Error > {
49
60
let mut prk = [ 0 ; 32 ] ;
@@ -308,6 +319,13 @@ pub(super) struct Channel {
308
319
channel_update_count : u32 ,
309
320
feerate_per_kw : u64 ,
310
321
322
+ #[ cfg( debug_assertions) ]
323
+ /// Max to_local and to_remote outputs in a locally-generated commitment transaction
324
+ max_commitment_tx_output_local : :: std:: sync:: Mutex < ( u64 , u64 ) > ,
325
+ #[ cfg( debug_assertions) ]
326
+ /// Max to_local and to_remote outputs in a remote-generated commitment transaction
327
+ max_commitment_tx_output_remote : :: std:: sync:: Mutex < ( u64 , u64 ) > ,
328
+
311
329
#[ cfg( test) ]
312
330
// Used in ChannelManager's tests to send a revoked transaction
313
331
pub last_local_commitment_txn : Vec < Transaction > ,
@@ -330,6 +348,7 @@ pub(super) struct Channel {
330
348
our_dust_limit_satoshis : u64 ,
331
349
their_max_htlc_value_in_flight_msat : u64 ,
332
350
//get_our_max_htlc_value_in_flight_msat(): u64,
351
+ /// minimum channel reserve for **self** to maintain - set by them.
333
352
their_channel_reserve_satoshis : u64 ,
334
353
//get_our_channel_reserve_satoshis(): u64,
335
354
their_htlc_minimum_msat : u64 ,
@@ -402,6 +421,8 @@ impl Channel {
402
421
channel_value_satoshis * 1000 / 10 //TODO
403
422
}
404
423
424
+ /// Returns a minimum channel reserve value **they** need to maintain
425
+ ///
405
426
/// Guaranteed to return a value no larger than channel_value_satoshis
406
427
fn get_our_channel_reserve_satoshis ( channel_value_satoshis : u64 ) -> u64 {
407
428
let ( q, _) = channel_value_satoshis. overflowing_div ( 100 ) ;
@@ -477,6 +498,11 @@ impl Channel {
477
498
next_remote_htlc_id : 0 ,
478
499
channel_update_count : 1 ,
479
500
501
+ #[ cfg( debug_assertions) ]
502
+ max_commitment_tx_output_local : :: std:: sync:: Mutex :: new ( ( channel_value_satoshis * 1000 - push_msat, push_msat) ) ,
503
+ #[ cfg( debug_assertions) ]
504
+ max_commitment_tx_output_remote : :: std:: sync:: Mutex :: new ( ( channel_value_satoshis * 1000 - push_msat, push_msat) ) ,
505
+
480
506
last_local_commitment_txn : Vec :: new ( ) ,
481
507
482
508
last_sent_closing_fee : None ,
@@ -627,6 +653,11 @@ impl Channel {
627
653
next_remote_htlc_id : 0 ,
628
654
channel_update_count : 1 ,
629
655
656
+ #[ cfg( debug_assertions) ]
657
+ max_commitment_tx_output_local : :: std:: sync:: Mutex :: new ( ( msg. push_msat , msg. funding_satoshis * 1000 - msg. push_msat ) ) ,
658
+ #[ cfg( debug_assertions) ]
659
+ max_commitment_tx_output_remote : :: std:: sync:: Mutex :: new ( ( msg. push_msat , msg. funding_satoshis * 1000 - msg. push_msat ) ) ,
660
+
630
661
last_local_commitment_txn : Vec :: new ( ) ,
631
662
632
663
last_sent_closing_fee : None ,
@@ -812,9 +843,32 @@ impl Channel {
812
843
}
813
844
814
845
846
+ let value_to_self_msat: i64 = ( self . value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset;
847
+ let value_to_remote_msat: i64 = ( self . channel_value_satoshis * 1000 - self . value_to_self_msat - remote_htlc_total_msat) as i64 - value_to_self_msat_offset;
848
+
849
+ #[ cfg( debug_assertions) ]
850
+ {
851
+ // Make sure that the to_self/to_remote is always either past the appropriate
852
+ // channel_reserve *or* it is making progress towards it.
853
+ // TODO: This should happen after fee calculation, but we don't handle that correctly
854
+ // yet!
855
+ let mut max_commitment_tx_output = if generated_by_local {
856
+ self . max_commitment_tx_output_local . lock ( ) . unwrap ( )
857
+ } else {
858
+ self . max_commitment_tx_output_remote . lock ( ) . unwrap ( )
859
+ } ;
860
+ debug_assert ! ( max_commitment_tx_output. 0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self . their_channel_reserve_satoshis as i64 ) ;
861
+ max_commitment_tx_output. 0 = cmp:: max ( max_commitment_tx_output. 0 , value_to_self_msat as u64 ) ;
862
+ debug_assert ! ( max_commitment_tx_output. 1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel :: get_our_channel_reserve_satoshis( self . channel_value_satoshis) as i64 ) ;
863
+ max_commitment_tx_output. 1 = cmp:: max ( max_commitment_tx_output. 1 , value_to_remote_msat as u64 ) ;
864
+ }
865
+
815
866
let total_fee: u64 = feerate_per_kw * ( COMMITMENT_TX_BASE_WEIGHT + ( txouts. len ( ) as u64 ) * COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ;
816
- let value_to_self: i64 = ( ( self . value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset) / 1000 - if self . channel_outbound { total_fee as i64 } else { 0 } ;
817
- let value_to_remote: i64 = ( ( ( self . channel_value_satoshis * 1000 - self . value_to_self_msat - remote_htlc_total_msat) as i64 - value_to_self_msat_offset) / 1000 ) - if self . channel_outbound { 0 } else { total_fee as i64 } ;
867
+ let ( value_to_self, value_to_remote) = if self . channel_outbound {
868
+ ( value_to_self_msat / 1000 - total_fee as i64 , value_to_remote_msat / 1000 )
869
+ } else {
870
+ ( value_to_self_msat / 1000 , value_to_remote_msat / 1000 - total_fee as i64 )
871
+ } ;
818
872
819
873
let value_to_a = if local { value_to_self } else { value_to_remote } ;
820
874
let value_to_b = if local { value_to_remote } else { value_to_self } ;
@@ -1415,42 +1469,23 @@ impl Channel {
1415
1469
Ok ( ( ) )
1416
1470
}
1417
1471
1418
- /// Returns (inbound_htlc_count, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat)
1419
- /// If its for a remote update check, we need to be more lax about checking against messages we
1420
- /// sent but they may not have received/processed before they sent this message. Further, for
1421
- /// our own sends, we're more conservative and even consider things they've removed against
1422
- /// totals, though there is little reason to outside of further avoiding any race condition
1423
- /// issues.
1424
- fn get_pending_htlc_stats ( & self , for_remote_update_check : bool ) -> ( u32 , u32 , u64 , u64 ) {
1425
- //TODO: Can probably split this into inbound/outbound
1426
- let mut inbound_htlc_count: u32 = 0 ;
1427
- let mut outbound_htlc_count: u32 = 0 ;
1428
- let mut htlc_outbound_value_msat = 0 ;
1472
+ /// Returns (inbound_htlc_count, htlc_inbound_value_msat)
1473
+ fn get_inbound_pending_htlc_stats ( & self ) -> ( u32 , u64 ) {
1429
1474
let mut htlc_inbound_value_msat = 0 ;
1430
1475
for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1431
- match htlc. state {
1432
- InboundHTLCState :: RemoteAnnounced => { } ,
1433
- InboundHTLCState :: AwaitingRemoteRevokeToAnnounce => { } ,
1434
- InboundHTLCState :: AwaitingAnnouncedRemoteRevoke => { } ,
1435
- InboundHTLCState :: Committed => { } ,
1436
- InboundHTLCState :: LocalRemoved => { } ,
1437
- }
1438
- inbound_htlc_count += 1 ;
1439
1476
htlc_inbound_value_msat += htlc. amount_msat ;
1440
1477
}
1478
+ ( self . pending_inbound_htlcs . len ( ) as u32 , htlc_inbound_value_msat)
1479
+ }
1480
+
1481
+ /// Returns (outbound_htlc_count, htlc_outbound_value_msat)
1482
+ fn get_outbound_pending_htlc_stats ( & self ) -> ( u32 , u64 ) {
1483
+ let mut htlc_outbound_value_msat = 0 ;
1441
1484
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1442
- match htlc. state {
1443
- OutboundHTLCState :: LocalAnnounced => { if for_remote_update_check { continue ; } } ,
1444
- OutboundHTLCState :: Committed => { } ,
1445
- OutboundHTLCState :: RemoteRemoved => { if for_remote_update_check { continue ; } } ,
1446
- OutboundHTLCState :: AwaitingRemoteRevokeToRemove => { if for_remote_update_check { continue ; } } ,
1447
- OutboundHTLCState :: AwaitingRemovedRemoteRevoke => { if for_remote_update_check { continue ; } } ,
1448
- }
1449
- outbound_htlc_count += 1 ;
1450
1485
htlc_outbound_value_msat += htlc. amount_msat ;
1451
1486
}
1452
1487
1453
- ( inbound_htlc_count , outbound_htlc_count , htlc_outbound_value_msat , htlc_inbound_value_msat )
1488
+ ( self . pending_outbound_htlcs . len ( ) as u32 , htlc_outbound_value_msat )
1454
1489
}
1455
1490
1456
1491
pub fn update_add_htlc ( & mut self , msg : & msgs:: UpdateAddHTLC , pending_forward_state : PendingHTLCStatus ) -> Result < ( ) , HandleError > {
@@ -1467,7 +1502,7 @@ impl Channel {
1467
1502
return Err ( HandleError { err : "Remote side tried to send less than our minimum HTLC value" , action : None } ) ;
1468
1503
}
1469
1504
1470
- let ( inbound_htlc_count, _ , htlc_outbound_value_msat , htlc_inbound_value_msat) = self . get_pending_htlc_stats ( true ) ;
1505
+ let ( inbound_htlc_count, htlc_inbound_value_msat) = self . get_inbound_pending_htlc_stats ( ) ;
1471
1506
if inbound_htlc_count + 1 > OUR_MAX_HTLCS as u32 {
1472
1507
return Err ( HandleError { err : "Remote tried to push more than our max accepted HTLCs" , action : None } ) ;
1473
1508
}
@@ -1479,7 +1514,7 @@ impl Channel {
1479
1514
// Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet
1480
1515
// the reserve_satoshis we told them to always have as direct payment so that they lose
1481
1516
// something if we punish them for broadcasting an old state).
1482
- if htlc_inbound_value_msat + htlc_outbound_value_msat + msg. amount_msat + self . value_to_self_msat > ( self . channel_value_satoshis - Channel :: get_our_channel_reserve_satoshis ( self . channel_value_satoshis ) ) * 1000 {
1517
+ if htlc_inbound_value_msat + msg. amount_msat + self . value_to_self_msat > ( self . channel_value_satoshis - Channel :: get_our_channel_reserve_satoshis ( self . channel_value_satoshis ) ) * 1000 {
1483
1518
return Err ( HandleError { err : "Remote HTLC add would put them over their reserve value" , action : None } ) ;
1484
1519
}
1485
1520
if self . next_remote_htlc_id != msg. htlc_id {
@@ -2349,6 +2384,30 @@ impl Channel {
2349
2384
& self . local_keys
2350
2385
}
2351
2386
2387
+ #[ cfg( test) ]
2388
+ pub fn get_value_stat ( & self ) -> ChannelValueStat {
2389
+ ChannelValueStat {
2390
+ value_to_self_msat : self . value_to_self_msat ,
2391
+ channel_value_msat : self . channel_value_satoshis * 1000 ,
2392
+ channel_reserve_msat : self . their_channel_reserve_satoshis * 1000 ,
2393
+ pending_outbound_htlcs_amount_msat : self . pending_outbound_htlcs . iter ( ) . map ( |ref h| h. amount_msat ) . sum :: < u64 > ( ) ,
2394
+ pending_inbound_htlcs_amount_msat : self . pending_inbound_htlcs . iter ( ) . map ( |ref h| h. amount_msat ) . sum :: < u64 > ( ) ,
2395
+ holding_cell_outbound_amount_msat : {
2396
+ let mut res = 0 ;
2397
+ for h in self . holding_cell_htlc_updates . iter ( ) {
2398
+ match h {
2399
+ & HTLCUpdateAwaitingACK :: AddHTLC { amount_msat, .. } => {
2400
+ res += amount_msat;
2401
+ }
2402
+ _ => { }
2403
+ }
2404
+ }
2405
+ res
2406
+ } ,
2407
+ their_max_htlc_value_in_flight_msat : self . their_max_htlc_value_in_flight_msat ,
2408
+ }
2409
+ }
2410
+
2352
2411
/// Allowed in any state (including after shutdown)
2353
2412
pub fn get_channel_update_count ( & self ) -> u32 {
2354
2413
self . channel_update_count
@@ -2722,7 +2781,7 @@ impl Channel {
2722
2781
return Err ( HandleError { err : "Cannot send an HTLC while disconnected" , action : Some ( ErrorAction :: IgnoreError ) } ) ;
2723
2782
}
2724
2783
2725
- let ( _ , outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat ) = self . get_pending_htlc_stats ( false ) ;
2784
+ let ( outbound_htlc_count, htlc_outbound_value_msat) = self . get_outbound_pending_htlc_stats ( ) ;
2726
2785
if outbound_htlc_count + 1 > self . their_max_accepted_htlcs as u32 {
2727
2786
return Err ( HandleError { err : "Cannot push more than their max accepted HTLCs" , action : None } ) ;
2728
2787
}
@@ -2731,8 +2790,20 @@ impl Channel {
2731
2790
if htlc_outbound_value_msat + amount_msat > self . their_max_htlc_value_in_flight_msat {
2732
2791
return Err ( HandleError { err : "Cannot send value that would put us over our max HTLC value in flight" , action : None } ) ;
2733
2792
}
2734
- // Check their_channel_reserve_satoshis:
2735
- if htlc_inbound_value_msat + htlc_outbound_value_msat + amount_msat + ( self . channel_value_satoshis * 1000 - self . value_to_self_msat ) > ( self . channel_value_satoshis - self . their_channel_reserve_satoshis ) * 1000 {
2793
+
2794
+ let mut holding_cell_outbound_amount_msat = 0 ;
2795
+ for holding_htlc in self . holding_cell_htlc_updates . iter ( ) {
2796
+ match holding_htlc {
2797
+ & HTLCUpdateAwaitingACK :: AddHTLC { ref amount_msat, .. } => {
2798
+ holding_cell_outbound_amount_msat += * amount_msat;
2799
+ }
2800
+ _ => { }
2801
+ }
2802
+ }
2803
+
2804
+ // Check self.their_channel_reserve_satoshis (the amount we must keep as
2805
+ // reserve for them to have something to claim if we misbehave)
2806
+ if self . value_to_self_msat < self . their_channel_reserve_satoshis * 1000 + amount_msat + holding_cell_outbound_amount_msat + htlc_outbound_value_msat {
2736
2807
return Err ( HandleError { err : "Cannot send value that would put us over our reserve value" , action : None } ) ;
2737
2808
}
2738
2809
0 commit comments