X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmanager.rs;h=27f470d40f8a0e6182b677ac925dd20687cd21ca;hb=6ab31a0d501db9fd96436deff190da8801ac73b7;hp=14b21e23a79b4928454c77a5c0786b2ac975adcf;hpb=b4078d992d2ff639df0530001f1b3fe08f1d0a46;p=rust-lightning diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 14b21e23..27f470d4 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -20,7 +20,8 @@ use ln::msgs::{HandleError,ChannelMessageHandler,MsgEncodable,MsgDecodable}; use util::{byte_utils, events, internal_traits, rng}; use util::sha2::Sha256; use util::chacha20poly1305rfc::ChaCha20; -use util::logger::{Logger, Record}; +use util::logger::Logger; +use util::errors::APIError; use crypto; use crypto::mac::{Mac,MacResult}; @@ -254,7 +255,8 @@ impl ChannelManager { /// may wish to avoid using 0 for user_id here. /// If successful, will generate a SendOpenChannel event, so you should probably poll /// PeerManager::process_events afterwards. - pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, user_id: u64) -> Result<(), HandleError> { + /// Raises APIError::APIMisuseError when channel_value_satoshis > 2**24 or push_msat being greater than channel_value_satoshis * 1k + pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64) -> Result<(), APIError> { let chan_keys = if cfg!(feature = "fuzztarget") { ChannelKeys { funding_key: SecretKey::from_slice(&self.secp_ctx, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap(), @@ -275,7 +277,7 @@ impl ChannelManager { } }; - let channel = Channel::new_outbound(&*self.fee_estimator, chan_keys, their_network_key, channel_value_satoshis, self.announce_channels_publicly, user_id, Arc::clone(&self.logger)); + let channel = Channel::new_outbound(&*self.fee_estimator, chan_keys, their_network_key, channel_value_satoshis, push_msat, self.announce_channels_publicly, user_id, Arc::clone(&self.logger))?; let res = channel.get_open_channel(self.genesis_hash.clone(), &*self.fee_estimator)?; let mut channel_state = self.channel_state.lock().unwrap(); match channel_state.by_id.insert(channel.channel_id(), channel) { @@ -413,6 +415,14 @@ impl ChannelManager { } } + /// Force close all channels, immediately broadcasting the latest local commitment transaction + /// for each to the chain and rejecting new HTLCs on each. + pub fn force_close_all_channels(&self) { + for chan in self.list_channels() { + self.force_close_channel(&chan.channel_id); + } + } + #[inline] fn gen_rho_mu_from_shared_secret(shared_secret: &SharedSecret) -> ([u8; 32], [u8; 32]) { ({ @@ -770,6 +780,8 @@ impl ChannelManager { /// Call this upon creation of a funding transaction for the given channel. /// Panics if a funding transaction has already been provided for this channel. + /// May panic if the funding_txo is duplicative with some other channel (note that this should + /// be trivially prevented by using unique funding transaction keys per-channel). pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) { macro_rules! add_pending_event { @@ -812,7 +824,14 @@ impl ChannelManager { }); let mut channel_state = self.channel_state.lock().unwrap(); - channel_state.by_id.insert(chan.channel_id(), chan); + match channel_state.by_id.entry(chan.channel_id()) { + hash_map::Entry::Occupied(_) => { + panic!("Generated duplicate funding txid?"); + }, + hash_map::Entry::Vacant(e) => { + e.insert(chan); + } + } } fn get_announcement_sigs(&self, chan: &Channel) -> Result, HandleError> { @@ -1350,7 +1369,17 @@ impl ChannelMessageHandler for ChannelManager { unimplemented!(); } let mut channel_state = self.channel_state.lock().unwrap(); - channel_state.by_id.insert(funding_msg.channel_id, chan); + match channel_state.by_id.entry(funding_msg.channel_id) { + hash_map::Entry::Occupied(_) => { + return Err(HandleError { + err: "Duplicate channel_id!", + action: Some(msgs::ErrorAction::SendErrorMessage { msg: msgs::ErrorMessage { channel_id: funding_msg.channel_id, data: "Already had channel with the new channel_id".to_owned() } }) + }); + }, + hash_map::Entry::Vacant(e) => { + e.insert(chan); + } + } Ok(funding_msg) } @@ -1604,8 +1633,6 @@ impl ChannelMessageHandler for ChannelManager { hmac: next_hop_data.hmac.clone(), }; - //TODO: Check amt_to_forward and outgoing_cltv_value are within acceptable ranges! - PendingForwardHTLCInfo { onion_packet: Some(outgoing_packet), payment_hash: msg.payment_hash.clone(), @@ -1627,6 +1654,17 @@ impl ChannelMessageHandler for ChannelManager { Some(id) => id.clone(), }; let chan = channel_state.by_id.get_mut(&forwarding_id).unwrap(); + let fee = chan.get_our_fee_base_msat(&*self.fee_estimator) + (pending_forward_info.amt_to_forward * self.fee_proportional_millionths as u64 / 1000000) as u32; + if msg.amount_msat < fee as u64 || (msg.amount_msat - fee as u64) < pending_forward_info.amt_to_forward { + log_debug!(self, "HTLC {} incorrect amount: in {} out {} fee required {}", msg.htlc_id, msg.amount_msat, pending_forward_info.amt_to_forward, fee); + let chan_update = self.get_channel_update(chan).unwrap(); + return_err!("Prior hop has deviated from specified fees parameters or origin node has obsolete ones", 0x1000 | 12, &chan_update.encode_with_len()[..]); + } + if (msg.cltv_expiry as u64) < pending_forward_info.outgoing_cltv_value as u64 + CLTV_EXPIRY_DELTA as u64 { + log_debug!(self, "HTLC {} incorrect CLTV: in {} out {} delta required {}", msg.htlc_id, msg.cltv_expiry, pending_forward_info.outgoing_cltv_value, CLTV_EXPIRY_DELTA); + let chan_update = self.get_channel_update(chan).unwrap(); + return_err!("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", 0x1000 | 13, &chan_update.encode_with_len()[..]); + } if !chan.is_live() { let chan_update = self.get_channel_update(chan).unwrap(); return_err!("Forwarding channel is not in a ready state.", 0x1000 | 7, &chan_update.encode_with_len()[..]); @@ -2173,7 +2211,7 @@ mod tests { static mut CHAN_COUNT: u32 = 0; fn create_chan_between_nodes(node_a: &Node, node_b: &Node) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) { - node_a.node.create_channel(node_b.node.get_our_node_id(), 100000, 42).unwrap(); + node_a.node.create_channel(node_b.node.get_our_node_id(), 100000, 10001, 42).unwrap(); let events_1 = node_a.node.get_and_clear_pending_events(); assert_eq!(events_1.len(), 1);