From: Matt Corallo Date: Fri, 3 Jan 2020 01:32:37 +0000 (-0500) Subject: Add ability to broadcast our own node_announcement. X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=0f3acf4a8487eb8bf5046069f98ace90fe9d845a;p=rust-lightning Add ability to broadcast our own node_announcement. This is a somewhat-obvious oversight in the capabilities of rust-lightning, though not a particularly interesting one until we start relying on node_features (eg for variable-length-onions and Base AMP). Sadly its not fully automated as we don't really want to store the list of available addresses from the user. However, with a simple call to ChannelManager::broadcast_node_announcement and a sensible peer_handler, the announcement is made. --- diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5f7e903fd..784173e13 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -29,8 +29,8 @@ use chain::chaininterface::{BroadcasterInterface,ChainListener,FeeEstimator}; 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::features::{InitFeatures, NodeFeatures}; use ln::router::Route; -use ln::features::InitFeatures; use ln::msgs; use ln::onion_utils; use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; @@ -368,6 +368,10 @@ pub struct ChannelManager>, our_network_key: SecretKey, + /// Used to track the last value sent in a node_announcement "timestamp" field. We just set + /// them to be monotonically increasing since we don't assume access to a time source. + 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. @@ -665,6 +669,8 @@ impl ChannelMan }), 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()), @@ -1334,6 +1340,39 @@ impl ChannelMan }) } + /// Generates a signed node_announcement from the given arguments and creates a + /// BroadcastNodeAnnouncement event. + /// + /// RGB is a node "color" and alias ia 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. These will be broadcast to the network, publicly tying these + /// addresses together. If you wish to preserve user privacy, addresses should likely contain + /// only Tor Onion addresses. + 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.into_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. @@ -2970,6 +3009,7 @@ impl 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, @@ -3288,6 +3328,8 @@ impl(nodes: &'a Vec(nodes: &'a 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 c533d46a0..6d1e8e7f0 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -140,6 +140,15 @@ impl Peer { InitSyncTracker::NodesSyncing(_) => true, } } + + /// Similar to the above, but for node announcements indexed by node_id. + 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 { @@ -975,6 +984,21 @@ impl PeerManager where } } }, + 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); + + 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 5fb70f654..2e568263c 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -278,12 +278,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.