X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=015894e594dc1246efecef452d312171eed099ba;hb=2f346414ade972ca54705cf9ed774a24151144de;hp=a59b85b6e5a6364fa1fe558facbbe664eeefc19f;hpb=4fa6d966dfc1106ca096dc455bb115806ee0f4b1;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index a59b85b6..015894e5 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -38,21 +38,19 @@ use chain::keysinterface::{ChannelKeys, KeysInterface, InMemoryChannelKeys}; use util::config::UserConfig; use util::{byte_utils, events}; use util::ser::{Readable, ReadableArgs, Writeable, Writer}; -use util::chacha20::ChaCha20; +use util::chacha20::{ChaCha20, ChaChaReader}; use util::logger::Logger; use util::errors::APIError; use std::{cmp, mem}; use std::collections::{HashMap, hash_map, HashSet}; -use std::io::Cursor; +use std::io::{Cursor, Read}; use std::sync::{Arc, Mutex, MutexGuard, RwLock}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; use std::marker::{Sync, Send}; use std::ops::Deref; -const SIXTY_FIVE_ZEROS: [u8; 65] = [0; 65]; - // We hold various information about HTLC relay in the HTLC objects in Channel itself: // // Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should @@ -196,7 +194,7 @@ impl MsgHandleErrInternal { } } #[inline] - fn from_chan_no_close(err: ChannelError, channel_id: [u8; 32]) -> Self { + fn from_chan_no_close(err: ChannelError, channel_id: [u8; 32]) -> Self { Self { err: match err { ChannelError::Ignore(msg) => LightningError { @@ -337,7 +335,7 @@ pub type SimpleRefChannelManager<'a, M> = ChannelManager where M::Target: ManyChannelMonitor { +pub struct ChannelManager where M::Target: ManyChannelMonitor { default_configuration: UserConfig, genesis_hash: Sha256dHash, fee_estimator: Arc, @@ -479,7 +477,7 @@ macro_rules! break_chan_entry { match $res { Ok(res) => res, Err(ChannelError::Ignore(msg)) => { - break Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $entry.key().clone())) + break Err(MsgHandleErrInternal::from_chan_no_close::(ChannelError::Ignore(msg), $entry.key().clone())) }, Err(ChannelError::Close(msg)) => { log_trace!($self, "Closing channel {} due to Close-required error: {}", log_bytes!($entry.key()[..]), msg); @@ -499,7 +497,7 @@ macro_rules! try_chan_entry { match $res { Ok(res) => res, Err(ChannelError::Ignore(msg)) => { - return Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $entry.key().clone())) + return Err(MsgHandleErrInternal::from_chan_no_close::(ChannelError::Ignore(msg), $entry.key().clone())) }, Err(ChannelError::Close(msg)) => { log_trace!($self, "Closing channel {} due to Close-required error: {}", log_bytes!($entry.key()[..]), msg); @@ -516,7 +514,7 @@ macro_rules! try_chan_entry { $channel_state.short_to_id.remove(&short_id); } if let Some(update) = update { - if let Err(e) = $self.monitor.add_update_monitor(update.get_funding_txo().unwrap(), update) { + if let Err(e) = $self.monitor.add_update_monitor(update.get_funding_txo().unwrap(), update.clone()) { match e { // Upstream channel is dead, but we want at least to fail backward HTLCs to save // downstream channels. In case of PermanentFailure, we are not going to be able @@ -582,7 +580,7 @@ macro_rules! handle_monitor_err { debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst || !$resend_commitment); } $entry.get_mut().monitor_update_failed($resend_raa, $resend_commitment, $failed_forwards, $failed_fails); - Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore("Failed to update ChannelMonitor"), *$entry.key())) + Err(MsgHandleErrInternal::from_chan_no_close::(ChannelError::Ignore("Failed to update ChannelMonitor"), *$entry.key())) }, } } @@ -609,7 +607,7 @@ macro_rules! maybe_break_monitor_err { } } -impl ChannelManager where M::Target: ManyChannelMonitor { +impl ChannelManager where M::Target: ManyChannelMonitor { /// Constructs a new ChannelManager to hold several channels and route between them. /// /// This is the main "logic hub" for all channel-related actions, and implements @@ -906,22 +904,30 @@ impl ChannelManager where M::T } let mut chacha = ChaCha20::new(&rho, &[0u8; 8]); - let next_hop_data = { - let mut decoded = [0; 65]; - chacha.process(&msg.onion_routing_packet.hop_data[0..65], &mut decoded); - match msgs::OnionHopData::read(&mut Cursor::new(&decoded[..])) { + let mut chacha_stream = ChaChaReader { chacha: &mut chacha, read: Cursor::new(&msg.onion_routing_packet.hop_data[..]) }; + let (next_hop_data, next_hop_hmac) = { + match msgs::OnionHopData::read(&mut chacha_stream) { Err(err) => { let error_code = match err { msgs::DecodeError::UnknownVersion => 0x4000 | 1, // unknown realm byte + msgs::DecodeError::UnknownRequiredFeature| + msgs::DecodeError::InvalidValue| + msgs::DecodeError::ShortRead => 0x4000 | 22, // invalid_onion_payload _ => 0x2000 | 2, // Should never happen }; return_err!("Unable to decode our hop data", error_code, &[0;0]); }, - Ok(msg) => msg + Ok(msg) => { + let mut hmac = [0; 32]; + if let Err(_) = chacha_stream.read_exact(&mut hmac[..]) { + return_err!("Unable to decode hop data", 0x4000 | 22, &[0;0]); + } + (msg, hmac) + }, } }; - let pending_forward_info = if next_hop_data.hmac == [0; 32] { + let pending_forward_info = if next_hop_hmac == [0; 32] { #[cfg(test)] { // In tests, make sure that the initial onion pcket data is, at least, non-0. @@ -931,10 +937,11 @@ impl ChannelManager where M::T // as-is (and were originally 0s). // Of course reverse path calculation is still pretty easy given naive routing // algorithms, but this fixes the most-obvious case. - let mut new_packet_data = [0; 19*65]; - chacha.process(&msg.onion_routing_packet.hop_data[65..], &mut new_packet_data[0..19*65]); - assert_ne!(new_packet_data[0..65], [0; 65][..]); - assert_ne!(new_packet_data[..], [0; 19*65][..]); + let mut next_bytes = [0; 32]; + chacha_stream.read_exact(&mut next_bytes).unwrap(); + assert_ne!(next_bytes[..], [0; 32][..]); + chacha_stream.read_exact(&mut next_bytes).unwrap(); + assert_ne!(next_bytes[..], [0; 32][..]); } // OUR PAYMENT! @@ -943,11 +950,11 @@ impl ChannelManager where M::T return_err!("The final CLTV expiry is too soon to handle", 17, &[0;0]); } // final_incorrect_htlc_amount - if next_hop_data.data.amt_to_forward > msg.amount_msat { + if next_hop_data.amt_to_forward > msg.amount_msat { return_err!("Upstream node sent less than we were supposed to receive in payment", 19, &byte_utils::be64_to_array(msg.amount_msat)); } // final_incorrect_cltv_expiry - if next_hop_data.data.outgoing_cltv_value != msg.cltv_expiry { + if next_hop_data.outgoing_cltv_value != msg.cltv_expiry { return_err!("Upstream node set CLTV to the wrong value", 18, &byte_utils::be32_to_array(msg.cltv_expiry)); } @@ -961,13 +968,24 @@ impl ChannelManager where M::T payment_hash: msg.payment_hash.clone(), short_channel_id: 0, incoming_shared_secret: shared_secret, - amt_to_forward: next_hop_data.data.amt_to_forward, - outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value, + amt_to_forward: next_hop_data.amt_to_forward, + outgoing_cltv_value: next_hop_data.outgoing_cltv_value, }) } else { let mut new_packet_data = [0; 20*65]; - chacha.process(&msg.onion_routing_packet.hop_data[65..], &mut new_packet_data[0..19*65]); - chacha.process(&SIXTY_FIVE_ZEROS[..], &mut new_packet_data[19*65..]); + let read_pos = chacha_stream.read(&mut new_packet_data).unwrap(); + #[cfg(debug_assertions)] + { + // Check two things: + // a) that the behavior of our stream here will return Ok(0) even if the TLV + // read above emptied out our buffer and the unwrap() wont needlessly panic + // b) that we didn't somehow magically end up with extra data. + let mut t = [0; 1]; + debug_assert!(chacha_stream.read(&mut t).unwrap() == 0); + } + // Once we've emptied the set of bytes our peer gave us, encrypt 0 bytes until we + // fill the onion hop data we'll forward to our next-hop peer. + chacha_stream.chacha.process_in_place(&mut new_packet_data[read_pos..]); let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap(); @@ -986,16 +1004,24 @@ impl ChannelManager where M::T version: 0, public_key, hop_data: new_packet_data, - hmac: next_hop_data.hmac.clone(), + hmac: next_hop_hmac.clone(), + }; + + let short_channel_id = match next_hop_data.format { + msgs::OnionHopDataFormat::Legacy { short_channel_id } => short_channel_id, + msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id, + msgs::OnionHopDataFormat::FinalNode => { + return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0;0]); + }, }; PendingHTLCStatus::Forward(PendingForwardHTLCInfo { onion_packet: Some(outgoing_packet), payment_hash: msg.payment_hash.clone(), - short_channel_id: next_hop_data.data.short_channel_id, + short_channel_id: short_channel_id, incoming_shared_secret: shared_secret, - amt_to_forward: next_hop_data.data.amt_to_forward, - outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value, + amt_to_forward: next_hop_data.amt_to_forward, + outgoing_cltv_value: next_hop_data.outgoing_cltv_value, }) }; @@ -1137,6 +1163,9 @@ impl ChannelManager where M::T let onion_keys = secp_call!(onion_utils::construct_onion_keys(&self.secp_ctx, &route, &session_priv), APIError::RouteError{err: "Pubkey along hop was maliciously selected"}); let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height)?; + if onion_utils::route_size_insane(&onion_payloads) { + return Err(APIError::RouteError{err: "Route size too large considering onion data"}); + } let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, &payment_hash); let _ = self.total_consistency_lock.read().unwrap(); @@ -1268,7 +1297,10 @@ impl ChannelManager where M::T } fn get_announcement_sigs(&self, chan: &Channel) -> Option { - if !chan.should_announce() { return None } + if !chan.should_announce() { + log_trace!(self, "Can't send announcement_signatures for private channel {}", log_bytes!(chan.channel_id())); + return None + } let (announcement, our_bitcoin_sig) = match chan.get_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone()) { Ok(res) => res, @@ -1984,6 +2016,7 @@ impl ChannelManager where M::T } try_chan_entry!(self, chan.get_mut().funding_locked(&msg), channel_state, chan); if let Some(announcement_sigs) = self.get_announcement_sigs(chan.get()) { + log_trace!(self, "Sending announcement_signatures for {} in response to funding_locked", log_bytes!(chan.get().channel_id())); // If we see locking block before receiving remote funding_locked, we broadcast our // announcement_sigs at remote funding_locked reception. If we receive remote // funding_locked before seeing locking block, we broadcast our announcement_sigs at locking @@ -2196,7 +2229,8 @@ impl ChannelManager where M::T return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id)); } if (msg.failure_code & 0x8000) == 0 { - try_chan_entry!(self, Err(ChannelError::Close("Got update_fail_malformed_htlc with BADONION not set")), channel_state, chan); + let chan_err: ChannelError = ChannelError::Close("Got update_fail_malformed_htlc with BADONION not set"); + try_chan_entry!(self, Err(chan_err), channel_state, chan); } try_chan_entry!(self, chan.get_mut().update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() }), channel_state, chan); Ok(()) @@ -2361,7 +2395,8 @@ impl ChannelManager where M::T let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]); if self.secp_ctx.verify(&msghash, &msg.node_signature, if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 }).is_err() || self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 }).is_err() { - try_chan_entry!(self, Err(ChannelError::Close("Bad announcement_signatures node_signature")), channel_state, chan); + let chan_err: ChannelError = ChannelError::Close("Bad announcement_signatures node_signature"); + try_chan_entry!(self, Err(chan_err), channel_state, chan); } let our_node_sig = self.secp_ctx.sign(&msghash, &self.our_network_key); @@ -2507,7 +2542,7 @@ impl ChannelManager where M::T } } -impl events::MessageSendEventsProvider for ChannelManager where M::Target: ManyChannelMonitor { +impl events::MessageSendEventsProvider for ChannelManager where M::Target: ManyChannelMonitor { fn get_and_clear_pending_msg_events(&self) -> Vec { // TODO: Event release to users and serialization is currently race-y: it's very easy for a // user to serialize a ChannelManager with pending events in it and lose those events on @@ -2532,7 +2567,7 @@ impl events::MessageSendEventsProvider for Ch } } -impl events::EventsProvider for ChannelManager where M::Target: ManyChannelMonitor { +impl events::EventsProvider for ChannelManager where M::Target: ManyChannelMonitor { fn get_and_clear_pending_events(&self) -> Vec { // TODO: Event release to users and serialization is currently race-y: it's very easy for a // user to serialize a ChannelManager with pending events in it and lose those events on @@ -2557,7 +2592,7 @@ impl events::EventsProvider for ChannelManage } } -impl ChainListener for ChannelManager where M::Target: ManyChannelMonitor { +impl ChainListener for ChannelManager where M::Target: ManyChannelMonitor { fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) { let header_hash = header.bitcoin_hash(); log_trace!(self, "Block {} at height {} connected with {} txn matched", header_hash, height, txn_matched.len()); @@ -2576,10 +2611,13 @@ impl ChainListener for ChannelM msg: funding_locked, }); if let Some(announcement_sigs) = self.get_announcement_sigs(channel) { + log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id())); pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures { node_id: channel.get_their_node_id(), msg: announcement_sigs, }); + } else { + log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id())); } short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id()); } else if let Err(e) = chan_res { @@ -2671,7 +2709,7 @@ impl ChainListener for ChannelM } } -impl ChannelMessageHandler for ChannelManager where M::Target: ManyChannelMonitor { +impl ChannelMessageHandler for ChannelManager where M::Target: ManyChannelMonitor { fn handle_open_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel) { let _ = self.total_consistency_lock.read().unwrap(); let res = self.internal_open_channel(their_node_id, their_features, msg); @@ -3141,7 +3179,7 @@ impl Readable for HTLCForwardInfo { } } -impl Writeable for ChannelManager where M::Target: ManyChannelMonitor { +impl Writeable for ChannelManager where M::Target: ManyChannelMonitor { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { let _ = self.total_consistency_lock.write().unwrap(); @@ -3212,7 +3250,7 @@ impl Writeable for ChannelManager /// 5) Move the ChannelMonitors into your local ManyChannelMonitor. /// 6) Disconnect/connect blocks on the ChannelManager. /// 7) Register the new ChannelManager with your ChainWatchInterface. -pub struct ChannelManagerReadArgs<'a, ChanSigner: ChannelKeys, M: Deref> where M::Target: ManyChannelMonitor { +pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref> where M::Target: ManyChannelMonitor { /// The keys provider which will give us relevant keys. Some keys will be loaded during /// deserialization. pub keys_manager: Arc>, @@ -3249,10 +3287,10 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: ChannelKeys, M: Deref> where M /// /// In such cases the latest local transactions will be sent to the tx_broadcaster included in /// this struct. - pub channel_monitors: &'a mut HashMap, + pub channel_monitors: &'a mut HashMap>, } -impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable, M: Deref> ReadableArgs> for (Sha256dHash, ChannelManager) where M::Target: ManyChannelMonitor { +impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable, M: Deref> ReadableArgs> for (Sha256dHash, ChannelManager) where M::Target: ManyChannelMonitor { fn read(reader: &mut R, args: ChannelManagerReadArgs<'a, ChanSigner, M>) -> Result { let _ver: u8 = Readable::read(reader)?; let min_ver: u8 = Readable::read(reader)?; @@ -3272,7 +3310,7 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable, M: Deref> R let mut short_to_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); for _ in 0..channel_count { let mut channel: Channel = ReadableArgs::read(reader, args.logger.clone())?; - if channel.last_block_connected != last_block_hash { + if channel.last_block_connected != Default::default() && channel.last_block_connected != last_block_hash { return Err(DecodeError::InvalidValue); }