diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index e2cf8ad7542..43957b302f6 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}; @@ -350,6 +350,8 @@ pub struct ChannelManager { channel_state: Mutex>, our_network_key: SecretKey, + last_node_announcement_serial: AtomicUsize, + /// Per-peer state storage. /// Because adding or removing an entry is rare, we usually take an outer read lock and then /// operate on the inner value freely. Sadly, this prevents parallel operation when opening a @@ -645,6 +647,8 @@ impl ChannelManager { }), 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()), @@ -1331,6 +1335,37 @@ impl ChannelManager { }) } + /// 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::our_features(), + 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. @@ -2925,6 +2960,7 @@ impl ChannelMessageHandler for ChannelManager 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, @@ -3238,6 +3274,8 @@ impl Writeable for ChannelManager> ReadableArg 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, @@ -3400,6 +3440,8 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable> ReadableArg }), 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()), diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 4a73aceaaf1..86203017545 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -298,10 +298,33 @@ pub fn create_announced_chan_between_nodes(nodes: &Vec, a: usize, b: usize pub fn create_announced_chan_between_nodes_with_value(nodes: &Vec, a: usize, b: usize, channel_value: u64, push_msat: u64, a_flags: InitFeatures, b_flags: InitFeatures) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) { let chan_announcement = create_chan_between_nodes_with_value(&nodes[a], &nodes[b], channel_value, push_msat, a_flags, b_flags); + + nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], msgs::NetAddressSet::new()); + let a_events = nodes[a].node.get_and_clear_pending_msg_events(); + assert_eq!(a_events.len(), 1); + let a_node_announcement = match a_events[0] { + MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { + (*msg).clone() + }, + _ => panic!("Unexpected event"), + }; + + nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], msgs::NetAddressSet::new()); + let b_events = nodes[b].node.get_and_clear_pending_msg_events(); + assert_eq!(b_events.len(), 1); + let b_node_announcement = match b_events[0] { + MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { + (*msg).clone() + }, + _ => panic!("Unexpected event"), + }; + for node in nodes { assert!(node.router.handle_channel_announcement(&chan_announcement.0).unwrap()); node.router.handle_channel_update(&chan_announcement.1).unwrap(); node.router.handle_channel_update(&chan_announcement.2).unwrap(); + node.router.handle_node_announcement(&a_node_announcement).unwrap(); + node.router.handle_node_announcement(&b_node_announcement).unwrap(); } (chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4) } diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 34146ebcf8b..4fa697907ac 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -133,6 +133,14 @@ impl Peer { InitSyncTracker::NodesSyncing(_) => true, } } + + fn should_forward_node(&self, node_id: PublicKey) -> bool { + match self.sync_status { + InitSyncTracker::NoSyncRequested => true, + InitSyncTracker::ChannelsSyncing(_) => false, + InitSyncTracker::NodesSyncing(pk) => pk < node_id, + } + } } struct PeerHolder { @@ -997,6 +1005,21 @@ impl PeerManager { } } }, + MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { + log_trace!(self, "Handling BroadcastNodeAnnouncement event in peer_handler"); + if self.message_handler.route_handler.handle_node_announcement(msg).is_ok() { + let encoded_msg = encode_msg!(msg, 257); + + for (ref descriptor, ref mut peer) in peers.peers.iter_mut() { + if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() || + !peer.should_forward_node(msg.contents.node_id) { + continue + } + peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_msg[..])); + self.do_attempt_write_data(&mut (*descriptor).clone(), peer); + } + } + }, MessageSendEvent::BroadcastChannelUpdate { ref msg } => { log_trace!(self, "Handling BroadcastChannelUpdate event in peer_handler for short channel id {}", msg.contents.short_channel_id); if self.message_handler.route_handler.handle_channel_update(msg).is_ok() { diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index e810368dbc3..8b6140c61c7 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -194,12 +194,20 @@ pub enum MessageSendEvent { }, /// Used to indicate that a channel_announcement and channel_update should be broadcast to all /// peers (except the peer with node_id either msg.contents.node_id_1 or msg.contents.node_id_2). + /// + /// Note that after doing so, you very likely (unless you did so very recently) want to call + /// ChannelManager::broadcast_node_announcement to trigger a BroadcastNodeAnnouncement event. BroadcastChannelAnnouncement { /// The channel_announcement which should be sent. msg: msgs::ChannelAnnouncement, /// The followup channel_update which should be sent. update_msg: msgs::ChannelUpdate, }, + /// Used to indicate that a node_announcement should be broadcast to all peers. + BroadcastNodeAnnouncement { + /// The node_announcement which should be sent. + msg: msgs::NodeAnnouncement, + }, /// Used to indicate that a channel_update should be broadcast to all peers. BroadcastChannelUpdate { /// The channel_update which should be sent.