Skip to content

Commit ead6a8c

Browse files
committed
Expose node announcement feature flags
Expose the feature flags advertised by the node in its node_announcement message via NodeStatus::node_features. For UniFFI consumers, expose NodeFeatures as an object with BOLT 9 byte encoding helpers and typed feature accessors. This intentionally avoids exposing freestanding Node methods for init, channel, invoice, or node feature contexts. Channel and invoice features are context-specific, and exposing node-level helpers for them could be confused with negotiated per-peer, per-channel, or per-invoice features. Those negotiated feature surfaces are handled separately.
1 parent 109978d commit ead6a8c

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/ffi/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub use lightning_liquidity::lsps0::ser::LSPSDateTime;
4444
pub use lightning_liquidity::lsps1::msgs::{
4545
LSPS1ChannelInfo, LSPS1OrderId, LSPS1OrderParams, LSPS1PaymentState,
4646
};
47+
use lightning_types::features::NodeFeatures;
4748
pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
4849
pub use lightning_types::string::UntrustedString;
4950
use vss_client::headers::{
@@ -1519,6 +1520,13 @@ pub enum ClosureReason {
15191520
},
15201521
}
15211522

1523+
#[cfg(feature = "uniffi")]
1524+
uniffi::custom_type!(NodeFeatures, Vec<u8>, {
1525+
remote,
1526+
try_lift: |val| Ok(NodeFeatures::from_le_bytes(val)),
1527+
lower: |obj| obj.le_flags().to_vec(),
1528+
});
1529+
15221530
#[cfg(test)]
15231531
mod tests {
15241532
use std::num::NonZeroU64;

src/lib.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ use lightning::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
151151
use lightning::ln::channel_state::ChannelDetails as LdkChannelDetails;
152152
pub use lightning::ln::channel_state::ChannelShutdownState;
153153
use lightning::ln::channelmanager::PaymentId;
154-
use lightning::ln::msgs::SocketAddress;
154+
use lightning::ln::msgs::{BaseMessageHandler, SocketAddress};
155+
use lightning::ln::peer_handler::CustomMessageHandler;
155156
use lightning::routing::gossip::NodeAlias;
156157
use lightning::sign::EntropySource;
157158
use lightning::util::persist::KVStoreSync;
@@ -160,6 +161,7 @@ use lightning_background_processor::process_events_async;
160161
pub use lightning_invoice;
161162
pub use lightning_liquidity;
162163
pub use lightning_types;
164+
use lightning_types::features::NodeFeatures;
163165
use liquidity::{LSPS1Liquidity, LiquiditySource};
164166
use lnurl_auth::LnurlAuth;
165167
use logger::{log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
@@ -775,6 +777,7 @@ impl Node {
775777
locked_node_metrics.latest_pathfinding_scores_sync_timestamp;
776778
let latest_node_announcement_broadcast_timestamp =
777779
locked_node_metrics.latest_node_announcement_broadcast_timestamp;
780+
let node_features = self.node_features();
778781

779782
NodeStatus {
780783
is_running,
@@ -786,6 +789,7 @@ impl Node {
786789
latest_rgs_snapshot_timestamp,
787790
latest_pathfinding_scores_sync_timestamp,
788791
latest_node_announcement_broadcast_timestamp,
792+
node_features,
789793
}
790794
}
791795

@@ -2053,6 +2057,28 @@ impl Node {
20532057
Error::PersistenceFailed
20542058
})
20552059
}
2060+
2061+
/// Return the features used in node announcement.
2062+
fn node_features(&self) -> NodeFeatures {
2063+
let gossip_features = match self.gossip_source.as_gossip_sync() {
2064+
lightning_background_processor::GossipSync::P2P(p2p_gossip_sync) => {
2065+
p2p_gossip_sync.provided_node_features()
2066+
},
2067+
lightning_background_processor::GossipSync::Rapid(_) => NodeFeatures::empty(),
2068+
lightning_background_processor::GossipSync::None => {
2069+
unreachable!("We must always have a gossip sync!")
2070+
},
2071+
};
2072+
self.channel_manager.node_features()
2073+
| self.chain_monitor.provided_node_features()
2074+
| self.onion_messenger.provided_node_features()
2075+
| gossip_features
2076+
| self
2077+
.liquidity_source
2078+
.as_ref()
2079+
.map(|ls| ls.liquidity_manager().provided_node_features())
2080+
.unwrap_or_else(NodeFeatures::empty)
2081+
}
20562082
}
20572083

20582084
impl Drop for Node {
@@ -2114,6 +2140,8 @@ pub struct NodeStatus {
21142140
///
21152141
/// Will be `None` if we have no public channels or we haven't broadcasted yet.
21162142
pub latest_node_announcement_broadcast_timestamp: Option<u64>,
2143+
/// The features used within a node_announcement message.
2144+
pub node_features: NodeFeatures,
21172145
}
21182146

21192147
/// Status fields that are persisted across restarts.

0 commit comments

Comments
 (0)