Broadcast node_announcements regularly.
authorMatt Corallo <git@bluematt.me>
Wed, 5 May 2021 02:47:42 +0000 (02:47 +0000)
committerMatt Corallo <git@bluematt.me>
Mon, 10 May 2021 19:18:40 +0000 (19:18 +0000)
README.md
src/cli.rs
src/main.rs

index 5dda263e31da6b421623d87ebaa0c47e8e2a2876..5b42054f191c5d9083d6c961ee13dfd153e00edd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ git clone git@github.com:lightningdevkit/ldk-sample.git
 ## Usage
 ```
 cd ldk-sample
-cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> <ldk_storage_directory_path> [<ldk-peer-listening-port>] [bitcoin-network]
+cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> <ldk_storage_directory_path> [<ldk-peer-listening-port>] [bitcoin-network] [announced-listen-addr announced-node-name]
 ```
 `bitcoind`'s RPC username and password likely can be found through `cat ~/.bitcoin/.cookie`.
 
@@ -17,6 +17,10 @@ cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<b
 
 `ldk-peer-listening-port`: defaults to 9735.
 
+`announced-listen-addr` and `announced-node-name`: default to nothing, disabling any public announcements of this node.
+`announced-listen-addr` can be set to an IPv4 or IPv6 address to announce that as a publicly-connectable address for this node.
+`announced-node-name` can be any string up to 32 bytes in length, representing this node's alias.
+
 ## License
 
 Licensed under either:
index 34987a8bc4f3e32ad10182fe89923dde627527f9..f762fe5e5d8f1bc322cd69687b953c7ef3291703 100644 (file)
@@ -9,6 +9,7 @@ use bitcoin::secp256k1::key::PublicKey;
 use lightning::chain;
 use lightning::chain::keysinterface::KeysManager;
 use lightning::ln::features::InvoiceFeatures;
+use lightning::ln::msgs::NetAddress;
 use lightning::ln::{PaymentHash, PaymentSecret};
 use lightning::routing::network_graph::NetGraphMsgHandler;
 use lightning::routing::router;
@@ -18,7 +19,7 @@ use lightning_invoice::{utils, Currency, Invoice};
 use std::env;
 use std::io;
 use std::io::{BufRead, Write};
-use std::net::{SocketAddr, ToSocketAddrs};
+use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
 use std::ops::Deref;
 use std::path::Path;
 use std::str::FromStr;
@@ -33,12 +34,14 @@ pub(crate) struct LdkUserInfo {
        pub(crate) bitcoind_rpc_host: String,
        pub(crate) ldk_storage_dir_path: String,
        pub(crate) ldk_peer_listening_port: u16,
+       pub(crate) ldk_announced_listen_addr: Option<NetAddress>,
+       pub(crate) ldk_announced_node_name: [u8; 32],
        pub(crate) network: Network,
 }
 
 pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
        if env::args().len() < 3 {
-               println!("ldk-tutorial-node requires 3 arguments: `cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> ldk_storage_directory_path [<ldk-incoming-peer-listening-port>] [bitcoin-network]`");
+               println!("ldk-tutorial-node requires 3 arguments: `cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> ldk_storage_directory_path [<ldk-incoming-peer-listening-port>] [bitcoin-network] [announced-listen-addr announced-node-name]`");
                return Err(());
        }
        let bitcoind_rpc_info = env::args().skip(1).next().unwrap();
@@ -84,6 +87,32 @@ pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
                Some(_) => panic!("Unsupported network provided. Options are: `regtest`, `testnet`"),
                None => Network::Testnet,
        };
+
+       let ldk_announced_listen_addr = match env::args().skip(arg_idx + 1).next().as_ref() {
+               Some(s) => match IpAddr::from_str(s) {
+                       Ok(IpAddr::V4(a)) => {
+                               Some(NetAddress::IPv4 { addr: a.octets(), port: ldk_peer_listening_port })
+                       }
+                       Ok(IpAddr::V6(a)) => {
+                               Some(NetAddress::IPv6 { addr: a.octets(), port: ldk_peer_listening_port })
+                       }
+                       Err(_) => panic!("Failed to parse announced-listen-addr into an IP address"),
+               },
+               None => None,
+       };
+
+       let ldk_announced_node_name = match env::args().skip(arg_idx + 2).next().as_ref() {
+               Some(s) => {
+                       if s.len() > 32 {
+                               panic!("Node Alias can not be longer than 32 bytes");
+                       }
+                       let mut bytes = [0; 32];
+                       bytes[..s.len()].copy_from_slice(s.as_bytes());
+                       bytes
+               }
+               None => [0; 32],
+       };
+
        Ok(LdkUserInfo {
                bitcoind_rpc_username,
                bitcoind_rpc_password,
@@ -91,6 +120,8 @@ pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
                bitcoind_rpc_port,
                ldk_storage_dir_path,
                ldk_peer_listening_port,
+               ldk_announced_listen_addr,
+               ldk_announced_node_name,
                network,
        })
 }
index f51528b7b57832b3caf279b2f7fd856b6377de87..31fb84eeebeb8e79f19602b41b12fec47558bc1f 100644 (file)
@@ -577,6 +577,26 @@ async fn start_ldk() {
                Err(e) => println!("ERROR: errored reading channel peer info from disk: {:?}", e),
        }
 
+       // Regularly broadcast our node_announcement. This is only required (or possible) if we have
+       // some public channels, and is only useful if we have public listen address(es) to announce.
+       // In a production environment, this should occur only after the announcement of new channels
+       // to avoid churn in the global network graph.
+       let chan_manager = Arc::clone(&channel_manager);
+       let network = args.network;
+       if args.ldk_announced_listen_addr.is_some() {
+               tokio::spawn(async move {
+                       let mut interval = tokio::time::interval(Duration::from_secs(60));
+                       loop {
+                               interval.tick().await;
+                               chan_manager.broadcast_node_announcement(
+                                       [0; 3],
+                                       args.ldk_announced_node_name,
+                                       vec![args.ldk_announced_listen_addr.as_ref().unwrap().clone()],
+                               );
+                       }
+               });
+       }
+
        // Start the CLI.
        cli::poll_for_user_input(
                peer_manager.clone(),
@@ -588,7 +608,7 @@ async fn start_ldk() {
                event_ntfn_sender,
                ldk_data_dir.clone(),
                logger.clone(),
-               args.network,
+               network,
        )
        .await;
 }