Skip to content

Commit a740401

Browse files
committed
refactor: improve channel announcement logic and fix binding tests
This commit addresses changes necessary to: - fix failing tests for generated bindings - remove unnecessary error variant previously introduced to capture failure associated with opening announced channels, and re-use existing variants that better capture the reasons, i.e. `InvalidNodeAlias` and `InvalidSocketAddress`, why opening an announced channel failed. - correct visibility specifiers for objects, and - cleanup nitpicks Specific modifications across several files include: - updating the UDL file, as well as tests related to python and kotlin that call `open_channel` and/or open_announced_channel - repositioning/rearranging methods and struct fields - introducing enums (`ChannelAnnouncementStatus` & `ChannelAnnouncementBlocker`) to capture and codify channel announceable eligibility, providing reasons for unannounceable channels - modifying `can_announce_channel` to utilize the aforementioned enums, as opposed to simply returning a boolean value. - cleaning up and renaming `connect_open_channel` to `open_channel_inner`, and maintaining a boolean flag for channel announcement - updating documentation, unit, and integration tests that factor all these changes
1 parent 6aff282 commit a740401

File tree

9 files changed

+194
-107
lines changed

9 files changed

+194
-107
lines changed

bindings/kotlin/ldk-node-jvm/lib/src/test/kotlin/org/lightningdevkit/ldknode/LibraryTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class LibraryTest {
175175
assertEquals(100000uL, totalBalance1)
176176
assertEquals(100000uL, totalBalance2)
177177

178-
node1.connectOpenChannel(nodeId2, listenAddress2, 50000u, null, null, true)
178+
node1.openChannel(nodeId2, listenAddress2, 50000u, null, null)
179179

180180
val channelPendingEvent1 = node1.waitNextEvent()
181181
println("Got event: $channelPendingEvent1")

bindings/ldk_node.udl

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ dictionary Config {
88
string? log_dir_path;
99
Network network;
1010
sequence<SocketAddress>? listening_addresses;
11+
NodeAlias? node_alias;
1112
u64 onchain_wallet_sync_interval_secs;
1213
u64 wallet_sync_interval_secs;
1314
u64 fee_rate_cache_update_interval_secs;
@@ -16,7 +17,6 @@ dictionary Config {
1617
LogLevel log_level;
1718
AnchorChannelsConfig? anchor_channels_config;
1819
SendingParameters? sending_parameters;
19-
NodeAlias? node_alias;
2020
};
2121

2222
dictionary AnchorChannelsConfig {
@@ -62,6 +62,7 @@ interface Node {
6262
void event_handled();
6363
PublicKey node_id();
6464
sequence<SocketAddress>? listening_addresses();
65+
NodeAlias? node_alias();
6566
Bolt11Payment bolt11_payment();
6667
Bolt12Payment bolt12_payment();
6768
SpontaneousPayment spontaneous_payment();
@@ -213,7 +214,6 @@ enum NodeError {
213214
"InsufficientFunds",
214215
"LiquiditySourceUnavailable",
215216
"LiquidityFeeTooHigh",
216-
"OpenAnnouncedChannelFailed"
217217
};
218218

219219
dictionary NodeStatus {
@@ -246,7 +246,6 @@ enum BuildError {
246246
"KVStoreSetupFailed",
247247
"WalletSetupFailed",
248248
"LoggerSetupFailed",
249-
"InvalidNodeAlias"
250249
};
251250

252251
[Enum]

bindings/python/src/ldk_node/test_ldk_node.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def test_channel_full_cycle(self):
155155
print("TOTAL 2:", total_balance_2)
156156
self.assertEqual(total_balance_2, 100000)
157157

158-
node_1.connect_open_channel(node_id_2, listening_addresses_2[0], 50000, None, None, True)
158+
node_1.open_channel(node_id_2, listening_addresses_2[0], 50000, None, None)
159159

160160
channel_pending_event_1 = node_1.wait_next_event()
161161
assert isinstance(channel_pending_event_1, Event.CHANNEL_PENDING)

src/builder.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -307,21 +307,22 @@ impl NodeBuilder {
307307
Ok(self)
308308
}
309309

310-
/// Sets the level at which [`Node`] will log messages.
311-
pub fn set_log_level(&mut self, level: LogLevel) -> &mut Self {
312-
self.config.log_level = level;
313-
self
314-
}
315-
316-
/// Sets the alias the [`Node`] will use in its announcement. The provided
317-
/// alias must be a valid UTF-8 string.
310+
/// Sets the alias the [`Node`] will use in its announcement.
311+
///
312+
/// The provided alias must be a valid UTF-8 string.
318313
pub fn set_node_alias(&mut self, node_alias: String) -> Result<&mut Self, BuildError> {
319314
let node_alias = sanitize_alias(&node_alias)?;
320315

321316
self.config.node_alias = Some(node_alias);
322317
Ok(self)
323318
}
324319

320+
/// Sets the level at which [`Node`] will log messages.
321+
pub fn set_log_level(&mut self, level: LogLevel) -> &mut Self {
322+
self.config.log_level = level;
323+
self
324+
}
325+
325326
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
326327
/// previously configured.
327328
pub fn build(&self) -> Result<Node, BuildError> {
@@ -514,16 +515,16 @@ impl ArcedNodeBuilder {
514515
self.inner.write().unwrap().set_listening_addresses(listening_addresses).map(|_| ())
515516
}
516517

517-
/// Sets the level at which [`Node`] will log messages.
518-
pub fn set_log_level(&self, level: LogLevel) {
519-
self.inner.write().unwrap().set_log_level(level);
520-
}
521-
522518
/// Sets the node alias.
523519
pub fn set_node_alias(&self, node_alias: String) -> Result<(), BuildError> {
524520
self.inner.write().unwrap().set_node_alias(node_alias).map(|_| ())
525521
}
526522

523+
/// Sets the level at which [`Node`] will log messages.
524+
pub fn set_log_level(&self, level: LogLevel) {
525+
self.inner.write().unwrap().set_log_level(level);
526+
}
527+
527528
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
528529
/// previously configured.
529530
pub fn build(&self) -> Result<Arc<Node>, BuildError> {
@@ -1070,7 +1071,7 @@ fn seed_bytes_from_config(
10701071
}
10711072

10721073
/// Sanitize the user-provided node alias to ensure that it is a valid protocol-specified UTF-8 string.
1073-
pub fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> {
1074+
pub(crate) fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> {
10741075
let alias = alias_str.trim();
10751076

10761077
// Alias must be 32-bytes long or less.
@@ -1085,9 +1086,7 @@ pub fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> {
10851086

10861087
#[cfg(test)]
10871088
mod tests {
1088-
use lightning::routing::gossip::NodeAlias;
1089-
1090-
use crate::{builder::sanitize_alias, BuildError};
1089+
use super::{sanitize_alias, BuildError, NodeAlias};
10911090

10921091
#[test]
10931092
fn sanitize_empty_node_alias() {

src/config.rs

+81-29
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub(crate) const WALLET_KEYS_SEED_LEN: usize = 64;
8787
/// | `log_dir_path` | None |
8888
/// | `network` | Bitcoin |
8989
/// | `listening_addresses` | None |
90+
/// | `node_alias` | None |
9091
/// | `default_cltv_expiry_delta` | 144 |
9192
/// | `onchain_wallet_sync_interval_secs` | 80 |
9293
/// | `wallet_sync_interval_secs` | 30 |
@@ -112,9 +113,14 @@ pub struct Config {
112113
pub network: Network,
113114
/// The addresses on which the node will listen for incoming connections.
114115
///
115-
/// **Note**: Node announcements will only be broadcast if the node_alias and the
116-
/// listening_addresses are set.
116+
/// **Note**: Node announcements will only be broadcast if the `node_alias` and the
117+
/// `listening_addresses` are set.
117118
pub listening_addresses: Option<Vec<SocketAddress>>,
119+
/// The node alias to be used in announcements.
120+
///
121+
/// **Note**: Node announcements will only be broadcast if the `node_alias` and the
122+
/// `listening_addresses` are set.
123+
pub node_alias: Option<NodeAlias>,
118124
/// The time in-between background sync attempts of the onchain wallet, in seconds.
119125
///
120126
/// **Note:** A minimum of 10 seconds is always enforced.
@@ -167,11 +173,6 @@ pub struct Config {
167173
/// **Note:** If unset, default parameters will be used, and you will be able to override the
168174
/// parameters on a per-payment basis in the corresponding method calls.
169175
pub sending_parameters: Option<SendingParameters>,
170-
/// The node alias to be used in announcements.
171-
///
172-
/// **Note**: Node announcements will only be broadcast if the node_alias and the
173-
/// listening_addresses are set.
174-
pub node_alias: Option<NodeAlias>,
175176
}
176177

177178
impl Default for Config {
@@ -275,33 +276,68 @@ pub fn default_config() -> Config {
275276
Config::default()
276277
}
277278

279+
/// Specifies reasons why a channel cannot be announced.
280+
#[derive(Debug, PartialEq)]
281+
pub(crate) enum ChannelAnnouncementBlocker {
282+
/// The node alias is not set.
283+
MissingNodeAlias,
284+
/// The listening addresses are not set.
285+
MissingListeningAddresses,
286+
// This listening addresses is set but the vector is empty.
287+
EmptyListeningAddresses,
288+
}
289+
290+
/// Enumeration defining the announcement status of a channel.
291+
#[derive(Debug, PartialEq)]
292+
pub(crate) enum ChannelAnnouncementStatus {
293+
/// The channel is announceable.
294+
Announceable,
295+
/// The channel is not announceable.
296+
Unannounceable(ChannelAnnouncementBlocker),
297+
}
298+
278299
/// 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().map_or(false, |addr_vec| !addr_vec.is_empty());
284-
let is_alias_set = config.node_alias.is_some();
285-
286-
is_alias_set && are_addresses_set
300+
/// alias and its listening addresses.
301+
///
302+
/// If either of them is unset, the node cannot announce the channel. This ability to announce/
303+
/// unannounce a channel is codified with `ChannelAnnouncementStatus`
304+
pub(crate) fn can_announce_channel(config: &Config) -> ChannelAnnouncementStatus {
305+
if config.node_alias.is_none() {
306+
return ChannelAnnouncementStatus::Unannounceable(
307+
ChannelAnnouncementBlocker::MissingNodeAlias,
308+
);
309+
}
310+
311+
match &config.listening_addresses {
312+
None => ChannelAnnouncementStatus::Unannounceable(
313+
ChannelAnnouncementBlocker::MissingListeningAddresses,
314+
),
315+
Some(addresses) if addresses.is_empty() => ChannelAnnouncementStatus::Unannounceable(
316+
ChannelAnnouncementBlocker::EmptyListeningAddresses,
317+
),
318+
Some(_) => ChannelAnnouncementStatus::Announceable,
319+
}
287320
}
288321

289322
pub(crate) fn default_user_config(config: &Config) -> UserConfig {
290323
// Initialize the default config values.
291324
//
292-
// Note that methods such as Node::connect_open_channel might override some of the values set
293-
// here, e.g. the ChannelHandshakeConfig, meaning these default values will mostly be relevant
294-
// for inbound channels.
325+
// Note that methods such as Node::open_channel and Node::open_announced_channel might override
326+
// some of the values set here, e.g. the ChannelHandshakeConfig, meaning these default values
327+
// will mostly be relevant for inbound channels.
295328
let mut user_config = UserConfig::default();
296329
user_config.channel_handshake_limits.force_announced_channel_preference = false;
297330
user_config.manually_accept_inbound_channels = true;
298331
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx =
299332
config.anchor_channels_config.is_some();
300333

301-
if !can_announce_channel(config) {
302-
user_config.accept_forwards_to_priv_channels = false;
303-
user_config.channel_handshake_config.announced_channel = false;
304-
user_config.channel_handshake_limits.force_announced_channel_preference = true;
334+
match can_announce_channel(config) {
335+
ChannelAnnouncementStatus::Announceable => (),
336+
ChannelAnnouncementStatus::Unannounceable(_) => {
337+
user_config.accept_forwards_to_priv_channels = false;
338+
user_config.channel_handshake_config.announced_channel = false;
339+
user_config.channel_handshake_limits.force_announced_channel_preference = true;
340+
},
305341
}
306342

307343
user_config
@@ -311,17 +347,23 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
311347
mod tests {
312348
use std::str::FromStr;
313349

314-
use lightning::{ln::msgs::SocketAddress, routing::gossip::NodeAlias};
315-
316-
use crate::config::can_announce_channel;
350+
use crate::config::ChannelAnnouncementStatus;
317351

352+
use super::can_announce_channel;
318353
use super::Config;
354+
use super::NodeAlias;
355+
use super::SocketAddress;
319356

320357
#[test]
321358
fn node_can_announce_channel() {
322359
// Default configuration with node alias and listening addresses unset
323360
let mut node_config = Config::default();
324-
assert_eq!(can_announce_channel(&node_config), false);
361+
assert_eq!(
362+
can_announce_channel(&node_config),
363+
ChannelAnnouncementStatus::Unannounceable(
364+
crate::config::ChannelAnnouncementBlocker::MissingNodeAlias
365+
)
366+
);
325367

326368
// Set node alias with listening addresses unset
327369
let alias_frm_str = |alias: &str| {
@@ -330,18 +372,28 @@ mod tests {
330372
NodeAlias(bytes)
331373
};
332374
node_config.node_alias = Some(alias_frm_str("LDK_Node"));
333-
assert_eq!(can_announce_channel(&node_config), false);
375+
assert_eq!(
376+
can_announce_channel(&node_config),
377+
ChannelAnnouncementStatus::Unannounceable(
378+
crate::config::ChannelAnnouncementBlocker::MissingListeningAddresses
379+
)
380+
);
334381

335382
// Set node alias with an empty list of listening addresses
336383
node_config.listening_addresses = Some(vec![]);
337-
assert_eq!(can_announce_channel(&node_config), false);
384+
assert_eq!(
385+
can_announce_channel(&node_config),
386+
ChannelAnnouncementStatus::Unannounceable(
387+
crate::config::ChannelAnnouncementBlocker::EmptyListeningAddresses
388+
)
389+
);
338390

339391
// Set node alias with a non-empty list of listening addresses
340392
let socket_address =
341393
SocketAddress::from_str("localhost:8000").expect("Socket address conversion failed.");
342394
if let Some(ref mut addresses) = node_config.listening_addresses {
343395
addresses.push(socket_address);
344396
}
345-
assert_eq!(can_announce_channel(&node_config), true);
397+
assert_eq!(can_announce_channel(&node_config), ChannelAnnouncementStatus::Announceable);
346398
}
347399
}

src/error.rs

-5
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,6 @@ pub enum Error {
110110
LiquiditySourceUnavailable,
111111
/// The given operation failed due to the LSP's required opening fee being too high.
112112
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,
117113
}
118114

119115
impl fmt::Display for Error {
@@ -185,7 +181,6 @@ impl fmt::Display for Error {
185181
Self::LiquidityFeeTooHigh => {
186182
write!(f, "The given operation failed due to the LSP's required opening fee being too high.")
187183
},
188-
Self::OpenAnnouncedChannelFailed => write!(f, "Failed to open an announced channel."),
189184
}
190185
}
191186
}

0 commit comments

Comments
 (0)