X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=1d736d41d6f799569a633e2c9de8b6895d28e34c;hb=84d779a65170676e0945d1b9c467703ee86ef817;hp=2dc7750e472be7d02a1a85fc2d109cb3a7031a67;hpb=dc4a8c1de248a668a37a370264f094bc041d5efe;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 2dc7750e..1d736d41 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -44,6 +44,17 @@ pub struct ChannelKeys { pub commitment_seed: [u8; 32], } +#[cfg(test)] +pub struct ChannelValueStat { + pub value_to_self_msat: u64, + pub channel_value_msat: u64, + pub channel_reserve_msat: u64, + pub pending_outbound_htlcs_amount_msat: u64, + pub pending_inbound_htlcs_amount_msat: u64, + pub holding_cell_outbound_amount_msat: u64, + pub their_max_htlc_value_in_flight_msat: u64, // outgoing +} + impl ChannelKeys { pub fn new_from_seed(seed: &[u8; 32]) -> Result { let mut prk = [0; 32]; @@ -308,6 +319,13 @@ pub(super) struct Channel { channel_update_count: u32, feerate_per_kw: u64, + #[cfg(debug_assertions)] + /// Max to_local and to_remote outputs in a locally-generated commitment transaction + max_commitment_tx_output_local: ::std::sync::Mutex<(u64, u64)>, + #[cfg(debug_assertions)] + /// Max to_local and to_remote outputs in a remote-generated commitment transaction + max_commitment_tx_output_remote: ::std::sync::Mutex<(u64, u64)>, + #[cfg(test)] // Used in ChannelManager's tests to send a revoked transaction pub last_local_commitment_txn: Vec, @@ -480,6 +498,11 @@ impl Channel { next_remote_htlc_id: 0, channel_update_count: 1, + #[cfg(debug_assertions)] + max_commitment_tx_output_local: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + #[cfg(debug_assertions)] + max_commitment_tx_output_remote: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + last_local_commitment_txn: Vec::new(), last_sent_closing_fee: None, @@ -630,6 +653,11 @@ impl Channel { next_remote_htlc_id: 0, channel_update_count: 1, + #[cfg(debug_assertions)] + max_commitment_tx_output_local: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), + #[cfg(debug_assertions)] + max_commitment_tx_output_remote: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), + last_local_commitment_txn: Vec::new(), last_sent_closing_fee: None, @@ -815,9 +843,32 @@ impl Channel { } + let value_to_self_msat: i64 = (self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset; + 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; + + #[cfg(debug_assertions)] + { + // Make sure that the to_self/to_remote is always either past the appropriate + // channel_reserve *or* it is making progress towards it. + // TODO: This should happen after fee calculation, but we don't handle that correctly + // yet! + let mut max_commitment_tx_output = if generated_by_local { + self.max_commitment_tx_output_local.lock().unwrap() + } else { + self.max_commitment_tx_output_remote.lock().unwrap() + }; + 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); + max_commitment_tx_output.0 = cmp::max(max_commitment_tx_output.0, value_to_self_msat as u64); + 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); + max_commitment_tx_output.1 = cmp::max(max_commitment_tx_output.1, value_to_remote_msat as u64); + } + let total_fee: u64 = feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; - 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 }; - 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 }; + let (value_to_self, value_to_remote) = if self.channel_outbound { + (value_to_self_msat / 1000 - total_fee as i64, value_to_remote_msat / 1000) + } else { + (value_to_self_msat / 1000, value_to_remote_msat / 1000 - total_fee as i64) + }; let value_to_a = if local { value_to_self } else { value_to_remote }; let value_to_b = if local { value_to_remote } else { value_to_self }; @@ -1418,42 +1469,23 @@ impl Channel { Ok(()) } - /// Returns (inbound_htlc_count, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) - /// If its for a remote update check, we need to be more lax about checking against messages we - /// sent but they may not have received/processed before they sent this message. Further, for - /// our own sends, we're more conservative and even consider things they've removed against - /// totals, though there is little reason to outside of further avoiding any race condition - /// issues. - fn get_pending_htlc_stats(&self, for_remote_update_check: bool) -> (u32, u32, u64, u64) { - //TODO: Can probably split this into inbound/outbound - let mut inbound_htlc_count: u32 = 0; - let mut outbound_htlc_count: u32 = 0; - let mut htlc_outbound_value_msat = 0; + /// Returns (inbound_htlc_count, htlc_inbound_value_msat) + fn get_inbound_pending_htlc_stats(&self) -> (u32, u64) { let mut htlc_inbound_value_msat = 0; for ref htlc in self.pending_inbound_htlcs.iter() { - match htlc.state { - InboundHTLCState::RemoteAnnounced => {}, - InboundHTLCState::AwaitingRemoteRevokeToAnnounce => {}, - InboundHTLCState::AwaitingAnnouncedRemoteRevoke => {}, - InboundHTLCState::Committed => {}, - InboundHTLCState::LocalRemoved => {}, - } - inbound_htlc_count += 1; htlc_inbound_value_msat += htlc.amount_msat; } + (self.pending_inbound_htlcs.len() as u32, htlc_inbound_value_msat) + } + + /// Returns (outbound_htlc_count, htlc_outbound_value_msat) + fn get_outbound_pending_htlc_stats(&self) -> (u32, u64) { + let mut htlc_outbound_value_msat = 0; for ref htlc in self.pending_outbound_htlcs.iter() { - match htlc.state { - OutboundHTLCState::LocalAnnounced => { if for_remote_update_check { continue; } }, - OutboundHTLCState::Committed => {}, - OutboundHTLCState::RemoteRemoved => { if for_remote_update_check { continue; } }, - OutboundHTLCState::AwaitingRemoteRevokeToRemove => { if for_remote_update_check { continue; } }, - OutboundHTLCState::AwaitingRemovedRemoteRevoke => { if for_remote_update_check { continue; } }, - } - outbound_htlc_count += 1; htlc_outbound_value_msat += htlc.amount_msat; } - (inbound_htlc_count, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) + (self.pending_outbound_htlcs.len() as u32, htlc_outbound_value_msat) } pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), HandleError> { @@ -1470,7 +1502,7 @@ impl Channel { return Err(HandleError{err: "Remote side tried to send less than our minimum HTLC value", action: None}); } - let (inbound_htlc_count, _, _, htlc_inbound_value_msat) = self.get_pending_htlc_stats(true); + let (inbound_htlc_count, htlc_inbound_value_msat) = self.get_inbound_pending_htlc_stats(); if inbound_htlc_count + 1 > OUR_MAX_HTLCS as u32 { return Err(HandleError{err: "Remote tried to push more than our max accepted HTLCs", action: None}); } @@ -2352,6 +2384,30 @@ impl Channel { &self.local_keys } + #[cfg(test)] + pub fn get_value_stat(&self) -> ChannelValueStat { + ChannelValueStat { + value_to_self_msat: self.value_to_self_msat, + channel_value_msat: self.channel_value_satoshis * 1000, + channel_reserve_msat: self.their_channel_reserve_satoshis * 1000, + pending_outbound_htlcs_amount_msat: self.pending_outbound_htlcs.iter().map(|ref h| h.amount_msat).sum::(), + pending_inbound_htlcs_amount_msat: self.pending_inbound_htlcs.iter().map(|ref h| h.amount_msat).sum::(), + holding_cell_outbound_amount_msat: { + let mut res = 0; + for h in self.holding_cell_htlc_updates.iter() { + match h { + &HTLCUpdateAwaitingACK::AddHTLC{amount_msat, .. } => { + res += amount_msat; + } + _ => {} + } + } + res + }, + their_max_htlc_value_in_flight_msat: self.their_max_htlc_value_in_flight_msat, + } + } + /// Allowed in any state (including after shutdown) pub fn get_channel_update_count(&self) -> u32 { self.channel_update_count @@ -2725,7 +2781,7 @@ impl Channel { return Err(HandleError{err: "Cannot send an HTLC while disconnected", action: Some(ErrorAction::IgnoreError)}); } - let (_, outbound_htlc_count, htlc_outbound_value_msat, _) = self.get_pending_htlc_stats(false); + let (outbound_htlc_count, htlc_outbound_value_msat) = self.get_outbound_pending_htlc_stats(); if outbound_htlc_count + 1 > self.their_max_accepted_htlcs as u32 { return Err(HandleError{err: "Cannot push more than their max accepted HTLCs", action: None}); }