From: Matt Corallo <649246+TheBlueMatt@users.noreply.github.com> Date: Fri, 19 Jul 2019 03:56:22 +0000 (-0400) Subject: Merge pull request #340 from TheBlueMatt/2019-06-channeldetails-fields X-Git-Tag: v0.0.12~207 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=100197c483d00883a01c09fd4e9efa613d470622;hp=-c;p=rust-lightning Merge pull request #340 from TheBlueMatt/2019-06-channeldetails-fields Add balance and is_live fields to ChannelDetails --- 100197c483d00883a01c09fd4e9efa613d470622 diff --combined src/ln/channel.rs index 9750e50db,14ef0c515..63f0f41ae --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@@ -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")); @@@ -3250,6 -3262,7 +3260,6 @@@ 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 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 2238a09bf,24947cbe5..e3bd06fd2 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@@ -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, - 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 @@@ -265,6 -266,7 +265,6 @@@ pub(super) struct MutChannelHolder<'a> { pub(super) by_id: &'a mut HashMap<[u8; 32], Channel>, pub(super) short_to_id: &'a mut HashMap, - pub(super) next_forward: &'a mut Instant, pub(super) forward_htlcs: &'a mut HashMap>, pub(super) claimable_htlcs: &'a mut HashMap>, pub(super) pending_msg_events: &'a mut Vec, @@@ -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(), @@@ -609,12 -627,16 +623,16 @@@ 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 @@@ -622,6 -644,9 +640,9 @@@ /// 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 { let channel_state = self.channel_state.lock().unwrap(); let mut res = Vec::with_capacity(channel_state.by_id.len()); @@@ -630,12 -655,16 +651,16 @@@ // 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, }); } } @@@ -1180,6 -1209,10 +1205,6 @@@ 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) { @@@ -1459,7 -1492,8 +1484,7 @@@ 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) => { @@@ -2068,7 -2102,8 +2093,7 @@@ 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(),