use std;
use std::default::Default;
use std::{cmp,mem};
-use std::time::Instant;
use std::sync::{Arc};
#[cfg(test)]
/// 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,
(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);
}
(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)?;
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)?,
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:
//
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>,
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,
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 {
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) {
channel_state: Mutex::new(ChannelHolder {
by_id,
short_to_id,
- next_forward: Instant::now(),
forward_htlcs,
claimable_htlcs,
pending_msg_events: Vec::new(),