Add Signet support
[ldk-sample] / src / cli.rs
1 use crate::disk;
2 use crate::hex_utils;
3 use crate::{
4         ChannelManager, FilesystemLogger, HTLCStatus, InvoicePayer, MillisatAmount, PaymentInfo,
5         PaymentInfoStorage, PeerManager,
6 };
7 use bitcoin::hashes::Hash;
8 use bitcoin::network::constants::Network;
9 use bitcoin::secp256k1::key::PublicKey;
10 use lightning::chain::keysinterface::{KeysInterface, KeysManager};
11 use lightning::ln::msgs::NetAddress;
12 use lightning::ln::PaymentHash;
13 use lightning::routing::network_graph::NetworkGraph;
14 use lightning::routing::router;
15 use lightning::routing::router::{Payee, RouteParameters};
16 use lightning::routing::scorer::Scorer;
17 use lightning::util::config::{ChannelConfig, ChannelHandshakeLimits, UserConfig};
18 use lightning::util::events::EventHandler;
19 use lightning_invoice::payment::PaymentError;
20 use lightning_invoice::{utils, Currency, Invoice};
21 use std::env;
22 use std::io;
23 use std::io::{BufRead, Write};
24 use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
25 use std::ops::Deref;
26 use std::path::Path;
27 use std::str::FromStr;
28 use std::sync::{Arc, Mutex};
29 use std::time::Duration;
30
31 pub(crate) struct LdkUserInfo {
32         pub(crate) bitcoind_rpc_username: String,
33         pub(crate) bitcoind_rpc_password: String,
34         pub(crate) bitcoind_rpc_port: u16,
35         pub(crate) bitcoind_rpc_host: String,
36         pub(crate) ldk_storage_dir_path: String,
37         pub(crate) ldk_peer_listening_port: u16,
38         pub(crate) ldk_announced_listen_addr: Vec<NetAddress>,
39         pub(crate) ldk_announced_node_name: [u8; 32],
40         pub(crate) network: Network,
41 }
42
43 pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
44         if env::args().len() < 3 {
45                 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-node-name announced-listen-addr*]`");
46                 return Err(());
47         }
48         let bitcoind_rpc_info = env::args().skip(1).next().unwrap();
49         let bitcoind_rpc_info_parts: Vec<&str> = bitcoind_rpc_info.rsplitn(2, "@").collect();
50         if bitcoind_rpc_info_parts.len() != 2 {
51                 println!("ERROR: bad bitcoind RPC URL provided");
52                 return Err(());
53         }
54         let rpc_user_and_password: Vec<&str> = bitcoind_rpc_info_parts[1].split(":").collect();
55         if rpc_user_and_password.len() != 2 {
56                 println!("ERROR: bad bitcoind RPC username/password combo provided");
57                 return Err(());
58         }
59         let bitcoind_rpc_username = rpc_user_and_password[0].to_string();
60         let bitcoind_rpc_password = rpc_user_and_password[1].to_string();
61         let bitcoind_rpc_path: Vec<&str> = bitcoind_rpc_info_parts[0].split(":").collect();
62         if bitcoind_rpc_path.len() != 2 {
63                 println!("ERROR: bad bitcoind RPC path provided");
64                 return Err(());
65         }
66         let bitcoind_rpc_host = bitcoind_rpc_path[0].to_string();
67         let bitcoind_rpc_port = bitcoind_rpc_path[1].parse::<u16>().unwrap();
68
69         let ldk_storage_dir_path = env::args().skip(2).next().unwrap();
70
71         let mut ldk_peer_port_set = true;
72         let ldk_peer_listening_port: u16 = match env::args().skip(3).next().map(|p| p.parse()) {
73                 Some(Ok(p)) => p,
74                 Some(Err(_)) => {
75                         ldk_peer_port_set = false;
76                         9735
77                 }
78                 None => {
79                         ldk_peer_port_set = false;
80                         9735
81                 }
82         };
83
84         let mut arg_idx = match ldk_peer_port_set {
85                 true => 4,
86                 false => 3,
87         };
88         let network: Network = match env::args().skip(arg_idx).next().as_ref().map(String::as_str) {
89                 Some("testnet") => Network::Testnet,
90                 Some("regtest") => Network::Regtest,
91                 Some("signet") => Network::Signet,
92                 Some(net) => {
93                         panic!("Unsupported network provided. Options are: `regtest`, `testnet`, and `signet`. Got {}", net);
94                 }
95                 None => Network::Testnet,
96         };
97
98         let ldk_announced_node_name = match env::args().skip(arg_idx + 1).next().as_ref() {
99                 Some(s) => {
100                         if s.len() > 32 {
101                                 panic!("Node Alias can not be longer than 32 bytes");
102                         }
103                         arg_idx += 1;
104                         let mut bytes = [0; 32];
105                         bytes[..s.len()].copy_from_slice(s.as_bytes());
106                         bytes
107                 }
108                 None => [0; 32],
109         };
110
111         let mut ldk_announced_listen_addr = Vec::new();
112         loop {
113                 match env::args().skip(arg_idx + 1).next().as_ref() {
114                         Some(s) => match IpAddr::from_str(s) {
115                                 Ok(IpAddr::V4(a)) => {
116                                         ldk_announced_listen_addr
117                                                 .push(NetAddress::IPv4 { addr: a.octets(), port: ldk_peer_listening_port });
118                                         arg_idx += 1;
119                                 }
120                                 Ok(IpAddr::V6(a)) => {
121                                         ldk_announced_listen_addr
122                                                 .push(NetAddress::IPv6 { addr: a.octets(), port: ldk_peer_listening_port });
123                                         arg_idx += 1;
124                                 }
125                                 Err(_) => panic!("Failed to parse announced-listen-addr into an IP address"),
126                         },
127                         None => break,
128                 }
129         }
130
131         Ok(LdkUserInfo {
132                 bitcoind_rpc_username,
133                 bitcoind_rpc_password,
134                 bitcoind_rpc_host,
135                 bitcoind_rpc_port,
136                 ldk_storage_dir_path,
137                 ldk_peer_listening_port,
138                 ldk_announced_listen_addr,
139                 ldk_announced_node_name,
140                 network,
141         })
142 }
143
144 pub(crate) async fn poll_for_user_input<E: EventHandler>(
145         invoice_payer: Arc<InvoicePayer<E>>, peer_manager: Arc<PeerManager>,
146         channel_manager: Arc<ChannelManager>, keys_manager: Arc<KeysManager>,
147         network_graph: Arc<NetworkGraph>, scorer: Arc<Mutex<Scorer>>,
148         inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage,
149         ldk_data_dir: String, logger: Arc<FilesystemLogger>, network: Network,
150 ) {
151         println!("LDK startup successful. To view available commands: \"help\".");
152         println!("LDK logs are available at <your-supplied-ldk-data-dir-path>/.ldk/logs");
153         println!("Local Node ID is {}.", channel_manager.get_our_node_id());
154         let stdin = io::stdin();
155         print!("> ");
156         io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
157         for line in stdin.lock().lines() {
158                 let line = line.unwrap();
159                 let mut words = line.split_whitespace();
160                 if let Some(word) = words.next() {
161                         match word {
162                                 "help" => help(),
163                                 "openchannel" => {
164                                         let peer_pubkey_and_ip_addr = words.next();
165                                         let channel_value_sat = words.next();
166                                         if peer_pubkey_and_ip_addr.is_none() || channel_value_sat.is_none() {
167                                                 println!("ERROR: openchannel has 2 required arguments: `openchannel pubkey@host:port channel_amt_satoshis` [--public]");
168                                                 print!("> ");
169                                                 io::stdout().flush().unwrap();
170                                                 continue;
171                                         }
172                                         let peer_pubkey_and_ip_addr = peer_pubkey_and_ip_addr.unwrap();
173                                         let (pubkey, peer_addr) =
174                                                 match parse_peer_info(peer_pubkey_and_ip_addr.to_string()) {
175                                                         Ok(info) => info,
176                                                         Err(e) => {
177                                                                 println!("{:?}", e.into_inner().unwrap());
178                                                                 print!("> ");
179                                                                 io::stdout().flush().unwrap();
180                                                                 continue;
181                                                         }
182                                                 };
183
184                                         let chan_amt_sat: Result<u64, _> = channel_value_sat.unwrap().parse();
185                                         if chan_amt_sat.is_err() {
186                                                 println!("ERROR: channel amount must be a number");
187                                                 print!("> ");
188                                                 io::stdout().flush().unwrap();
189                                                 continue;
190                                         }
191
192                                         if connect_peer_if_necessary(pubkey, peer_addr, peer_manager.clone())
193                                                 .await
194                                                 .is_err()
195                                         {
196                                                 print!("> ");
197                                                 io::stdout().flush().unwrap();
198                                                 continue;
199                                         };
200
201                                         let announce_channel = match words.next() {
202                                                 Some("--public") | Some("--public=true") => true,
203                                                 Some("--public=false") => false,
204                                                 Some(_) => {
205                                                         println!("ERROR: invalid `--public` command format. Valid formats: `--public`, `--public=true` `--public=false`");
206                                                         print!("> ");
207                                                         io::stdout().flush().unwrap();
208                                                         continue;
209                                                 }
210                                                 None => false,
211                                         };
212
213                                         if open_channel(
214                                                 pubkey,
215                                                 chan_amt_sat.unwrap(),
216                                                 announce_channel,
217                                                 channel_manager.clone(),
218                                         )
219                                         .is_ok()
220                                         {
221                                                 let peer_data_path = format!("{}/channel_peer_data", ldk_data_dir.clone());
222                                                 let _ = disk::persist_channel_peer(
223                                                         Path::new(&peer_data_path),
224                                                         peer_pubkey_and_ip_addr,
225                                                 );
226                                         }
227                                 }
228                                 "sendpayment" => {
229                                         let invoice_str = words.next();
230                                         if invoice_str.is_none() {
231                                                 println!("ERROR: sendpayment requires an invoice: `sendpayment <invoice>`");
232                                                 print!("> ");
233                                                 io::stdout().flush().unwrap();
234                                                 continue;
235                                         }
236
237                                         let invoice = match Invoice::from_str(invoice_str.unwrap()) {
238                                                 Ok(inv) => inv,
239                                                 Err(e) => {
240                                                         println!("ERROR: invalid invoice: {:?}", e);
241                                                         print!("> ");
242                                                         io::stdout().flush().unwrap();
243                                                         continue;
244                                                 }
245                                         };
246
247                                         send_payment(&*invoice_payer, &invoice, outbound_payments.clone());
248                                 }
249                                 "keysend" => {
250                                         let dest_pubkey = match words.next() {
251                                                 Some(dest) => match hex_utils::to_compressed_pubkey(dest) {
252                                                         Some(pk) => pk,
253                                                         None => {
254                                                                 println!("ERROR: couldn't parse destination pubkey");
255                                                                 print!("> ");
256                                                                 io::stdout().flush().unwrap();
257                                                                 continue;
258                                                         }
259                                                 },
260                                                 None => {
261                                                         println!("ERROR: keysend requires a destination pubkey: `keysend <dest_pubkey> <amt_msat>`");
262                                                         print!("> ");
263                                                         io::stdout().flush().unwrap();
264                                                         continue;
265                                                 }
266                                         };
267                                         let amt_msat_str = match words.next() {
268                                                 Some(amt) => amt,
269                                                 None => {
270                                                         println!("ERROR: keysend requires an amount in millisatoshis: `keysend <dest_pubkey> <amt_msat>`");
271
272                                                         print!("> ");
273                                                         io::stdout().flush().unwrap();
274                                                         continue;
275                                                 }
276                                         };
277                                         let amt_msat: u64 = match amt_msat_str.parse() {
278                                                 Ok(amt) => amt,
279                                                 Err(e) => {
280                                                         println!("ERROR: couldn't parse amount_msat: {}", e);
281                                                         print!("> ");
282                                                         io::stdout().flush().unwrap();
283                                                         continue;
284                                                 }
285                                         };
286                                         keysend(
287                                                 dest_pubkey,
288                                                 amt_msat,
289                                                 network_graph.clone(),
290                                                 channel_manager.clone(),
291                                                 outbound_payments.clone(),
292                                                 logger.clone(),
293                                                 scorer.clone(),
294                                         );
295                                 }
296                                 "getinvoice" => {
297                                         let amt_str = words.next();
298                                         if amt_str.is_none() {
299                                                 println!("ERROR: getinvoice requires an amount in millisatoshis");
300                                                 print!("> ");
301                                                 io::stdout().flush().unwrap();
302                                                 continue;
303                                         }
304
305                                         let amt_msat: Result<u64, _> = amt_str.unwrap().parse();
306                                         if amt_msat.is_err() {
307                                                 println!("ERROR: getinvoice provided payment amount was not a number");
308                                                 print!("> ");
309                                                 io::stdout().flush().unwrap();
310                                                 continue;
311                                         }
312                                         get_invoice(
313                                                 amt_msat.unwrap(),
314                                                 inbound_payments.clone(),
315                                                 channel_manager.clone(),
316                                                 keys_manager.clone(),
317                                                 network,
318                                         );
319                                 }
320                                 "connectpeer" => {
321                                         let peer_pubkey_and_ip_addr = words.next();
322                                         if peer_pubkey_and_ip_addr.is_none() {
323                                                 println!("ERROR: connectpeer requires peer connection info: `connectpeer pubkey@host:port`");
324                                                 print!("> ");
325                                                 io::stdout().flush().unwrap();
326                                                 continue;
327                                         }
328                                         let (pubkey, peer_addr) =
329                                                 match parse_peer_info(peer_pubkey_and_ip_addr.unwrap().to_string()) {
330                                                         Ok(info) => info,
331                                                         Err(e) => {
332                                                                 println!("{:?}", e.into_inner().unwrap());
333                                                                 print!("> ");
334                                                                 io::stdout().flush().unwrap();
335                                                                 continue;
336                                                         }
337                                                 };
338                                         if connect_peer_if_necessary(pubkey, peer_addr, peer_manager.clone())
339                                                 .await
340                                                 .is_ok()
341                                         {
342                                                 println!("SUCCESS: connected to peer {}", pubkey);
343                                         }
344                                 }
345                                 "listchannels" => list_channels(channel_manager.clone()),
346                                 "listpayments" => {
347                                         list_payments(inbound_payments.clone(), outbound_payments.clone())
348                                 }
349                                 "closechannel" => {
350                                         let channel_id_str = words.next();
351                                         if channel_id_str.is_none() {
352                                                 println!("ERROR: closechannel requires a channel ID: `closechannel <channel_id>`");
353                                                 print!("> ");
354                                                 io::stdout().flush().unwrap();
355                                                 continue;
356                                         }
357                                         let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
358                                         if channel_id_vec.is_none() {
359                                                 println!("ERROR: couldn't parse channel_id as hex");
360                                                 print!("> ");
361                                                 io::stdout().flush().unwrap();
362                                                 continue;
363                                         }
364                                         let mut channel_id = [0; 32];
365                                         channel_id.copy_from_slice(&channel_id_vec.unwrap());
366                                         close_channel(channel_id, channel_manager.clone());
367                                 }
368                                 "forceclosechannel" => {
369                                         let channel_id_str = words.next();
370                                         if channel_id_str.is_none() {
371                                                 println!("ERROR: forceclosechannel requires a channel ID: `forceclosechannel <channel_id>`");
372                                                 print!("> ");
373                                                 io::stdout().flush().unwrap();
374                                                 continue;
375                                         }
376                                         let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
377                                         if channel_id_vec.is_none() {
378                                                 println!("ERROR: couldn't parse channel_id as hex");
379                                                 print!("> ");
380                                                 io::stdout().flush().unwrap();
381                                                 continue;
382                                         }
383                                         let mut channel_id = [0; 32];
384                                         channel_id.copy_from_slice(&channel_id_vec.unwrap());
385                                         force_close_channel(channel_id, channel_manager.clone());
386                                 }
387                                 "nodeinfo" => node_info(channel_manager.clone(), peer_manager.clone()),
388                                 "listpeers" => list_peers(peer_manager.clone()),
389                                 "signmessage" => {
390                                         const MSG_STARTPOS: usize = "signmsg".len() + 1;
391                                         if line.as_bytes().len() <= MSG_STARTPOS {
392                                                 println!("ERROR: signmsg requires a message");
393                                                 print!("> ");
394                                                 io::stdout().flush().unwrap();
395                                                 continue;
396                                         }
397                                         println!(
398                                                 "{:?}",
399                                                 lightning::util::message_signing::sign(
400                                                         &line.as_bytes()[MSG_STARTPOS..],
401                                                         &keys_manager.get_node_secret()
402                                                 )
403                                         );
404                                         print!("> ");
405                                         io::stdout().flush().unwrap();
406                                 }
407                                 _ => println!("Unknown command. See `\"help\" for available commands."),
408                         }
409                 }
410                 print!("> ");
411                 io::stdout().flush().unwrap();
412         }
413 }
414
415 fn help() {
416         println!("openchannel pubkey@host:port <amt_satoshis>");
417         println!("sendpayment <invoice>");
418         println!("getinvoice <amt_millisatoshis>");
419         println!("connectpeer pubkey@host:port");
420         println!("listchannels");
421         println!("listpayments");
422         println!("closechannel <channel_id>");
423         println!("forceclosechannel <channel_id>");
424         println!("nodeinfo");
425         println!("listpeers");
426         println!("signmessage <message>");
427 }
428
429 fn node_info(channel_manager: Arc<ChannelManager>, peer_manager: Arc<PeerManager>) {
430         println!("\t{{");
431         println!("\t\t node_pubkey: {}", channel_manager.get_our_node_id());
432         println!("\t\t num_channels: {}", channel_manager.list_channels().len());
433         println!("\t\t num_usable_channels: {}", channel_manager.list_usable_channels().len());
434         println!("\t\t num_peers: {}", peer_manager.get_peer_node_ids().len());
435         println!("\t}},");
436 }
437
438 fn list_peers(peer_manager: Arc<PeerManager>) {
439         println!("\t{{");
440         for pubkey in peer_manager.get_peer_node_ids() {
441                 println!("\t\t pubkey: {}", pubkey);
442         }
443         println!("\t}},");
444 }
445
446 fn list_channels(channel_manager: Arc<ChannelManager>) {
447         print!("[");
448         for chan_info in channel_manager.list_channels() {
449                 println!("");
450                 println!("\t{{");
451                 println!("\t\tchannel_id: {},", hex_utils::hex_str(&chan_info.channel_id[..]));
452                 if let Some(funding_txo) = chan_info.funding_txo {
453                         println!("\t\tfunding_txid: {},", funding_txo.txid);
454                 }
455                 println!(
456                         "\t\tpeer_pubkey: {},",
457                         hex_utils::hex_str(&chan_info.counterparty.node_id.serialize())
458                 );
459                 if let Some(id) = chan_info.short_channel_id {
460                         println!("\t\tshort_channel_id: {},", id);
461                 }
462                 println!("\t\tis_confirmed_onchain: {},", chan_info.is_funding_locked);
463                 println!("\t\tchannel_value_satoshis: {},", chan_info.channel_value_satoshis);
464                 println!(
465                         "\t\tlocal_balance_msat: {},",
466                         chan_info.outbound_capacity_msat
467                                 + chan_info.unspendable_punishment_reserve.unwrap_or(0) * 1000
468                 );
469                 if chan_info.is_usable {
470                         println!("\t\tavailable_balance_for_send_msat: {},", chan_info.outbound_capacity_msat);
471                         println!("\t\tavailable_balance_for_recv_msat: {},", chan_info.inbound_capacity_msat);
472                 }
473                 println!("\t\tchannel_can_send_payments: {},", chan_info.is_usable);
474                 println!("\t\tpublic: {},", chan_info.is_public);
475                 println!("\t}},");
476         }
477         println!("]");
478 }
479
480 fn list_payments(inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage) {
481         let inbound = inbound_payments.lock().unwrap();
482         let outbound = outbound_payments.lock().unwrap();
483         print!("[");
484         for (payment_hash, payment_info) in inbound.deref() {
485                 println!("");
486                 println!("\t{{");
487                 println!("\t\tamount_millisatoshis: {},", payment_info.amt_msat);
488                 println!("\t\tpayment_hash: {},", hex_utils::hex_str(&payment_hash.0));
489                 println!("\t\thtlc_direction: inbound,");
490                 println!(
491                         "\t\thtlc_status: {},",
492                         match payment_info.status {
493                                 HTLCStatus::Pending => "pending",
494                                 HTLCStatus::Succeeded => "succeeded",
495                                 HTLCStatus::Failed => "failed",
496                         }
497                 );
498
499                 println!("\t}},");
500         }
501
502         for (payment_hash, payment_info) in outbound.deref() {
503                 println!("");
504                 println!("\t{{");
505                 println!("\t\tamount_millisatoshis: {},", payment_info.amt_msat);
506                 println!("\t\tpayment_hash: {},", hex_utils::hex_str(&payment_hash.0));
507                 println!("\t\thtlc_direction: outbound,");
508                 println!(
509                         "\t\thtlc_status: {},",
510                         match payment_info.status {
511                                 HTLCStatus::Pending => "pending",
512                                 HTLCStatus::Succeeded => "succeeded",
513                                 HTLCStatus::Failed => "failed",
514                         }
515                 );
516
517                 println!("\t}},");
518         }
519         println!("]");
520 }
521
522 pub(crate) async fn connect_peer_if_necessary(
523         pubkey: PublicKey, peer_addr: SocketAddr, peer_manager: Arc<PeerManager>,
524 ) -> Result<(), ()> {
525         for node_pubkey in peer_manager.get_peer_node_ids() {
526                 if node_pubkey == pubkey {
527                         return Ok(());
528                 }
529         }
530         match lightning_net_tokio::connect_outbound(Arc::clone(&peer_manager), pubkey, peer_addr).await
531         {
532                 Some(connection_closed_future) => {
533                         let mut connection_closed_future = Box::pin(connection_closed_future);
534                         loop {
535                                 match futures::poll!(&mut connection_closed_future) {
536                                         std::task::Poll::Ready(_) => {
537                                                 println!("ERROR: Peer disconnected before we finished the handshake");
538                                                 return Err(());
539                                         }
540                                         std::task::Poll::Pending => {}
541                                 }
542                                 // Avoid blocking the tokio context by sleeping a bit
543                                 match peer_manager.get_peer_node_ids().iter().find(|id| **id == pubkey) {
544                                         Some(_) => break,
545                                         None => tokio::time::sleep(Duration::from_millis(10)).await,
546                                 }
547                         }
548                 }
549                 None => {
550                         println!("ERROR: failed to connect to peer");
551                         return Err(());
552                 }
553         }
554         Ok(())
555 }
556
557 fn open_channel(
558         peer_pubkey: PublicKey, channel_amt_sat: u64, announced_channel: bool,
559         channel_manager: Arc<ChannelManager>,
560 ) -> Result<(), ()> {
561         let config = UserConfig {
562                 peer_channel_config_limits: ChannelHandshakeLimits {
563                         // lnd's max to_self_delay is 2016, so we want to be compatible.
564                         their_to_self_delay: 2016,
565                         ..Default::default()
566                 },
567                 channel_options: ChannelConfig { announced_channel, ..Default::default() },
568                 ..Default::default()
569         };
570
571         match channel_manager.create_channel(peer_pubkey, channel_amt_sat, 0, 0, Some(config)) {
572                 Ok(_) => {
573                         println!("EVENT: initiated channel with peer {}. ", peer_pubkey);
574                         return Ok(());
575                 }
576                 Err(e) => {
577                         println!("ERROR: failed to open channel: {:?}", e);
578                         return Err(());
579                 }
580         }
581 }
582
583 fn send_payment<E: EventHandler>(
584         invoice_payer: &InvoicePayer<E>, invoice: &Invoice, payment_storage: PaymentInfoStorage,
585 ) {
586         let status = match invoice_payer.pay_invoice(invoice) {
587                 Ok(_payment_id) => {
588                         let payee_pubkey = invoice.recover_payee_pub_key();
589                         let amt_msat = invoice.amount_milli_satoshis().unwrap();
590                         println!("EVENT: initiated sending {} msats to {}", amt_msat, payee_pubkey);
591                         print!("> ");
592                         HTLCStatus::Pending
593                 }
594                 Err(PaymentError::Invoice(e)) => {
595                         println!("ERROR: invalid invoice: {}", e);
596                         print!("> ");
597                         return;
598                 }
599                 Err(PaymentError::Routing(e)) => {
600                         println!("ERROR: failed to find route: {}", e.err);
601                         print!("> ");
602                         return;
603                 }
604                 Err(PaymentError::Sending(e)) => {
605                         println!("ERROR: failed to send payment: {:?}", e);
606                         print!("> ");
607                         HTLCStatus::Failed
608                 }
609         };
610         let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
611         let payment_secret = Some(invoice.payment_secret().clone());
612
613         let mut payments = payment_storage.lock().unwrap();
614         payments.insert(
615                 payment_hash,
616                 PaymentInfo {
617                         preimage: None,
618                         secret: payment_secret,
619                         status,
620                         amt_msat: MillisatAmount(invoice.amount_milli_satoshis()),
621                 },
622         );
623 }
624
625 fn keysend(
626         payee_pubkey: PublicKey, amt_msat: u64, network_graph: Arc<NetworkGraph>,
627         channel_manager: Arc<ChannelManager>, payment_storage: PaymentInfoStorage,
628         logger: Arc<FilesystemLogger>, scorer: Arc<Mutex<Scorer>>,
629 ) {
630         let first_hops = channel_manager.list_usable_channels();
631         let payer_pubkey = channel_manager.get_our_node_id();
632
633         let payee = Payee::for_keysend(payee_pubkey);
634         let params = RouteParameters { payee, final_value_msat: amt_msat, final_cltv_expiry_delta: 40 };
635
636         let route = match router::find_route(
637                 &payer_pubkey,
638                 &params,
639                 &network_graph,
640                 Some(&first_hops.iter().collect::<Vec<_>>()),
641                 logger,
642                 &scorer.lock().unwrap(),
643         ) {
644                 Ok(r) => r,
645                 Err(e) => {
646                         println!("ERROR: failed to find route: {}", e.err);
647                         return;
648                 }
649         };
650
651         let mut payments = payment_storage.lock().unwrap();
652         let payment_hash = channel_manager.send_spontaneous_payment(&route, None).unwrap().0;
653         payments.insert(
654                 payment_hash,
655                 PaymentInfo {
656                         preimage: None,
657                         secret: None,
658                         status: HTLCStatus::Pending,
659                         amt_msat: MillisatAmount(Some(amt_msat)),
660                 },
661         );
662 }
663
664 fn get_invoice(
665         amt_msat: u64, payment_storage: PaymentInfoStorage, channel_manager: Arc<ChannelManager>,
666         keys_manager: Arc<KeysManager>, network: Network,
667 ) {
668         let mut payments = payment_storage.lock().unwrap();
669         let currency = match network {
670                 Network::Bitcoin => Currency::Bitcoin,
671                 Network::Testnet => Currency::BitcoinTestnet,
672                 Network::Regtest => Currency::Regtest,
673                 Network::Signet => Currency::Signet,
674         };
675         let invoice = match utils::create_invoice_from_channelmanager(
676                 &channel_manager,
677                 keys_manager,
678                 currency,
679                 Some(amt_msat),
680                 "ldk-tutorial-node".to_string(),
681         ) {
682                 Ok(inv) => {
683                         println!("SUCCESS: generated invoice: {}", inv);
684                         inv
685                 }
686                 Err(e) => {
687                         println!("ERROR: failed to create invoice: {:?}", e);
688                         return;
689                 }
690         };
691
692         let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
693         payments.insert(
694                 payment_hash,
695                 PaymentInfo {
696                         preimage: None,
697                         secret: Some(invoice.payment_secret().clone()),
698                         status: HTLCStatus::Pending,
699                         amt_msat: MillisatAmount(Some(amt_msat)),
700                 },
701         );
702 }
703
704 fn close_channel(channel_id: [u8; 32], channel_manager: Arc<ChannelManager>) {
705         match channel_manager.close_channel(&channel_id) {
706                 Ok(()) => println!("EVENT: initiating channel close"),
707                 Err(e) => println!("ERROR: failed to close channel: {:?}", e),
708         }
709 }
710
711 fn force_close_channel(channel_id: [u8; 32], channel_manager: Arc<ChannelManager>) {
712         match channel_manager.force_close_channel(&channel_id) {
713                 Ok(()) => println!("EVENT: initiating channel force-close"),
714                 Err(e) => println!("ERROR: failed to force-close channel: {:?}", e),
715         }
716 }
717
718 pub(crate) fn parse_peer_info(
719         peer_pubkey_and_ip_addr: String,
720 ) -> Result<(PublicKey, SocketAddr), std::io::Error> {
721         let mut pubkey_and_addr = peer_pubkey_and_ip_addr.split("@");
722         let pubkey = pubkey_and_addr.next();
723         let peer_addr_str = pubkey_and_addr.next();
724         if peer_addr_str.is_none() || peer_addr_str.is_none() {
725                 return Err(std::io::Error::new(
726                         std::io::ErrorKind::Other,
727                         "ERROR: incorrectly formatted peer info. Should be formatted as: `pubkey@host:port`",
728                 ));
729         }
730
731         let peer_addr = peer_addr_str.unwrap().to_socket_addrs().map(|mut r| r.next());
732         if peer_addr.is_err() || peer_addr.as_ref().unwrap().is_none() {
733                 return Err(std::io::Error::new(
734                         std::io::ErrorKind::Other,
735                         "ERROR: couldn't parse pubkey@host:port into a socket address",
736                 ));
737         }
738
739         let pubkey = hex_utils::to_compressed_pubkey(pubkey.unwrap());
740         if pubkey.is_none() {
741                 return Err(std::io::Error::new(
742                         std::io::ErrorKind::Other,
743                         "ERROR: unable to parse given pubkey for node",
744                 ));
745         }
746
747         Ok((pubkey.unwrap(), peer_addr.unwrap().unwrap()))
748 }