Skip to content

Commit 32e7096

Browse files
committed
refactor: decompose connecting w/ peer & opening a channel
What this commit does: + Decomposes connect_open_channel into two different functions: open_channel and open_announced_channel. This allows opening announced channels based on configured node alias and listening addresses values. + This enforces channel announcement only on the condition that both configuration values are set. + Additionally, a new error variant `OpenAnnouncedChannelFailed` is introduced to capture failure. Note: I thought I added the `InvalidNodeAlias` variant in the previous commit
1 parent 81a0f4d commit 32e7096

File tree

4 files changed

+118
-16
lines changed

4 files changed

+118
-16
lines changed

bindings/ldk_node.udl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ interface Node {
7272
[Throws=NodeError]
7373
void disconnect(PublicKey node_id);
7474
[Throws=NodeError]
75-
UserChannelId connect_open_channel(PublicKey node_id, SocketAddress address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config, boolean announce_channel);
75+
UserChannelId open_channel(PublicKey node_id, SocketAddress address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
76+
[Throws=NodeError]
77+
UserChannelId open_announced_channel(PublicKey node_id, SocketAddress address, u64 channel_amount_sats, u64? push_to_counterparty_msat, ChannelConfig? channel_config);
7678
[Throws=NodeError]
7779
void close_channel([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id);
7880
[Throws=NodeError]
@@ -211,6 +213,7 @@ enum NodeError {
211213
"InsufficientFunds",
212214
"LiquiditySourceUnavailable",
213215
"LiquidityFeeTooHigh",
216+
"OpenAnnouncedChannelFailed"
214217
};
215218

216219
dictionary NodeStatus {

src/config.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ pub struct Config {
111111
/// The used Bitcoin network.
112112
pub network: Network,
113113
/// The addresses on which the node will listen for incoming connections.
114+
///
115+
/// **Note**: Node announcements will only be broadcast if the node_alias and the
116+
/// listening_addresses are set.
114117
pub listening_addresses: Option<Vec<SocketAddress>>,
115118
/// The time in-between background sync attempts of the onchain wallet, in seconds.
116119
///
@@ -272,6 +275,17 @@ pub fn default_config() -> Config {
272275
Config::default()
273276
}
274277

278+
/// Checks if a node is can announce a channel based on the configured values of both the node's
279+
/// alias and its listening addresses. If either of them is unset, the node cannot announce the
280+
/// channel.
281+
pub fn can_announce_channel(config: &Config) -> bool {
282+
let are_addresses_set =
283+
config.listening_addresses.clone().is_some_and(|addr_vec| !addr_vec.is_empty());
284+
let is_alias_set = config.node_alias.is_some();
285+
286+
is_alias_set && are_addresses_set
287+
}
288+
275289
pub(crate) fn default_user_config(config: &Config) -> UserConfig {
276290
// Initialize the default config values.
277291
//
@@ -284,11 +298,50 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
284298
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx =
285299
config.anchor_channels_config.is_some();
286300

287-
if config.listening_addresses.is_none() || config.node_alias.is_none() {
301+
if !can_announce_channel(config) {
288302
user_config.accept_forwards_to_priv_channels = false;
289303
user_config.channel_handshake_config.announced_channel = false;
290304
user_config.channel_handshake_limits.force_announced_channel_preference = true;
291305
}
292306

293307
user_config
294308
}
309+
310+
#[cfg(test)]
311+
mod tests {
312+
use std::str::FromStr;
313+
314+
use lightning::{ln::msgs::SocketAddress, routing::gossip::NodeAlias};
315+
316+
use crate::config::can_announce_channel;
317+
318+
use super::Config;
319+
320+
#[test]
321+
fn node_can_announce_channel() {
322+
// Default configuration with node alias and listening addresses unset
323+
let mut node_config = Config::default();
324+
assert_eq!(can_announce_channel(&node_config), false);
325+
326+
// Set node alias with listening addresses unset
327+
let alias_frm_str = |alias: &str| {
328+
let mut bytes = [0u8; 32];
329+
bytes[..alias.as_bytes().len()].copy_from_slice(alias.as_bytes());
330+
NodeAlias(bytes)
331+
};
332+
node_config.node_alias = Some(alias_frm_str("LDK_Node"));
333+
assert_eq!(can_announce_channel(&node_config), false);
334+
335+
// Set node alias with an empty list of listening addresses
336+
node_config.listening_addresses = Some(vec![]);
337+
assert_eq!(can_announce_channel(&node_config), false);
338+
339+
// Set node alias with a non-empty list of listening addresses
340+
let socket_address =
341+
SocketAddress::from_str("localhost:8000").expect("Socket address conversion failed.");
342+
if let Some(ref mut addresses) = node_config.listening_addresses {
343+
addresses.push(socket_address);
344+
}
345+
assert_eq!(can_announce_channel(&node_config), true);
346+
}
347+
}

src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ pub enum Error {
9898
InvalidUri,
9999
/// The given quantity is invalid.
100100
InvalidQuantity,
101+
/// The given node alias is invalid.
102+
InvalidNodeAlias,
101103
/// A payment with the given hash has already been initiated.
102104
DuplicatePayment,
103105
/// The provided offer was denonminated in an unsupported currency.
@@ -108,6 +110,10 @@ pub enum Error {
108110
LiquiditySourceUnavailable,
109111
/// The given operation failed due to the LSP's required opening fee being too high.
110112
LiquidityFeeTooHigh,
113+
/// Returned when trying to open an announced channel with a peer. This
114+
/// error occurs when a [`crate::Node`'s] alias or listening addresses
115+
/// are unconfigured.
116+
OpenAnnouncedChannelFailed,
111117
}
112118

113119
impl fmt::Display for Error {
@@ -163,6 +169,7 @@ impl fmt::Display for Error {
163169
Self::InvalidNetwork => write!(f, "The given network is invalid."),
164170
Self::InvalidUri => write!(f, "The given URI is invalid."),
165171
Self::InvalidQuantity => write!(f, "The given quantity is invalid."),
172+
Self::InvalidNodeAlias => write!(f, "The given node alias is invalid."),
166173
Self::DuplicatePayment => {
167174
write!(f, "A payment with the given hash has already been initiated.")
168175
},
@@ -178,6 +185,7 @@ impl fmt::Display for Error {
178185
Self::LiquidityFeeTooHigh => {
179186
write!(f, "The given operation failed due to the LSP's required opening fee being too high.")
180187
},
188+
Self::OpenAnnouncedChannelFailed => write!(f, "Failed to open an announced channel."),
181189
}
182190
}
183191
}

src/lib.rs

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
//!
4848
//! let node_id = PublicKey::from_str("NODE_ID").unwrap();
4949
//! let node_addr = SocketAddress::from_str("IP_ADDR:PORT").unwrap();
50-
//! node.connect_open_channel(node_id, node_addr, 10000, None, None, false).unwrap();
50+
//! node.open_channel(node_id, node_addr, 10000, None, None).unwrap();
5151
//!
5252
//! let event = node.wait_next_event();
5353
//! println!("EVENT: {:?}", event);
@@ -63,7 +63,8 @@
6363
//! [`build`]: Builder::build
6464
//! [`start`]: Node::start
6565
//! [`stop`]: Node::stop
66-
//! [`connect_open_channel`]: Node::connect_open_channel
66+
//! [`open_channel`]: Node::open_channel
67+
//! [`open_announced_channel`]: Node::open_announced_channel
6768
//! [`send`]: Bolt11Payment::send
6869
//!
6970
#![cfg_attr(not(feature = "uniffi"), deny(missing_docs))]
@@ -114,15 +115,17 @@ pub use io::utils::generate_entropy_mnemonic;
114115
#[cfg(feature = "uniffi")]
115116
use uniffi_types::*;
116117

118+
pub use builder::sanitize_alias;
117119
#[cfg(feature = "uniffi")]
118120
pub use builder::ArcedNodeBuilder as Builder;
119121
pub use builder::BuildError;
120122
#[cfg(not(feature = "uniffi"))]
121123
pub use builder::NodeBuilder as Builder;
122124

123125
use config::{
124-
default_user_config, LDK_WALLET_SYNC_TIMEOUT_SECS, NODE_ANN_BCAST_INTERVAL,
125-
PEER_RECONNECTION_INTERVAL, RESOLVED_CHANNEL_MONITOR_ARCHIVAL_INTERVAL, RGS_SYNC_INTERVAL,
126+
can_announce_channel, default_user_config, LDK_WALLET_SYNC_TIMEOUT_SECS,
127+
NODE_ANN_BCAST_INTERVAL, PEER_RECONNECTION_INTERVAL,
128+
RESOLVED_CHANNEL_MONITOR_ARCHIVAL_INTERVAL, RGS_SYNC_INTERVAL,
126129
WALLET_SYNC_INTERVAL_MINIMUM_SECS,
127130
};
128131
use connection::ConnectionManager;
@@ -601,7 +604,8 @@ impl Node {
601604
let bcast_logger = Arc::clone(&self.logger);
602605
let bcast_ann_timestamp = Arc::clone(&self.latest_node_announcement_broadcast_timestamp);
603606
let mut stop_bcast = self.stop_sender.subscribe();
604-
let node_alias = self.config().node_alias;
607+
let node_alias = self.config.node_alias.clone();
608+
let can_announce_channel = can_announce_channel(&self.config);
605609
runtime.spawn(async move {
606610
// We check every 30 secs whether our last broadcast is NODE_ANN_BCAST_INTERVAL away.
607611
#[cfg(not(test))]
@@ -646,17 +650,19 @@ impl Node {
646650

647651
let addresses = bcast_config.listening_addresses.clone().unwrap_or(Vec::new());
648652
let alias = node_alias.clone().map(|alias| {
649-
let mut buf = [0_u8; 32];
650-
buf[..alias.as_bytes().len()].copy_from_slice(alias.as_bytes());
651-
buf
653+
alias.0
652654
});
653655

654-
if addresses.is_empty() || alias.is_none() {
656+
if !can_announce_channel {
655657
// Skip if we are not listening on any addresses or if the node alias is not set.
656658
continue;
657659
}
658660

659-
bcast_pm.broadcast_node_announcement([0; 3], alias.unwrap(), addresses);
661+
if let Some(node_alias) = alias {
662+
bcast_pm.broadcast_node_announcement([0; 3], node_alias, addresses);
663+
} else {
664+
continue
665+
}
660666

661667
let unix_time_secs_opt =
662668
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
@@ -1189,10 +1195,9 @@ impl Node {
11891195
/// opening the channel.
11901196
///
11911197
/// Returns a [`UserChannelId`] allowing to locally keep track of the channel.
1192-
pub fn connect_open_channel(
1198+
fn connect_open_channel(
11931199
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
11941200
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
1195-
announce_channel: bool,
11961201
) -> Result<UserChannelId, Error> {
11971202
let rt_lock = self.runtime.read().unwrap();
11981203
if rt_lock.is_none() {
@@ -1254,12 +1259,13 @@ impl Node {
12541259
}
12551260

12561261
let mut user_config = default_user_config(&self.config);
1257-
user_config.channel_handshake_config.announced_channel = announce_channel;
1262+
let can_announce_channel = can_announce_channel(&self.config);
1263+
user_config.channel_handshake_config.announced_channel = can_announce_channel;
12581264
user_config.channel_config = (channel_config.unwrap_or_default()).clone().into();
12591265
// We set the max inflight to 100% for private channels.
12601266
// FIXME: LDK will default to this behavior soon, too, at which point we should drop this
12611267
// manual override.
1262-
if !announce_channel {
1268+
if !can_announce_channel {
12631269
user_config
12641270
.channel_handshake_config
12651271
.max_inbound_htlc_value_in_flight_percent_of_channel = 100;
@@ -1292,6 +1298,38 @@ impl Node {
12921298
}
12931299
}
12941300

1301+
/// Opens a channel with a peer.
1302+
pub fn open_channel(
1303+
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
1304+
push_to_counterparty_msat: Option<u64>, channel_config: Option<Arc<ChannelConfig>>,
1305+
) -> Result<UserChannelId, Error> {
1306+
self.connect_open_channel(
1307+
node_id,
1308+
address,
1309+
channel_amount_sats,
1310+
push_to_counterparty_msat,
1311+
channel_config,
1312+
)
1313+
}
1314+
1315+
/// Opens an announced channel with a peer.
1316+
pub fn open_announced_channel(
1317+
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
1318+
push_to_counterparty_msat: Option<u64>, channel_config: Option<Arc<ChannelConfig>>,
1319+
) -> Result<UserChannelId, Error> {
1320+
if !can_announce_channel(&self.config) {
1321+
return Err(Error::OpenAnnouncedChannelFailed);
1322+
}
1323+
1324+
self.open_channel(
1325+
node_id,
1326+
address,
1327+
channel_amount_sats,
1328+
push_to_counterparty_msat,
1329+
channel_config,
1330+
)
1331+
}
1332+
12951333
/// Manually sync the LDK and BDK wallets with the current chain state and update the fee rate
12961334
/// cache.
12971335
///

0 commit comments

Comments
 (0)