Skip to content

Commit b51f9e8

Browse files
authored
Merge pull request #52 from tnull/2023-03-expose-connect-method
2 parents 2ceb197 + f07ec07 commit b51f9e8

File tree

6 files changed

+127
-118
lines changed

6 files changed

+127
-118
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The primary abstraction of the library is the `Node`, which can be retrieved by
1010
```rust
1111
use ldk_node::Builder;
1212
use ldk_node::lightning_invoice::Invoice;
13+
use ldk_node::bitcoin::secp256k1::PublicKey;
1314
use std::str::FromStr;
1415

1516
fn main() {
@@ -23,13 +24,15 @@ fn main() {
2324
let _funding_address = node.new_funding_address();
2425

2526
// .. fund address ..
26-
27+
2728
node.sync_wallets().unwrap();
2829

29-
node.connect_open_channel("NODE_ID@PEER_ADDR:PORT", 10000, None, false).unwrap();
30+
let node_id = PublicKey::from_str("NODE_ID").unwrap();
31+
let node_addr = "IP_ADDR:PORT".parse().unwrap();
32+
node.connect_open_channel(node_id, node_addr, 10000, None, false).unwrap();
3033

3134
let invoice = Invoice::from_str("INVOICE_STR").unwrap();
32-
node.send_payment(invoice).unwrap();
35+
node.send_payment(&invoice).unwrap();
3336

3437
node.stop().unwrap();
3538
}

src/hex_utils.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use bitcoin::secp256k1::PublicKey;
21
use std::fmt::Write;
32

43
pub fn to_vec(hex: &str) -> Option<Vec<u8>> {
@@ -30,17 +29,3 @@ pub fn to_string(value: &[u8]) -> String {
3029
}
3130
res
3231
}
33-
34-
pub fn to_compressed_pubkey(hex: &str) -> Option<PublicKey> {
35-
if hex.len() != 33 * 2 {
36-
return None;
37-
}
38-
let data = match to_vec(&hex[0..33 * 2]) {
39-
Some(bytes) => bytes,
40-
None => return None,
41-
};
42-
match PublicKey::from_slice(&data) {
43-
Ok(pk) => Some(pk),
44-
Err(_) => None,
45-
}
46-
}

src/lib.rs

Lines changed: 96 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
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() {
@@ -44,10 +45,12 @@
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
//! }
@@ -60,8 +63,8 @@
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

101104
use lightning::chain::keysinterface::EntropySource;
102105
use lightning::chain::{chainmonitor, BestBlock, Confirm, Watch};
103-
use lightning::ln::channelmanager::{self, RecipientOnionFields};
104106
use lightning::ln::channelmanager::{
105-
ChainParameters, ChannelDetails, ChannelManagerReadArgs, PaymentId, Retry,
107+
self, ChainParameters, ChannelDetails, ChannelManagerReadArgs, PaymentId, RecipientOnionFields,
108+
Retry,
106109
};
107110
use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler};
108111
use lightning::ln::{PaymentHash, PaymentPreimage};
@@ -133,7 +136,7 @@ use bitcoin::BlockHash;
133136

134137
use rand::Rng;
135138

136-
use std::convert::{TryFrom, TryInto};
139+
use std::convert::TryInto;
137140
use std::default::Default;
138141
use std::fs;
139142
use 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

Comments
 (0)