Merge pull request #51 from jkczyz/2022-03-ldk-106
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Mon, 4 Apr 2022 20:09:44 +0000 (20:09 +0000)
committerGitHub <noreply@github.com>
Mon, 4 Apr 2022 20:09:44 +0000 (20:09 +0000)
Update to LDK 0.0.106

src/bitcoind_client.rs
src/cli.rs
src/hex_utils.rs
src/main.rs

index 0b37ac34823e9c44dc62135141170c9cc375714b..15ee8cf9b696dbbbccbf3db8abc76415934cdcab 100644 (file)
@@ -265,6 +265,7 @@ impl BroadcasterInterface for BitcoindClient {
                                        if !err_str.contains("Transaction already in block chain")
                                                && !err_str.contains("Inputs missing or spent")
                                                && !err_str.contains("bad-txns-inputs-missingorspent")
+                                               && !err_str.contains("txn-mempool-conflict")
                                                && !err_str.contains("non-BIP68-final")
                                                && !err_str.contains("insufficient fee, rejecting replacement ")
                                        {
index c7dffd280b3bbc3a74119bd09f1dd9ec669ed809..681714f17936093dc218c4411df1bce0b27b5b97 100644 (file)
@@ -11,6 +11,7 @@ use bitcoin::secp256k1::key::PublicKey;
 use lightning::chain::keysinterface::{KeysInterface, KeysManager, Recipient};
 use lightning::ln::msgs::NetAddress;
 use lightning::ln::{PaymentHash, PaymentPreimage};
+use lightning::routing::network_graph::{NetworkGraph, NodeId};
 use lightning::util::config::{ChannelConfig, ChannelHandshakeLimits, UserConfig};
 use lightning::util::events::EventHandler;
 use lightning_invoice::payment::PaymentError;
@@ -141,8 +142,8 @@ pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
 pub(crate) async fn poll_for_user_input<E: EventHandler>(
        invoice_payer: Arc<InvoicePayer<E>>, peer_manager: Arc<PeerManager>,
        channel_manager: Arc<ChannelManager>, keys_manager: Arc<KeysManager>,
-       inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage,
-       ldk_data_dir: String, network: Network,
+       network_graph: Arc<NetworkGraph>, inbound_payments: PaymentInfoStorage,
+       outbound_payments: PaymentInfoStorage, ldk_data_dir: String, network: Network,
 ) {
        println!("LDK startup successful. To view available commands: \"help\".");
        println!("LDK logs are available at <your-supplied-ldk-data-dir-path>/.ldk/logs");
@@ -309,7 +310,7 @@ pub(crate) async fn poll_for_user_input<E: EventHandler>(
                                                println!("SUCCESS: connected to peer {}", pubkey);
                                        }
                                }
-                               "listchannels" => list_channels(channel_manager.clone()),
+                               "listchannels" => list_channels(&channel_manager, &network_graph),
                                "listpayments" => {
                                        list_payments(inbound_payments.clone(), outbound_payments.clone())
                                }
@@ -320,8 +321,8 @@ pub(crate) async fn poll_for_user_input<E: EventHandler>(
                                                continue;
                                        }
                                        let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
-                                       if channel_id_vec.is_none() {
-                                               println!("ERROR: couldn't parse channel_id as hex");
+                                       if channel_id_vec.is_none() || channel_id_vec.as_ref().unwrap().len() != 32 {
+                                               println!("ERROR: couldn't parse channel_id");
                                                continue;
                                        }
                                        let mut channel_id = [0; 32];
@@ -335,15 +336,15 @@ pub(crate) async fn poll_for_user_input<E: EventHandler>(
                                                continue;
                                        }
                                        let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
-                                       if channel_id_vec.is_none() {
-                                               println!("ERROR: couldn't parse channel_id as hex");
+                                       if channel_id_vec.is_none() || channel_id_vec.as_ref().unwrap().len() != 32 {
+                                               println!("ERROR: couldn't parse channel_id");
                                                continue;
                                        }
                                        let mut channel_id = [0; 32];
                                        channel_id.copy_from_slice(&channel_id_vec.unwrap());
                                        force_close_channel(channel_id, channel_manager.clone());
                                }
-                               "nodeinfo" => node_info(channel_manager.clone(), peer_manager.clone()),
+                               "nodeinfo" => node_info(&channel_manager, &peer_manager),
                                "listpeers" => list_peers(peer_manager.clone()),
                                "signmessage" => {
                                        const MSG_STARTPOS: usize = "signmessage".len() + 1;
@@ -379,16 +380,13 @@ fn help() {
        println!("signmessage <message>");
 }
 
-fn node_info(channel_manager: Arc<ChannelManager>, peer_manager: Arc<PeerManager>) {
+fn node_info(channel_manager: &Arc<ChannelManager>, peer_manager: &Arc<PeerManager>) {
        println!("\t{{");
        println!("\t\t node_pubkey: {}", channel_manager.get_our_node_id());
        let chans = channel_manager.list_channels();
        println!("\t\t num_channels: {}", chans.len());
        println!("\t\t num_usable_channels: {}", chans.iter().filter(|c| c.is_usable).count());
-       let local_balance_msat = chans
-               .iter()
-               .map(|c| c.unspendable_punishment_reserve.unwrap_or(0) * 1000 + c.outbound_capacity_msat)
-               .sum::<u64>();
+       let local_balance_msat = chans.iter().map(|c| c.balance_msat).sum::<u64>();
        println!("\t\t local_balance_msat: {}", local_balance_msat);
        println!("\t\t num_peers: {}", peer_manager.get_peer_node_ids().len());
        println!("\t}},");
@@ -402,7 +400,20 @@ fn list_peers(peer_manager: Arc<PeerManager>) {
        println!("\t}},");
 }
 
-fn list_channels(channel_manager: Arc<ChannelManager>) {
+/// Takes some untrusted bytes and returns a sanitized string that is safe to print
+fn sanitize_string(bytes: &[u8]) -> String {
+       let mut ret = String::with_capacity(bytes.len());
+       // We should really support some sane subset of UTF-8 here, but limiting to printable ASCII
+       // instead makes this trivial.
+       for b in bytes {
+               if *b >= 0x20 && *b <= 0x7e {
+                       ret.push(*b as char);
+               }
+       }
+       ret
+}
+
+fn list_channels(channel_manager: &Arc<ChannelManager>, network_graph: &Arc<NetworkGraph>) {
        print!("[");
        for chan_info in channel_manager.list_channels() {
                println!("");
@@ -411,20 +422,27 @@ fn list_channels(channel_manager: Arc<ChannelManager>) {
                if let Some(funding_txo) = chan_info.funding_txo {
                        println!("\t\tfunding_txid: {},", funding_txo.txid);
                }
+
                println!(
                        "\t\tpeer_pubkey: {},",
                        hex_utils::hex_str(&chan_info.counterparty.node_id.serialize())
                );
+               if let Some(node_info) = network_graph
+                       .read_only()
+                       .nodes()
+                       .get(&NodeId::from_pubkey(&chan_info.counterparty.node_id))
+               {
+                       if let Some(announcement) = &node_info.announcement_info {
+                               println!("\t\tpeer_alias: {}", sanitize_string(&announcement.alias));
+                       }
+               }
+
                if let Some(id) = chan_info.short_channel_id {
                        println!("\t\tshort_channel_id: {},", id);
                }
                println!("\t\tis_confirmed_onchain: {},", chan_info.is_funding_locked);
                println!("\t\tchannel_value_satoshis: {},", chan_info.channel_value_satoshis);
-               println!(
-                       "\t\tlocal_balance_msat: {},",
-                       chan_info.outbound_capacity_msat
-                               + chan_info.unspendable_punishment_reserve.unwrap_or(0) * 1000
-               );
+               println!("\t\tlocal_balance_msat: {},", chan_info.balance_msat);
                if chan_info.is_usable {
                        println!("\t\tavailable_balance_for_send_msat: {},", chan_info.outbound_capacity_msat);
                        println!("\t\tavailable_balance_for_recv_msat: {},", chan_info.inbound_capacity_msat);
index 70fe28b13f30d8c5cf13ae3c6257bc3f3ece701c..0eee5af03beaa7938f8fd60a54765a79362d6b6b 100644 (file)
@@ -31,6 +31,9 @@ pub fn hex_str(value: &[u8]) -> String {
 }
 
 pub fn to_compressed_pubkey(hex: &str) -> Option<PublicKey> {
+       if hex.len() != 33 * 2 {
+               return None;
+       }
        let data = match to_vec(&hex[0..33 * 2]) {
                Some(bytes) => bytes,
                None => return None,
index 07afa66436164c15b0b5af0e018fc8135549d917..f48a11897b825457a4a3faf1bc7fbd471bb0875e 100644 (file)
@@ -48,6 +48,7 @@ use std::io;
 use std::io::Write;
 use std::ops::Deref;
 use std::path::Path;
+use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, Mutex};
 use std::time::{Duration, SystemTime};
 
@@ -542,6 +543,8 @@ async fn start_ldk() {
 
        let peer_manager_connection_handler = peer_manager.clone();
        let listening_port = args.ldk_peer_listening_port;
+       let stop_listen = Arc::new(AtomicBool::new(false));
+       let stop_listen_ref = Arc::clone(&stop_listen);
        tokio::spawn(async move {
                let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", listening_port))
                        .await
@@ -549,6 +552,9 @@ async fn start_ldk() {
                loop {
                        let peer_mgr = peer_manager_connection_handler.clone();
                        let tcp_stream = listener.accept().await.unwrap().0;
+                       if stop_listen_ref.load(Ordering::Acquire) {
+                               return;
+                       }
                        tokio::spawn(async move {
                                lightning_net_tokio::setup_inbound(
                                        peer_mgr.clone(),
@@ -709,10 +715,11 @@ async fn start_ldk() {
 
        // Start the CLI.
        cli::poll_for_user_input(
-               invoice_payer.clone(),
-               peer_manager.clone(),
-               channel_manager.clone(),
-               keys_manager.clone(),
+               Arc::clone(&invoice_payer),
+               Arc::clone(&peer_manager),
+               Arc::clone(&channel_manager),
+               Arc::clone(&keys_manager),
+               Arc::clone(&network_graph),
                inbound_payments,
                outbound_payments,
                ldk_data_dir.clone(),
@@ -720,6 +727,11 @@ async fn start_ldk() {
        )
        .await;
 
+       // Disconnect our peers and stop accepting new connections. This ensures we don't continue
+       // updating our channel data after we've stopped the background processor.
+       stop_listen.store(true, Ordering::Release);
+       peer_manager.disconnect_all_peers();
+
        // Stop the background processor.
        background_processor.stop().unwrap();
 }