Skip to content

Commit 3cb0f3f

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 3cb0f3f

File tree

6 files changed

+135
-54
lines changed

6 files changed

+135
-54
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: 15 additions & 6 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
)
@@ -792,7 +792,7 @@ pub async fn splice_in_with_all(
792792

793793
pub(crate) async fn do_channel_full_cycle<E: ElectrumApi>(
794794
node_a: TestNode, node_b: TestNode, bitcoind: &BitcoindClient, electrsd: &E, allow_0conf: bool,
795-
expect_anchor_channel: bool, force_close: bool,
795+
expect_anchor_channel: bool, force_close: bool, connect_first: bool,
796796
) {
797797
let addr_a = node_a.onchain_payment().new_address().unwrap();
798798
let addr_b = node_b.onchain_payment().new_address().unwrap();
@@ -845,13 +845,22 @@ pub(crate) async fn do_channel_full_cycle<E: ElectrumApi>(
845845
assert_eq!(node_a.next_event(), None);
846846
assert_eq!(node_b.next_event(), None);
847847

848+
let addr = node_b.listening_addresses().unwrap().first().unwrap().clone();
849+
let addr_opt = if connect_first {
850+
// set persist=false so we make sure we test that it is persisted with the open
851+
node_a.connect(node_b.node_id(), addr, false).unwrap();
852+
None
853+
} else {
854+
Some(addr)
855+
};
856+
848857
println!("\nA -- open_channel -> B");
849858
let funding_amount_sat = 2_080_000;
850859
let push_msat = (funding_amount_sat / 2) * 1000; // balance the channel
851860
node_a
852861
.open_announced_channel(
853862
node_b.node_id(),
854-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
863+
addr_opt,
855864
funding_amount_sat,
856865
Some(push_msat),
857866
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: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,44 +46,107 @@ async fn channel_full_cycle() {
4646
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
4747
let chain_source = random_chain_source(&bitcoind, &electrsd);
4848
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false);
49-
do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, false)
50-
.await;
49+
do_channel_full_cycle(
50+
node_a,
51+
node_b,
52+
&bitcoind.client,
53+
&electrsd.client,
54+
false,
55+
true,
56+
false,
57+
false,
58+
)
59+
.await;
5160
}
5261

5362
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
5463
async fn channel_full_cycle_force_close() {
5564
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
5665
let chain_source = random_chain_source(&bitcoind, &electrsd);
5766
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false);
58-
do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, true)
59-
.await;
67+
do_channel_full_cycle(
68+
node_a,
69+
node_b,
70+
&bitcoind.client,
71+
&electrsd.client,
72+
false,
73+
true,
74+
true,
75+
false,
76+
)
77+
.await;
6078
}
6179

6280
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
6381
async fn channel_full_cycle_force_close_trusted_no_reserve() {
6482
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
6583
let chain_source = random_chain_source(&bitcoind, &electrsd);
6684
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, true);
67-
do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, true)
68-
.await;
85+
do_channel_full_cycle(
86+
node_a,
87+
node_b,
88+
&bitcoind.client,
89+
&electrsd.client,
90+
false,
91+
true,
92+
true,
93+
false,
94+
)
95+
.await;
6996
}
7097

7198
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
7299
async fn channel_full_cycle_0conf() {
73100
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
74101
let chain_source = random_chain_source(&bitcoind, &electrsd);
75102
let (node_a, node_b) = setup_two_nodes(&chain_source, true, true, false);
76-
do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, true, true, false)
77-
.await;
103+
do_channel_full_cycle(
104+
node_a,
105+
node_b,
106+
&bitcoind.client,
107+
&electrsd.client,
108+
true,
109+
true,
110+
false,
111+
false,
112+
)
113+
.await;
78114
}
79115

80116
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
81117
async fn channel_full_cycle_legacy_staticremotekey() {
82118
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
83119
let chain_source = random_chain_source(&bitcoind, &electrsd);
84120
let (node_a, node_b) = setup_two_nodes(&chain_source, false, false, false);
85-
do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, false, false)
86-
.await;
121+
do_channel_full_cycle(
122+
node_a,
123+
node_b,
124+
&bitcoind.client,
125+
&electrsd.client,
126+
false,
127+
false,
128+
false,
129+
false,
130+
)
131+
.await;
132+
}
133+
134+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
135+
async fn channel_full_cycle_connect_first() {
136+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
137+
let chain_source = random_chain_source(&bitcoind, &electrsd);
138+
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false);
139+
do_channel_full_cycle(
140+
node_a,
141+
node_b,
142+
&bitcoind.client,
143+
&electrsd.client,
144+
false,
145+
true,
146+
false,
147+
true,
148+
)
149+
.await;
87150
}
88151

89152
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
@@ -114,7 +177,7 @@ async fn channel_open_fails_when_funds_insufficient() {
114177
Err(NodeError::InsufficientFunds),
115178
node_a.open_channel(
116179
node_b.node_id(),
117-
node_b.listening_addresses().unwrap().first().unwrap().clone(),
180+
node_b.listening_addresses().unwrap().first().cloned(),
118181
120000,
119182
None,
120183
None,

0 commit comments

Comments
 (0)