X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=4d790cfc91e422433d1cc213f9dcc17292e62180;hb=refs%2Fheads%2F2019-07-more-chanmon-fuzz;hp=9750e50db0b39ef31d9cb94c349bacf0e2a4e238;hpb=fbd58b400b84da76284c7886f9b004215e61c7d5;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 9750e50d..4d790cfc 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -16,7 +16,7 @@ use secp256k1::{Secp256k1,Signature}; 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}; @@ -522,7 +522,7 @@ 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, logger: Arc, config: &UserConfig) -> Result { + pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, their_local_features: LocalFeatures, 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(); @@ -625,6 +625,27 @@ impl Channel { channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); channel_monitor.set_their_to_self_delay(msg.to_self_delay); + let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() { + match &msg.shutdown_scriptpubkey { + &OptionalField::Present(ref script) => { + // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg + if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wsh() || script.is_v0_p2wpkh() { + Some(script.clone()) + // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything + } else if script.len() == 0 { + None + // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. Fail the channel + } else { + return Err(ChannelError::Close("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format")); + } + }, + // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel + &OptionalField::Absent => { + return Err(ChannelError::Close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out")); + } + } + } else { None }; + let mut chan = Channel { user_id: user_id, config: local_config, @@ -692,7 +713,7 @@ impl Channel { their_prev_commitment_point: None, their_node_id: their_node_id, - their_shutdown_scriptpubkey: None, + their_shutdown_scriptpubkey, channel_monitor: channel_monitor, @@ -1341,7 +1362,7 @@ impl Channel { // 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")); @@ -1400,6 +1421,27 @@ impl Channel { return Err(ChannelError::Close("We consider the minimum depth to be unreasonably large")); } + let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() { + match &msg.shutdown_scriptpubkey { + &OptionalField::Present(ref script) => { + // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg + if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wsh() || script.is_v0_p2wpkh() { + Some(script.clone()) + // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything + } else if script.len() == 0 { + None + // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. Fail the channel + } else { + return Err(ChannelError::Close("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format")); + } + }, + // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel + &OptionalField::Absent => { + return Err(ChannelError::Close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out")); + } + } + } else { None }; + self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); self.their_dust_limit_satoshis = msg.dust_limit_satoshis; @@ -1415,6 +1457,7 @@ impl Channel { self.their_delayed_payment_basepoint = Some(msg.delayed_payment_basepoint); self.their_htlc_basepoint = Some(msg.htlc_basepoint); self.their_cur_commitment_point = Some(msg.first_per_commitment_point); + self.their_shutdown_scriptpubkey = their_shutdown_scriptpubkey; let obscure_factor = self.get_commitment_transaction_number_obscure_factor(); self.channel_monitor.set_commitment_obscure_factor(obscure_factor); @@ -1581,6 +1624,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")); @@ -3028,7 +3081,7 @@ impl Channel { 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.config.announced_channel {1} else {0}, - shutdown_scriptpubkey: OptionalField::Absent + shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) } } @@ -3060,7 +3113,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), - shutdown_scriptpubkey: OptionalField::Absent + shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) } }