X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=60c7a6a2bef70801fe08949c623dd18aab599dbe;hb=a0f8c2519b522e7d600946cf5d90f97c2188bc19;hp=6c1f1abbb4b446d38f36a58ef6c6acb6ad8dd878;hpb=b3dd229711bc095645ebbc6b291005e7f8c43895;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 6c1f1abb..60c7a6a2 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -30,7 +30,7 @@ use chain::transaction::OutPoint; use ln::channel::{Channel, ChannelError}; use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, ManyChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY}; use ln::router::Route; -use ln::features::InitFeatures; +use ln::features::{InitFeatures, NodeFeatures}; use ln::msgs; use ln::onion_utils; use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; @@ -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 @@ -357,6 +355,8 @@ pub struct ChannelManager where M::Target: Ma channel_state: Mutex>, our_network_key: SecretKey, + last_node_announcement_serial: AtomicUsize, + /// The bulk of our storage will eventually be here (channels and message queues and the like). /// If we are connected to a peer we always at least have an entry here, even if no channels /// are currently open with that peer. @@ -651,6 +651,8 @@ impl ChannelManager where M::T }), our_network_key: keys_manager.get_node_secret(), + last_node_announcement_serial: AtomicUsize::new(0), + per_peer_state: RwLock::new(HashMap::new()), pending_events: Mutex::new(Vec::new()), @@ -906,22 +908,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 +941,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! @@ -966,8 +977,19 @@ impl ChannelManager where M::T }) } 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,13 +1008,21 @@ 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.short_channel_id, + short_channel_id: short_channel_id, incoming_shared_secret: shared_secret, amt_to_forward: next_hop_data.amt_to_forward, outgoing_cltv_value: next_hop_data.outgoing_cltv_value, @@ -1137,6 +1167,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 had too large size once"}); + } let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, &payment_hash); let _ = self.total_consistency_lock.read().unwrap(); @@ -1285,6 +1318,37 @@ impl ChannelManager where M::T }) } + /// Generates a signed node_announcement from the given arguments and creates a + /// BroadcastNodeAnnouncement event. + /// + /// RGB is a node "color" and alias a printable human-readable string to describe this node to + /// humans. They carry no in-protocol meaning. + /// + /// addresses represent the set (possibly empty) of socket addresses on which this node accepts + /// incoming connections. + pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], addresses: msgs::NetAddressSet) { + let _ = self.total_consistency_lock.read().unwrap(); + + let announcement = msgs::UnsignedNodeAnnouncement { + features: NodeFeatures::supported(), + timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32, + node_id: self.get_our_node_id(), + rgb, alias, + addresses: addresses.to_vec(), + excess_address_data: Vec::new(), + excess_data: Vec::new(), + }; + let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]); + + let mut channel_state = self.channel_state.lock().unwrap(); + channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement { + msg: msgs::NodeAnnouncement { + signature: self.secp_ctx.sign(&msghash, &self.our_network_key), + contents: announcement + }, + }); + } + /// Processes HTLCs which are pending waiting on random forward delay. /// /// Should only really ever be called in response to a PendingHTLCsForwardable event. @@ -2880,6 +2944,7 @@ impl ChannelMessageHandler for &events::MessageSendEvent::SendShutdown { ref node_id, .. } => node_id != their_node_id, &events::MessageSendEvent::SendChannelReestablish { ref node_id, .. } => node_id != their_node_id, &events::MessageSendEvent::BroadcastChannelAnnouncement { .. } => true, + &events::MessageSendEvent::BroadcastNodeAnnouncement { .. } => true, &events::MessageSendEvent::BroadcastChannelUpdate { .. } => true, &events::MessageSendEvent::HandleError { ref node_id, .. } => node_id != their_node_id, &events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => true, @@ -3193,6 +3258,8 @@ impl Writeable for ChannelManager peer_state.latest_features.write(writer)?; } + (self.last_node_announcement_serial.load(Ordering::Acquire) as u32).write(writer)?; + Ok(()) } } @@ -3336,6 +3403,8 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable, M: Deref> R per_peer_state.insert(peer_pubkey, Mutex::new(peer_state)); } + let last_node_announcement_serial: u32 = Readable::read(reader)?; + let channel_manager = ChannelManager { genesis_hash, fee_estimator: args.fee_estimator, @@ -3355,6 +3424,8 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable, M: Deref> R }), our_network_key: args.keys_manager.get_node_secret(), + last_node_announcement_serial: AtomicUsize::new(last_node_announcement_serial as usize), + per_peer_state: RwLock::new(per_peer_state), pending_events: Mutex::new(Vec::new()),