@@ -44,6 +44,17 @@ pub struct ChannelKeys {
4444 pub commitment_seed : [ u8 ; 32 ] ,
4545}
4646
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+
4758impl ChannelKeys {
4859 pub fn new_from_seed ( seed : & [ u8 ; 32 ] ) -> Result < ChannelKeys , secp256k1:: Error > {
4960 let mut prk = [ 0 ; 32 ] ;
@@ -308,6 +319,13 @@ pub(super) struct Channel {
308319 channel_update_count : u32 ,
309320 feerate_per_kw : u64 ,
310321
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+
311329 #[ cfg( test) ]
312330 // Used in ChannelManager's tests to send a revoked transaction
313331 pub last_local_commitment_txn : Vec < Transaction > ,
@@ -330,6 +348,7 @@ pub(super) struct Channel {
330348 our_dust_limit_satoshis : u64 ,
331349 their_max_htlc_value_in_flight_msat : u64 ,
332350 //get_our_max_htlc_value_in_flight_msat(): u64,
351+ /// minimum channel reserve for **self** to maintain - set by them.
333352 their_channel_reserve_satoshis : u64 ,
334353 //get_our_channel_reserve_satoshis(): u64,
335354 their_htlc_minimum_msat : u64 ,
@@ -402,6 +421,8 @@ impl Channel {
402421 channel_value_satoshis * 1000 / 10 //TODO
403422 }
404423
424+ /// Returns a minimum channel reserve value **they** need to maintain
425+ ///
405426 /// Guaranteed to return a value no larger than channel_value_satoshis
406427 fn get_our_channel_reserve_satoshis ( channel_value_satoshis : u64 ) -> u64 {
407428 let ( q, _) = channel_value_satoshis. overflowing_div ( 100 ) ;
@@ -477,6 +498,11 @@ impl Channel {
477498 next_remote_htlc_id : 0 ,
478499 channel_update_count : 1 ,
479500
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+
480506 last_local_commitment_txn : Vec :: new ( ) ,
481507
482508 last_sent_closing_fee : None ,
@@ -627,6 +653,11 @@ impl Channel {
627653 next_remote_htlc_id : 0 ,
628654 channel_update_count : 1 ,
629655
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+
630661 last_local_commitment_txn : Vec :: new ( ) ,
631662
632663 last_sent_closing_fee : None ,
@@ -812,9 +843,32 @@ impl Channel {
812843 }
813844
814845
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+
815866 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+ } ;
818872
819873 let value_to_a = if local { value_to_self } else { value_to_remote } ;
820874 let value_to_b = if local { value_to_remote } else { value_to_self } ;
@@ -1415,42 +1469,23 @@ impl Channel {
14151469 Ok ( ( ) )
14161470 }
14171471
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 ) {
14291474 let mut htlc_inbound_value_msat = 0 ;
14301475 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 ;
14391476 htlc_inbound_value_msat += htlc. amount_msat ;
14401477 }
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 ;
14411484 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 ;
14501485 htlc_outbound_value_msat += htlc. amount_msat ;
14511486 }
14521487
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 )
14541489 }
14551490
14561491 pub fn update_add_htlc ( & mut self , msg : & msgs:: UpdateAddHTLC , pending_forward_state : PendingHTLCStatus ) -> Result < ( ) , HandleError > {
@@ -1467,7 +1502,7 @@ impl Channel {
14671502 return Err ( HandleError { err : "Remote side tried to send less than our minimum HTLC value" , action : None } ) ;
14681503 }
14691504
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 ( ) ;
14711506 if inbound_htlc_count + 1 > OUR_MAX_HTLCS as u32 {
14721507 return Err ( HandleError { err : "Remote tried to push more than our max accepted HTLCs" , action : None } ) ;
14731508 }
@@ -1479,7 +1514,7 @@ impl Channel {
14791514 // Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet
14801515 // the reserve_satoshis we told them to always have as direct payment so that they lose
14811516 // 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 {
14831518 return Err ( HandleError { err : "Remote HTLC add would put them over their reserve value" , action : None } ) ;
14841519 }
14851520 if self . next_remote_htlc_id != msg. htlc_id {
@@ -2349,6 +2384,30 @@ impl Channel {
23492384 & self . local_keys
23502385 }
23512386
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+
23522411 /// Allowed in any state (including after shutdown)
23532412 pub fn get_channel_update_count ( & self ) -> u32 {
23542413 self . channel_update_count
@@ -2722,7 +2781,7 @@ impl Channel {
27222781 return Err ( HandleError { err : "Cannot send an HTLC while disconnected" , action : Some ( ErrorAction :: IgnoreError ) } ) ;
27232782 }
27242783
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 ( ) ;
27262785 if outbound_htlc_count + 1 > self . their_max_accepted_htlcs as u32 {
27272786 return Err ( HandleError { err : "Cannot push more than their max accepted HTLCs" , action : None } ) ;
27282787 }
@@ -2731,8 +2790,20 @@ impl Channel {
27312790 if htlc_outbound_value_msat + amount_msat > self . their_max_htlc_value_in_flight_msat {
27322791 return Err ( HandleError { err : "Cannot send value that would put us over our max HTLC value in flight" , action : None } ) ;
27332792 }
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 {
27362807 return Err ( HandleError { err : "Cannot send value that would put us over our reserve value" , action : None } ) ;
27372808 }
27382809
0 commit comments