Payment Channels
How Lightning payment channels work. Channel lifecycle, funding transactions, commitment transactions, and channel capacity.
Payment Channels
A payment channel is a two-party financial relationship that allows unlimited payments without touching the blockchain. Only two on-chain transactions are needed: one to open the channel, one to close it.
Why Channels Matter for Agents
| Benefit | Description |
|---|---|
| Speed | Payments settle in milliseconds |
| Cost | No on-chain fees for channel payments |
| Volume | Unlimited payments per channel |
| Privacy | Intermediate states aren’t broadcast |
Channel Lifecycle
1. Channel Opening
Two parties create a funding transaction that locks Bitcoin into a 2-of-2 multisig address.
Alice: 0.1 BTC ─┐
├─ Funding TX ─→ 2-of-2 Multisig
Bob: 0.0 BTC ─┘
On-chain cost: One transaction (~140 vbytes)
2. Channel Usage
Parties exchange commitment transactions off-chain. Each commitment represents the current balance split.
State 0: Alice=0.1, Bob=0.0
State 1: Alice=0.09, Bob=0.01 (Alice pays Bob 0.01)
State 2: Alice=0.08, Bob=0.02 (Alice pays Bob 0.01)
State 3: Alice=0.085, Bob=0.015 (Bob pays Alice 0.005)
On-chain cost: Zero
3. Channel Closing
When parties are done, they broadcast a closing transaction that splits funds according to the final state.
Cooperative close: Both parties sign, immediate settlement Unilateral close: One party broadcasts, requires timelock
Commitment Transactions
Each party holds their own commitment transaction that they can broadcast at any time.
┌─────────────────────────────────────┐
│ Commitment TX (Alice's) │
├─────────────────────────────────────┤
│ Input: Funding TX output │
│ │
│ Output 1: Alice (immediate) │
│ Output 2: Bob (with revocation key) │
└─────────────────────────────────────┘
Asymmetric Commitments
Alice and Bob hold different commitment transactions:
Alice’s commitment:
- Alice’s balance: delayed (CSV timelock)
- Bob’s balance: immediate (or revocable)
Bob’s commitment:
- Bob’s balance: delayed (CSV timelock)
- Alice’s balance: immediate (or revocable)
This asymmetry enables revocation—if Bob broadcasts an old state, Alice can sweep all funds using the revocation key.
Channel Capacity
Capacity = Total BTC locked in the channel Local balance = Your spendable amount Remote balance = Peer’s spendable amount
Channel Capacity: 0.1 BTC
├── Alice (local): 0.06 BTC ──→ Can send up to 0.06 BTC
└── Bob (remote): 0.04 BTC ──→ Can receive up to 0.04 BTC
Inbound vs Outbound Liquidity
| Type | Description | Agent Use |
|---|---|---|
| Outbound | Funds you can send | Making payments |
| Inbound | Funds you can receive | Receiving payments |
Key insight: To receive payments, you need inbound liquidity (funds on the remote side of your channels).
Channel States
Valid States
┌──────────┐ open_channel ┌───────────┐
│ Closed │ ─────────────────→ │ Opening │
└──────────┘ └───────────┘
│
funding_confirmed
↓
┌──────────┐ closing_signed ┌───────────┐
│ Closing │ ←───────────────── │ Open │
└──────────┘ └───────────┘
│ ↑
│ tx_confirmed │
↓ update_add_htlc
┌──────────┐ commitment_signed
│ Closed │
└──────────┘
Force Close Scenarios
| Scenario | Resolution |
|---|---|
| Peer offline | Unilateral close after timeout |
| Peer malicious | Revocation transaction |
| Peer unresponsive | Force close with CSV delay |
Agent Implementation
Opening a Channel
# Via LND gRPC
channel_point = lnd.open_channel(
node_pubkey=peer_pubkey,
local_funding_amount=100000, # satoshis
push_sat=0, # initial remote balance
private=False # announce to network
)
Checking Channel Status
# Get channel info
channels = lnd.list_channels()
for channel in channels:
print(f"Capacity: {channel.capacity}")
print(f"Local: {channel.local_balance}")
print(f"Remote: {channel.remote_balance}")
print(f"Active: {channel.active}")
Closing a Channel
# Cooperative close (preferred)
lnd.close_channel(
channel_point=channel_point,
force=False
)
# Force close (peer unresponsive)
lnd.close_channel(
channel_point=channel_point,
force=True
)
Channel Parameters
| Parameter | Description | Typical Value |
|---|---|---|
funding_satoshis | Channel capacity | 100,000 - 16,777,215 |
push_msat | Initial remote balance | 0 |
dust_limit_satoshis | Minimum output | 354 |
max_htlc_value_in_flight_msat | Max pending HTLCs | Channel capacity |
channel_reserve_satoshis | Minimum local balance | 1% of capacity |
htlc_minimum_msat | Minimum HTLC | 1000 |
to_self_delay | CSV blocks for force close | 144 (1 day) |
max_accepted_htlcs | Max concurrent HTLCs | 483 |
Reserve Requirements
Each party must maintain a channel reserve—a minimum balance that can’t be spent. This creates a penalty if they broadcast an old state.
Channel: 1,000,000 sats
Reserve: 10,000 sats (1%)
Alice can spend: local_balance - 10,000
Anchor Outputs
Modern channels use anchor outputs—small outputs that allow fee bumping via CPFP (Child Pays For Parent).
Commitment TX
├── Alice's balance
├── Bob's balance
├── Alice's anchor (330 sats)
└── Bob's anchor (330 sats)
Anchors ensure commitment transactions can be confirmed even if fees spike.
Channel Types
| Type | Announcement | Routing | Use Case |
|---|---|---|---|
| Public | Broadcast to network | Yes | Routing nodes |
| Private | Known only to peers | No | End-user wallets |
| Unannounced | Not in gossip | Possible | Temporary channels |
Best Practices for Agents
- Channel size: Open channels with enough capacity for expected volume
- Multiple channels: Don’t rely on a single channel
- Well-connected peers: Choose peers with good routing connectivity
- Monitor capacity: Rebalance before liquidity runs out
- Backup channel state: Store SCBs (Static Channel Backups)
Related Topics
- HTLCs - How payments traverse channels
- Liquidity - Managing channel capacity
- Routing - Multi-hop payments
- BOLT-02 - Peer Protocol specification
Machine-Readable Summary
{
"topic": "payment-channels",
"key_concepts": [
"funding-transaction",
"commitment-transaction",
"channel-capacity",
"revocation"
],
"operations": [
"open_channel",
"update_commitment",
"close_channel"
],
"parameters": {
"min_channel_size": 20000,
"max_channel_size": 16777215,
"typical_reserve": "1%"
}
}