Skip to content

Commit 0668b4f

Browse files
committed
fixup! Expose node announcement feature flags
Switch the UniFFI NodeFeatures exposure from a raw custom Vec<u8> conversion to an object wrapper with BOLT 9 byte encoding helpers and typed feature accessors.
1 parent ead6a8c commit 0668b4f

2 files changed

Lines changed: 307 additions & 13 deletions

File tree

src/ffi/types.rs

Lines changed: 295 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +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;
47+
use lightning_types::features::NodeFeatures as LdkNodeFeatures;
4848
pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
4949
pub use lightning_types::string::UntrustedString;
5050
use vss_client::headers::{
@@ -1520,12 +1520,300 @@ pub enum ClosureReason {
15201520
},
15211521
}
15221522

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-
});
1523+
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
1524+
#[uniffi::export(Debug, Eq)]
1525+
pub struct NodeFeatures {
1526+
pub(crate) inner: LdkNodeFeatures,
1527+
}
1528+
1529+
impl NodeFeatures {
1530+
/// Constructs node features from big-endian BOLT 9 encoded bytes.
1531+
#[uniffi::constructor]
1532+
pub fn from_bytes(bytes: &[u8]) -> Self {
1533+
Self { inner: LdkNodeFeatures::from_be_bytes(bytes.to_vec()) }
1534+
}
1535+
1536+
/// Returns the BOLT 9 big-endian encoded representation of these features.
1537+
pub fn to_bytes(&self) -> Vec<u8> {
1538+
self.inner.encode()
1539+
}
1540+
1541+
/// Whether this node's `node_announcement` advertises support for `option_data_loss_protect` (bit 1).
1542+
pub fn supports_data_loss_protect(&self) -> bool {
1543+
self.inner.supports_data_loss_protect()
1544+
}
1545+
1546+
/// Whether this node's `node_announcement` requires `option_data_loss_protect` (bit 0).
1547+
pub fn requires_data_loss_protect(&self) -> bool {
1548+
self.inner.requires_data_loss_protect()
1549+
}
1550+
1551+
/// Whether this node's `node_announcement` advertises support for `option_upfront_shutdown_script` (bit 5).
1552+
pub fn supports_upfront_shutdown_script(&self) -> bool {
1553+
self.inner.supports_upfront_shutdown_script()
1554+
}
1555+
1556+
/// Whether this node's `node_announcement` requires `option_upfront_shutdown_script` (bit 4).
1557+
pub fn requires_upfront_shutdown_script(&self) -> bool {
1558+
self.inner.requires_upfront_shutdown_script()
1559+
}
1560+
1561+
/// Whether this node's `node_announcement` advertises support for `gossip_queries` (bit 7).
1562+
pub fn supports_gossip_queries(&self) -> bool {
1563+
self.inner.supports_gossip_queries()
1564+
}
1565+
1566+
/// Whether this node's `node_announcement` requires `gossip_queries` (bit 6).
1567+
pub fn requires_gossip_queries(&self) -> bool {
1568+
self.inner.requires_gossip_queries()
1569+
}
1570+
1571+
/// Whether this node's `node_announcement` advertises support for `var_onion_optin` (bit 9).
1572+
pub fn supports_variable_length_onion(&self) -> bool {
1573+
self.inner.supports_variable_length_onion()
1574+
}
1575+
1576+
/// Whether this node's `node_announcement` requires `var_onion_optin` (bit 8).
1577+
pub fn requires_variable_length_onion(&self) -> bool {
1578+
self.inner.requires_variable_length_onion()
1579+
}
1580+
1581+
/// Whether this node's `node_announcement` advertises support for `option_static_remotekey` (bit 13).
1582+
pub fn supports_static_remote_key(&self) -> bool {
1583+
self.inner.supports_static_remote_key()
1584+
}
1585+
1586+
/// Whether this node's `node_announcement` requires `option_static_remotekey` (bit 12).
1587+
pub fn requires_static_remote_key(&self) -> bool {
1588+
self.inner.requires_static_remote_key()
1589+
}
1590+
1591+
/// Whether this node's `node_announcement` advertises support for `payment_secret` (bit 15).
1592+
pub fn supports_payment_secret(&self) -> bool {
1593+
self.inner.supports_payment_secret()
1594+
}
1595+
1596+
/// Whether this node's `node_announcement` requires `payment_secret` (bit 14).
1597+
pub fn requires_payment_secret(&self) -> bool {
1598+
self.inner.requires_payment_secret()
1599+
}
1600+
1601+
/// Whether this node's `node_announcement` advertises support for `basic_mpp` (bit 17).
1602+
pub fn supports_basic_mpp(&self) -> bool {
1603+
self.inner.supports_basic_mpp()
1604+
}
1605+
1606+
/// Whether this node's `node_announcement` requires `basic_mpp` (bit 16).
1607+
pub fn requires_basic_mpp(&self) -> bool {
1608+
self.inner.requires_basic_mpp()
1609+
}
1610+
1611+
/// Whether this node's `node_announcement` advertises support for `option_support_large_channel` (bit 19).
1612+
pub fn supports_wumbo(&self) -> bool {
1613+
self.inner.supports_wumbo()
1614+
}
1615+
1616+
/// Whether this node's `node_announcement` requires `option_support_large_channel` (bit 18).
1617+
pub fn requires_wumbo(&self) -> bool {
1618+
self.inner.requires_wumbo()
1619+
}
1620+
1621+
/// Whether this node's `node_announcement` advertises support for `option_anchors_nonzero_fee_htlc_tx` (bit 21).
1622+
pub fn supports_anchors_nonzero_fee_htlc_tx(&self) -> bool {
1623+
self.inner.supports_anchors_nonzero_fee_htlc_tx()
1624+
}
1625+
1626+
/// Whether this node's `node_announcement` requires `option_anchors_nonzero_fee_htlc_tx` (bit 20).
1627+
pub fn requires_anchors_nonzero_fee_htlc_tx(&self) -> bool {
1628+
self.inner.requires_anchors_nonzero_fee_htlc_tx()
1629+
}
1630+
1631+
/// Whether this node's `node_announcement` advertises support for `option_anchors_zero_fee_htlc_tx` (bit 23).
1632+
pub fn supports_anchors_zero_fee_htlc_tx(&self) -> bool {
1633+
self.inner.supports_anchors_zero_fee_htlc_tx()
1634+
}
1635+
1636+
/// Whether this node's `node_announcement` requires `option_anchors_zero_fee_htlc_tx` (bit 22).
1637+
pub fn requires_anchors_zero_fee_htlc_tx(&self) -> bool {
1638+
self.inner.requires_anchors_zero_fee_htlc_tx()
1639+
}
1640+
1641+
/// Whether this node's `node_announcement` advertises support for `option_route_blinding` (bit 25).
1642+
pub fn supports_route_blinding(&self) -> bool {
1643+
self.inner.supports_route_blinding()
1644+
}
1645+
1646+
/// Whether this node's `node_announcement` requires `option_route_blinding` (bit 24).
1647+
pub fn requires_route_blinding(&self) -> bool {
1648+
self.inner.requires_route_blinding()
1649+
}
1650+
1651+
/// Whether this node's `node_announcement` advertises support for `opt_shutdown_anysegwit` (bit 27).
1652+
pub fn supports_shutdown_anysegwit(&self) -> bool {
1653+
self.inner.supports_shutdown_anysegwit()
1654+
}
1655+
1656+
/// Whether this node's `node_announcement` requires `opt_shutdown_anysegwit` (bit 26).
1657+
pub fn requires_shutdown_anysegwit(&self) -> bool {
1658+
self.inner.requires_shutdown_anysegwit()
1659+
}
1660+
1661+
/// Whether this node's `node_announcement` advertises support for `option_dual_fund` (bit 29).
1662+
pub fn supports_dual_fund(&self) -> bool {
1663+
self.inner.supports_dual_fund()
1664+
}
1665+
1666+
/// Whether this node's `node_announcement` requires `option_dual_fund` (bit 28).
1667+
pub fn requires_dual_fund(&self) -> bool {
1668+
self.inner.requires_dual_fund()
1669+
}
1670+
1671+
/// Whether this node's `node_announcement` advertises support for `option_taproot` (bit 31).
1672+
pub fn supports_taproot(&self) -> bool {
1673+
self.inner.supports_taproot()
1674+
}
1675+
1676+
/// Whether this node's `node_announcement` requires `option_taproot` (bit 30).
1677+
pub fn requires_taproot(&self) -> bool {
1678+
self.inner.requires_taproot()
1679+
}
1680+
1681+
/// Whether this node's `node_announcement` advertises support for `option_quiesce` (bit 35).
1682+
pub fn supports_quiescence(&self) -> bool {
1683+
self.inner.supports_quiescence()
1684+
}
1685+
1686+
/// Whether this node's `node_announcement` requires `option_quiesce` (bit 34).
1687+
pub fn requires_quiescence(&self) -> bool {
1688+
self.inner.requires_quiescence()
1689+
}
1690+
1691+
/// Whether this node's `node_announcement` advertises support for `option_onion_messages` (bit 39).
1692+
pub fn supports_onion_messages(&self) -> bool {
1693+
self.inner.supports_onion_messages()
1694+
}
1695+
1696+
/// Whether this node's `node_announcement` requires `option_onion_messages` (bit 38).
1697+
pub fn requires_onion_messages(&self) -> bool {
1698+
self.inner.requires_onion_messages()
1699+
}
1700+
1701+
/// Whether this node's `node_announcement` advertises support for `option_provide_storage` (bit 43).
1702+
pub fn supports_provide_storage(&self) -> bool {
1703+
self.inner.supports_provide_storage()
1704+
}
1705+
1706+
/// Whether this node's `node_announcement` requires `option_provide_storage` (bit 42).
1707+
pub fn requires_provide_storage(&self) -> bool {
1708+
self.inner.requires_provide_storage()
1709+
}
1710+
1711+
/// Whether this node's `node_announcement` advertises support for `option_channel_type` (bit 45).
1712+
pub fn supports_channel_type(&self) -> bool {
1713+
self.inner.supports_channel_type()
1714+
}
1715+
1716+
/// Whether this node's `node_announcement` requires `option_channel_type` (bit 44).
1717+
pub fn requires_channel_type(&self) -> bool {
1718+
self.inner.requires_channel_type()
1719+
}
1720+
1721+
/// Whether this node's `node_announcement` advertises support for `option_scid_alias` (bit 47).
1722+
pub fn supports_scid_privacy(&self) -> bool {
1723+
self.inner.supports_scid_privacy()
1724+
}
1725+
1726+
/// Whether this node's `node_announcement` requires `option_scid_alias` (bit 46).
1727+
pub fn requires_scid_privacy(&self) -> bool {
1728+
self.inner.requires_scid_privacy()
1729+
}
1730+
1731+
/// Whether this node's `node_announcement` advertises support for `option_zeroconf` (bit 51).
1732+
pub fn supports_zero_conf(&self) -> bool {
1733+
self.inner.supports_zero_conf()
1734+
}
1735+
1736+
/// Whether this node's `node_announcement` requires `option_zeroconf` (bit 50).
1737+
pub fn requires_zero_conf(&self) -> bool {
1738+
self.inner.requires_zero_conf()
1739+
}
1740+
1741+
/// Whether this node's `node_announcement` advertises support for `keysend` (bit 55).
1742+
pub fn supports_keysend(&self) -> bool {
1743+
self.inner.supports_keysend()
1744+
}
1745+
1746+
/// Whether this node's `node_announcement` requires `keysend` (bit 54).
1747+
pub fn requires_keysend(&self) -> bool {
1748+
self.inner.requires_keysend()
1749+
}
1750+
1751+
/// Whether this node's `node_announcement` advertises support for `option_trampoline` (bit 57).
1752+
pub fn supports_trampoline_routing(&self) -> bool {
1753+
self.inner.supports_trampoline_routing()
1754+
}
1755+
1756+
/// Whether this node's `node_announcement` requires `option_trampoline` (bit 56).
1757+
pub fn requires_trampoline_routing(&self) -> bool {
1758+
self.inner.requires_trampoline_routing()
1759+
}
1760+
1761+
/// Whether this node's `node_announcement` advertises support for `option_simple_close` (bit 61).
1762+
pub fn supports_simple_close(&self) -> bool {
1763+
self.inner.supports_simple_close()
1764+
}
1765+
1766+
/// Whether this node's `node_announcement` requires `option_simple_close` (bit 60).
1767+
pub fn requires_simple_close(&self) -> bool {
1768+
self.inner.requires_simple_close()
1769+
}
1770+
1771+
/// Whether this node's `node_announcement` advertises support for `option_splice` (bit 63).
1772+
pub fn supports_splicing(&self) -> bool {
1773+
self.inner.supports_splicing()
1774+
}
1775+
1776+
/// Whether this node's `node_announcement` requires `option_splice` (bit 62).
1777+
pub fn requires_splicing(&self) -> bool {
1778+
self.inner.requires_splicing()
1779+
}
1780+
1781+
/// Whether this node's `node_announcement` advertises support for `option_zero_fee_commitments` (bit 141, experimental).
1782+
pub fn supports_anchor_zero_fee_commitments(&self) -> bool {
1783+
self.inner.supports_anchor_zero_fee_commitments()
1784+
}
1785+
1786+
/// Whether this node's `node_announcement` requires `option_zero_fee_commitments` (bit 140, experimental).
1787+
pub fn requires_anchor_zero_fee_commitments(&self) -> bool {
1788+
self.inner.requires_anchor_zero_fee_commitments()
1789+
}
1790+
1791+
/// Whether this node's `node_announcement` advertises support for HTLC hold (bit 153, experimental).
1792+
pub fn supports_htlc_hold(&self) -> bool {
1793+
self.inner.supports_htlc_hold()
1794+
}
1795+
1796+
/// Whether this node's `node_announcement` requires HTLC hold (bit 152, experimental).
1797+
pub fn requires_htlc_hold(&self) -> bool {
1798+
self.inner.requires_htlc_hold()
1799+
}
1800+
1801+
/// Whether this node's `node_announcement` advertises support for DNS resolution (bit 259).
1802+
pub fn supports_dns_resolution(&self) -> bool {
1803+
self.inner.supports_dns_resolution()
1804+
}
1805+
1806+
/// Whether this node's `node_announcement` requires DNS resolution (bit 258).
1807+
pub fn requires_dns_resolution(&self) -> bool {
1808+
self.inner.requires_dns_resolution()
1809+
}
1810+
}
1811+
1812+
impl From<LdkNodeFeatures> for NodeFeatures {
1813+
fn from(features: LdkNodeFeatures) -> Self {
1814+
Self { inner: features }
1815+
}
1816+
}
15291817

15301818
#[cfg(test)]
15311819
mod tests {

src/lib.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
113113
#[cfg(cycle_tests)]
114114
use std::{any::Any, sync::Weak};
115115

116+
use crate::ffi::maybe_wrap;
116117
pub use balance::{BalanceDetails, LightningBalance, PendingSweepBalance};
117118
pub use bip39;
118119
pub use bitcoin;
@@ -161,7 +162,7 @@ use lightning_background_processor::process_events_async;
161162
pub use lightning_invoice;
162163
pub use lightning_liquidity;
163164
pub use lightning_types;
164-
use lightning_types::features::NodeFeatures;
165+
use lightning_types::features::NodeFeatures as LdkNodeFeatures;
165166
use liquidity::{LSPS1Liquidity, LiquiditySource};
166167
use lnurl_auth::LnurlAuth;
167168
use logger::{log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
@@ -185,6 +186,11 @@ pub use vss_client;
185186
use crate::scoring::setup_background_pathfinding_scores_sync;
186187
use crate::wallet::FundingAmount;
187188

189+
#[cfg(not(feature = "uniffi"))]
190+
type NodeFeatures = LdkNodeFeatures;
191+
#[cfg(feature = "uniffi")]
192+
type NodeFeatures = Arc<crate::ffi::NodeFeatures>;
193+
188194
#[cfg(feature = "uniffi")]
189195
uniffi::include_scaffolding!("ldk_node");
190196

@@ -777,7 +783,7 @@ impl Node {
777783
locked_node_metrics.latest_pathfinding_scores_sync_timestamp;
778784
let latest_node_announcement_broadcast_timestamp =
779785
locked_node_metrics.latest_node_announcement_broadcast_timestamp;
780-
let node_features = self.node_features();
786+
let node_features = maybe_wrap(self.node_features());
781787

782788
NodeStatus {
783789
is_running,
@@ -2059,12 +2065,12 @@ impl Node {
20592065
}
20602066

20612067
/// Return the features used in node announcement.
2062-
fn node_features(&self) -> NodeFeatures {
2068+
fn node_features(&self) -> LdkNodeFeatures {
20632069
let gossip_features = match self.gossip_source.as_gossip_sync() {
20642070
lightning_background_processor::GossipSync::P2P(p2p_gossip_sync) => {
20652071
p2p_gossip_sync.provided_node_features()
20662072
},
2067-
lightning_background_processor::GossipSync::Rapid(_) => NodeFeatures::empty(),
2073+
lightning_background_processor::GossipSync::Rapid(_) => LdkNodeFeatures::empty(),
20682074
lightning_background_processor::GossipSync::None => {
20692075
unreachable!("We must always have a gossip sync!")
20702076
},
@@ -2077,7 +2083,7 @@ impl Node {
20772083
.liquidity_source
20782084
.as_ref()
20792085
.map(|ls| ls.liquidity_manager().provided_node_features())
2080-
.unwrap_or_else(NodeFeatures::empty)
2086+
.unwrap_or_else(LdkNodeFeatures::empty)
20812087
}
20822088
}
20832089

@@ -2140,7 +2146,7 @@ pub struct NodeStatus {
21402146
///
21412147
/// Will be `None` if we have no public channels or we haven't broadcasted yet.
21422148
pub latest_node_announcement_broadcast_timestamp: Option<u64>,
2143-
/// The features used within a node_announcement message.
2149+
/// The features advertised in this node's `node_announcement` message.
21442150
pub node_features: NodeFeatures,
21452151
}
21462152

0 commit comments

Comments
 (0)