Skip to content

Commit 84d779a

Browse files
authored
Merge pull request #206 from TheBlueMatt/2018-10-189-rebase
#189 rebased
2 parents a82a5f7 + 99e01b2 commit 84d779a

File tree

2 files changed

+392
-38
lines changed

2 files changed

+392
-38
lines changed

src/ln/channel.rs

Lines changed: 106 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4758
impl 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

Comments
 (0)