Skip to content

Commit 02daf3f

Browse files
committed
Make node's address optional when opening channel
Previously we always required providing the node's address when opening a channel, this made the api annoying in some cases as you may already be connected to the peer but still need to provide the socket address. Here we make it optional and will return a `ConnectionFailed` error when the socket address is not provided and we are not connected to the peer.
1 parent 804f00f commit 02daf3f

File tree

6 files changed

+100
-43
lines changed

6 files changed

+100
-43
lines changed

bindings/ldk_node.udl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ interface Node {
105105
[Throws=NodeError]
106106
void disconnect(PublicKey node_id);
107107
[Throws=NodeError]
108-
UserChannelId open_channel(PublicKey node_id, SocketAddress address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
108+
UserChannelId open_channel(PublicKey node_id, SocketAddress? address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
109109
[Throws=NodeError]
110-
UserChannelId open_announced_channel(PublicKey node_id, SocketAddress address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
110+
UserChannelId open_announced_channel(PublicKey node_id, SocketAddress? address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
111111
[Throws=NodeError]
112-
UserChannelId open_channel_with_all(PublicKey node_id, SocketAddress address, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
112+
UserChannelId open_channel_with_all(PublicKey node_id, SocketAddress? address, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
113113
[Throws=NodeError]
114-
UserChannelId open_announced_channel_with_all(PublicKey node_id, SocketAddress address, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
114+
UserChannelId open_announced_channel_with_all(PublicKey node_id, SocketAddress? address, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
115115
[Throws=NodeError]
116116
void splice_in([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id, u64 splice_amount_sats);
117117
[Throws=NodeError]

src/lib.rs

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
//!
5555
//! let node_id = PublicKey::from_str("NODE_ID").unwrap();
5656
//! let node_addr = SocketAddress::from_str("IP_ADDR:PORT").unwrap();
57-
//! node.open_channel(node_id, node_addr, 10000, None, None).unwrap();
57+
//! node.open_channel(node_id, Some(node_addr), 10000, None, None).unwrap();
5858
//!
5959
//! let event = node.wait_next_event();
6060
//! println!("EVENT: {:?}", event);
@@ -1126,39 +1126,47 @@ impl Node {
11261126
}
11271127

11281128
fn open_channel_inner(
1129-
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: FundingAmount,
1130-
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
1131-
announce_for_forwarding: bool,
1129+
&self, node_id: PublicKey, address: Option<SocketAddress>,
1130+
channel_amount_sats: FundingAmount, push_to_counterparty_msat: Option<u64>,
1131+
channel_config: Option<ChannelConfig>, announce_for_forwarding: bool,
11321132
) -> Result<UserChannelId, Error> {
11331133
if !*self.is_running.read().unwrap() {
11341134
return Err(Error::NotRunning);
11351135
}
11361136

1137-
let peer_info = PeerInfo { node_id, address };
1138-
1139-
let con_node_id = peer_info.node_id;
1140-
let con_addr = peer_info.address.clone();
1141-
let con_cm = Arc::clone(&self.connection_manager);
1142-
1143-
// We need to use our main runtime here as a local runtime might not be around to poll
1144-
// connection futures going forward.
1145-
self.runtime.block_on(async move {
1146-
con_cm.connect_peer_if_necessary(con_node_id, con_addr).await
1147-
})?;
1137+
// if we don't have the socket address, check if we are already connected
1138+
let address = match address {
1139+
Some(address) => {
1140+
// We need to use our main runtime here as a local runtime might not be around to poll
1141+
// connection futures going forward.
1142+
let con_cm = Arc::clone(&self.connection_manager);
1143+
let con_addr = address.clone();
1144+
self.runtime.block_on(async move {
1145+
con_cm.connect_peer_if_necessary(node_id, con_addr).await
1146+
})?;
1147+
Some(address)
1148+
},
1149+
None => {
1150+
// If we are connected, grab the socket address as we need to make sure we have it persisted
1151+
// in our peer storage for future reconnections.
1152+
let peer =
1153+
self.peer_manager.peer_by_node_id(&node_id).ok_or(Error::ConnectionFailed)?;
1154+
peer.socket_address
1155+
},
1156+
};
11481157

11491158
let channel_amount_sats = match channel_amount_sats {
11501159
FundingAmount::Exact { amount_sats } => {
11511160
// Check funds availability after connection (includes anchor reserve
11521161
// calculation).
1153-
self.check_sufficient_funds_for_channel(amount_sats, &peer_info.node_id)?;
1162+
self.check_sufficient_funds_for_channel(amount_sats, &node_id)?;
11541163
amount_sats
11551164
},
11561165
FundingAmount::Max => {
11571166
// Determine max funding amount from all available on-chain funds.
11581167
let cur_anchor_reserve_sats =
11591168
total_anchor_channels_reserve_sats(&self.channel_manager, &self.config);
1160-
let new_channel_reserve =
1161-
self.new_channel_anchor_reserve_sats(&peer_info.node_id)?;
1169+
let new_channel_reserve = self.new_channel_anchor_reserve_sats(&node_id)?;
11621170
let total_anchor_reserve_sats = cur_anchor_reserve_sats + new_channel_reserve;
11631171

11641172
let fee_rate =
@@ -1197,20 +1205,21 @@ impl Node {
11971205
);
11981206

11991207
match self.channel_manager.create_channel(
1200-
peer_info.node_id,
1208+
node_id,
12011209
channel_amount_sats,
12021210
push_msat,
12031211
user_channel_id,
12041212
None,
12051213
Some(user_config),
12061214
) {
12071215
Ok(_) => {
1208-
log_info!(
1209-
self.logger,
1210-
"Initiated channel creation with peer {}. ",
1211-
peer_info.node_id
1212-
);
1213-
self.peer_store.add_peer(peer_info)?;
1216+
log_info!(self.logger, "Initiated channel creation with peer {}. ", node_id);
1217+
1218+
if let Some(address) = address {
1219+
let peer_info = PeerInfo { node_id, address };
1220+
self.peer_store.add_peer(peer_info)?;
1221+
}
1222+
12141223
Ok(UserChannelId(user_channel_id))
12151224
},
12161225
Err(e) => {
@@ -1280,7 +1289,7 @@ impl Node {
12801289
///
12811290
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
12821291
pub fn open_channel(
1283-
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
1292+
&self, node_id: PublicKey, address: Option<SocketAddress>, channel_amount_sats: u64,
12841293
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
12851294
) -> Result<UserChannelId, Error> {
12861295
self.open_channel_inner(
@@ -1315,7 +1324,7 @@ impl Node {
13151324
///
13161325
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
13171326
pub fn open_announced_channel(
1318-
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
1327+
&self, node_id: PublicKey, address: Option<SocketAddress>, channel_amount_sats: u64,
13191328
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
13201329
) -> Result<UserChannelId, Error> {
13211330
if let Err(err) = may_announce_channel(&self.config) {
@@ -1348,8 +1357,8 @@ impl Node {
13481357
///
13491358
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
13501359
pub fn open_channel_with_all(
1351-
&self, node_id: PublicKey, address: SocketAddress, push_to_counterparty_msat: Option<u64>,
1352-
channel_config: Option<ChannelConfig>,
1360+
&self, node_id: PublicKey, address: Option<SocketAddress>,
1361+
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
13531362
) -> Result<UserChannelId, Error> {
13541363
self.open_channel_inner(
13551364
node_id,
@@ -1380,8 +1389,8 @@ impl Node {
13801389
///
13811390
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
13821391
pub fn open_announced_channel_with_all(
1383-
&self, node_id: PublicKey, address: SocketAddress, push_to_counterparty_msat: Option<u64>,
1384-
channel_config: Option<ChannelConfig>,
1392+
&self, node_id: PublicKey, address: Option<SocketAddress>,
1393+
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
13851394
) -> Result<UserChannelId, Error> {
13861395
if let Err(err) = may_announce_channel(&self.config) {
13871396
log_error!(self.logger, "Failed to open announced channel as the node hasn't been sufficiently configured to act as a forwarding node: {err}");

tests/common/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ pub async fn open_channel_push_amt(
721721
node_a
722722
.open_announced_channel(
723723
node_b.node_id(),
724-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
724+
node_b.listening_addresses().unwrap().first().cloned(),
725725
funding_amount_sat,
726726
push_amount_msat,
727727
None,
@@ -731,7 +731,7 @@ pub async fn open_channel_push_amt(
731731
node_a
732732
.open_channel(
733733
node_b.node_id(),
734-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
734+
node_b.listening_addresses().unwrap().first().cloned(),
735735
funding_amount_sat,
736736
push_amount_msat,
737737
None,
@@ -755,7 +755,7 @@ pub async fn open_channel_with_all(
755755
node_a
756756
.open_announced_channel_with_all(
757757
node_b.node_id(),
758-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
758+
node_b.listening_addresses().unwrap().first().cloned(),
759759
None,
760760
None,
761761
)
@@ -764,7 +764,7 @@ pub async fn open_channel_with_all(
764764
node_a
765765
.open_channel_with_all(
766766
node_b.node_id(),
767-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
767+
node_b.listening_addresses().unwrap().first().cloned(),
768768
None,
769769
None,
770770
)
@@ -851,7 +851,7 @@ pub(crate) async fn do_channel_full_cycle<E: ElectrumApi>(
851851
node_a
852852
.open_announced_channel(
853853
node_b.node_id(),
854-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
854+
node_b.listening_addresses().unwrap().first().cloned(),
855855
funding_amount_sat,
856856
Some(push_msat),
857857
None,

tests/integration_tests_cln.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ async fn test_cln() {
8989
// Open the channel
9090
let funding_amount_sat = 1_000_000;
9191

92-
node.open_channel(cln_node_id, cln_address, funding_amount_sat, Some(500_000_000), None)
92+
node.open_channel(cln_node_id, Some(cln_address), funding_amount_sat, Some(500_000_000), None)
9393
.unwrap();
9494

9595
let funding_txo = common::expect_channel_pending_event!(node, cln_node_id);

tests/integration_tests_lnd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ async fn test_lnd() {
7070
// Open the channel
7171
let funding_amount_sat = 1_000_000;
7272

73-
node.open_channel(lnd_node_id, lnd_address, funding_amount_sat, Some(500_000_000), None)
73+
node.open_channel(lnd_node_id, Some(lnd_address), funding_amount_sat, Some(500_000_000), None)
7474
.unwrap();
7575

7676
let funding_txo = common::expect_channel_pending_event!(node, lnd_node_id);

tests/integration_tests_rust.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ async fn channel_open_fails_when_funds_insufficient() {
114114
Err(NodeError::InsufficientFunds),
115115
node_a.open_channel(
116116
node_b.node_id(),
117-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
117+
node_b.listening_addresses().unwrap().first().cloned(),
118118
120000,
119119
None,
120120
None,
@@ -877,6 +877,54 @@ async fn do_connection_restart_behavior(persist: bool) {
877877
}
878878
}
879879

880+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
881+
async fn open_channel_with_optional_address() {
882+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
883+
let chain_source = random_chain_source(&bitcoind, &electrsd);
884+
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false);
885+
886+
let addr_a = node_a.onchain_payment().new_address().unwrap();
887+
let addr_b = node_b.onchain_payment().new_address().unwrap();
888+
889+
let premine_amount_sat = 2_125_000;
890+
891+
premine_and_distribute_funds(
892+
&bitcoind.client,
893+
&electrsd.client,
894+
vec![addr_a, addr_b],
895+
Amount::from_sat(premine_amount_sat),
896+
)
897+
.await;
898+
node_a.sync_wallets().unwrap();
899+
node_b.sync_wallets().unwrap();
900+
901+
// Opening a channel with no address and no prior connection should fail.
902+
let res = node_a.open_channel(node_b.node_id(), None, 120000, None, None);
903+
assert_eq!(res, Err(NodeError::ConnectionFailed));
904+
905+
// Connect to the peer with persist=false.
906+
let node_addr_b = node_b.listening_addresses().unwrap().first().unwrap().clone();
907+
node_a.connect(node_b.node_id(), node_addr_b, false).unwrap();
908+
assert!(!node_a.list_peers().first().unwrap().is_persisted);
909+
910+
// Opening a channel with no address should now succeed since we're already connected.
911+
node_a.open_channel(node_b.node_id(), None, 120000, None, None).unwrap();
912+
913+
// The peer should now be persisted after the channel open.
914+
assert!(node_a.list_peers().first().unwrap().is_persisted);
915+
916+
let funding_txo = expect_channel_pending_event!(node_a, node_b.node_id());
917+
expect_channel_pending_event!(node_b, node_a.node_id());
918+
919+
wait_for_tx(&electrsd.client, funding_txo.txid).await;
920+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
921+
node_a.sync_wallets().unwrap();
922+
node_b.sync_wallets().unwrap();
923+
924+
expect_channel_ready_event!(node_a, node_b.node_id());
925+
expect_channel_ready_event!(node_b, node_a.node_id());
926+
}
927+
880928
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
881929
async fn concurrent_connections_succeed() {
882930
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();

0 commit comments

Comments
 (0)