Skip to content

Commit ac2c446

Browse files
committed
Switch to use NetAddress for peer addresses
While we're still blocked on upstream changes, we now switch our peer info to use a newtype around `NetAddress` so that we won't have to break serialization compatibility when the upstream changes becom available post-0.1.
1 parent dbc466b commit ac2c446

File tree

7 files changed

+233
-122
lines changed

7 files changed

+233
-122
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LDK Node is a non-custodial Lightning node in library form. Its central goal is
88
The primary abstraction of the library is the `Node`, which can be retrieved by setting up and configuring a `Builder` to your liking and calling `build()`. `Node` can then be controlled via commands such as `start`, `stop`, `connect_open_channel`, `send_payment`, etc.:
99

1010
```rust
11-
use ldk_node::Builder;
11+
use ldk_node::{Builder, NetAddress};
1212
use ldk_node::lightning_invoice::Invoice;
1313
use ldk_node::bitcoin::secp256k1::PublicKey;
1414
use std::str::FromStr;
@@ -28,7 +28,7 @@ fn main() {
2828
node.sync_wallets().unwrap();
2929

3030
let node_id = PublicKey::from_str("NODE_ID").unwrap();
31-
let node_addr = "IP_ADDR:PORT".parse().unwrap();
31+
let node_addr = NetAddress::from_str("IP_ADDR:PORT").unwrap();
3232
node.connect_open_channel(node_id, node_addr, 10000, None, false).unwrap();
3333

3434
let invoice = Invoice::from_str("INVOICE_STR").unwrap();

bindings/ldk_node.udl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ interface Node {
3636
[Throws=NodeError]
3737
u64 total_onchain_balance_sats();
3838
[Throws=NodeError]
39-
void connect(PublicKey node_id, SocketAddr address, boolean permanently);
39+
void connect(PublicKey node_id, NetAddress address, boolean permanently);
4040
[Throws=NodeError]
4141
void disconnect(PublicKey node_id);
4242
[Throws=NodeError]
43-
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel);
43+
void connect_open_channel(PublicKey node_id, NetAddress address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel);
4444
[Throws=NodeError]
4545
void close_channel([ByRef]ChannelId channel_id, PublicKey counterparty_node_id);
4646
[Throws=NodeError]
@@ -73,7 +73,6 @@ enum NodeError {
7373
"ConnectionFailed",
7474
"InvoiceCreationFailed",
7575
"PaymentFailed",
76-
"PeerInfoParseFailed",
7776
"ChannelCreationFailed",
7877
"ChannelClosingFailed",
7978
"PersistenceFailed",
@@ -83,6 +82,7 @@ enum NodeError {
8382
"TxSyncFailed",
8483
"GossipUpdateFailed",
8584
"InvalidAddress",
85+
"InvalidNetAddress",
8686
"InvalidPublicKey",
8787
"InvalidPaymentHash",
8888
"InvalidPaymentPreimage",
@@ -151,7 +151,7 @@ dictionary ChannelDetails {
151151

152152
dictionary PeerDetails {
153153
PublicKey node_id;
154-
SocketAddr address;
154+
NetAddress address;
155155
boolean is_connected;
156156
};
157157

@@ -161,6 +161,9 @@ typedef string Txid;
161161
[Custom]
162162
typedef string SocketAddr;
163163

164+
[Custom]
165+
typedef string NetAddress;
166+
164167
[Custom]
165168
typedef string PublicKey;
166169

src/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ pub enum Error {
1515
InvoiceCreationFailed,
1616
/// An attempted payment has failed.
1717
PaymentFailed,
18-
/// A given peer info could not be parsed.
19-
PeerInfoParseFailed,
2018
/// A channel could not be opened.
2119
ChannelCreationFailed,
2220
/// A channel could not be closed.
@@ -35,6 +33,8 @@ pub enum Error {
3533
GossipUpdateFailed,
3634
/// The given address is invalid.
3735
InvalidAddress,
36+
/// The given network address is invalid.
37+
InvalidNetAddress,
3838
/// The given public key is invalid.
3939
InvalidPublicKey,
4040
/// The given payment hash is invalid.
@@ -68,7 +68,6 @@ impl fmt::Display for Error {
6868
Self::ConnectionFailed => write!(f, "Network connection closed."),
6969
Self::InvoiceCreationFailed => write!(f, "Failed to create invoice."),
7070
Self::PaymentFailed => write!(f, "Failed to send the given payment."),
71-
Self::PeerInfoParseFailed => write!(f, "Failed to parse the given peer information."),
7271
Self::ChannelCreationFailed => write!(f, "Failed to create channel."),
7372
Self::ChannelClosingFailed => write!(f, "Failed to close channel."),
7473
Self::PersistenceFailed => write!(f, "Failed to persist data."),
@@ -78,6 +77,7 @@ impl fmt::Display for Error {
7877
Self::TxSyncFailed => write!(f, "Failed to sync transactions."),
7978
Self::GossipUpdateFailed => write!(f, "Failed to update gossip data."),
8079
Self::InvalidAddress => write!(f, "The given address is invalid."),
80+
Self::InvalidNetAddress => write!(f, "The given network address is invalid."),
8181
Self::InvalidPublicKey => write!(f, "The given public key is invalid."),
8282
Self::InvalidPaymentHash => write!(f, "The given payment hash is invalid."),
8383
Self::InvalidPaymentPreimage => write!(f, "The given payment preimage is invalid."),

src/lib.rs

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
//! [`send_payment`], etc.:
2727
//!
2828
//! ```no_run
29-
//! use ldk_node::Builder;
29+
//! use ldk_node::{Builder, NetAddress};
3030
//! use ldk_node::lightning_invoice::Invoice;
3131
//! use ldk_node::bitcoin::secp256k1::PublicKey;
3232
//! use std::str::FromStr;
@@ -46,7 +46,7 @@
4646
//! node.sync_wallets().unwrap();
4747
//!
4848
//! let node_id = PublicKey::from_str("NODE_ID").unwrap();
49-
//! let node_addr = "IP_ADDR:PORT".parse().unwrap();
49+
//! let node_addr = NetAddress::from_str("IP_ADDR:PORT").unwrap();
5050
//! node.connect_open_channel(node_id, node_addr, 10000, None, false).unwrap();
5151
//!
5252
//! let invoice = Invoice::from_str("INVOICE_STR").unwrap();
@@ -97,6 +97,8 @@ pub use error::Error as NodeError;
9797
use error::Error;
9898

9999
pub use event::Event;
100+
pub use types::NetAddress;
101+
100102
use event::{EventHandler, EventQueue};
101103
use gossip::GossipSource;
102104
use io::fs_store::FilesystemStore;
@@ -149,7 +151,7 @@ use rand::Rng;
149151
use std::convert::TryInto;
150152
use std::default::Default;
151153
use std::fs;
152-
use std::net::SocketAddr;
154+
use std::net::{SocketAddr, ToSocketAddrs};
153155
use std::str::FromStr;
154156
use std::sync::atomic::{AtomicBool, Ordering};
155157
use std::sync::{Arc, Mutex, RwLock};
@@ -861,7 +863,7 @@ impl Node {
861863
{
862864
if let Some(peer_info) = connect_peer_store.get_peer(&node_id) {
863865
let _ = do_connect_peer(
864-
peer_info.pubkey,
866+
peer_info.node_id,
865867
peer_info.address,
866868
Arc::clone(&connect_pm),
867869
Arc::clone(&connect_logger),
@@ -1013,18 +1015,18 @@ impl Node {
10131015
///
10141016
/// If `permanently` is set to `true`, we'll remember the peer and reconnect to it on restart.
10151017
pub fn connect(
1016-
&self, node_id: PublicKey, address: SocketAddr, permanently: bool,
1018+
&self, node_id: PublicKey, address: NetAddress, permanently: bool,
10171019
) -> Result<(), Error> {
10181020
let rt_lock = self.runtime.read().unwrap();
10191021
if rt_lock.is_none() {
10201022
return Err(Error::NotRunning);
10211023
}
10221024
let runtime = rt_lock.as_ref().unwrap();
10231025

1024-
let peer_info = PeerInfo { pubkey: node_id, address };
1026+
let peer_info = PeerInfo { node_id, address };
10251027

1026-
let con_peer_pubkey = peer_info.pubkey;
1027-
let con_peer_addr = peer_info.address;
1028+
let con_node_id = peer_info.node_id;
1029+
let con_addr = peer_info.address.clone();
10281030
let con_success = Arc::new(AtomicBool::new(false));
10291031
let con_success_cloned = Arc::clone(&con_success);
10301032
let con_logger = Arc::clone(&self.logger);
@@ -1033,8 +1035,7 @@ impl Node {
10331035
tokio::task::block_in_place(move || {
10341036
runtime.block_on(async move {
10351037
let res =
1036-
connect_peer_if_necessary(con_peer_pubkey, con_peer_addr, con_pm, con_logger)
1037-
.await;
1038+
connect_peer_if_necessary(con_node_id, con_addr, con_pm, con_logger).await;
10381039
con_success_cloned.store(res.is_ok(), Ordering::Release);
10391040
})
10401041
});
@@ -1043,7 +1044,7 @@ impl Node {
10431044
return Err(Error::ConnectionFailed);
10441045
}
10451046

1046-
log_info!(self.logger, "Connected to peer {}@{}. ", peer_info.pubkey, peer_info.address,);
1047+
log_info!(self.logger, "Connected to peer {}@{}. ", peer_info.node_id, peer_info.address);
10471048

10481049
if permanently {
10491050
self.peer_store.add_peer(peer_info)?;
@@ -1085,7 +1086,7 @@ impl Node {
10851086
///
10861087
/// Returns a temporary channel id.
10871088
pub fn connect_open_channel(
1088-
&self, node_id: PublicKey, address: SocketAddr, channel_amount_sats: u64,
1089+
&self, node_id: PublicKey, address: NetAddress, channel_amount_sats: u64,
10891090
push_to_counterparty_msat: Option<u64>, announce_channel: bool,
10901091
) -> Result<(), Error> {
10911092
let rt_lock = self.runtime.read().unwrap();
@@ -1100,10 +1101,10 @@ impl Node {
11001101
return Err(Error::InsufficientFunds);
11011102
}
11021103

1103-
let peer_info = PeerInfo { pubkey: node_id, address };
1104+
let peer_info = PeerInfo { node_id, address };
11041105

1105-
let con_peer_pubkey = peer_info.pubkey;
1106-
let con_peer_addr = peer_info.address;
1106+
let con_node_id = peer_info.node_id;
1107+
let con_addr = peer_info.address.clone();
11071108
let con_success = Arc::new(AtomicBool::new(false));
11081109
let con_success_cloned = Arc::clone(&con_success);
11091110
let con_logger = Arc::clone(&self.logger);
@@ -1112,8 +1113,7 @@ impl Node {
11121113
tokio::task::block_in_place(move || {
11131114
runtime.block_on(async move {
11141115
let res =
1115-
connect_peer_if_necessary(con_peer_pubkey, con_peer_addr, con_pm, con_logger)
1116-
.await;
1116+
connect_peer_if_necessary(con_node_id, con_addr, con_pm, con_logger).await;
11171117
con_success_cloned.store(res.is_ok(), Ordering::Release);
11181118
})
11191119
});
@@ -1139,7 +1139,7 @@ impl Node {
11391139
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
11401140

11411141
match self.channel_manager.create_channel(
1142-
peer_info.pubkey,
1142+
peer_info.node_id,
11431143
channel_amount_sats,
11441144
push_msat,
11451145
user_channel_id,
@@ -1149,7 +1149,7 @@ impl Node {
11491149
log_info!(
11501150
self.logger,
11511151
"Initiated channel creation with peer {}. ",
1152-
peer_info.pubkey
1152+
peer_info.node_id
11531153
);
11541154
self.peer_store.add_peer(peer_info)?;
11551155
Ok(())
@@ -1550,9 +1550,9 @@ impl Node {
15501550
.list_peers()
15511551
.iter()
15521552
.map(|p| PeerDetails {
1553-
node_id: p.pubkey,
1554-
address: p.address,
1555-
is_connected: active_connected_peers.contains(&p.pubkey),
1553+
node_id: p.node_id,
1554+
address: p.address.clone(),
1555+
is_connected: active_connected_peers.contains(&p.node_id),
15561556
})
15571557
.collect()
15581558
}
@@ -1581,44 +1581,55 @@ impl Drop for Node {
15811581
}
15821582

15831583
async fn connect_peer_if_necessary(
1584-
pubkey: PublicKey, peer_addr: SocketAddr, peer_manager: Arc<PeerManager>,
1584+
node_id: PublicKey, addr: NetAddress, peer_manager: Arc<PeerManager>,
15851585
logger: Arc<FilesystemLogger>,
15861586
) -> Result<(), Error> {
1587-
for (node_pubkey, _addr) in peer_manager.get_peer_node_ids() {
1588-
if node_pubkey == pubkey {
1587+
for (pman_node_id, _pman_addr) in peer_manager.get_peer_node_ids() {
1588+
if node_id == pman_node_id {
15891589
return Ok(());
15901590
}
15911591
}
15921592

1593-
do_connect_peer(pubkey, peer_addr, peer_manager, logger).await
1593+
do_connect_peer(node_id, addr, peer_manager, logger).await
15941594
}
15951595

15961596
async fn do_connect_peer(
1597-
pubkey: PublicKey, peer_addr: SocketAddr, peer_manager: Arc<PeerManager>,
1597+
node_id: PublicKey, addr: NetAddress, peer_manager: Arc<PeerManager>,
15981598
logger: Arc<FilesystemLogger>,
15991599
) -> Result<(), Error> {
1600-
log_info!(logger, "Connecting to peer: {}@{}", pubkey, peer_addr);
1601-
match lightning_net_tokio::connect_outbound(Arc::clone(&peer_manager), pubkey, peer_addr).await
1600+
log_info!(logger, "Connecting to peer: {}@{}", node_id, addr);
1601+
1602+
let socket_addr = addr
1603+
.to_socket_addrs()
1604+
.map_err(|e| {
1605+
log_error!(logger, "Failed to resolve network address: {}", e);
1606+
Error::InvalidNetAddress
1607+
})?
1608+
.next()
1609+
.ok_or(Error::ConnectionFailed)?;
1610+
1611+
match lightning_net_tokio::connect_outbound(Arc::clone(&peer_manager), node_id, socket_addr)
1612+
.await
16021613
{
16031614
Some(connection_closed_future) => {
16041615
let mut connection_closed_future = Box::pin(connection_closed_future);
16051616
loop {
16061617
match futures::poll!(&mut connection_closed_future) {
16071618
std::task::Poll::Ready(_) => {
1608-
log_info!(logger, "Peer connection closed: {}@{}", pubkey, peer_addr);
1619+
log_info!(logger, "Peer connection closed: {}@{}", node_id, addr);
16091620
return Err(Error::ConnectionFailed);
16101621
}
16111622
std::task::Poll::Pending => {}
16121623
}
16131624
// Avoid blocking the tokio context by sleeping a bit
1614-
match peer_manager.get_peer_node_ids().iter().find(|(id, _addr)| *id == pubkey) {
1625+
match peer_manager.get_peer_node_ids().iter().find(|(id, _addr)| *id == node_id) {
16151626
Some(_) => return Ok(()),
16161627
None => tokio::time::sleep(Duration::from_millis(10)).await,
16171628
}
16181629
}
16191630
}
16201631
None => {
1621-
log_error!(logger, "Failed to connect to peer: {}@{}", pubkey, peer_addr);
1632+
log_error!(logger, "Failed to connect to peer: {}@{}", node_id, addr);
16221633
Err(Error::ConnectionFailed)
16231634
}
16241635
}

0 commit comments

Comments
 (0)