# Managing Channels
Channels are the basic building blocks of the Lightning Network. With channels, you can transact not only with your immediate peers but with others on the network. Let's explore how to open and close channels with LDK.
# Opening a Channel
Now that you have a peer, you can open a channel with them using
ChannelManager
. You'll need the peer's pubkey as before along with:
- the amount in sats to use when funding the channel,
- any msats to push to your peer,
- an id which is given back in the
FundingGenerationReady
event, and - an optional
UserConfig
for overridingChannelManager
defaults
Channels can be announced to the network or can remain private, which is
controlled via UserConfig::announced_channel
.
- Rust
- Java
let amount = 10_000;
let push_msat = 1_000;
let user_id = 42;
let config = UserConfig {
channel_options: ChannelConfig { announced_channel: true, ..Default::default() },
..Default::default()
};
match channel_manager.create_channel(pubkey, amount, push_msat, user_id, Some(config)) {
Ok(_) => println!("EVENT: initiated channel with peer {}", pubkey),
Err(e) => panic!("ERROR: failed to open channel: {:?}", e),
}
At this point, an outbound channel has been initiated with your peer and it will
appear in ChannelManager::list_channels
. However, the channel is not yet
funded. Once your peer accepts the channel, you will be notified with a
FundingGenerationReady
event. It's then your responsibility to construct the
funding transaction and pass it to ChannelManager
, which will broadcast it
once it receives your channel counterparty's signature.
- Rust
- Java
// In the event handler passed to BackgroundProcessor::start
match event {
Event::FundingGenerationReady {
temporary_channel_id,
channel_value_satoshis,
output_script,
user_channel_id,
} => {
// This is the same channel created earler.
assert_eq!(event.user_channel_id, 42);
// Construct the raw transaction with one output, that is paid the amount of the
// channel.
let network = bitcoin_bech32::constants::Network::Testnet;
let address = WitnessProgram::from_scriptpubkey(&output_script[..], network)
.unwrap().to_address;
let mut outputs = vec![HashMap::with_capacity(1)];
outputs[0].insert(address, channel_value_satoshis as f64 / 100_000_000.0);
let raw_tx = bitcoind_client.create_raw_transaction(outputs).await;
// Have your wallet put the inputs into the transaction such that the output is
// satisfied.
let funded_tx = bitcoind_client.fund_raw_transaction(raw_tx).await;
assert!(funded_tx.changepos == 0 || funded_tx.changepos == 1);
// Sign the funding transaction and give it to ChannelManager to broadcast.
let signed_tx = bitcoind_client.sign_raw_transaction_with_wallet(funded_tx.hex).await;
assert_eq!(signed_tx.complete, true);
let final_tx: Transaction =
encode::deserialize(&hex_utils::to_vec(&signed_tx.hex).unwrap()).unwrap();
channel_manager.funding_transaction_generated(&temporary_channel_id, final_tx).unwrap();
}
// ...
}
After ChannelManager
has broadcast the funding transaction, the channel will
become usable once the transaction has enough confirmations and will appear in
ChannelManager::list_usable_channels
. See the guide on
Blockchain Data for details on confirmations.
With a fully funded channel, you can now make Lightning payments! No more hefty on-chain fees and long confirmation times when you're transacting on layer 2.
# Closing a Channel
While a channel can remain open indefinitely, there may come a time when you need to close it. There are two ways to close a channel: either cooperatively or unilaterally. The cooperative case makes for lower fees and immediate access to funds while the unilateral case does not. The latter may be necessary if your peer isn't behaving properly or has gone offline.
- Rust
- Java
let channel_id = channel_manager
.list_channels()
.iter()
.find(|channel| channel.user_id == user_id)
.expect("ERROR: Channel not found")
.channel_id;
// Example: Cooperative close
channel_manager.close_channel(&channel_id).expect("ERROR: Failed to close channel");
// Example: Unilateral close
channel_manager.force_close_channel(&channel_id).expect("ERROR: Failed to close channel");
Now that we know how to manage channels, let's put our new channel to use!