X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=b9a81f6ebc0465cf34396eb44073b790fd7c3925;hb=224fb05cc53526e7b861e746183451d3d74ad549;hp=5c04414a2daed0532591fcaf405279fbf2a21bc8;hpb=4a51f4f073a7864b75d48c05397f23f8a2792e12;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 5c04414a..b9a81f6e 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -28,6 +28,7 @@ use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor}; use util::sha2::Sha256; use util::logger::Logger; use util::errors::APIError; +use util::config::{UserConfig,ChannelConfig}; use std; use std::default::Default; @@ -230,13 +231,14 @@ const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; // calling channel_id() before we're set up or things like get_outbound_funding_signed on an // inbound channel. pub(super) struct Channel { + config: ChannelConfig, + user_id: u64, channel_id: [u8; 32], channel_state: u32, channel_outbound: bool, secp_ctx: Secp256k1, - announce_publicly: bool, channel_value_satoshis: u64, local_keys: ChannelKeys, @@ -326,6 +328,7 @@ pub(super) struct Channel { //implied by BREAKDOWN_TIMEOUT: our_to_self_delay: u16, their_max_accepted_htlcs: u16, //implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16, + minimum_depth: u32, their_funding_pubkey: Option, their_revocation_basepoint: Option, @@ -399,7 +402,7 @@ impl Channel { } fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 { - at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000 //TODO + cmp::max(at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000, 546) //TODO } fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 { @@ -413,13 +416,8 @@ impl Channel { CONF_TARGET } - fn derive_maximum_minimum_depth(_channel_value_satoshis_msat: u64, _value_to_self_msat: u64) -> u32 { - const CONF_TARGET: u32 = 12; //TODO: Should be much higher - CONF_TARGET * 2 - } - // Constructors: - pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, announce_publicly: bool, user_id: u64, logger: Arc) -> Result { + pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result { let chan_keys = keys_provider.get_channel_keys(false); if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { @@ -445,12 +443,12 @@ impl Channel { Ok(Channel { user_id: user_id, + config: config.channel_options.clone(), channel_id: rng::rand_u832(), channel_state: ChannelState::OurInitSent as u32, channel_outbound: true, secp_ctx: secp_ctx, - announce_publicly: announce_publicly, channel_value_satoshis: channel_value_satoshis, local_keys: chan_keys, @@ -498,6 +496,7 @@ impl Channel { our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(feerate), their_to_self_delay: 0, their_max_accepted_htlcs: 0, + minimum_depth: 0, // Filled in in accept_channel their_funding_pubkey: None, their_revocation_basepoint: None, @@ -529,8 +528,9 @@ impl Channel { /// 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, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, require_announce: bool, allow_announce: bool, logger: Arc) -> Result { + pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config: &UserConfig) -> Result { let chan_keys = keys_provider.get_channel_keys(true); + let mut local_config = (*config).channel_options.clone(); // Check sanity of message fields: if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS { @@ -563,22 +563,46 @@ impl Channel { return Err(ChannelError::Close("max_accpted_htlcs > 483")); } + // Now check against optional parameters as set by config... + if msg.funding_satoshis < config.channel_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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 require_announce && !their_announce { - return Err(ChannelError::Close("Peer tried to open unannounced channel, but we require public ones")); - } - if !allow_announce && their_announce { - return Err(ChannelError::Close("Peer tried to open announced channel, but we require private ones")); + if config.channel_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")); + } } + // we either accept their preference or the preferences match + local_config.announced_channel = their_announce; let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); let our_dust_limit_satoshis = Channel::derive_our_dust_limit_satoshis(background_feerate); let our_channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(msg.funding_satoshis); if our_channel_reserve_satoshis < our_dust_limit_satoshis { - return Err(ChannelError::Close("Suitalbe channel reserve not found. aborting")); + return Err(ChannelError::Close("Suitable channel reserve not found. aborting")); } if msg.channel_reserve_satoshis < our_dust_limit_satoshis { return Err(ChannelError::Close("channel_reserve_satoshis too small")); @@ -609,12 +633,12 @@ impl Channel { let mut chan = Channel { user_id: user_id, + config: local_config, channel_id: msg.temporary_channel_id, channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32), channel_outbound: false, secp_ctx: secp_ctx, - announce_publicly: their_announce, local_keys: chan_keys, shutdown_pubkey: keys_provider.get_shutdown_pubkey(), @@ -662,6 +686,7 @@ impl Channel { 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), their_funding_pubkey: Some(msg.funding_pubkey), their_revocation_basepoint: Some(msg.revocation_basepoint), @@ -1264,7 +1289,7 @@ impl Channel { // Message handlers: - pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel) -> Result<(), ChannelError> { + pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig) -> Result<(), ChannelError> { // Check sanity of message fields: if !self.channel_outbound { return Err(ChannelError::Close("Got an accept_channel message from an inbound peer")); @@ -1290,9 +1315,6 @@ impl Channel { if msg.htlc_minimum_msat >= (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000 { return Err(ChannelError::Close("Minimum htlc value is full channel value")); } - if msg.minimum_depth > Channel::derive_maximum_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat) { - return Err(ChannelError::Close("minimum_depth too large")); - } if msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT { return Err(ChannelError::Close("They wanted our payments to be delayed by a needlessly long period")); } @@ -1303,14 +1325,28 @@ impl Channel { return Err(ChannelError::Close("max_accpted_htlcs > 483")); } - // TODO: Optional additional constraints mentioned in the spec - // MAY fail the channel if - // funding_satoshi is too small - // htlc_minimum_msat too large - // max_htlc_value_in_flight_msat too small - // channel_reserve_satoshis too large - // max_accepted_htlcs too small - // dust_limit_satoshis too small + // Now check against optional parameters as set by config... + if msg.htlc_minimum_msat > config.channel_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 { + 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 { + 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 { + 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 { + 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 { + return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit")); + } + if msg.minimum_depth > config.channel_limits.max_minimum_depth { + return Err(ChannelError::Close("We consider the minimum depth to be unreasonably large")); + } self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); @@ -1320,6 +1356,7 @@ impl Channel { self.their_htlc_minimum_msat = msg.htlc_minimum_msat; self.their_to_self_delay = msg.to_self_delay; self.their_max_accepted_htlcs = msg.max_accepted_htlcs; + self.minimum_depth = msg.minimum_depth; self.their_funding_pubkey = Some(msg.funding_pubkey); self.their_revocation_basepoint = Some(msg.revocation_basepoint); self.their_payment_basepoint = Some(msg.payment_basepoint); @@ -1516,6 +1553,12 @@ impl Channel { //TODO: Check msg.cltv_expiry further? Do this in channel manager? + if self.channel_state & ChannelState::LocalShutdownSent as u32 != 0 { + if let PendingHTLCStatus::Forward(_) = pending_forward_state { + panic!("ChannelManager shouldn't be trying to add a forwardable HTLC after we've started closing"); + } + } + // Now update local state: self.next_remote_htlc_id += 1; self.pending_inbound_htlcs.push(InboundHTLCOutput { @@ -1595,13 +1638,16 @@ impl Channel { self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason)) } - pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option, ChannelMonitor), HandleError> { + pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned, fee_estimator: &FeeEstimator) -> Result<(msgs::RevokeAndACK, Option, Option, ChannelMonitor), HandleError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", action: None}); } if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(HandleError{err: "Peer sent commitment_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent commitment_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); } + if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK == BOTH_SIDES_SHUTDOWN_MASK && self.last_sent_closing_fee.is_some() { + return Err(HandleError{err: "Peer sent commitment_signed after we'd started exchanging closing_signeds", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent commitment_signed after we'd started exchanging closing_signeds".to_string(), channel_id: msg.channel_id}})}); + } let funding_script = self.get_funding_redeemscript(); @@ -1693,19 +1739,21 @@ impl Channel { return Err(HandleError{err: "Previous monitor update failure prevented generation of RAA", action: Some(ErrorAction::IgnoreError)}); } - let (our_commitment_signed, monitor_update) = if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 { + let (our_commitment_signed, monitor_update, closing_signed) = if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 { // If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok - // we'll send one right away when we get the revoke_and_ack when we // free_holding_cell_htlcs(). let (msg, monitor) = self.send_commitment_no_status_check()?; - (Some(msg), monitor) - } else { (None, self.channel_monitor.clone()) }; + (Some(msg), monitor, None) + } else if !need_our_commitment { + (None, self.channel_monitor.clone(), self.maybe_propose_first_closing_signed(fee_estimator)) + } else { (None, self.channel_monitor.clone(), None) }; Ok((msgs::RevokeAndACK { channel_id: self.channel_id, per_commitment_secret: per_commitment_secret, next_per_commitment_point: next_per_commitment_point, - }, our_commitment_signed, monitor_update)) + }, our_commitment_signed, closing_signed, monitor_update)) } /// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them @@ -1806,13 +1854,16 @@ impl Channel { /// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail, /// generating an appropriate error *after* the channel state has been updated based on the /// revoke_and_ack message. - pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK) -> Result<(Option, Vec<(PendingForwardHTLCInfo, u64)>, Vec<(HTLCSource, [u8; 32], HTLCFailReason)>, ChannelMonitor), HandleError> { + pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &FeeEstimator) -> Result<(Option, Vec<(PendingForwardHTLCInfo, u64)>, Vec<(HTLCSource, [u8; 32], HTLCFailReason)>, Option, ChannelMonitor), HandleError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", action: None}); } if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(HandleError{err: "Peer sent revoke_and_ack when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent revoke_and_ack when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); } + if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK == BOTH_SIDES_SHUTDOWN_MASK && self.last_sent_closing_fee.is_some() { + return Err(HandleError{err: "Peer sent revoke_and_ack after we'd started exchanging closing_signeds", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent revoke_and_ack after we'd started exchanging closing_signeds".to_string(), channel_id: msg.channel_id}})}); + } if let Some(their_prev_commitment_point) = self.their_prev_commitment_point { if PublicKey::from_secret_key(&self.secp_ctx, &secp_call!(SecretKey::from_slice(&self.secp_ctx, &msg.per_commitment_secret), "Peer provided an invalid per_commitment_secret", self.channel_id())) != their_prev_commitment_point { @@ -1934,7 +1985,7 @@ impl Channel { } self.monitor_pending_forwards.append(&mut to_forward_infos); self.monitor_pending_failures.append(&mut revoked_htlcs); - return Ok((None, Vec::new(), Vec::new(), self.channel_monitor.clone())); + return Ok((None, Vec::new(), Vec::new(), None, self.channel_monitor.clone())); } match self.free_holding_cell_htlcs()? { @@ -1947,7 +1998,7 @@ impl Channel { for fail_msg in update_fail_malformed_htlcs.drain(..) { commitment_update.0.update_fail_malformed_htlcs.push(fail_msg); } - Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, commitment_update.1)) + Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, None, commitment_update.1)) }, None => { if require_commitment { @@ -1959,9 +2010,9 @@ impl Channel { update_fail_malformed_htlcs, update_fee: None, commitment_signed - }), to_forward_infos, revoked_htlcs, monitor_update)) + }), to_forward_infos, revoked_htlcs, None, monitor_update)) } else { - Ok((None, to_forward_infos, revoked_htlcs, self.channel_monitor.clone())) + Ok((None, to_forward_infos, revoked_htlcs, self.maybe_propose_first_closing_signed(fee_estimator), self.channel_monitor.clone())) } } } @@ -2020,6 +2071,9 @@ impl Channel { self.channel_state = ChannelState::ShutdownComplete as u32; return outbound_drops; } + // Upon reconnect we have to start the closing_signed dance over, but shutdown messages + // will be retransmitted. + self.last_sent_closing_fee = None; let mut inbound_drop_count = 0; self.pending_inbound_htlcs.retain(|htlc| { @@ -2207,7 +2261,7 @@ impl Channel { /// May panic if some calls other than message-handling calls (which will all Err immediately) /// have been called between remove_uncommitted_htlcs_and_mark_paused and this call. - pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option, Option, Option, Option, RAACommitmentOrder), ChannelError> { + pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option, Option, Option, Option, RAACommitmentOrder, Option), ChannelError> { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { // While BOLT 2 doesn't indicate explicitly we should error this channel here, it // almost certainly indicates we are going to end up out-of-sync in some way, so we @@ -2223,9 +2277,16 @@ impl Channel { // remaining cases either succeed or ErrorMessage-fail). self.channel_state &= !(ChannelState::PeerDisconnected as u32); + let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 { + Some(msgs::Shutdown { + channel_id: self.channel_id, + scriptpubkey: self.get_closing_scriptpubkey(), + }) + } else { None }; + if self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) == ChannelState::FundingSent as u32 { // Short circuit the whole handler as there is nothing we can resend them - return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst)); + return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); } if msg.next_local_commitment_number == 0 || msg.next_remote_commitment_number == 0 { @@ -2238,7 +2299,7 @@ impl Channel { return Ok((Some(msgs::FundingLocked { channel_id: self.channel_id(), next_per_commitment_point: next_per_commitment_point, - }), None, None, None, RAACommitmentOrder::CommitmentFirst)); + }), None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); } let required_revoke = if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number { @@ -2301,11 +2362,11 @@ impl Channel { panic!("Got non-channel-failing result from free_holding_cell_htlcs"); } }, - Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor), order)), - Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None, order)), + Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor), order, shutdown_msg)), + Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None, order, shutdown_msg)), } } else { - return Ok((resend_funding_locked, required_revoke, None, None, order)); + return Ok((resend_funding_locked, required_revoke, None, None, order, shutdown_msg)); } } else if msg.next_local_commitment_number == our_next_remote_commitment_number - 1 { if required_revoke.is_some() { @@ -2319,71 +2380,78 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { self.monitor_pending_commitment_signed = true; - return Ok((resend_funding_locked, None, None, None, order)); + return Ok((resend_funding_locked, None, None, None, order, shutdown_msg)); } - return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update()), None, order)); + return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update()), None, order, shutdown_msg)); } else { return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction")); } } - pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option, Option, Vec<(HTLCSource, [u8; 32])>), HandleError> { + fn maybe_propose_first_closing_signed(&mut self, fee_estimator: &FeeEstimator) -> Option { + if !self.channel_outbound || !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() || + self.channel_state & (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32) != BOTH_SIDES_SHUTDOWN_MASK || + self.last_sent_closing_fee.is_some() || + self.cur_remote_commitment_transaction_number != self.cur_local_commitment_transaction_number{ + return None; + } + + let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); + if self.feerate_per_kw > proposed_feerate { + proposed_feerate = self.feerate_per_kw; + } + let tx_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap()); + let proposed_total_fee_satoshis = proposed_feerate * tx_weight / 1000; + + let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false); + let funding_redeemscript = self.get_funding_redeemscript(); + let sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap(); + + self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis)); + Some(msgs::ClosingSigned { + channel_id: self.channel_id, + fee_satoshis: total_fee_satoshis, + signature: self.secp_ctx.sign(&sighash, &self.local_keys.funding_key), + }) + } + + pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option, Option, Vec<(HTLCSource, [u8; 32])>), ChannelError> { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { - return Err(HandleError{err: "Peer sent shutdown when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent shutdown when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish")); } if self.channel_state < ChannelState::FundingSent as u32 { - self.channel_state = ChannelState::ShutdownComplete as u32; - self.channel_update_count += 1; - return Ok((None, None, Vec::new())); + // Spec says we should fail the connection, not the channel, but that's nonsense, there + // are plenty of reasons you may want to fail a channel pre-funding, and spec says you + // can do that via error message without getting a connection fail anyway... + return Err(ChannelError::Close("Peer sent shutdown pre-funding generation")); } for htlc in self.pending_inbound_htlcs.iter() { if let InboundHTLCState::RemoteAnnounced(_) = htlc.state { - return Err(HandleError{err: "Got shutdown with remote pending HTLCs", action: None}); + return Err(ChannelError::Close("Got shutdown with remote pending HTLCs")); } } - if (self.channel_state & ChannelState::RemoteShutdownSent as u32) == ChannelState::RemoteShutdownSent as u32 { - return Err(HandleError{err: "Remote peer sent duplicate shutdown message", action: None}); - } assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); // BOLT 2 says we must only send a scriptpubkey of certain standard forms, which are up to // 34 bytes in length, so dont let the remote peer feed us some super fee-heavy script. if self.channel_outbound && msg.scriptpubkey.len() > 34 { - return Err(HandleError{err: "Got shutdown_scriptpubkey of absurd length from remote peer", action: None}); + return Err(ChannelError::Close("Got shutdown_scriptpubkey of absurd length from remote peer")); } //Check shutdown_scriptpubkey form as BOLT says we must - if !(msg.scriptpubkey.is_p2pkh()) && !(msg.scriptpubkey.is_p2sh()) - && !(msg.scriptpubkey.is_v0_p2wpkh()) && !(msg.scriptpubkey.is_v0_p2wsh()){ - return Err(HandleError{err: "Got an invalid scriptpubkey from remote peer", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })}); + if !msg.scriptpubkey.is_p2pkh() && !msg.scriptpubkey.is_p2sh() && !msg.scriptpubkey.is_v0_p2wpkh() && !msg.scriptpubkey.is_v0_p2wsh() { + return Err(ChannelError::Close("Got a nonstandard scriptpubkey from remote peer")); } if self.their_shutdown_scriptpubkey.is_some() { if Some(&msg.scriptpubkey) != self.their_shutdown_scriptpubkey.as_ref() { - return Err(HandleError{err: "Got shutdown request with a scriptpubkey which did not match their previous scriptpubkey", action: None}); + return Err(ChannelError::Close("Got shutdown request with a scriptpubkey which did not match their previous scriptpubkey")); } } else { self.their_shutdown_scriptpubkey = Some(msg.scriptpubkey.clone()); } - let our_closing_script = self.get_closing_scriptpubkey(); - - let (proposed_feerate, proposed_fee, our_sig) = if self.channel_outbound && self.pending_inbound_htlcs.is_empty() && self.pending_outbound_htlcs.is_empty() { - let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if self.feerate_per_kw > proposed_feerate { - proposed_feerate = self.feerate_per_kw; - } - let tx_weight = Self::get_closing_transaction_weight(&our_closing_script, &msg.scriptpubkey); - let proposed_total_fee_satoshis = proposed_feerate * tx_weight / 1000; - - let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false); - let funding_redeemscript = self.get_funding_redeemscript(); - let sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap(); - - (Some(proposed_feerate), Some(total_fee_satoshis), Some(self.secp_ctx.sign(&sighash, &self.local_keys.funding_key))) - } else { (None, None, None) }; - // From here on out, we may not fail! self.channel_state |= ChannelState::RemoteShutdownSent as u32; @@ -2392,6 +2460,7 @@ impl Channel { // We can't send our shutdown until we've committed all of our pending HTLCs, but the // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding // cell HTLCs and return them to fail the payment. + self.holding_cell_update_fee = None; let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len()); self.holding_cell_htlc_updates.retain(|htlc_update| { match htlc_update { @@ -2402,35 +2471,22 @@ impl Channel { _ => true } }); - for htlc in self.pending_outbound_htlcs.iter() { - if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { - return Ok((None, None, dropped_outbound_htlcs)); - } - } + // If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc + // immediately after the commitment dance, but we can send a Shutdown cause we won't send + // any further commitment updates after we set LocalShutdownSent. let our_shutdown = if (self.channel_state & ChannelState::LocalShutdownSent as u32) == ChannelState::LocalShutdownSent as u32 { None } else { Some(msgs::Shutdown { channel_id: self.channel_id, - scriptpubkey: our_closing_script, + scriptpubkey: self.get_closing_scriptpubkey(), }) }; self.channel_state |= ChannelState::LocalShutdownSent as u32; self.channel_update_count += 1; - if self.pending_inbound_htlcs.is_empty() && self.pending_outbound_htlcs.is_empty() && self.channel_outbound { - // There are no more HTLCs and we're the funder, this means we start the closing_signed - // dance with an initial fee proposal! - self.last_sent_closing_fee = Some((proposed_feerate.unwrap(), proposed_fee.unwrap())); - Ok((our_shutdown, Some(msgs::ClosingSigned { - channel_id: self.channel_id, - fee_satoshis: proposed_fee.unwrap(), - signature: our_sig.unwrap(), - }), dropped_outbound_htlcs)) - } else { - Ok((our_shutdown, None, dropped_outbound_htlcs)) - } + Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs)) } pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option, Option), HandleError> { @@ -2575,6 +2631,10 @@ impl Channel { self.channel_value_satoshis } + pub fn get_fee_proportional_millionths(&self) -> u32 { + self.config.fee_proportional_millionths + } + #[cfg(test)] pub fn get_feerate(&self) -> u64 { self.feerate_per_kw @@ -2628,7 +2688,7 @@ impl Channel { } pub fn should_announce(&self) -> bool { - self.announce_publicly + self.config.announced_channel } pub fn is_outbound(&self) -> bool { @@ -2708,7 +2768,7 @@ impl Channel { self.channel_monitor.last_block_hash = self.last_block_connected; if self.funding_tx_confirmations > 0 { self.funding_tx_confirmations += 1; - if self.funding_tx_confirmations == Channel::derive_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat) as u64 { + if self.funding_tx_confirmations == self.minimum_depth as u64 { let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 { self.channel_state |= ChannelState::OurFundingLocked as u32; true @@ -2785,7 +2845,7 @@ impl Channel { } } if Some(header.bitcoin_hash()) == self.funding_tx_confirmed_in { - self.funding_tx_confirmations = Channel::derive_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat) as u64 - 1; + self.funding_tx_confirmations = self.minimum_depth as u64 - 1; } self.last_block_connected = header.bitcoin_hash(); self.channel_monitor.last_block_hash = self.last_block_connected; @@ -2827,7 +2887,7 @@ impl Channel { delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key), htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key), first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), - channel_flags: if self.announce_publicly {1} else {0}, + channel_flags: if self.config.announced_channel {1} else {0}, shutdown_scriptpubkey: None, } } @@ -2851,7 +2911,7 @@ impl Channel { max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis), htlc_minimum_msat: self.our_htlc_minimum_msat, - minimum_depth: Channel::derive_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat), + minimum_depth: self.minimum_depth, to_self_delay: BREAKDOWN_TIMEOUT, max_accepted_htlcs: OUR_MAX_HTLCS, funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key), @@ -2931,7 +2991,7 @@ impl Channel { /// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see /// https://github.com/lightningnetwork/lightning-rfc/issues/468 pub fn get_channel_announcement(&self, our_node_id: PublicKey, chain_hash: Sha256dHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> { - if !self.announce_publicly { + if !self.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements")); } if self.channel_state & (ChannelState::ChannelFunded as u32) == 0 { @@ -3209,9 +3269,9 @@ impl Channel { } self.channel_update_count += 1; - // We can't send our shutdown until we've committed all of our pending HTLCs, but the - // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding - // cell HTLCs and return them to fail the payment. + // Go ahead and drop holding cell updates as we'd rather fail payments than wait to send + // our shutdown until we've committed all of the pending changes. + self.holding_cell_update_fee = None; let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len()); self.holding_cell_htlc_updates.retain(|htlc_update| { match htlc_update { @@ -3307,11 +3367,11 @@ impl Writeable for Channel { writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?; self.user_id.write(writer)?; + self.config.write(writer)?; self.channel_id.write(writer)?; (self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?; self.channel_outbound.write(writer)?; - self.announce_publicly.write(writer)?; self.channel_value_satoshis.write(writer)?; self.local_keys.write(writer)?; @@ -3482,6 +3542,7 @@ impl Writeable for Channel { self.our_htlc_minimum_msat.write(writer)?; self.their_to_self_delay.write(writer)?; self.their_max_accepted_htlcs.write(writer)?; + self.minimum_depth.write(writer)?; write_option!(self.their_funding_pubkey); write_option!(self.their_revocation_basepoint); @@ -3509,11 +3570,11 @@ impl ReadableArgs> for Channel { } let user_id = Readable::read(reader)?; + let config: ChannelConfig = Readable::read(reader)?; let channel_id = Readable::read(reader)?; let channel_state = Readable::read(reader)?; let channel_outbound = Readable::read(reader)?; - let announce_publicly = Readable::read(reader)?; let channel_value_satoshis = Readable::read(reader)?; let local_keys = Readable::read(reader)?; @@ -3655,6 +3716,7 @@ impl ReadableArgs> for Channel { let our_htlc_minimum_msat = Readable::read(reader)?; let their_to_self_delay = Readable::read(reader)?; let their_max_accepted_htlcs = Readable::read(reader)?; + let minimum_depth = Readable::read(reader)?; let their_funding_pubkey = read_option!(); let their_revocation_basepoint = read_option!(); @@ -3677,11 +3739,11 @@ impl ReadableArgs> for Channel { Ok(Channel { user_id, + config, channel_id, channel_state, channel_outbound, secp_ctx: Secp256k1::new(), - announce_publicly, channel_value_satoshis, local_keys, @@ -3731,6 +3793,7 @@ impl ReadableArgs> for Channel { our_htlc_minimum_msat, their_to_self_delay, their_max_accepted_htlcs, + minimum_depth, their_funding_pubkey, their_revocation_basepoint, @@ -3767,6 +3830,7 @@ mod tests { use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::keysinterface::KeysInterface; use chain::transaction::OutPoint; + use util::config::UserConfig; use util::test_utils; use util::logger::Logger; use secp256k1::{Secp256k1,Message,Signature}; @@ -3833,7 +3897,9 @@ mod tests { let keys_provider: Arc = Arc::new(Keys { chan_keys }); let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap()); - let mut chan = Channel::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, false, 42, Arc::clone(&logger)).unwrap(); // Nothing uses their network key in this test + let mut config = UserConfig::new(); + config.channel_options.announced_channel = false; + let mut chan = Channel::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test chan.their_to_self_delay = 144; chan.our_dust_limit_satoshis = 546;