2828//! ```no_run
2929//! use ldk_node::Builder;
3030//! use ldk_node::lightning_invoice::Invoice;
31+ //! use ldk_node::bitcoin::secp256k1::PublicKey;
3132//! use std::str::FromStr;
3233//!
3334//! fn main() {
4445//!
4546//! node.sync_wallets().unwrap();
4647//!
47- //! node.connect_open_channel("NODE_ID@PEER_ADDR:PORT", 10000, None, false).unwrap();
48+ //! let node_id = PublicKey::from_str("NODE_ID").unwrap();
49+ //! let node_addr = "IP_ADDR:PORT".parse().unwrap();
50+ //! node.connect_open_channel(node_id, node_addr, 10000, None, false).unwrap();
4851//!
4952//! let invoice = Invoice::from_str("INVOICE_STR").unwrap();
50- //! node.send_payment(invoice).unwrap();
53+ //! node.send_payment(& invoice).unwrap();
5154//!
5255//! node.stop().unwrap();
5356//! }
6063//! [`send_payment`]: Node::send_payment
6164//!
6265#![ deny( missing_docs) ]
63- #![ deny( broken_intra_doc_links) ]
64- #![ deny( private_intra_doc_links) ]
66+ #![ deny( rustdoc :: broken_intra_doc_links) ]
67+ #![ deny( rustdoc :: private_intra_doc_links) ]
6568#![ allow( bare_trait_objects) ]
6669#![ allow( ellipsis_inclusive_range_patterns) ]
6770#![ cfg_attr( docsrs, feature( doc_auto_cfg) ) ]
@@ -100,9 +103,9 @@ use logger::{log_error, log_info, FilesystemLogger, Logger};
100103
101104use lightning:: chain:: keysinterface:: EntropySource ;
102105use lightning:: chain:: { chainmonitor, BestBlock , Confirm , Watch } ;
103- use lightning:: ln:: channelmanager:: { self , RecipientOnionFields } ;
104106use lightning:: ln:: channelmanager:: {
105- ChainParameters , ChannelDetails , ChannelManagerReadArgs , PaymentId , Retry ,
107+ self , ChainParameters , ChannelDetails , ChannelManagerReadArgs , PaymentId , RecipientOnionFields ,
108+ Retry ,
106109} ;
107110use lightning:: ln:: peer_handler:: { IgnoringMessageHandler , MessageHandler } ;
108111use lightning:: ln:: { PaymentHash , PaymentPreimage } ;
@@ -133,7 +136,7 @@ use bitcoin::BlockHash;
133136
134137use rand:: Rng ;
135138
136- use std:: convert:: { TryFrom , TryInto } ;
139+ use std:: convert:: TryInto ;
137140use std:: default:: Default ;
138141use std:: fs;
139142use std:: net:: SocketAddr ;
@@ -167,7 +170,7 @@ pub struct Config {
167170 /// The used Bitcoin network.
168171 pub network : bitcoin:: Network ,
169172 /// The IP address and TCP port the node will listen on.
170- pub listening_address : Option < String > ,
173+ pub listening_address : Option < SocketAddr > ,
171174 /// The default CLTV expiry delta to be used for payments.
172175 pub default_cltv_expiry_delta : u32 ,
173176}
@@ -178,7 +181,7 @@ impl Default for Config {
178181 storage_dir_path : "/tmp/ldk_node/" . to_string ( ) ,
179182 esplora_server_url : "http://localhost:3002" . to_string ( ) ,
180183 network : bitcoin:: Network :: Regtest ,
181- listening_address : Some ( "0.0.0.0:9735" . to_string ( ) ) ,
184+ listening_address : Some ( "0.0.0.0:9735" . parse ( ) . unwrap ( ) ) ,
182185 default_cltv_expiry_delta : 144 ,
183186 }
184187 }
@@ -262,9 +265,8 @@ impl Builder {
262265
263266 /// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
264267 ///
265- /// Format: `ADDR:PORT`
266268 /// Default: `0.0.0.0:9735`
267- pub fn set_listening_address ( & mut self , listening_address : String ) -> & mut Self {
269+ pub fn set_listening_address ( & mut self , listening_address : SocketAddr ) -> & mut Self {
268270 self . config . listening_address = Some ( listening_address) ;
269271 self
270272 }
@@ -819,9 +821,9 @@ impl Node {
819821 self . channel_manager . get_our_node_id ( )
820822 }
821823
822- /// Returns our own listening address and port .
823- pub fn listening_address ( & self ) -> Option < String > {
824- self . config . listening_address . clone ( )
824+ /// Returns our own listening address.
825+ pub fn listening_address ( & self ) -> Option < & SocketAddr > {
826+ self . config . listening_address . as_ref ( )
825827 }
826828
827829 /// Retrieve a new on-chain/funding address.
@@ -841,7 +843,74 @@ impl Node {
841843 self . channel_manager . list_channels ( )
842844 }
843845
844- /// Connect to a node and opens a new channel.
846+ /// Connect to a node on the peer-to-peer network.
847+ ///
848+ /// If `permanently` is set to `true`, we'll remember the peer and reconnect to it on restart.
849+ pub fn connect (
850+ & self , node_id : PublicKey , address : SocketAddr , permanently : bool ,
851+ ) -> Result < ( ) , Error > {
852+ let runtime_lock = self . running . read ( ) . unwrap ( ) ;
853+ if runtime_lock. is_none ( ) {
854+ return Err ( Error :: NotRunning ) ;
855+ }
856+
857+ let runtime = runtime_lock. as_ref ( ) . unwrap ( ) ;
858+
859+ let peer_info = PeerInfo { pubkey : node_id, address } ;
860+
861+ let con_peer_pubkey = peer_info. pubkey ;
862+ let con_peer_addr = peer_info. address ;
863+ let con_success = Arc :: new ( AtomicBool :: new ( false ) ) ;
864+ let con_success_cloned = Arc :: clone ( & con_success) ;
865+ let con_logger = Arc :: clone ( & self . logger ) ;
866+ let con_pm = Arc :: clone ( & self . peer_manager ) ;
867+
868+ tokio:: task:: block_in_place ( move || {
869+ runtime. tokio_runtime . block_on ( async move {
870+ let res =
871+ connect_peer_if_necessary ( con_peer_pubkey, con_peer_addr, con_pm, con_logger)
872+ . await ;
873+ con_success_cloned. store ( res. is_ok ( ) , Ordering :: Release ) ;
874+ } )
875+ } ) ;
876+
877+ if !con_success. load ( Ordering :: Acquire ) {
878+ return Err ( Error :: ConnectionFailed ) ;
879+ }
880+
881+ log_info ! ( self . logger, "Connected to peer {}@{}. " , peer_info. pubkey, peer_info. address, ) ;
882+
883+ if permanently {
884+ self . peer_store . add_peer ( peer_info) ?;
885+ }
886+
887+ Ok ( ( ) )
888+ }
889+
890+ /// Disconnects the peer with the given node id.
891+ ///
892+ /// Will also remove the peer from the peer store, i.e., after this has been called we won't
893+ /// try to reconnect on restart.
894+ pub fn disconnect ( & self , counterparty_node_id : & PublicKey ) -> Result < ( ) , Error > {
895+ let runtime_lock = self . running . read ( ) . unwrap ( ) ;
896+ if runtime_lock. is_none ( ) {
897+ return Err ( Error :: NotRunning ) ;
898+ }
899+
900+ log_info ! ( self . logger, "Disconnecting peer {}.." , counterparty_node_id) ;
901+
902+ match self . peer_store . remove_peer ( & counterparty_node_id) {
903+ Ok ( ( ) ) => { }
904+ Err ( e) => {
905+ log_error ! ( self . logger, "Failed to remove peer {}: {}" , counterparty_node_id, e)
906+ }
907+ }
908+
909+ self . peer_manager . disconnect_by_node_id ( * counterparty_node_id) ;
910+ Ok ( ( ) )
911+ }
912+
913+ /// Connect to a node and open a new channel. Disconnects and re-connects are handled automatically
845914 ///
846915 /// Disconnects and reconnects are handled automatically.
847916 ///
@@ -851,7 +920,7 @@ impl Node {
851920 ///
852921 /// Returns a temporary channel id.
853922 pub fn connect_open_channel (
854- & self , node_pubkey_and_address : & str , channel_amount_sats : u64 ,
923+ & self , node_id : PublicKey , address : SocketAddr , channel_amount_sats : u64 ,
855924 push_to_counterparty_msat : Option < u64 > , announce_channel : bool ,
856925 ) -> Result < ( ) , Error > {
857926 let runtime_lock = self . running . read ( ) . unwrap ( ) ;
@@ -867,10 +936,10 @@ impl Node {
867936 return Err ( Error :: InsufficientFunds ) ;
868937 }
869938
870- let peer_info = PeerInfo :: try_from ( node_pubkey_and_address . to_string ( ) ) ? ;
939+ let peer_info = PeerInfo { pubkey : node_id , address } ;
871940
872- let con_peer_pubkey = peer_info. pubkey . clone ( ) ;
873- let con_peer_addr = peer_info. address . clone ( ) ;
941+ let con_peer_pubkey = peer_info. pubkey ;
942+ let con_peer_addr = peer_info. address ;
874943 let con_success = Arc :: new ( AtomicBool :: new ( false ) ) ;
875944 let con_success_cloned = Arc :: clone ( & con_success) ;
876945 let con_logger = Arc :: clone ( & self . logger ) ;
@@ -913,12 +982,12 @@ impl Node {
913982 Some ( user_config) ,
914983 ) {
915984 Ok ( _) => {
916- self . peer_store . add_peer ( peer_info. clone ( ) ) ?;
917985 log_info ! (
918986 self . logger,
919987 "Initiated channel creation with peer {}. " ,
920988 peer_info. pubkey
921989 ) ;
990+ self . peer_store . add_peer ( peer_info) ?;
922991 Ok ( ( ) )
923992 }
924993 Err ( e) => {
@@ -1005,7 +1074,7 @@ impl Node {
10051074 }
10061075
10071076 /// Send a payement given an invoice.
1008- pub fn send_payment ( & self , invoice : Invoice ) -> Result < PaymentHash , Error > {
1077+ pub fn send_payment ( & self , invoice : & Invoice ) -> Result < PaymentHash , Error > {
10091078 if self . running . read ( ) . unwrap ( ) . is_none ( ) {
10101079 return Err ( Error :: NotRunning ) ;
10111080 }
@@ -1070,7 +1139,7 @@ impl Node {
10701139 /// This can be used to pay a so-called "zero-amount" invoice, i.e., an invoice that leaves the
10711140 /// amount paid to be determined by the user.
10721141 pub fn send_payment_using_amount (
1073- & self , invoice : Invoice , amount_msat : u64 ,
1142+ & self , invoice : & Invoice , amount_msat : u64 ,
10741143 ) -> Result < PaymentHash , Error > {
10751144 if self . running . read ( ) . unwrap ( ) . is_none ( ) {
10761145 return Err ( Error :: NotRunning ) ;
@@ -1158,20 +1227,18 @@ impl Node {
11581227
11591228 /// Send a spontaneous, aka. "keysend", payment
11601229 pub fn send_spontaneous_payment (
1161- & self , amount_msat : u64 , node_id : & str ,
1230+ & self , amount_msat : u64 , node_id : & PublicKey ,
11621231 ) -> Result < PaymentHash , Error > {
11631232 if self . running . read ( ) . unwrap ( ) . is_none ( ) {
11641233 return Err ( Error :: NotRunning ) ;
11651234 }
11661235
1167- let pubkey = hex_utils:: to_compressed_pubkey ( node_id) . ok_or ( Error :: PeerInfoParseFailed ) ?;
1168-
11691236 let payment_preimage = PaymentPreimage ( self . keys_manager . get_secure_random_bytes ( ) ) ;
11701237 let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
11711238
11721239 let route_params = RouteParameters {
11731240 payment_params : PaymentParameters :: from_node_id (
1174- pubkey ,
1241+ * node_id ,
11751242 self . config . default_cltv_expiry_delta ,
11761243 ) ,
11771244 final_value_msat : amount_msat,
@@ -1330,15 +1397,15 @@ async fn do_connect_peer(
13301397 pubkey : PublicKey , peer_addr : SocketAddr , peer_manager : Arc < PeerManager > ,
13311398 logger : Arc < FilesystemLogger > ,
13321399) -> Result < ( ) , Error > {
1333- log_info ! ( logger, "connecting to peer: {}@{}" , pubkey, peer_addr) ;
1400+ log_info ! ( logger, "Connecting to peer: {}@{}" , pubkey, peer_addr) ;
13341401 match lightning_net_tokio:: connect_outbound ( Arc :: clone ( & peer_manager) , pubkey, peer_addr) . await
13351402 {
13361403 Some ( connection_closed_future) => {
13371404 let mut connection_closed_future = Box :: pin ( connection_closed_future) ;
13381405 loop {
13391406 match futures:: poll!( & mut connection_closed_future) {
13401407 std:: task:: Poll :: Ready ( _) => {
1341- log_info ! ( logger, "peer connection closed: {}@{}" , pubkey, peer_addr) ;
1408+ log_info ! ( logger, "Peer connection closed: {}@{}" , pubkey, peer_addr) ;
13421409 return Err ( Error :: ConnectionFailed ) ;
13431410 }
13441411 std:: task:: Poll :: Pending => { }
@@ -1351,7 +1418,7 @@ async fn do_connect_peer(
13511418 }
13521419 }
13531420 None => {
1354- log_error ! ( logger, "failed to connect to peer: {}@{}" , pubkey, peer_addr) ;
1421+ log_error ! ( logger, "Failed to connect to peer: {}@{}" , pubkey, peer_addr) ;
13551422 Err ( Error :: ConnectionFailed )
13561423 }
13571424 }
0 commit comments