Merge pull request #340 from TheBlueMatt/2019-06-channeldetails-fields
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Fri, 19 Jul 2019 03:56:22 +0000 (23:56 -0400)
committerGitHub <noreply@github.com>
Fri, 19 Jul 2019 03:56:22 +0000 (23:56 -0400)
Add balance and is_live fields to ChannelDetails

1  2 
src/ln/channel.rs
src/ln/channelmanager.rs

diff --combined src/ln/channel.rs
index 9750e50db0b39ef31d9cb94c349bacf0e2a4e238,14ef0c5152f38132e4f8d4bc0f78ab16b9d77a7f..63f0f41ae20bd806b5280decf2fa9ce6ce40bd76
@@@ -33,6 -33,7 +33,6 @@@ use util::config::{UserConfig,ChannelCo
  use std;
  use std::default::Default;
  use std::{cmp,mem};
 -use std::time::Instant;
  use std::sync::{Arc};
  
  #[cfg(test)]
@@@ -132,13 -133,14 +132,13 @@@ struct OutboundHTLCOutput 
  
  /// See AwaitingRemoteRevoke ChannelState for more info
  enum HTLCUpdateAwaitingACK {
 -      AddHTLC {
 +      AddHTLC { // TODO: Time out if we're getting close to cltv_expiry
                // always outbound
                amount_msat: u64,
                cltv_expiry: u32,
                payment_hash: PaymentHash,
                source: HTLCSource,
                onion_routing_packet: msgs::OnionPacket,
 -              time_created: Instant, //TODO: Some kind of timeout thing-a-majig
        },
        ClaimHTLC {
                payment_preimage: PaymentPreimage,
@@@ -1581,6 -1583,16 +1581,16 @@@ impl Channel 
                (htlc_outbound_count as u32, htlc_outbound_value_msat)
        }
  
+       /// Get the available (ie not including pending HTLCs) inbound and outbound balance in msat.
+       /// Doesn't bother handling the
+       /// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
+       /// corner case properly.
+       pub fn get_inbound_outbound_available_balance_msat(&self) -> (u64, u64) {
+               // Note that we have to handle overflow due to the above case.
+               (cmp::min(self.channel_value_satoshis as i64 * 1000 - self.value_to_self_msat as i64 - self.get_inbound_pending_htlc_stats().1 as i64, 0) as u64,
+               cmp::min(self.value_to_self_msat as i64 - self.get_outbound_pending_htlc_stats().1 as i64, 0) as u64)
+       }
        pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), ChannelError> {
                if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
                        return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state"));
                                cltv_expiry: cltv_expiry,
                                source,
                                onion_routing_packet: onion_routing_packet,
 -                              time_created: Instant::now(),
                        });
                        return Ok(None);
                }
@@@ -3619,13 -3632,14 +3629,13 @@@ impl Writeable for Channel 
                (self.holding_cell_htlc_updates.len() as u64).write(writer)?;
                for update in self.holding_cell_htlc_updates.iter() {
                        match update {
 -                              &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, ref cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, time_created: _ } => {
 +                              &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, ref cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet } => {
                                        0u8.write(writer)?;
                                        amount_msat.write(writer)?;
                                        cltv_expiry.write(writer)?;
                                        payment_hash.write(writer)?;
                                        source.write(writer)?;
                                        onion_routing_packet.write(writer)?;
 -                                      // time_created is not serialized - we re-init the timeout upon deserialization
                                },
                                &HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, ref htlc_id } => {
                                        1u8.write(writer)?;
@@@ -3792,6 -3806,7 +3802,6 @@@ impl<R : ::std::io::Read> ReadableArgs<
                                        payment_hash: Readable::read(reader)?,
                                        source: Readable::read(reader)?,
                                        onion_routing_packet: Readable::read(reader)?,
 -                                      time_created: Instant::now(),
                                },
                                1 => HTLCUpdateAwaitingACK::ClaimHTLC {
                                        payment_preimage: Readable::read(reader)?,
diff --combined src/ln/channelmanager.rs
index 2238a09bf7fdfeb8f21e6f197960bcc66ae9b9c1,24947cbe5568a0d550734dcd26708b2d8d385c18..e3bd06fd2bb72d0137bdfa8482ae34453801b499
@@@ -46,7 -46,7 +46,7 @@@ use std::collections::{HashMap, hash_ma
  use std::io::Cursor;
  use std::sync::{Arc, Mutex, MutexGuard, RwLock};
  use std::sync::atomic::{AtomicUsize, Ordering};
 -use std::time::{Instant,Duration};
 +use std::time::Duration;
  
  // We hold various information about HTLC relay in the HTLC objects in Channel itself:
  //
@@@ -247,6 -247,7 +247,6 @@@ pub(super) enum RAACommitmentOrder 
  pub(super) struct ChannelHolder {
        pub(super) by_id: HashMap<[u8; 32], Channel>,
        pub(super) short_to_id: HashMap<u64, [u8; 32]>,
 -      pub(super) next_forward: Instant,
        /// short channel id -> forward infos. Key of 0 means payments received
        /// Note that while this is held in the same mutex as the channels themselves, no consistency
        /// guarantees are made about the existence of a channel with the short id here, nor the short
  pub(super) struct MutChannelHolder<'a> {
        pub(super) by_id: &'a mut HashMap<[u8; 32], Channel>,
        pub(super) short_to_id: &'a mut HashMap<u64, [u8; 32]>,
 -      pub(super) next_forward: &'a mut Instant,
        pub(super) forward_htlcs: &'a mut HashMap<u64, Vec<HTLCForwardInfo>>,
        pub(super) claimable_htlcs: &'a mut HashMap<PaymentHash, Vec<(u64, HTLCPreviousHopData)>>,
        pub(super) pending_msg_events: &'a mut Vec<events::MessageSendEvent>,
@@@ -274,6 -276,7 +274,6 @@@ impl ChannelHolder 
                MutChannelHolder {
                        by_id: &mut self.by_id,
                        short_to_id: &mut self.short_to_id,
 -                      next_forward: &mut self.next_forward,
                        forward_htlcs: &mut self.forward_htlcs,
                        claimable_htlcs: &mut self.claimable_htlcs,
                        pending_msg_events: &mut self.pending_msg_events,
@@@ -388,6 -391,20 +388,20 @@@ pub struct ChannelDetails 
        pub channel_value_satoshis: u64,
        /// The user_id passed in to create_channel, or 0 if the channel was inbound.
        pub user_id: u64,
+       /// The available outbound capacity for sending HTLCs to the remote peer. This does not include
+       /// any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
+       /// available for inclusion in new outbound HTLCs). This further does not include any pending
+       /// outgoing HTLCs which are awaiting some other resolution to be sent.
+       pub outbound_capacity_msat: u64,
+       /// The available inbound capacity for the remote peer to send HTLCs to us. This does not
+       /// include any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
+       /// available for inclusion in new inbound HTLCs).
+       /// Note that there are some corner cases not fully handled here, so the actual available
+       /// inbound capacity may be slightly higher than this.
+       pub inbound_capacity_msat: u64,
+       /// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
+       /// the peer is connected, and (c) no monitor update failure is pending resolution.
+       pub is_live: bool,
  }
  
  macro_rules! handle_error {
@@@ -546,6 -563,7 +560,6 @@@ impl ChannelManager 
                        channel_state: Mutex::new(ChannelHolder{
                                by_id: HashMap::new(),
                                short_to_id: HashMap::new(),
 -                              next_forward: Instant::now(),
                                forward_htlcs: HashMap::new(),
                                claimable_htlcs: HashMap::new(),
                                pending_msg_events: Vec::new(),
                let channel_state = self.channel_state.lock().unwrap();
                let mut res = Vec::with_capacity(channel_state.by_id.len());
                for (channel_id, channel) in channel_state.by_id.iter() {
+                       let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat();
                        res.push(ChannelDetails {
                                channel_id: (*channel_id).clone(),
                                short_channel_id: channel.get_short_channel_id(),
                                remote_network_id: channel.get_their_node_id(),
                                channel_value_satoshis: channel.get_value_satoshis(),
+                               inbound_capacity_msat,
+                               outbound_capacity_msat,
                                user_id: channel.get_user_id(),
+                               is_live: channel.is_live(),
                        });
                }
                res
  
        /// Gets the list of usable channels, in random order. Useful as an argument to
        /// Router::get_route to ensure non-announced channels are used.
+       ///
+       /// These are guaranteed to have their is_live value set to true, see the documentation for
+       /// ChannelDetails::is_live for more info on exactly what the criteria are.
        pub fn list_usable_channels(&self) -> Vec<ChannelDetails> {
                let channel_state = self.channel_state.lock().unwrap();
                let mut res = Vec::with_capacity(channel_state.by_id.len());
                        // internal/external nomenclature, but that's ok cause that's probably what the user
                        // really wanted anyway.
                        if channel.is_live() {
+                               let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat();
                                res.push(ChannelDetails {
                                        channel_id: (*channel_id).clone(),
                                        short_channel_id: channel.get_short_channel_id(),
                                        remote_network_id: channel.get_their_node_id(),
                                        channel_value_satoshis: channel.get_value_satoshis(),
+                                       inbound_capacity_msat,
+                                       outbound_capacity_msat,
                                        user_id: channel.get_user_id(),
+                                       is_live: true,
                                });
                        }
                }
                        let mut channel_state_lock = self.channel_state.lock().unwrap();
                        let channel_state = channel_state_lock.borrow_parts();
  
 -                      if cfg!(not(feature = "fuzztarget")) && Instant::now() < *channel_state.next_forward {
 -                              return;
 -                      }
 -
                        for (short_chan_id, mut pending_forwards) in channel_state.forward_htlcs.drain() {
                                if short_chan_id != 0 {
                                        let forward_chan_id = match channel_state.short_to_id.get(&short_chan_id) {
  
                                let mut forward_event = None;
                                if channel_state_lock.forward_htlcs.is_empty() {
 -                                      forward_event = Some(Instant::now() + Duration::from_millis(((rng::rand_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64));
 -                                      channel_state_lock.next_forward = forward_event.unwrap();
 +                                      forward_event = Some(Duration::from_millis(((rng::rand_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64));
                                }
                                match channel_state_lock.forward_htlcs.entry(short_channel_id) {
                                        hash_map::Entry::Occupied(mut entry) => {
                        if !pending_forwards.is_empty() {
                                let mut channel_state = self.channel_state.lock().unwrap();
                                if channel_state.forward_htlcs.is_empty() {
 -                                      forward_event = Some(Instant::now() + Duration::from_millis(((rng::rand_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64));
 -                                      channel_state.next_forward = forward_event.unwrap();
 +                                      forward_event = Some(Duration::from_millis(((rng::rand_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64));
                                }
                                for (forward_info, prev_htlc_id) in pending_forwards.drain(..) {
                                        match channel_state.forward_htlcs.entry(forward_info.short_channel_id) {
@@@ -3077,6 -3112,7 +3102,6 @@@ impl<'a, R : ::std::io::Read> ReadableA
                        channel_state: Mutex::new(ChannelHolder {
                                by_id,
                                short_to_id,
 -                              next_forward: Instant::now(),
                                forward_htlcs,
                                claimable_htlcs,
                                pending_msg_events: Vec::new(),