Skip to content

Commit 83b5b84

Browse files
committed
Add a channels section to ChannelManager docs
1 parent 8198628 commit 83b5b84

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,186 @@ where
11971197
/// respectively. The remaining requirements can be met using the [`lightning-background-processor`]
11981198
/// crate. For languages other than Rust, the availability of similar utilities may vary.
11991199
///
1200+
/// # Channels
1201+
///
1202+
/// [`ChannelManager`]'s primary function involves managing a channel state. Without channels,
1203+
/// payments can't be sent. Use [`list_channels`] or [`list_usable_channels`] for a snapshot of the
1204+
/// currently open channels.
1205+
///
1206+
/// ```
1207+
/// # use lightning::ln::channelmanager::AChannelManager;
1208+
/// #
1209+
/// # fn example<T: AChannelManager>(channel_manager: T) {
1210+
/// # let channel_manager = channel_manager.get_cm();
1211+
/// let channels = channel_manager.list_usable_channels();
1212+
/// for details in channels {
1213+
/// println!("{:?}", details);
1214+
/// }
1215+
/// # }
1216+
/// ```
1217+
///
1218+
/// Each channel is identified using a [`ChannelId`], which will change throughout the channel's
1219+
/// life cycle. Additionally, channels are assigned a `user_channel_id`, which is given in
1220+
/// [`Event`]s associated with the channel and serves as a fixed identifier but is otherwise unused
1221+
/// by [`ChannelManager`].
1222+
///
1223+
/// ## Opening Channels
1224+
///
1225+
/// To an open a channel with a peer, call [`create_channel`]. This will initiate the process of
1226+
/// opening an outbound channel, which requires self-funding when handling
1227+
/// [`Event::FundingGenerationReady`].
1228+
///
1229+
/// ```
1230+
/// # use bitcoin::{ScriptBuf, Transaction};
1231+
/// # use bitcoin::secp256k1::PublicKey;
1232+
/// # use lightning::ln::channelmanager::AChannelManager;
1233+
/// use lightning::events::{Event, EventsProvider};
1234+
///
1235+
/// # struct Wallet {}
1236+
/// # impl Wallet {
1237+
/// # fn create_funding_transaction(
1238+
/// # &self, _amount_sats: u64, _output_script: ScriptBuf
1239+
/// # ) -> Transaction {
1240+
/// # unimplemented!();
1241+
/// # }
1242+
/// # }
1243+
/// #
1244+
/// # fn example<T: AChannelManager>(channel_manager: T, wallet: Wallet, peer_id: PublicKey) {
1245+
/// # let channel_manager = channel_manager.get_cm();
1246+
/// let value_sats = 1_000_000;
1247+
/// let push_msats = 10_000_000;
1248+
/// let user_channel_id = 42;
1249+
///
1250+
/// match channel_manager.create_channel(peer_id, value_sats, push_msats, user_channel_id, None, None) {
1251+
/// Ok(channel_id) => println!(
1252+
/// "Opening channel {} (user_channel_id: {})", channel_id, user_channel_id
1253+
/// ),
1254+
/// Err(e) => println!(
1255+
/// "Error opening channel (user_channel_id: {}): {:?}", user_channel_id, e
1256+
/// ),
1257+
/// }
1258+
///
1259+
/// // On the event processing thread
1260+
/// channel_manager.process_pending_events(&|event| match event {
1261+
/// Event::FundingGenerationReady {
1262+
/// temporary_channel_id, counterparty_node_id, channel_value_satoshis, output_script,
1263+
/// user_channel_id, ..
1264+
/// } => {
1265+
/// let funding_transaction = wallet.create_funding_transaction(
1266+
/// channel_value_satoshis, output_script
1267+
/// );
1268+
/// match channel_manager.funding_transaction_generated(
1269+
/// &temporary_channel_id, &counterparty_node_id, funding_transaction
1270+
/// ) {
1271+
/// Ok(()) => println!(
1272+
/// "Funding channel {} (user_channel_id: {})", temporary_channel_id,
1273+
/// user_channel_id
1274+
/// ),
1275+
/// Err(e) => println!(
1276+
/// "Error funding channel {} (user_channel_id: {}): {:?}", temporary_channel_id,
1277+
/// user_channel_id, e
1278+
/// ),
1279+
/// }
1280+
/// },
1281+
/// Event::ChannelPending { channel_id, user_channel_id, former_temporary_channel_id, .. } => {
1282+
/// println!(
1283+
/// "Channel {} (user_channel_id: {}) pending confirmations; old channel id: {}",
1284+
/// channel_id, user_channel_id, former_temporary_channel_id.unwrap()
1285+
/// );
1286+
/// },
1287+
/// Event::ChannelReady { channel_id, user_channel_id, .. } => {
1288+
/// println!("Channel {} (user_channel_id: {}) ready", channel_id, user_channel_id);
1289+
/// },
1290+
/// // ...
1291+
/// # _ => {},
1292+
/// });
1293+
/// # }
1294+
/// ```
1295+
///
1296+
/// ## Accepting Channels
1297+
///
1298+
/// Inbound channels are initiated by peers and are automatically accepted unless [`ChannelManager`]
1299+
/// has [`UserConfig::manually_accept_inbound_channels`] set. In that case, the channel may be
1300+
/// either accepted or rejected when handling [`Event::OpenChannelRequest`].
1301+
///
1302+
/// ```
1303+
/// # use bitcoin::secp256k1::PublicKey;
1304+
/// # use lightning::ln::channelmanager::AChannelManager;
1305+
/// use lightning::events::{Event, EventsProvider};
1306+
///
1307+
/// # fn is_trusted(counterparty_node_id: PublicKey) -> bool {
1308+
/// # // ...
1309+
/// # unimplemented!()
1310+
/// # }
1311+
/// #
1312+
/// # fn example<T: AChannelManager>(channel_manager: T) {
1313+
/// # let channel_manager = channel_manager.get_cm();
1314+
/// channel_manager.process_pending_events(&|event| match event {
1315+
/// Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => {
1316+
/// if !is_trusted(counterparty_node_id) {
1317+
/// match channel_manager.force_close_without_broadcasting_txn(
1318+
/// &temporary_channel_id, &counterparty_node_id
1319+
/// ) {
1320+
/// Ok(()) => println!("Rejecting channel {}", temporary_channel_id),
1321+
/// Err(e) => println!("Error rejecting channel {}: {:?}", temporary_channel_id, e),
1322+
/// }
1323+
/// return;
1324+
/// }
1325+
///
1326+
/// let user_channel_id = 43;
1327+
/// match channel_manager.accept_inbound_channel(
1328+
/// &temporary_channel_id, &counterparty_node_id, user_channel_id
1329+
/// ) {
1330+
/// Ok(()) => println!(
1331+
/// "Accepting channel {} (user_channel_id: {})", temporary_channel_id,
1332+
/// user_channel_id
1333+
/// ),
1334+
/// Err(e) => println!(
1335+
/// "Error accepting channel {} (user_channel_id: {}): {:?}", temporary_channel_id,
1336+
/// user_channel_id, e
1337+
/// ),
1338+
/// }
1339+
/// },
1340+
/// // ...
1341+
/// # _ => {},
1342+
/// });
1343+
/// # }
1344+
/// ```
1345+
///
1346+
/// ## Closing Channels
1347+
///
1348+
/// There are two ways to close a channel: either cooperatively using [`close_channel`] or
1349+
/// unilaterally using [`force_close_broadcasting_latest_txn`]. The former is ideal as it makes for
1350+
/// lower fees and immediate access to funds. However, the latter may be necessary if the
1351+
/// counterparty isn't behaving properly or has gone offline. [`Event::ChannelClosed`] is generated
1352+
/// once the channel has been closed successfully.
1353+
///
1354+
/// ```
1355+
/// # use bitcoin::secp256k1::PublicKey;
1356+
/// # use lightning::ln::ChannelId;
1357+
/// # use lightning::ln::channelmanager::AChannelManager;
1358+
/// use lightning::events::{Event, EventsProvider};
1359+
///
1360+
/// # fn example<T: AChannelManager>(
1361+
/// # channel_manager: T, channel_id: ChannelId, counterparty_node_id: PublicKey
1362+
/// # ) {
1363+
/// # let channel_manager = channel_manager.get_cm();
1364+
/// match channel_manager.close_channel(&channel_id, &counterparty_node_id) {
1365+
/// Ok(()) => println!("Closing channel {}", channel_id),
1366+
/// Err(e) => println!("Error closing channel {}: {:?}", channel_id, e),
1367+
/// }
1368+
///
1369+
/// // On the event processing thread
1370+
/// channel_manager.process_pending_events(&|event| match event {
1371+
/// Event::ChannelClosed { channel_id, user_channel_id, .. } => {
1372+
/// println!("Channel {} (user_channel_id: {}) closed", channel_id, user_channel_id);
1373+
/// },
1374+
/// // ...
1375+
/// # _ => {},
1376+
/// });
1377+
/// # }
1378+
/// ```
1379+
///
12001380
/// # Persistence
12011381
///
12021382
/// Implements [`Writeable`] to write out all channel state to disk. Implies [`peer_disconnected`] for
@@ -1255,6 +1435,11 @@ where
12551435
/// [`lightning-block-sync`]: https://docs.rs/lightning_block_sync/latest/lightning_block_sync
12561436
/// [`lightning-transaction-sync`]: https://docs.rs/lightning_transaction_sync/latest/lightning_transaction_sync
12571437
/// [`lightning-background-processor`]: https://docs.rs/lightning_background_processor/lightning_background_processor
1438+
/// [`list_channels`]: Self::list_channels
1439+
/// [`list_usable_channels`]: Self::list_usable_channels
1440+
/// [`create_channel`]: Self::create_channel
1441+
/// [`close_channel`]: Self::force_close_broadcasting_latest_txn
1442+
/// [`force_close_broadcasting_latest_txn`]: Self::force_close_broadcasting_latest_txn
12581443
/// [`peer_disconnected`]: msgs::ChannelMessageHandler::peer_disconnected
12591444
/// [`funding_created`]: msgs::FundingCreated
12601445
/// [`funding_transaction_generated`]: Self::funding_transaction_generated

0 commit comments

Comments
 (0)