28
28
//! ```no_run
29
29
//! use ldk_node::Builder;
30
30
//! use ldk_node::lightning_invoice::Invoice;
31
+ //! use ldk_node::bitcoin::secp256k1::PublicKey;
31
32
//! use std::str::FromStr;
32
33
//!
33
34
//! fn main() {
44
45
//!
45
46
//! node.sync_wallets().unwrap();
46
47
//!
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();
48
51
//!
49
52
//! let invoice = Invoice::from_str("INVOICE_STR").unwrap();
50
- //! node.send_payment(invoice).unwrap();
53
+ //! node.send_payment(& invoice).unwrap();
51
54
//!
52
55
//! node.stop().unwrap();
53
56
//! }
60
63
//! [`send_payment`]: Node::send_payment
61
64
//!
62
65
#![ 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) ]
65
68
#![ allow( bare_trait_objects) ]
66
69
#![ allow( ellipsis_inclusive_range_patterns) ]
67
70
#![ cfg_attr( docsrs, feature( doc_auto_cfg) ) ]
@@ -100,9 +103,9 @@ use logger::{log_error, log_info, FilesystemLogger, Logger};
100
103
101
104
use lightning:: chain:: keysinterface:: EntropySource ;
102
105
use lightning:: chain:: { chainmonitor, BestBlock , Confirm , Watch } ;
103
- use lightning:: ln:: channelmanager:: { self , RecipientOnionFields } ;
104
106
use lightning:: ln:: channelmanager:: {
105
- ChainParameters , ChannelDetails , ChannelManagerReadArgs , PaymentId , Retry ,
107
+ self , ChainParameters , ChannelDetails , ChannelManagerReadArgs , PaymentId , RecipientOnionFields ,
108
+ Retry ,
106
109
} ;
107
110
use lightning:: ln:: peer_handler:: { IgnoringMessageHandler , MessageHandler } ;
108
111
use lightning:: ln:: { PaymentHash , PaymentPreimage } ;
@@ -133,7 +136,7 @@ use bitcoin::BlockHash;
133
136
134
137
use rand:: Rng ;
135
138
136
- use std:: convert:: { TryFrom , TryInto } ;
139
+ use std:: convert:: TryInto ;
137
140
use std:: default:: Default ;
138
141
use std:: fs;
139
142
use std:: net:: SocketAddr ;
@@ -167,7 +170,7 @@ pub struct Config {
167
170
/// The used Bitcoin network.
168
171
pub network : bitcoin:: Network ,
169
172
/// The IP address and TCP port the node will listen on.
170
- pub listening_address : Option < String > ,
173
+ pub listening_address : Option < SocketAddr > ,
171
174
/// The default CLTV expiry delta to be used for payments.
172
175
pub default_cltv_expiry_delta : u32 ,
173
176
}
@@ -178,7 +181,7 @@ impl Default for Config {
178
181
storage_dir_path : "/tmp/ldk_node/" . to_string ( ) ,
179
182
esplora_server_url : "http://localhost:3002" . to_string ( ) ,
180
183
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 ( ) ) ,
182
185
default_cltv_expiry_delta : 144 ,
183
186
}
184
187
}
@@ -262,9 +265,8 @@ impl Builder {
262
265
263
266
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
264
267
///
265
- /// Format: `ADDR:PORT`
266
268
/// 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 {
268
270
self . config . listening_address = Some ( listening_address) ;
269
271
self
270
272
}
@@ -819,9 +821,9 @@ impl Node {
819
821
self . channel_manager . get_our_node_id ( )
820
822
}
821
823
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 ( )
825
827
}
826
828
827
829
/// Retrieve a new on-chain/funding address.
@@ -841,7 +843,74 @@ impl Node {
841
843
self . channel_manager . list_channels ( )
842
844
}
843
845
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
845
914
///
846
915
/// Disconnects and reconnects are handled automatically.
847
916
///
@@ -851,7 +920,7 @@ impl Node {
851
920
///
852
921
/// Returns a temporary channel id.
853
922
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 ,
855
924
push_to_counterparty_msat : Option < u64 > , announce_channel : bool ,
856
925
) -> Result < ( ) , Error > {
857
926
let runtime_lock = self . running . read ( ) . unwrap ( ) ;
@@ -867,10 +936,10 @@ impl Node {
867
936
return Err ( Error :: InsufficientFunds ) ;
868
937
}
869
938
870
- let peer_info = PeerInfo :: try_from ( node_pubkey_and_address . to_string ( ) ) ? ;
939
+ let peer_info = PeerInfo { pubkey : node_id , address } ;
871
940
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 ;
874
943
let con_success = Arc :: new ( AtomicBool :: new ( false ) ) ;
875
944
let con_success_cloned = Arc :: clone ( & con_success) ;
876
945
let con_logger = Arc :: clone ( & self . logger ) ;
@@ -913,12 +982,12 @@ impl Node {
913
982
Some ( user_config) ,
914
983
) {
915
984
Ok ( _) => {
916
- self . peer_store . add_peer ( peer_info. clone ( ) ) ?;
917
985
log_info ! (
918
986
self . logger,
919
987
"Initiated channel creation with peer {}. " ,
920
988
peer_info. pubkey
921
989
) ;
990
+ self . peer_store . add_peer ( peer_info) ?;
922
991
Ok ( ( ) )
923
992
}
924
993
Err ( e) => {
@@ -1005,7 +1074,7 @@ impl Node {
1005
1074
}
1006
1075
1007
1076
/// 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 > {
1009
1078
if self . running . read ( ) . unwrap ( ) . is_none ( ) {
1010
1079
return Err ( Error :: NotRunning ) ;
1011
1080
}
@@ -1070,7 +1139,7 @@ impl Node {
1070
1139
/// This can be used to pay a so-called "zero-amount" invoice, i.e., an invoice that leaves the
1071
1140
/// amount paid to be determined by the user.
1072
1141
pub fn send_payment_using_amount (
1073
- & self , invoice : Invoice , amount_msat : u64 ,
1142
+ & self , invoice : & Invoice , amount_msat : u64 ,
1074
1143
) -> Result < PaymentHash , Error > {
1075
1144
if self . running . read ( ) . unwrap ( ) . is_none ( ) {
1076
1145
return Err ( Error :: NotRunning ) ;
@@ -1158,20 +1227,18 @@ impl Node {
1158
1227
1159
1228
/// Send a spontaneous, aka. "keysend", payment
1160
1229
pub fn send_spontaneous_payment (
1161
- & self , amount_msat : u64 , node_id : & str ,
1230
+ & self , amount_msat : u64 , node_id : & PublicKey ,
1162
1231
) -> Result < PaymentHash , Error > {
1163
1232
if self . running . read ( ) . unwrap ( ) . is_none ( ) {
1164
1233
return Err ( Error :: NotRunning ) ;
1165
1234
}
1166
1235
1167
- let pubkey = hex_utils:: to_compressed_pubkey ( node_id) . ok_or ( Error :: PeerInfoParseFailed ) ?;
1168
-
1169
1236
let payment_preimage = PaymentPreimage ( self . keys_manager . get_secure_random_bytes ( ) ) ;
1170
1237
let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
1171
1238
1172
1239
let route_params = RouteParameters {
1173
1240
payment_params : PaymentParameters :: from_node_id (
1174
- pubkey ,
1241
+ * node_id ,
1175
1242
self . config . default_cltv_expiry_delta ,
1176
1243
) ,
1177
1244
final_value_msat : amount_msat,
@@ -1330,15 +1397,15 @@ async fn do_connect_peer(
1330
1397
pubkey : PublicKey , peer_addr : SocketAddr , peer_manager : Arc < PeerManager > ,
1331
1398
logger : Arc < FilesystemLogger > ,
1332
1399
) -> Result < ( ) , Error > {
1333
- log_info ! ( logger, "connecting to peer: {}@{}" , pubkey, peer_addr) ;
1400
+ log_info ! ( logger, "Connecting to peer: {}@{}" , pubkey, peer_addr) ;
1334
1401
match lightning_net_tokio:: connect_outbound ( Arc :: clone ( & peer_manager) , pubkey, peer_addr) . await
1335
1402
{
1336
1403
Some ( connection_closed_future) => {
1337
1404
let mut connection_closed_future = Box :: pin ( connection_closed_future) ;
1338
1405
loop {
1339
1406
match futures:: poll!( & mut connection_closed_future) {
1340
1407
std:: task:: Poll :: Ready ( _) => {
1341
- log_info ! ( logger, "peer connection closed: {}@{}" , pubkey, peer_addr) ;
1408
+ log_info ! ( logger, "Peer connection closed: {}@{}" , pubkey, peer_addr) ;
1342
1409
return Err ( Error :: ConnectionFailed ) ;
1343
1410
}
1344
1411
std:: task:: Poll :: Pending => { }
@@ -1351,7 +1418,7 @@ async fn do_connect_peer(
1351
1418
}
1352
1419
}
1353
1420
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) ;
1355
1422
Err ( Error :: ConnectionFailed )
1356
1423
}
1357
1424
}
0 commit comments