Drop `futures` dependency with `tokio::select`
[ldk-sample] / src / cli.rs
1 use crate::disk;
2 use crate::hex_utils;
3 use crate::{
4         ChannelManager, HTLCStatus, MillisatAmount, NetworkGraph, OnionMessenger, PaymentInfo,
5         PaymentInfoStorage, PeerManager,
6 };
7 use bitcoin::hashes::sha256::Hash as Sha256;
8 use bitcoin::hashes::Hash;
9 use bitcoin::network::constants::Network;
10 use bitcoin::secp256k1::PublicKey;
11 use lightning::chain::keysinterface::{EntropySource, KeysManager};
12 use lightning::ln::channelmanager::{PaymentId, Retry};
13 use lightning::ln::msgs::NetAddress;
14 use lightning::ln::{PaymentHash, PaymentPreimage};
15 use lightning::onion_message::{CustomOnionMessageContents, Destination, OnionMessageContents};
16 use lightning::routing::gossip::NodeId;
17 use lightning::routing::router::{PaymentParameters, RouteParameters};
18 use lightning::util::config::{ChannelHandshakeConfig, ChannelHandshakeLimits, UserConfig};
19 use lightning::util::ser::{Writeable, Writer};
20 use lightning_invoice::payment::pay_invoice;
21 use lightning_invoice::{utils, Currency, Invoice};
22 use std::env;
23 use std::io;
24 use std::io::Write;
25 use std::net::{SocketAddr, ToSocketAddrs};
26 use std::ops::Deref;
27 use std::path::Path;
28 use std::str::FromStr;
29 use std::sync::Arc;
30 use std::time::Duration;
31
32 pub(crate) struct LdkUserInfo {
33         pub(crate) bitcoind_rpc_username: String,
34         pub(crate) bitcoind_rpc_password: String,
35         pub(crate) bitcoind_rpc_port: u16,
36         pub(crate) bitcoind_rpc_host: String,
37         pub(crate) ldk_storage_dir_path: String,
38         pub(crate) ldk_peer_listening_port: u16,
39         pub(crate) ldk_announced_listen_addr: Vec<NetAddress>,
40         pub(crate) ldk_announced_node_name: [u8; 32],
41         pub(crate) network: Network,
42 }
43
44 struct UserOnionMessageContents {
45         tlv_type: u64,
46         data: Vec<u8>,
47 }
48
49 impl CustomOnionMessageContents for UserOnionMessageContents {
50         fn tlv_type(&self) -> u64 {
51                 self.tlv_type
52         }
53 }
54
55 impl Writeable for UserOnionMessageContents {
56         fn write<W: Writer>(&self, w: &mut W) -> Result<(), std::io::Error> {
57                 w.write_all(&self.data)
58         }
59 }
60
61 pub(crate) async fn poll_for_user_input(
62         peer_manager: Arc<PeerManager>, channel_manager: Arc<ChannelManager>,
63         keys_manager: Arc<KeysManager>, network_graph: Arc<NetworkGraph>,
64         onion_messenger: Arc<OnionMessenger>, inbound_payments: PaymentInfoStorage,
65         outbound_payments: PaymentInfoStorage, ldk_data_dir: String, network: Network,
66         logger: Arc<disk::FilesystemLogger>,
67 ) {
68         println!(
69                 "LDK startup successful. Enter \"help\" to view available commands. Press Ctrl-D to quit."
70         );
71         println!("LDK logs are available at <your-supplied-ldk-data-dir-path>/.ldk/logs");
72         println!("Local Node ID is {}.", channel_manager.get_our_node_id());
73         loop {
74                 print!("> ");
75                 io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
76                 let mut line = String::new();
77                 if let Err(e) = io::stdin().read_line(&mut line) {
78                         break println!("ERROR: {}", e);
79                 }
80
81                 if line.len() == 0 {
82                         // We hit EOF / Ctrl-D
83                         break;
84                 }
85
86                 let mut words = line.split_whitespace();
87                 if let Some(word) = words.next() {
88                         match word {
89                                 "help" => help(),
90                                 "openchannel" => {
91                                         let peer_pubkey_and_ip_addr = words.next();
92                                         let channel_value_sat = words.next();
93                                         if peer_pubkey_and_ip_addr.is_none() || channel_value_sat.is_none() {
94                                                 println!("ERROR: openchannel has 2 required arguments: `openchannel pubkey@host:port channel_amt_satoshis` [--public]");
95                                                 continue;
96                                         }
97                                         let peer_pubkey_and_ip_addr = peer_pubkey_and_ip_addr.unwrap();
98                                         let (pubkey, peer_addr) =
99                                                 match parse_peer_info(peer_pubkey_and_ip_addr.to_string()) {
100                                                         Ok(info) => info,
101                                                         Err(e) => {
102                                                                 println!("{:?}", e.into_inner().unwrap());
103                                                                 continue;
104                                                         }
105                                                 };
106
107                                         let chan_amt_sat: Result<u64, _> = channel_value_sat.unwrap().parse();
108                                         if chan_amt_sat.is_err() {
109                                                 println!("ERROR: channel amount must be a number");
110                                                 continue;
111                                         }
112
113                                         if connect_peer_if_necessary(pubkey, peer_addr, peer_manager.clone())
114                                                 .await
115                                                 .is_err()
116                                         {
117                                                 continue;
118                                         };
119
120                                         let announce_channel = match words.next() {
121                                                 Some("--public") | Some("--public=true") => true,
122                                                 Some("--public=false") => false,
123                                                 Some(_) => {
124                                                         println!("ERROR: invalid `--public` command format. Valid formats: `--public`, `--public=true` `--public=false`");
125                                                         continue;
126                                                 }
127                                                 None => false,
128                                         };
129
130                                         if open_channel(
131                                                 pubkey,
132                                                 chan_amt_sat.unwrap(),
133                                                 announce_channel,
134                                                 channel_manager.clone(),
135                                         )
136                                         .is_ok()
137                                         {
138                                                 let peer_data_path = format!("{}/channel_peer_data", ldk_data_dir.clone());
139                                                 let _ = disk::persist_channel_peer(
140                                                         Path::new(&peer_data_path),
141                                                         peer_pubkey_and_ip_addr,
142                                                 );
143                                         }
144                                 }
145                                 "sendpayment" => {
146                                         let invoice_str = words.next();
147                                         if invoice_str.is_none() {
148                                                 println!("ERROR: sendpayment requires an invoice: `sendpayment <invoice>`");
149                                                 continue;
150                                         }
151
152                                         let invoice = match Invoice::from_str(invoice_str.unwrap()) {
153                                                 Ok(inv) => inv,
154                                                 Err(e) => {
155                                                         println!("ERROR: invalid invoice: {:?}", e);
156                                                         continue;
157                                                 }
158                                         };
159
160                                         send_payment(&*channel_manager, &invoice, outbound_payments.clone());
161                                 }
162                                 "keysend" => {
163                                         let dest_pubkey = match words.next() {
164                                                 Some(dest) => match hex_utils::to_compressed_pubkey(dest) {
165                                                         Some(pk) => pk,
166                                                         None => {
167                                                                 println!("ERROR: couldn't parse destination pubkey");
168                                                                 continue;
169                                                         }
170                                                 },
171                                                 None => {
172                                                         println!("ERROR: keysend requires a destination pubkey: `keysend <dest_pubkey> <amt_msat>`");
173                                                         continue;
174                                                 }
175                                         };
176                                         let amt_msat_str = match words.next() {
177                                                 Some(amt) => amt,
178                                                 None => {
179                                                         println!("ERROR: keysend requires an amount in millisatoshis: `keysend <dest_pubkey> <amt_msat>`");
180                                                         continue;
181                                                 }
182                                         };
183                                         let amt_msat: u64 = match amt_msat_str.parse() {
184                                                 Ok(amt) => amt,
185                                                 Err(e) => {
186                                                         println!("ERROR: couldn't parse amount_msat: {}", e);
187                                                         continue;
188                                                 }
189                                         };
190                                         keysend(
191                                                 &*channel_manager,
192                                                 dest_pubkey,
193                                                 amt_msat,
194                                                 &*keys_manager,
195                                                 outbound_payments.clone(),
196                                         );
197                                 }
198                                 "getinvoice" => {
199                                         let amt_str = words.next();
200                                         if amt_str.is_none() {
201                                                 println!("ERROR: getinvoice requires an amount in millisatoshis");
202                                                 continue;
203                                         }
204
205                                         let amt_msat: Result<u64, _> = amt_str.unwrap().parse();
206                                         if amt_msat.is_err() {
207                                                 println!("ERROR: getinvoice provided payment amount was not a number");
208                                                 continue;
209                                         }
210
211                                         let expiry_secs_str = words.next();
212                                         if expiry_secs_str.is_none() {
213                                                 println!("ERROR: getinvoice requires an expiry in seconds");
214                                                 continue;
215                                         }
216
217                                         let expiry_secs: Result<u32, _> = expiry_secs_str.unwrap().parse();
218                                         if expiry_secs.is_err() {
219                                                 println!("ERROR: getinvoice provided expiry was not a number");
220                                                 continue;
221                                         }
222
223                                         get_invoice(
224                                                 amt_msat.unwrap(),
225                                                 Arc::clone(&inbound_payments),
226                                                 &*channel_manager,
227                                                 Arc::clone(&keys_manager),
228                                                 network,
229                                                 expiry_secs.unwrap(),
230                                                 Arc::clone(&logger),
231                                         );
232                                 }
233                                 "connectpeer" => {
234                                         let peer_pubkey_and_ip_addr = words.next();
235                                         if peer_pubkey_and_ip_addr.is_none() {
236                                                 println!("ERROR: connectpeer requires peer connection info: `connectpeer pubkey@host:port`");
237                                                 continue;
238                                         }
239                                         let (pubkey, peer_addr) =
240                                                 match parse_peer_info(peer_pubkey_and_ip_addr.unwrap().to_string()) {
241                                                         Ok(info) => info,
242                                                         Err(e) => {
243                                                                 println!("{:?}", e.into_inner().unwrap());
244                                                                 continue;
245                                                         }
246                                                 };
247                                         if connect_peer_if_necessary(pubkey, peer_addr, peer_manager.clone())
248                                                 .await
249                                                 .is_ok()
250                                         {
251                                                 println!("SUCCESS: connected to peer {}", pubkey);
252                                         }
253                                 }
254                                 "disconnectpeer" => {
255                                         let peer_pubkey = words.next();
256                                         if peer_pubkey.is_none() {
257                                                 println!("ERROR: disconnectpeer requires peer public key: `disconnectpeer <peer_pubkey>`");
258                                                 continue;
259                                         }
260
261                                         let peer_pubkey =
262                                                 match bitcoin::secp256k1::PublicKey::from_str(peer_pubkey.unwrap()) {
263                                                         Ok(pubkey) => pubkey,
264                                                         Err(e) => {
265                                                                 println!("ERROR: {}", e.to_string());
266                                                                 continue;
267                                                         }
268                                                 };
269
270                                         if do_disconnect_peer(
271                                                 peer_pubkey,
272                                                 peer_manager.clone(),
273                                                 channel_manager.clone(),
274                                         )
275                                         .is_ok()
276                                         {
277                                                 println!("SUCCESS: disconnected from peer {}", peer_pubkey);
278                                         }
279                                 }
280                                 "listchannels" => list_channels(&channel_manager, &network_graph),
281                                 "listpayments" => {
282                                         list_payments(inbound_payments.clone(), outbound_payments.clone())
283                                 }
284                                 "closechannel" => {
285                                         let channel_id_str = words.next();
286                                         if channel_id_str.is_none() {
287                                                 println!("ERROR: closechannel requires a channel ID: `closechannel <channel_id> <peer_pubkey>`");
288                                                 continue;
289                                         }
290                                         let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
291                                         if channel_id_vec.is_none() || channel_id_vec.as_ref().unwrap().len() != 32 {
292                                                 println!("ERROR: couldn't parse channel_id");
293                                                 continue;
294                                         }
295                                         let mut channel_id = [0; 32];
296                                         channel_id.copy_from_slice(&channel_id_vec.unwrap());
297
298                                         let peer_pubkey_str = words.next();
299                                         if peer_pubkey_str.is_none() {
300                                                 println!("ERROR: closechannel requires a peer pubkey: `closechannel <channel_id> <peer_pubkey>`");
301                                                 continue;
302                                         }
303                                         let peer_pubkey_vec = match hex_utils::to_vec(peer_pubkey_str.unwrap()) {
304                                                 Some(peer_pubkey_vec) => peer_pubkey_vec,
305                                                 None => {
306                                                         println!("ERROR: couldn't parse peer_pubkey");
307                                                         continue;
308                                                 }
309                                         };
310                                         let peer_pubkey = match PublicKey::from_slice(&peer_pubkey_vec) {
311                                                 Ok(peer_pubkey) => peer_pubkey,
312                                                 Err(_) => {
313                                                         println!("ERROR: couldn't parse peer_pubkey");
314                                                         continue;
315                                                 }
316                                         };
317
318                                         close_channel(channel_id, peer_pubkey, channel_manager.clone());
319                                 }
320                                 "forceclosechannel" => {
321                                         let channel_id_str = words.next();
322                                         if channel_id_str.is_none() {
323                                                 println!("ERROR: forceclosechannel requires a channel ID: `forceclosechannel <channel_id> <peer_pubkey>`");
324                                                 continue;
325                                         }
326                                         let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
327                                         if channel_id_vec.is_none() || channel_id_vec.as_ref().unwrap().len() != 32 {
328                                                 println!("ERROR: couldn't parse channel_id");
329                                                 continue;
330                                         }
331                                         let mut channel_id = [0; 32];
332                                         channel_id.copy_from_slice(&channel_id_vec.unwrap());
333
334                                         let peer_pubkey_str = words.next();
335                                         if peer_pubkey_str.is_none() {
336                                                 println!("ERROR: forceclosechannel requires a peer pubkey: `forceclosechannel <channel_id> <peer_pubkey>`");
337                                                 continue;
338                                         }
339                                         let peer_pubkey_vec = match hex_utils::to_vec(peer_pubkey_str.unwrap()) {
340                                                 Some(peer_pubkey_vec) => peer_pubkey_vec,
341                                                 None => {
342                                                         println!("ERROR: couldn't parse peer_pubkey");
343                                                         continue;
344                                                 }
345                                         };
346                                         let peer_pubkey = match PublicKey::from_slice(&peer_pubkey_vec) {
347                                                 Ok(peer_pubkey) => peer_pubkey,
348                                                 Err(_) => {
349                                                         println!("ERROR: couldn't parse peer_pubkey");
350                                                         continue;
351                                                 }
352                                         };
353
354                                         force_close_channel(channel_id, peer_pubkey, channel_manager.clone());
355                                 }
356                                 "nodeinfo" => node_info(&channel_manager, &peer_manager),
357                                 "listpeers" => list_peers(peer_manager.clone()),
358                                 "signmessage" => {
359                                         const MSG_STARTPOS: usize = "signmessage".len() + 1;
360                                         if line.as_bytes().len() <= MSG_STARTPOS {
361                                                 println!("ERROR: signmsg requires a message");
362                                                 continue;
363                                         }
364                                         println!(
365                                                 "{:?}",
366                                                 lightning::util::message_signing::sign(
367                                                         &line.as_bytes()[MSG_STARTPOS..],
368                                                         &keys_manager.get_node_secret_key()
369                                                 )
370                                         );
371                                 }
372                                 "sendonionmessage" => {
373                                         let path_pks_str = words.next();
374                                         if path_pks_str.is_none() {
375                                                 println!(
376                                                         "ERROR: sendonionmessage requires at least one node id for the path"
377                                                 );
378                                                 continue;
379                                         }
380                                         let mut node_pks = Vec::new();
381                                         let mut errored = false;
382                                         for pk_str in path_pks_str.unwrap().split(",") {
383                                                 let node_pubkey_vec = match hex_utils::to_vec(pk_str) {
384                                                         Some(peer_pubkey_vec) => peer_pubkey_vec,
385                                                         None => {
386                                                                 println!("ERROR: couldn't parse peer_pubkey");
387                                                                 errored = true;
388                                                                 break;
389                                                         }
390                                                 };
391                                                 let node_pubkey = match PublicKey::from_slice(&node_pubkey_vec) {
392                                                         Ok(peer_pubkey) => peer_pubkey,
393                                                         Err(_) => {
394                                                                 println!("ERROR: couldn't parse peer_pubkey");
395                                                                 errored = true;
396                                                                 break;
397                                                         }
398                                                 };
399                                                 node_pks.push(node_pubkey);
400                                         }
401                                         if errored {
402                                                 continue;
403                                         }
404                                         let tlv_type = match words.next().map(|ty_str| ty_str.parse()) {
405                                                 Some(Ok(ty)) if ty >= 64 => ty,
406                                                 _ => {
407                                                         println!("Need an integral message type above 64");
408                                                         continue;
409                                                 }
410                                         };
411                                         let data = match words.next().map(|s| hex_utils::to_vec(s)) {
412                                                 Some(Some(data)) => data,
413                                                 _ => {
414                                                         println!("Need a hex data string");
415                                                         continue;
416                                                 }
417                                         };
418                                         let destination_pk = node_pks.pop().unwrap();
419                                         match onion_messenger.send_onion_message(
420                                                 &node_pks,
421                                                 Destination::Node(destination_pk),
422                                                 OnionMessageContents::Custom(UserOnionMessageContents { tlv_type, data }),
423                                                 None,
424                                         ) {
425                                                 Ok(()) => println!("SUCCESS: forwarded onion message to first hop"),
426                                                 Err(e) => println!("ERROR: failed to send onion message: {:?}", e),
427                                         }
428                                 }
429                                 "quit" | "exit" => break,
430                                 _ => println!("Unknown command. See `\"help\" for available commands."),
431                         }
432                 }
433         }
434 }
435
436 fn help() {
437         let package_version = env!("CARGO_PKG_VERSION");
438         let package_name = env!("CARGO_PKG_NAME");
439         println!("\nVERSION:");
440         println!("  {} v{}", package_name, package_version);
441         println!("\nUSAGE:");
442         println!("  Command [arguments]");
443         println!("\nCOMMANDS:");
444         println!("  help\tShows a list of commands.");
445         println!("  quit\tClose the application.");
446         println!("\n  Channels:");
447         println!("      openchannel pubkey@host:port <amt_satoshis> [--public]");
448         println!("      closechannel <channel_id> <peer_pubkey>");
449         println!("      forceclosechannel <channel_id> <peer_pubkey>");
450         println!("      listchannels");
451         println!("\n  Peers:");
452         println!("      connectpeer pubkey@host:port");
453         println!("      disconnectpeer <peer_pubkey>");
454         println!("      listpeers");
455         println!("\n  Payments:");
456         println!("      sendpayment <invoice>");
457         println!("      keysend <dest_pubkey> <amt_msats>");
458         println!("      listpayments");
459         println!("\n  Invoices:");
460         println!("      getinvoice <amt_msats> <expiry_secs>");
461         println!("\n  Other:");
462         println!("      signmessage <message>");
463         println!(
464                 "      sendonionmessage <node_id_1,node_id_2,..,destination_node_id> <type> <hex_bytes>"
465         );
466         println!("      nodeinfo");
467 }
468
469 fn node_info(channel_manager: &Arc<ChannelManager>, peer_manager: &Arc<PeerManager>) {
470         println!("\t{{");
471         println!("\t\t node_pubkey: {}", channel_manager.get_our_node_id());
472         let chans = channel_manager.list_channels();
473         println!("\t\t num_channels: {}", chans.len());
474         println!("\t\t num_usable_channels: {}", chans.iter().filter(|c| c.is_usable).count());
475         let local_balance_msat = chans.iter().map(|c| c.balance_msat).sum::<u64>();
476         println!("\t\t local_balance_msat: {}", local_balance_msat);
477         println!("\t\t num_peers: {}", peer_manager.get_peer_node_ids().len());
478         println!("\t}},");
479 }
480
481 fn list_peers(peer_manager: Arc<PeerManager>) {
482         println!("\t{{");
483         for (pubkey, _) in peer_manager.get_peer_node_ids() {
484                 println!("\t\t pubkey: {}", pubkey);
485         }
486         println!("\t}},");
487 }
488
489 fn list_channels(channel_manager: &Arc<ChannelManager>, network_graph: &Arc<NetworkGraph>) {
490         print!("[");
491         for chan_info in channel_manager.list_channels() {
492                 println!("");
493                 println!("\t{{");
494                 println!("\t\tchannel_id: {},", hex_utils::hex_str(&chan_info.channel_id[..]));
495                 if let Some(funding_txo) = chan_info.funding_txo {
496                         println!("\t\tfunding_txid: {},", funding_txo.txid);
497                 }
498
499                 println!(
500                         "\t\tpeer_pubkey: {},",
501                         hex_utils::hex_str(&chan_info.counterparty.node_id.serialize())
502                 );
503                 if let Some(node_info) = network_graph
504                         .read_only()
505                         .nodes()
506                         .get(&NodeId::from_pubkey(&chan_info.counterparty.node_id))
507                 {
508                         if let Some(announcement) = &node_info.announcement_info {
509                                 println!("\t\tpeer_alias: {}", announcement.alias);
510                         }
511                 }
512
513                 if let Some(id) = chan_info.short_channel_id {
514                         println!("\t\tshort_channel_id: {},", id);
515                 }
516                 println!("\t\tis_channel_ready: {},", chan_info.is_channel_ready);
517                 println!("\t\tchannel_value_satoshis: {},", chan_info.channel_value_satoshis);
518                 println!("\t\tlocal_balance_msat: {},", chan_info.balance_msat);
519                 if chan_info.is_usable {
520                         println!("\t\tavailable_balance_for_send_msat: {},", chan_info.outbound_capacity_msat);
521                         println!("\t\tavailable_balance_for_recv_msat: {},", chan_info.inbound_capacity_msat);
522                 }
523                 println!("\t\tchannel_can_send_payments: {},", chan_info.is_usable);
524                 println!("\t\tpublic: {},", chan_info.is_public);
525                 println!("\t}},");
526         }
527         println!("]");
528 }
529
530 fn list_payments(inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage) {
531         let inbound = inbound_payments.lock().unwrap();
532         let outbound = outbound_payments.lock().unwrap();
533         print!("[");
534         for (payment_hash, payment_info) in inbound.deref() {
535                 println!("");
536                 println!("\t{{");
537                 println!("\t\tamount_millisatoshis: {},", payment_info.amt_msat);
538                 println!("\t\tpayment_hash: {},", hex_utils::hex_str(&payment_hash.0));
539                 println!("\t\thtlc_direction: inbound,");
540                 println!(
541                         "\t\thtlc_status: {},",
542                         match payment_info.status {
543                                 HTLCStatus::Pending => "pending",
544                                 HTLCStatus::Succeeded => "succeeded",
545                                 HTLCStatus::Failed => "failed",
546                         }
547                 );
548
549                 println!("\t}},");
550         }
551
552         for (payment_hash, payment_info) in outbound.deref() {
553                 println!("");
554                 println!("\t{{");
555                 println!("\t\tamount_millisatoshis: {},", payment_info.amt_msat);
556                 println!("\t\tpayment_hash: {},", hex_utils::hex_str(&payment_hash.0));
557                 println!("\t\thtlc_direction: outbound,");
558                 println!(
559                         "\t\thtlc_status: {},",
560                         match payment_info.status {
561                                 HTLCStatus::Pending => "pending",
562                                 HTLCStatus::Succeeded => "succeeded",
563                                 HTLCStatus::Failed => "failed",
564                         }
565                 );
566
567                 println!("\t}},");
568         }
569         println!("]");
570 }
571
572 pub(crate) async fn connect_peer_if_necessary(
573         pubkey: PublicKey, peer_addr: SocketAddr, peer_manager: Arc<PeerManager>,
574 ) -> Result<(), ()> {
575         for (node_pubkey, _) in peer_manager.get_peer_node_ids() {
576                 if node_pubkey == pubkey {
577                         return Ok(());
578                 }
579         }
580         let res = do_connect_peer(pubkey, peer_addr, peer_manager).await;
581         if res.is_err() {
582                 println!("ERROR: failed to connect to peer");
583         }
584         res
585 }
586
587 pub(crate) async fn do_connect_peer(
588         pubkey: PublicKey, peer_addr: SocketAddr, peer_manager: Arc<PeerManager>,
589 ) -> Result<(), ()> {
590         match lightning_net_tokio::connect_outbound(Arc::clone(&peer_manager), pubkey, peer_addr).await
591         {
592                 Some(connection_closed_future) => {
593                         let mut connection_closed_future = Box::pin(connection_closed_future);
594                         loop {
595                                 tokio::select! {
596                                         _ = &mut connection_closed_future => return Err(()),
597                                         _ = tokio::time::sleep(Duration::from_millis(10)) => {},
598                                 };
599                                 if peer_manager.get_peer_node_ids().iter().find(|(id, _)| *id == pubkey).is_some() {
600                                         return Ok(());
601                                 }
602                         }
603                 }
604                 None => Err(()),
605         }
606 }
607
608 fn do_disconnect_peer(
609         pubkey: bitcoin::secp256k1::PublicKey, peer_manager: Arc<PeerManager>,
610         channel_manager: Arc<ChannelManager>,
611 ) -> Result<(), ()> {
612         //check for open channels with peer
613         for channel in channel_manager.list_channels() {
614                 if channel.counterparty.node_id == pubkey {
615                         println!("Error: Node has an active channel with this peer, close any channels first");
616                         return Err(());
617                 }
618         }
619
620         //check the pubkey matches a valid connected peer
621         let peers = peer_manager.get_peer_node_ids();
622         if !peers.iter().any(|(pk, _)| &pubkey == pk) {
623                 println!("Error: Could not find peer {}", pubkey);
624                 return Err(());
625         }
626
627         peer_manager.disconnect_by_node_id(pubkey);
628         Ok(())
629 }
630
631 fn open_channel(
632         peer_pubkey: PublicKey, channel_amt_sat: u64, announced_channel: bool,
633         channel_manager: Arc<ChannelManager>,
634 ) -> Result<(), ()> {
635         let config = UserConfig {
636                 channel_handshake_limits: ChannelHandshakeLimits {
637                         // lnd's max to_self_delay is 2016, so we want to be compatible.
638                         their_to_self_delay: 2016,
639                         ..Default::default()
640                 },
641                 channel_handshake_config: ChannelHandshakeConfig {
642                         announced_channel,
643                         ..Default::default()
644                 },
645                 ..Default::default()
646         };
647
648         match channel_manager.create_channel(peer_pubkey, channel_amt_sat, 0, 0, Some(config)) {
649                 Ok(_) => {
650                         println!("EVENT: initiated channel with peer {}. ", peer_pubkey);
651                         return Ok(());
652                 }
653                 Err(e) => {
654                         println!("ERROR: failed to open channel: {:?}", e);
655                         return Err(());
656                 }
657         }
658 }
659
660 fn send_payment(
661         channel_manager: &ChannelManager, invoice: &Invoice, payment_storage: PaymentInfoStorage,
662 ) {
663         let status =
664                 match pay_invoice(invoice, Retry::Timeout(Duration::from_secs(10)), channel_manager) {
665                         Ok(_payment_id) => {
666                                 let payee_pubkey = invoice.recover_payee_pub_key();
667                                 let amt_msat = invoice.amount_milli_satoshis().unwrap();
668                                 println!("EVENT: initiated sending {} msats to {}", amt_msat, payee_pubkey);
669                                 print!("> ");
670                                 HTLCStatus::Pending
671                         }
672                         Err(e) => {
673                                 println!("ERROR: failed to send payment: {:?}", e);
674                                 print!("> ");
675                                 HTLCStatus::Failed
676                         }
677                 };
678         let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
679         let payment_secret = Some(invoice.payment_secret().clone());
680
681         let mut payments = payment_storage.lock().unwrap();
682         payments.insert(
683                 payment_hash,
684                 PaymentInfo {
685                         preimage: None,
686                         secret: payment_secret,
687                         status,
688                         amt_msat: MillisatAmount(invoice.amount_milli_satoshis()),
689                 },
690         );
691 }
692
693 fn keysend<E: EntropySource>(
694         channel_manager: &ChannelManager, payee_pubkey: PublicKey, amt_msat: u64, entropy_source: &E,
695         payment_storage: PaymentInfoStorage,
696 ) {
697         let payment_preimage = PaymentPreimage(entropy_source.get_secure_random_bytes());
698         let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
699
700         let route_params = RouteParameters {
701                 payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
702                 final_value_msat: amt_msat,
703         };
704         let status = match channel_manager.send_spontaneous_payment_with_retry(
705                 Some(payment_preimage),
706                 PaymentId(payment_hash.0),
707                 route_params,
708                 Retry::Timeout(Duration::from_secs(10)),
709         ) {
710                 Ok(_payment_hash) => {
711                         println!("EVENT: initiated sending {} msats to {}", amt_msat, payee_pubkey);
712                         print!("> ");
713                         HTLCStatus::Pending
714                 }
715                 Err(e) => {
716                         println!("ERROR: failed to send payment: {:?}", e);
717                         print!("> ");
718                         HTLCStatus::Failed
719                 }
720         };
721
722         let mut payments = payment_storage.lock().unwrap();
723         payments.insert(
724                 payment_hash,
725                 PaymentInfo {
726                         preimage: None,
727                         secret: None,
728                         status,
729                         amt_msat: MillisatAmount(Some(amt_msat)),
730                 },
731         );
732 }
733
734 fn get_invoice(
735         amt_msat: u64, payment_storage: PaymentInfoStorage, channel_manager: &ChannelManager,
736         keys_manager: Arc<KeysManager>, network: Network, expiry_secs: u32,
737         logger: Arc<disk::FilesystemLogger>,
738 ) {
739         let mut payments = payment_storage.lock().unwrap();
740         let currency = match network {
741                 Network::Bitcoin => Currency::Bitcoin,
742                 Network::Testnet => Currency::BitcoinTestnet,
743                 Network::Regtest => Currency::Regtest,
744                 Network::Signet => Currency::Signet,
745         };
746         let invoice = match utils::create_invoice_from_channelmanager(
747                 channel_manager,
748                 keys_manager,
749                 logger,
750                 currency,
751                 Some(amt_msat),
752                 "ldk-tutorial-node".to_string(),
753                 expiry_secs,
754                 None,
755         ) {
756                 Ok(inv) => {
757                         println!("SUCCESS: generated invoice: {}", inv);
758                         inv
759                 }
760                 Err(e) => {
761                         println!("ERROR: failed to create invoice: {:?}", e);
762                         return;
763                 }
764         };
765
766         let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
767         payments.insert(
768                 payment_hash,
769                 PaymentInfo {
770                         preimage: None,
771                         secret: Some(invoice.payment_secret().clone()),
772                         status: HTLCStatus::Pending,
773                         amt_msat: MillisatAmount(Some(amt_msat)),
774                 },
775         );
776 }
777
778 fn close_channel(
779         channel_id: [u8; 32], counterparty_node_id: PublicKey, channel_manager: Arc<ChannelManager>,
780 ) {
781         match channel_manager.close_channel(&channel_id, &counterparty_node_id) {
782                 Ok(()) => println!("EVENT: initiating channel close"),
783                 Err(e) => println!("ERROR: failed to close channel: {:?}", e),
784         }
785 }
786
787 fn force_close_channel(
788         channel_id: [u8; 32], counterparty_node_id: PublicKey, channel_manager: Arc<ChannelManager>,
789 ) {
790         match channel_manager.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id) {
791                 Ok(()) => println!("EVENT: initiating channel force-close"),
792                 Err(e) => println!("ERROR: failed to force-close channel: {:?}", e),
793         }
794 }
795
796 pub(crate) fn parse_peer_info(
797         peer_pubkey_and_ip_addr: String,
798 ) -> Result<(PublicKey, SocketAddr), std::io::Error> {
799         let mut pubkey_and_addr = peer_pubkey_and_ip_addr.split("@");
800         let pubkey = pubkey_and_addr.next();
801         let peer_addr_str = pubkey_and_addr.next();
802         if peer_addr_str.is_none() {
803                 return Err(std::io::Error::new(
804                         std::io::ErrorKind::Other,
805                         "ERROR: incorrectly formatted peer info. Should be formatted as: `pubkey@host:port`",
806                 ));
807         }
808
809         let peer_addr = peer_addr_str.unwrap().to_socket_addrs().map(|mut r| r.next());
810         if peer_addr.is_err() || peer_addr.as_ref().unwrap().is_none() {
811                 return Err(std::io::Error::new(
812                         std::io::ErrorKind::Other,
813                         "ERROR: couldn't parse pubkey@host:port into a socket address",
814                 ));
815         }
816
817         let pubkey = hex_utils::to_compressed_pubkey(pubkey.unwrap());
818         if pubkey.is_none() {
819                 return Err(std::io::Error::new(
820                         std::io::ErrorKind::Other,
821                         "ERROR: unable to parse given pubkey for node",
822                 ));
823         }
824
825         Ok((pubkey.unwrap(), peer_addr.unwrap().unwrap()))
826 }