Skip to content

Commit 7528e91

Browse files
authored
Merge pull request #484 from aylagreystone/announced-addresses
Support separate node announcement addresses
2 parents 0dd78ee + 5432ed8 commit 7528e91

File tree

6 files changed

+253
-44
lines changed

6 files changed

+253
-44
lines changed

bindings/ldk_node.udl

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ dictionary Config {
77
string storage_dir_path;
88
Network network;
99
sequence<SocketAddress>? listening_addresses;
10+
sequence<SocketAddress>? announcement_addresses;
1011
NodeAlias? node_alias;
1112
sequence<PublicKey> trusted_peers_0conf;
1213
u64 probing_liquidity_limit_multiplier;
@@ -84,6 +85,8 @@ interface Builder {
8485
[Throws=BuildError]
8586
void set_listening_addresses(sequence<SocketAddress> listening_addresses);
8687
[Throws=BuildError]
88+
void set_announcement_addresses(sequence<SocketAddress> announcement_addresses);
89+
[Throws=BuildError]
8790
void set_node_alias(string node_alias);
8891
[Throws=BuildError]
8992
Node build();
@@ -112,6 +115,7 @@ interface Node {
112115
void event_handled();
113116
PublicKey node_id();
114117
sequence<SocketAddress>? listening_addresses();
118+
sequence<SocketAddress>? announcement_addresses();
115119
NodeAlias? node_alias();
116120
Bolt11Payment bolt11_payment();
117121
Bolt12Payment bolt12_payment();
@@ -319,6 +323,7 @@ enum BuildError {
319323
"InvalidSystemTime",
320324
"InvalidChannelMonitor",
321325
"InvalidListeningAddresses",
326+
"InvalidAnnouncementAddresses",
322327
"InvalidNodeAlias",
323328
"ReadFailed",
324329
"WriteFailed",

src/builder.rs

+52-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
use crate::chain::{ChainSource, DEFAULT_ESPLORA_SERVER_URL};
99
use crate::config::{
10-
default_user_config, Config, EsploraSyncConfig, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
11-
WALLET_KEYS_SEED_LEN,
10+
default_user_config, may_announce_channel, AnnounceError, Config, EsploraSyncConfig,
11+
DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL, WALLET_KEYS_SEED_LEN,
1212
};
1313

1414
use crate::connection::ConnectionManager;
@@ -32,8 +32,7 @@ use crate::types::{
3232
};
3333
use crate::wallet::persist::KVStoreWalletPersister;
3434
use crate::wallet::Wallet;
35-
use crate::Node;
36-
use crate::{io, NodeMetrics};
35+
use crate::{io, Node, NodeMetrics};
3736

3837
use lightning::chain::{chainmonitor, BestBlock, Watch};
3938
use lightning::io::Cursor;
@@ -148,6 +147,8 @@ pub enum BuildError {
148147
InvalidChannelMonitor,
149148
/// The given listening addresses are invalid, e.g. too many were passed.
150149
InvalidListeningAddresses,
150+
/// The given announcement addresses are invalid, e.g. too many were passed.
151+
InvalidAnnouncementAddresses,
151152
/// The provided alias is invalid.
152153
InvalidNodeAlias,
153154
/// We failed to read data from the [`KVStore`].
@@ -184,6 +185,9 @@ impl fmt::Display for BuildError {
184185
write!(f, "Failed to watch a deserialized ChannelMonitor")
185186
},
186187
Self::InvalidListeningAddresses => write!(f, "Given listening addresses are invalid."),
188+
Self::InvalidAnnouncementAddresses => {
189+
write!(f, "Given announcement addresses are invalid.")
190+
},
187191
Self::ReadFailed => write!(f, "Failed to read from store."),
188192
Self::WriteFailed => write!(f, "Failed to write to store."),
189193
Self::StoragePathAccessFailed => write!(f, "Failed to access the given storage path."),
@@ -413,6 +417,22 @@ impl NodeBuilder {
413417
Ok(self)
414418
}
415419

420+
/// Sets the IP address and TCP port which [`Node`] will announce to the gossip network that it accepts connections on.
421+
///
422+
/// **Note**: If unset, the [`listening_addresses`] will be used as the list of addresses to announce.
423+
///
424+
/// [`listening_addresses`]: Self::set_listening_addresses
425+
pub fn set_announcement_addresses(
426+
&mut self, announcement_addresses: Vec<SocketAddress>,
427+
) -> Result<&mut Self, BuildError> {
428+
if announcement_addresses.len() > 100 {
429+
return Err(BuildError::InvalidAnnouncementAddresses);
430+
}
431+
432+
self.config.announcement_addresses = Some(announcement_addresses);
433+
Ok(self)
434+
}
435+
416436
/// Sets the node alias that will be used when broadcasting announcements to the gossip
417437
/// network.
418438
///
@@ -776,6 +796,17 @@ impl ArcedNodeBuilder {
776796
self.inner.write().unwrap().set_listening_addresses(listening_addresses).map(|_| ())
777797
}
778798

799+
/// Sets the IP address and TCP port which [`Node`] will announce to the gossip network that it accepts connections on.
800+
///
801+
/// **Note**: If unset, the [`listening_addresses`] will be used as the list of addresses to announce.
802+
///
803+
/// [`listening_addresses`]: Self::set_listening_addresses
804+
pub fn set_announcement_addresses(
805+
&self, announcement_addresses: Vec<SocketAddress>,
806+
) -> Result<(), BuildError> {
807+
self.inner.write().unwrap().set_announcement_addresses(announcement_addresses).map(|_| ())
808+
}
809+
779810
/// Sets the node alias that will be used when broadcasting announcements to the gossip
780811
/// network.
781812
///
@@ -880,6 +911,23 @@ fn build_with_store_internal(
880911
liquidity_source_config: Option<&LiquiditySourceConfig>, seed_bytes: [u8; 64],
881912
logger: Arc<Logger>, kv_store: Arc<DynStore>,
882913
) -> Result<Node, BuildError> {
914+
if let Err(err) = may_announce_channel(&config) {
915+
if config.announcement_addresses.is_some() {
916+
log_error!(logger, "Announcement addresses were set but some required configuration options for node announcement are missing: {}", err);
917+
let build_error = if matches!(err, AnnounceError::MissingNodeAlias) {
918+
BuildError::InvalidNodeAlias
919+
} else {
920+
BuildError::InvalidListeningAddresses
921+
};
922+
return Err(build_error);
923+
}
924+
925+
if config.node_alias.is_some() {
926+
log_error!(logger, "Node alias was set but some required configuration options for node announcement are missing: {}", err);
927+
return Err(BuildError::InvalidListeningAddresses);
928+
}
929+
}
930+
883931
// Initialize the status fields.
884932
let is_listening = Arc::new(AtomicBool::new(false));
885933
let node_metrics = match read_node_metrics(Arc::clone(&kv_store), Arc::clone(&logger)) {

src/config.rs

+63-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use lightning::util::config::UserConfig;
1919
use bitcoin::secp256k1::PublicKey;
2020
use bitcoin::Network;
2121

22+
use std::fmt;
2223
use std::time::Duration;
2324

2425
// Config defaults
@@ -117,6 +118,12 @@ pub struct Config {
117118
/// **Note**: We will only allow opening and accepting public channels if the `node_alias` and the
118119
/// `listening_addresses` are set.
119120
pub listening_addresses: Option<Vec<SocketAddress>>,
121+
/// The addresses which the node will announce to the gossip network that it accepts connections on.
122+
///
123+
/// **Note**: If unset, the [`listening_addresses`] will be used as the list of addresses to announce.
124+
///
125+
/// [`listening_addresses`]: Config::listening_addresses
126+
pub announcement_addresses: Option<Vec<SocketAddress>>,
120127
/// The node alias that will be used when broadcasting announcements to the gossip network.
121128
///
122129
/// The provided alias must be a valid UTF-8 string and no longer than 32 bytes in total.
@@ -168,6 +175,7 @@ impl Default for Config {
168175
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
169176
network: DEFAULT_NETWORK,
170177
listening_addresses: None,
178+
announcement_addresses: None,
171179
trusted_peers_0conf: Vec::new(),
172180
probing_liquidity_limit_multiplier: DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER,
173181
anchor_channels_config: Some(AnchorChannelsConfig::default()),
@@ -256,9 +264,37 @@ pub fn default_config() -> Config {
256264
Config::default()
257265
}
258266

259-
pub(crate) fn may_announce_channel(config: &Config) -> bool {
260-
config.node_alias.is_some()
261-
&& config.listening_addresses.as_ref().map_or(false, |addrs| !addrs.is_empty())
267+
#[derive(Debug, PartialEq)]
268+
pub(crate) enum AnnounceError {
269+
MissingNodeAlias,
270+
MissingListeningAddresses,
271+
MissingAliasAndAddresses,
272+
}
273+
274+
impl fmt::Display for AnnounceError {
275+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276+
match self {
277+
AnnounceError::MissingNodeAlias => write!(f, "Node alias is not configured"),
278+
AnnounceError::MissingListeningAddresses => {
279+
write!(f, "Listening addresses are not configured")
280+
},
281+
AnnounceError::MissingAliasAndAddresses => {
282+
write!(f, "Node alias and listening addresses are not configured")
283+
},
284+
}
285+
}
286+
}
287+
288+
pub(crate) fn may_announce_channel(config: &Config) -> Result<(), AnnounceError> {
289+
let has_listening_addresses =
290+
config.listening_addresses.as_ref().map_or(false, |addrs| !addrs.is_empty());
291+
292+
match (config.node_alias.is_some(), has_listening_addresses) {
293+
(true, true) => Ok(()),
294+
(true, false) => Err(AnnounceError::MissingListeningAddresses),
295+
(false, true) => Err(AnnounceError::MissingNodeAlias),
296+
(false, false) => Err(AnnounceError::MissingAliasAndAddresses),
297+
}
262298
}
263299

264300
pub(crate) fn default_user_config(config: &Config) -> UserConfig {
@@ -273,7 +309,7 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
273309
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx =
274310
config.anchor_channels_config.is_some();
275311

276-
if !may_announce_channel(config) {
312+
if may_announce_channel(config).is_err() {
277313
user_config.accept_forwards_to_priv_channels = false;
278314
user_config.channel_handshake_config.announce_for_forwarding = false;
279315
user_config.channel_handshake_limits.force_announced_channel_preference = true;
@@ -461,6 +497,7 @@ mod tests {
461497
use std::str::FromStr;
462498

463499
use super::may_announce_channel;
500+
use super::AnnounceError;
464501
use super::Config;
465502
use super::NodeAlias;
466503
use super::SocketAddress;
@@ -469,7 +506,10 @@ mod tests {
469506
fn node_announce_channel() {
470507
// Default configuration with node alias and listening addresses unset
471508
let mut node_config = Config::default();
472-
assert!(!may_announce_channel(&node_config));
509+
assert_eq!(
510+
may_announce_channel(&node_config),
511+
Err(AnnounceError::MissingAliasAndAddresses)
512+
);
473513

474514
// Set node alias with listening addresses unset
475515
let alias_frm_str = |alias: &str| {
@@ -478,18 +518,33 @@ mod tests {
478518
NodeAlias(bytes)
479519
};
480520
node_config.node_alias = Some(alias_frm_str("LDK_Node"));
481-
assert!(!may_announce_channel(&node_config));
521+
assert_eq!(
522+
may_announce_channel(&node_config),
523+
Err(AnnounceError::MissingListeningAddresses)
524+
);
525+
526+
// Set announcement addresses with listening addresses unset
527+
let announcement_address = SocketAddress::from_str("123.45.67.89:9735")
528+
.expect("Socket address conversion failed.");
529+
node_config.announcement_addresses = Some(vec![announcement_address]);
530+
assert_eq!(
531+
may_announce_channel(&node_config),
532+
Err(AnnounceError::MissingListeningAddresses)
533+
);
482534

483535
// Set node alias with an empty list of listening addresses
484536
node_config.listening_addresses = Some(vec![]);
485-
assert!(!may_announce_channel(&node_config));
537+
assert_eq!(
538+
may_announce_channel(&node_config),
539+
Err(AnnounceError::MissingListeningAddresses)
540+
);
486541

487542
// Set node alias with a non-empty list of listening addresses
488543
let socket_address =
489544
SocketAddress::from_str("localhost:8000").expect("Socket address conversion failed.");
490545
if let Some(ref mut addresses) = node_config.listening_addresses {
491546
addresses.push(socket_address);
492547
}
493-
assert!(may_announce_channel(&node_config));
548+
assert!(may_announce_channel(&node_config).is_ok());
494549
}
495550
}

src/event.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -1077,23 +1077,21 @@ where
10771077
is_announced,
10781078
params: _,
10791079
} => {
1080-
if is_announced && !may_announce_channel(&*self.config) {
1081-
log_error!(
1082-
self.logger,
1083-
"Rejecting inbound announced channel from peer {} as not all required details are set. Please ensure node alias and listening addresses have been configured.",
1084-
counterparty_node_id,
1085-
);
1080+
if is_announced {
1081+
if let Err(err) = may_announce_channel(&*self.config) {
1082+
log_error!(self.logger, "Rejecting inbound announced channel from peer {} due to missing configuration: {}", counterparty_node_id, err);
10861083

1087-
self.channel_manager
1088-
.force_close_without_broadcasting_txn(
1089-
&temporary_channel_id,
1090-
&counterparty_node_id,
1091-
"Channel request rejected".to_string(),
1092-
)
1093-
.unwrap_or_else(|e| {
1094-
log_error!(self.logger, "Failed to reject channel: {:?}", e)
1095-
});
1096-
return Ok(());
1084+
self.channel_manager
1085+
.force_close_without_broadcasting_txn(
1086+
&temporary_channel_id,
1087+
&counterparty_node_id,
1088+
"Channel request rejected".to_string(),
1089+
)
1090+
.unwrap_or_else(|e| {
1091+
log_error!(self.logger, "Failed to reject channel: {:?}", e)
1092+
});
1093+
return Ok(());
1094+
}
10971095
}
10981096

10991097
let anchor_channel = channel_type.requires_anchors_zero_fee_htlc_tx();

src/lib.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ impl Node {
414414
let bcast_node_metrics = Arc::clone(&self.node_metrics);
415415
let mut stop_bcast = self.stop_sender.subscribe();
416416
let node_alias = self.config.node_alias.clone();
417-
if may_announce_channel(&self.config) {
417+
if may_announce_channel(&self.config).is_ok() {
418418
runtime.spawn(async move {
419419
// We check every 30 secs whether our last broadcast is NODE_ANN_BCAST_INTERVAL away.
420420
#[cfg(not(test))]
@@ -457,8 +457,10 @@ impl Node {
457457
continue;
458458
}
459459

460-
let addresses = if let Some(addresses) = bcast_config.listening_addresses.clone() {
461-
addresses
460+
let addresses = if let Some(announcement_addresses) = bcast_config.announcement_addresses.clone() {
461+
announcement_addresses
462+
} else if let Some(listening_addresses) = bcast_config.listening_addresses.clone() {
463+
listening_addresses
462464
} else {
463465
debug_assert!(false, "We checked whether the node may announce, so listening addresses should always be set");
464466
continue;
@@ -802,6 +804,14 @@ impl Node {
802804
self.config.listening_addresses.clone()
803805
}
804806

807+
/// Returns the addresses that the node will announce to the network.
808+
pub fn announcement_addresses(&self) -> Option<Vec<SocketAddress>> {
809+
self.config
810+
.announcement_addresses
811+
.clone()
812+
.or_else(|| self.config.listening_addresses.clone())
813+
}
814+
805815
/// Returns our node alias.
806816
pub fn node_alias(&self) -> Option<NodeAlias> {
807817
self.config.node_alias
@@ -1201,19 +1211,19 @@ impl Node {
12011211
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
12021212
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
12031213
) -> Result<UserChannelId, Error> {
1204-
if may_announce_channel(&self.config) {
1205-
self.open_channel_inner(
1206-
node_id,
1207-
address,
1208-
channel_amount_sats,
1209-
push_to_counterparty_msat,
1210-
channel_config,
1211-
true,
1212-
)
1213-
} else {
1214-
log_error!(self.logger, "Failed to open announced channel as the node hasn't been sufficiently configured to act as a forwarding node. Please make sure to configure listening addreesses and node alias");
1214+
if let Err(err) = may_announce_channel(&self.config) {
1215+
log_error!(self.logger, "Failed to open announced channel as the node hasn't been sufficiently configured to act as a forwarding node: {}", err);
12151216
return Err(Error::ChannelCreationFailed);
12161217
}
1218+
1219+
self.open_channel_inner(
1220+
node_id,
1221+
address,
1222+
channel_amount_sats,
1223+
push_to_counterparty_msat,
1224+
channel_config,
1225+
true,
1226+
)
12171227
}
12181228

12191229
/// Manually sync the LDK and BDK wallets with the current chain state and update the fee rate

0 commit comments

Comments
 (0)