Skip to content

Commit ce70bfe

Browse files
committed
Expose list_{channels, peers} to bindings
# Conflicts: # bindings/ldk_node.udl # Conflicts: # src/types.rs
1 parent bc7a4ba commit ce70bfe

File tree

4 files changed

+160
-7
lines changed

4 files changed

+160
-7
lines changed

bindings/ldk_node.udl

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ interface Node {
5858
PaymentDetails? payment([ByRef]PaymentHash payment_hash);
5959
[Throws=NodeError]
6060
boolean remove_payment([ByRef]PaymentHash payment_hash);
61+
sequence<PeerDetails> list_peers();
62+
sequence<ChannelDetails> list_channels();
6163
};
6264

6365
[Error]
@@ -119,8 +121,33 @@ dictionary PaymentDetails {
119121
};
120122

121123
dictionary OutPoint {
122-
Txid txid;
123-
u32 vout;
124+
Txid txid;
125+
u32 vout;
126+
};
127+
128+
dictionary ChannelDetails {
129+
ChannelId channel_id;
130+
PublicKey counterparty_node_id;
131+
OutPoint? funding_txo;
132+
u64 channel_value_satoshis;
133+
u64? unspendable_punishment_reserve;
134+
UserChannelId user_channel_id;
135+
u64 balance_msat;
136+
u64 outbound_capacity_msat;
137+
u64 inbound_capacity_msat;
138+
u32? confirmations_required;
139+
u32? confirmations;
140+
boolean is_outbound;
141+
boolean is_channel_ready;
142+
boolean is_usable;
143+
boolean is_public;
144+
u16? cltv_expiry_delta;
145+
};
146+
147+
dictionary PeerDetails {
148+
PublicKey node_id;
149+
SocketAddr address;
150+
boolean is_connected;
124151
};
125152

126153
[Custom]

src/lib.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,15 @@ use types::{
105105
ChainMonitor, ChannelManager, GossipSync, KeysManager, NetworkGraph, OnionMessenger,
106106
PeerManager, Scorer,
107107
};
108-
pub use types::{ChannelId, UserChannelId};
108+
pub use types::{ChannelDetails, ChannelId, PeerDetails, UserChannelId};
109109
use wallet::Wallet;
110110

111111
use logger::{log_error, log_info, FilesystemLogger, Logger};
112112

113113
use lightning::chain::keysinterface::EntropySource;
114114
use lightning::chain::{chainmonitor, BestBlock, Confirm, Watch};
115115
use lightning::ln::channelmanager::{
116-
self, ChainParameters, ChannelDetails, ChannelManagerReadArgs, PaymentId, RecipientOnionFields,
117-
Retry,
116+
self, ChainParameters, ChannelManagerReadArgs, PaymentId, RecipientOnionFields, Retry,
118117
};
119118
use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler};
120119
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
@@ -903,7 +902,7 @@ impl Node {
903902

904903
/// Retrieve a list of known channels.
905904
pub fn list_channels(&self) -> Vec<ChannelDetails> {
906-
self.channel_manager.list_channels()
905+
self.channel_manager.list_channels().into_iter().map(|c| c.into()).collect()
907906
}
908907

909908
/// Connect to a node on the peer-to-peer network.
@@ -1438,6 +1437,21 @@ impl Node {
14381437
) -> Vec<PaymentDetails> {
14391438
self.payment_store.list_filter(f)
14401439
}
1440+
1441+
/// Retrieves a list of known peers.
1442+
pub fn list_peers(&self) -> Vec<PeerDetails> {
1443+
let active_connected_peers: Vec<PublicKey> =
1444+
self.peer_manager.get_peer_node_ids().iter().map(|p| p.0).collect();
1445+
self.peer_store
1446+
.list_peers()
1447+
.iter()
1448+
.map(|p| PeerDetails {
1449+
node_id: p.pubkey,
1450+
address: p.address,
1451+
is_connected: active_connected_peers.contains(&p.pubkey),
1452+
})
1453+
.collect()
1454+
}
14411455
}
14421456

14431457
async fn connect_peer_if_necessary(

src/test/functional_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ fn channel_full_cycle() {
4646
)
4747
.unwrap();
4848

49+
assert_eq!(node_a.list_peers().first().unwrap().node_id, node_b.node_id());
4950
expect_event!(node_a, ChannelPending);
5051

5152
let funding_txo = match node_b.next_event() {

src/types.rs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::UniffiCustomTypeConverter;
77

88
use lightning::chain::chainmonitor;
99
use lightning::chain::keysinterface::InMemorySigner;
10+
use lightning::ln::channelmanager::ChannelDetails as LdkChannelDetails;
1011
use lightning::ln::peer_handler::IgnoringMessageHandler;
1112
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
1213
use lightning::routing::gossip;
@@ -22,7 +23,7 @@ use lightning_transaction_sync::EsploraSyncClient;
2223
use bitcoin::hashes::sha256::Hash as Sha256;
2324
use bitcoin::hashes::Hash;
2425
use bitcoin::secp256k1::PublicKey;
25-
use bitcoin::{Address, Network, Txid};
26+
use bitcoin::{Address, Network, OutPoint, Txid};
2627

2728
use std::convert::TryInto;
2829
use std::net::SocketAddr;
@@ -290,3 +291,113 @@ impl UniffiCustomTypeConverter for Txid {
290291
obj.to_string()
291292
}
292293
}
294+
295+
/// Details of a channel as returned by [`Node::list_channels`].
296+
///
297+
/// [`Node::list_channels`]: [`crate::Node::list_channels`]
298+
pub struct ChannelDetails {
299+
/// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
300+
/// thereafter this is the transaction ID of the funding transaction XOR the funding transaction
301+
/// output).
302+
///
303+
/// Note that this means this value is *not* persistent - it can change once during the
304+
/// lifetime of the channel.
305+
pub channel_id: ChannelId,
306+
/// The `node_id` of our channel's counterparty.
307+
pub counterparty_node_id: PublicKey,
308+
/// The channel's funding transaction output, if we've negotiated the funding transaction with
309+
/// our counterparty already.
310+
pub funding_txo: Option<OutPoint>,
311+
/// The value, in satoshis, of this channel as appears in the funding output.
312+
pub channel_value_satoshis: u64,
313+
/// The value, in satoshis, that must always be held in the channel for us. This value ensures
314+
/// that if we broadcast a revoked state, our counterparty can punish us by claiming at least
315+
/// this value on chain.
316+
///
317+
/// This value is not included in [`outbound_capacity_msat`] as it can never be spent.
318+
///
319+
/// This value will be `None` for outbound channels until the counterparty accepts the channel.
320+
///
321+
/// [`outbound_capacity_msat`]: Self::outbound_capacity_msat
322+
pub unspendable_punishment_reserve: Option<u64>,
323+
/// The local `user_channel_id` of this channel.
324+
pub user_channel_id: UserChannelId,
325+
/// Total balance of the channel. This is the amount that will be returned to the user if the
326+
/// channel is closed.
327+
///
328+
/// The value is not exact, due to potential in-flight and fee-rate changes. Therefore, exactly
329+
/// this amount is likely irrecoverable on close.
330+
pub balance_msat: u64,
331+
/// Available outbound capacity for sending HTLCs to the remote peer.
332+
///
333+
/// The amount does not include any pending HTLCs which are not yet resolved (and, thus, whose
334+
/// balance is not available for inclusion in new outbound HTLCs). This further does not include
335+
/// any pending outgoing HTLCs which are awaiting some other resolution to be sent.
336+
pub outbound_capacity_msat: u64,
337+
/// Available outbound capacity for sending HTLCs to the remote peer.
338+
///
339+
/// The amount does not include any pending HTLCs which are not yet resolved
340+
/// (and, thus, whose balance is not available for inclusion in new inbound HTLCs). This further
341+
/// does not include any pending outgoing HTLCs which are awaiting some other resolution to be
342+
/// sent.
343+
pub inbound_capacity_msat: u64,
344+
/// The number of required confirmations on the funding transactions before the funding is
345+
/// considered "locked". The amount is selected by the channel fundee.
346+
///
347+
/// The value will be `None` for outbound channels until the counterparty accepts the channel.
348+
pub confirmations_required: Option<u32>,
349+
/// The current number of confirmations on the funding transaction.
350+
pub confirmations: Option<u32>,
351+
/// Returns `true` if the channel was initiated (and therefore funded) by us.
352+
pub is_outbound: bool,
353+
/// Returns `true` if the channel is confirmed, both parties have exchanged `channel_ready`
354+
/// messages, and the channel is not currently being shut down. Both parties exchange
355+
/// `channel_ready` messages upon independently verifying that the required confirmations count
356+
/// provided by `confirmations_required` has been reached.
357+
pub is_channel_ready: bool,
358+
/// Returns `true` if the channel is (a) confirmed and `channel_ready` has been exchanged,
359+
/// (b) the peer is connected, and (c) the channel is not currently negotiating shutdown.
360+
///
361+
/// This is a strict superset of `is_channel_ready`.
362+
pub is_usable: bool,
363+
/// Returns `true` if this channel is (or will be) publicly-announced
364+
pub is_public: bool,
365+
/// The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over
366+
/// the channel.
367+
pub cltv_expiry_delta: Option<u16>,
368+
}
369+
370+
impl From<LdkChannelDetails> for ChannelDetails {
371+
fn from(value: LdkChannelDetails) -> Self {
372+
ChannelDetails {
373+
channel_id: ChannelId(value.channel_id),
374+
counterparty_node_id: value.counterparty.node_id,
375+
funding_txo: value.funding_txo.and_then(|o| Some(o.into_bitcoin_outpoint())),
376+
channel_value_satoshis: value.channel_value_satoshis,
377+
unspendable_punishment_reserve: value.unspendable_punishment_reserve,
378+
user_channel_id: UserChannelId(value.user_channel_id),
379+
balance_msat: value.balance_msat,
380+
outbound_capacity_msat: value.outbound_capacity_msat,
381+
inbound_capacity_msat: value.inbound_capacity_msat,
382+
confirmations_required: value.confirmations_required,
383+
confirmations: value.confirmations,
384+
is_outbound: value.is_outbound,
385+
is_channel_ready: value.is_channel_ready,
386+
is_usable: value.is_usable,
387+
is_public: value.is_public,
388+
cltv_expiry_delta: value.config.and_then(|c| Some(c.cltv_expiry_delta)),
389+
}
390+
}
391+
}
392+
393+
/// Details of a known Lightning peer as returned by [`Node::list_peers`].
394+
///
395+
/// [`Node::list_peers`]: [`crate::Node::list_peers`]
396+
pub struct PeerDetails {
397+
/// Our peer's node ID.
398+
pub node_id: PublicKey,
399+
/// The IP address and TCP port of the peer.
400+
pub address: SocketAddr,
401+
/// Indicates whether or not the user is currently has an active connection with the peer.
402+
pub is_connected: bool,
403+
}

0 commit comments

Comments
 (0)