use secp256k1;
use ln::msgs;
-use ln::msgs::{DecodeError, OptionalField};
+use ln::msgs::{DecodeError, OptionalField, LocalFeatures};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
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,
1000 // TODO
}
- fn derive_minimum_depth(_channel_value_satoshis_msat: u64, _value_to_self_msat: u64) -> u32 {
- // Note that in order to comply with BOLT 7 announcement_signatures requirements this must
- // be at least 6.
- const CONF_TARGET: u32 = 12; //TODO: Should be much higher
- CONF_TARGET
- }
-
// Constructors:
pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel, APIError> {
let chan_keys = keys_provider.get_channel_keys(false);
/// Creates a new channel from a remote sides' request for one.
/// Assumes chain_hash has already been checked and corresponds with what we expect!
- pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel, ChannelError> {
+ pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, _their_local_features: LocalFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel, ChannelError> {
let chan_keys = keys_provider.get_channel_keys(true);
let mut local_config = (*config).channel_options.clone();
}
// Now check against optional parameters as set by config...
- if msg.funding_satoshis < config.channel_limits.min_funding_satoshis {
+ if msg.funding_satoshis < config.peer_channel_config_limits.min_funding_satoshis {
return Err(ChannelError::Close("funding satoshis is less than the user specified limit"));
}
- if msg.htlc_minimum_msat > config.channel_limits.max_htlc_minimum_msat {
+ if msg.htlc_minimum_msat > config.peer_channel_config_limits.max_htlc_minimum_msat {
return Err(ChannelError::Close("htlc minimum msat is higher than the user specified limit"));
}
- if msg.max_htlc_value_in_flight_msat < config.channel_limits.min_max_htlc_value_in_flight_msat {
+ if msg.max_htlc_value_in_flight_msat < config.peer_channel_config_limits.min_max_htlc_value_in_flight_msat {
return Err(ChannelError::Close("max htlc value in flight msat is less than the user specified limit"));
}
- if msg.channel_reserve_satoshis > config.channel_limits.max_channel_reserve_satoshis {
+ if msg.channel_reserve_satoshis > config.peer_channel_config_limits.max_channel_reserve_satoshis {
return Err(ChannelError::Close("channel reserve satoshis is higher than the user specified limit"));
}
- if msg.max_accepted_htlcs < config.channel_limits.min_max_accepted_htlcs {
+ if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs {
return Err(ChannelError::Close("max accepted htlcs is less than the user specified limit"));
}
- if msg.dust_limit_satoshis < config.channel_limits.min_dust_limit_satoshis {
+ if msg.dust_limit_satoshis < config.peer_channel_config_limits.min_dust_limit_satoshis {
return Err(ChannelError::Close("dust limit satoshis is less than the user specified limit"));
}
- if msg.dust_limit_satoshis > config.channel_limits.max_dust_limit_satoshis {
+ if msg.dust_limit_satoshis > config.peer_channel_config_limits.max_dust_limit_satoshis {
return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit"));
}
// Convert things into internal flags and prep our state:
let their_announce = if (msg.channel_flags & 1) == 1 { true } else { false };
- if config.channel_limits.force_announced_channel_preference {
+ if config.peer_channel_config_limits.force_announced_channel_preference {
if local_config.announced_channel != their_announce {
return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours"));
}
our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64),
their_to_self_delay: msg.to_self_delay,
their_max_accepted_htlcs: msg.max_accepted_htlcs,
- minimum_depth: Channel::derive_minimum_depth(msg.funding_satoshis*1000, msg.push_msat),
+ minimum_depth: config.own_channel_config.minimum_depth,
their_funding_pubkey: Some(msg.funding_pubkey),
their_revocation_basepoint: Some(msg.revocation_basepoint),
let value_to_b = if local { value_to_remote } else { value_to_self };
if value_to_a >= (dust_limit_satoshis as i64) {
+ log_trace!(self, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, value_to_a);
txouts.push((TxOut {
script_pubkey: chan_utils::get_revokeable_redeemscript(&keys.revocation_key,
if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT },
}
if value_to_b >= (dust_limit_satoshis as i64) {
+ log_trace!(self, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, value_to_b);
txouts.push((TxOut {
script_pubkey: Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
.push_slice(&Hash160::hash(&keys.b_payment_key.serialize())[..])
// Message handlers:
- pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig) -> Result<(), ChannelError> {
+ pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig, _their_local_features: LocalFeatures) -> Result<(), ChannelError> {
// Check sanity of message fields:
if !self.channel_outbound {
return Err(ChannelError::Close("Got an accept_channel message from an inbound peer"));
}
// Now check against optional parameters as set by config...
- if msg.htlc_minimum_msat > config.channel_limits.max_htlc_minimum_msat {
+ if msg.htlc_minimum_msat > config.peer_channel_config_limits.max_htlc_minimum_msat {
return Err(ChannelError::Close("htlc minimum msat is higher than the user specified limit"));
}
- if msg.max_htlc_value_in_flight_msat < config.channel_limits.min_max_htlc_value_in_flight_msat {
+ if msg.max_htlc_value_in_flight_msat < config.peer_channel_config_limits.min_max_htlc_value_in_flight_msat {
return Err(ChannelError::Close("max htlc value in flight msat is less than the user specified limit"));
}
- if msg.channel_reserve_satoshis > config.channel_limits.max_channel_reserve_satoshis {
+ if msg.channel_reserve_satoshis > config.peer_channel_config_limits.max_channel_reserve_satoshis {
return Err(ChannelError::Close("channel reserve satoshis is higher than the user specified limit"));
}
- if msg.max_accepted_htlcs < config.channel_limits.min_max_accepted_htlcs {
+ if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs {
return Err(ChannelError::Close("max accepted htlcs is less than the user specified limit"));
}
- if msg.dust_limit_satoshis < config.channel_limits.min_dust_limit_satoshis {
+ if msg.dust_limit_satoshis < config.peer_channel_config_limits.min_dust_limit_satoshis {
return Err(ChannelError::Close("dust limit satoshis is less than the user specified limit"));
}
- if msg.dust_limit_satoshis > config.channel_limits.max_dust_limit_satoshis {
+ if msg.dust_limit_satoshis > config.peer_channel_config_limits.max_dust_limit_satoshis {
return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit"));
}
- if msg.minimum_depth > config.channel_limits.max_minimum_depth {
+ if msg.minimum_depth > config.peer_channel_config_limits.max_minimum_depth {
return Err(ChannelError::Close("We consider the minimum depth to be unreasonably large"));
}
(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)?,