Skip to content

Commit 436fb95

Browse files
committed
Expose APIs to access supported feature flags
With this, we can read the features supported by the node as announced in node and channel announcements, within an init message, and within a BOLT 11 invoice. We write a small integration test to assert that, at minimum, certain features are supported by default, for example, keysend support.
1 parent b0e159a commit 436fb95

2 files changed

Lines changed: 96 additions & 1 deletion

File tree

src/lib.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ use lightning::impl_writeable_tlv_based;
147147
use lightning::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
148148
use lightning::ln::channel_state::{ChannelDetails as LdkChannelDetails, ChannelShutdownState};
149149
use lightning::ln::channelmanager::PaymentId;
150-
use lightning::ln::msgs::SocketAddress;
150+
use lightning::ln::msgs::{BaseMessageHandler, SocketAddress};
151+
use lightning::ln::peer_handler::CustomMessageHandler;
151152
use lightning::routing::gossip::NodeAlias;
152153
use lightning::sign::EntropySource;
153154
use lightning::util::persist::KVStoreSync;
@@ -156,6 +157,9 @@ use lightning_background_processor::process_events_async;
156157
pub use lightning_invoice;
157158
pub use lightning_liquidity;
158159
pub use lightning_types;
160+
use lightning_types::features::{
161+
Bolt11InvoiceFeatures, ChannelFeatures, InitFeatures, NodeFeatures,
162+
};
159163
use liquidity::{LSPS1Liquidity, LiquiditySource};
160164
use lnurl_auth::LnurlAuth;
161165
use logger::{log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
@@ -1931,6 +1935,63 @@ impl Node {
19311935
Error::PersistenceFailed
19321936
})
19331937
}
1938+
1939+
/// Return the features used in node announcement.
1940+
pub fn node_features(&self) -> NodeFeatures {
1941+
let gossip_features = match self.gossip_source.as_gossip_sync() {
1942+
lightning_background_processor::GossipSync::P2P(p2p_gossip_sync) => {
1943+
p2p_gossip_sync.provided_node_features()
1944+
},
1945+
lightning_background_processor::GossipSync::Rapid(_) => NodeFeatures::empty(),
1946+
lightning_background_processor::GossipSync::None => {
1947+
unreachable!("We must always have a gossip sync!")
1948+
},
1949+
};
1950+
self.channel_manager.node_features()
1951+
| self.chain_monitor.provided_node_features()
1952+
| self.onion_messenger.provided_node_features()
1953+
| gossip_features
1954+
| self
1955+
.liquidity_source
1956+
.as_ref()
1957+
.map(|ls| ls.liquidity_manager().provided_node_features())
1958+
.unwrap_or_else(NodeFeatures::empty)
1959+
}
1960+
1961+
/// Return the node's init features.
1962+
pub fn init_features(&self) -> InitFeatures {
1963+
let gossip_init_features = match self.gossip_source.as_gossip_sync() {
1964+
lightning_background_processor::GossipSync::P2P(p2p_gossip_sync) => {
1965+
p2p_gossip_sync.provided_init_features(self.node_id())
1966+
},
1967+
lightning_background_processor::GossipSync::Rapid(_) => InitFeatures::empty(),
1968+
lightning_background_processor::GossipSync::None => {
1969+
unreachable!("We must always have a gossip sync!")
1970+
},
1971+
};
1972+
self.channel_manager.init_features()
1973+
| self.chain_monitor.provided_init_features(self.node_id())
1974+
| self.onion_messenger.provided_init_features(self.node_id())
1975+
| gossip_init_features
1976+
| self
1977+
.liquidity_source
1978+
.as_ref()
1979+
.map(|ls| ls.liquidity_manager().provided_init_features(self.node_id()))
1980+
.unwrap_or_else(InitFeatures::empty)
1981+
}
1982+
1983+
/// Return the node's channel features.
1984+
pub fn channel_features(&self) -> ChannelFeatures {
1985+
self.channel_manager.channel_features()
1986+
}
1987+
1988+
/// Return the node's BOLT 11 invoice features.
1989+
pub fn bolt11_invoice_features(&self) -> Bolt11InvoiceFeatures {
1990+
// bolt11_invoice_features() is not public because feature
1991+
// flags can vary due to invoice type, so we convert from
1992+
// context.
1993+
self.channel_manager.init_features().to_context()
1994+
}
19341995
}
19351996

19361997
impl Drop for Node {

tests/integration_tests_rust.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2805,3 +2805,37 @@ async fn splice_in_with_all_balance() {
28052805
node_a.stop().unwrap();
28062806
node_b.stop().unwrap();
28072807
}
2808+
2809+
#[test]
2810+
fn node_feature_flags() {
2811+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
2812+
let chain_source = random_chain_source(&bitcoind, &electrsd);
2813+
let config = random_config(true);
2814+
let node = setup_node(&chain_source, config);
2815+
2816+
// NodeFeatures
2817+
let node_features = node.node_features();
2818+
assert!(node_features.supports_variable_length_onion());
2819+
assert!(node_features.supports_payment_secret());
2820+
assert!(node_features.supports_basic_mpp());
2821+
assert!(node_features.supports_keysend());
2822+
assert!(node_features.supports_onion_messages());
2823+
2824+
// InitFeatures
2825+
let init_features = node.init_features();
2826+
assert!(init_features.supports_variable_length_onion());
2827+
assert!(init_features.supports_payment_secret());
2828+
assert!(init_features.supports_basic_mpp());
2829+
assert!(init_features.supports_onion_messages());
2830+
2831+
// ChannelFeatures (non-empty)
2832+
let _channel_features = node.channel_features();
2833+
2834+
// Bolt11InvoiceFeatures
2835+
let bolt11_features = node.bolt11_invoice_features();
2836+
assert!(bolt11_features.supports_variable_length_onion());
2837+
assert!(bolt11_features.supports_payment_secret());
2838+
assert!(bolt11_features.supports_basic_mpp());
2839+
2840+
node.stop().unwrap();
2841+
}

0 commit comments

Comments
 (0)