Skip to content

Commit 6458793

Browse files
authored
Merge pull request #810 from enigbe/2026-02-expose-node-features-api
Expose node-invariant features via NodeStatus
2 parents 34577b6 + 888ba66 commit 6458793

2 files changed

Lines changed: 331 additions & 1 deletion

File tree

src/ffi/types.rs

Lines changed: 296 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 as LdkNodeFeatures;
4748
pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
4849
pub use lightning_types::string::UntrustedString;
4950
use vss_client::headers::{
@@ -1519,6 +1520,301 @@ pub enum ClosureReason {
15191520
},
15201521
}
15211522

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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
1672+
pub fn supports_taproot(&self) -> bool {
1673+
self.inner.supports_taproot()
1674+
}
1675+
1676+
/// Whether this node's `node_announcement` requires `option_taproot`.
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`.
1682+
pub fn supports_quiescence(&self) -> bool {
1683+
self.inner.supports_quiescence()
1684+
}
1685+
1686+
/// Whether this node's `node_announcement` requires `option_quiesce`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
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`.
1742+
pub fn supports_keysend(&self) -> bool {
1743+
self.inner.supports_keysend()
1744+
}
1745+
1746+
/// Whether this node's `node_announcement` requires `keysend`.
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`.
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`.
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`.
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`.
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`.
1772+
pub fn supports_splicing(&self) -> bool {
1773+
self.inner.supports_splicing()
1774+
}
1775+
1776+
/// Whether this node's `node_announcement` requires `option_splice`.
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`.
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`.
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.
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.
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.
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.
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+
}
1817+
15221818
#[cfg(test)]
15231819
mod tests {
15241820
use std::num::NonZeroU64;

0 commit comments

Comments
 (0)