Skip to content

Commit 0c58f58

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 9e0a812 commit 0c58f58

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
@@ -151,7 +151,8 @@ use lightning::impl_writeable_tlv_based;
151151
use lightning::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
152152
use lightning::ln::channel_state::{ChannelDetails as LdkChannelDetails, 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,9 @@ 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::{
165+
Bolt11InvoiceFeatures, ChannelFeatures, InitFeatures, NodeFeatures,
166+
};
163167
use liquidity::{LSPS1Liquidity, LiquiditySource};
164168
use lnurl_auth::LnurlAuth;
165169
use logger::{log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
@@ -1949,6 +1953,63 @@ impl Node {
19491953
Error::PersistenceFailed
19501954
})
19511955
}
1956+
1957+
/// Return the features used in node announcement.
1958+
pub fn node_features(&self) -> NodeFeatures {
1959+
let gossip_features = match self.gossip_source.as_gossip_sync() {
1960+
lightning_background_processor::GossipSync::P2P(p2p_gossip_sync) => {
1961+
p2p_gossip_sync.provided_node_features()
1962+
},
1963+
lightning_background_processor::GossipSync::Rapid(_) => NodeFeatures::empty(),
1964+
lightning_background_processor::GossipSync::None => {
1965+
unreachable!("We must always have a gossip sync!")
1966+
},
1967+
};
1968+
self.channel_manager.node_features()
1969+
| self.chain_monitor.provided_node_features()
1970+
| self.onion_messenger.provided_node_features()
1971+
| gossip_features
1972+
| self
1973+
.liquidity_source
1974+
.as_ref()
1975+
.map(|ls| ls.liquidity_manager().provided_node_features())
1976+
.unwrap_or_else(NodeFeatures::empty)
1977+
}
1978+
1979+
/// Return the node's init features.
1980+
pub fn init_features(&self) -> InitFeatures {
1981+
let gossip_init_features = match self.gossip_source.as_gossip_sync() {
1982+
lightning_background_processor::GossipSync::P2P(p2p_gossip_sync) => {
1983+
p2p_gossip_sync.provided_init_features(self.node_id())
1984+
},
1985+
lightning_background_processor::GossipSync::Rapid(_) => InitFeatures::empty(),
1986+
lightning_background_processor::GossipSync::None => {
1987+
unreachable!("We must always have a gossip sync!")
1988+
},
1989+
};
1990+
self.channel_manager.init_features()
1991+
| self.chain_monitor.provided_init_features(self.node_id())
1992+
| self.onion_messenger.provided_init_features(self.node_id())
1993+
| gossip_init_features
1994+
| self
1995+
.liquidity_source
1996+
.as_ref()
1997+
.map(|ls| ls.liquidity_manager().provided_init_features(self.node_id()))
1998+
.unwrap_or_else(InitFeatures::empty)
1999+
}
2000+
2001+
/// Return the node's channel features.
2002+
pub fn channel_features(&self) -> ChannelFeatures {
2003+
self.channel_manager.channel_features()
2004+
}
2005+
2006+
/// Return the node's BOLT 11 invoice features.
2007+
pub fn bolt11_invoice_features(&self) -> Bolt11InvoiceFeatures {
2008+
// bolt11_invoice_features() is not public because feature
2009+
// flags can vary due to invoice type, so we convert from
2010+
// context.
2011+
self.channel_manager.init_features().to_context()
2012+
}
19522013
}
19532014

19542015
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)