Skip to content

fix(channeld): handle NULL short_channel_id in AWAITING_LOCKIN state #8435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
12 changes: 10 additions & 2 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -6412,6 +6412,8 @@ static void init_channel(struct peer *peer)
struct penalty_base *pbases;
struct channel_type *channel_type;
bool found_locked_inflight;
bool has_funding_short_id;
struct short_channel_id *funding_short_id;

assert(!(fcntl(MASTER_FD, F_GETFL) & O_NONBLOCK));

Expand Down Expand Up @@ -6449,9 +6451,9 @@ static void init_channel(struct peer *peer)
&peer->revocations_received,
&peer->htlc_id,
&htlcs,
&peer->channel_ready[LOCAL],
&has_funding_short_id,
&peer->channel_ready[REMOTE],
&peer->short_channel_ids[LOCAL],
&funding_short_id,
&reconnected,
&peer->send_shutdown,
&peer->shutdown_sent[REMOTE],
Expand All @@ -6471,6 +6473,12 @@ static void init_channel(struct peer *peer)
master_badmsg(WIRE_CHANNELD_INIT, msg);
}

if (has_funding_short_id && funding_short_id) {
peer->short_channel_ids[LOCAL] = *funding_short_id;
} else {
peer->short_channel_ids[LOCAL] = peer->local_alias;
}

peer->final_index = tal_dup(peer, u32, &final_index);
peer->final_ext_key = tal_dup(peer, struct ext_key, &final_ext_key);
peer->splice_state->count = tal_count(peer->splice_state->inflights);
Expand Down
4 changes: 2 additions & 2 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ msgdata,channeld_init,revocations_received,u64,
msgdata,channeld_init,next_htlc_id,u64,
msgdata,channeld_init,num_existing_htlcs,u16,
msgdata,channeld_init,htlcs,existing_htlc,num_existing_htlcs
msgdata,channeld_init,local_channel_ready,bool,
msgdata,channeld_init,has_funding_short_id,bool,
msgdata,channeld_init,remote_channel_ready,bool,
msgdata,channeld_init,funding_short_id,short_channel_id,
msgdata,channeld_init,funding_short_id,?short_channel_id,
msgdata,channeld_init,reestablish,bool,
msgdata,channeld_init,send_shutdown,bool,
msgdata,channeld_init,remote_shutdown_received,bool,
Expand Down
8 changes: 4 additions & 4 deletions contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contrib/pyln-grpc-proto/pyln/grpc/node_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pyln.grpc import node_pb2 as node__pb2

GRPC_GENERATED_VERSION = '1.69.0'
GRPC_GENERATED_VERSION = '1.74.0'
GRPC_VERSION = grpc.__version__
_version_not_supported = False

Expand Down
8 changes: 4 additions & 4 deletions contrib/pyln-grpc-proto/pyln/grpc/primitives_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 81 additions & 0 deletions doc/orphaned-channel-cleanup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Orphaned Channel Cleanup Process

## Overview
Channels can become "orphaned" when they get stuck in the `CHANNELD_AWAITING_LOCKIN` state with a funding transaction that never confirms. This can happen if:
- The funding transaction was never broadcast
- The funding transaction was dropped from the mempool
- The transaction fee was too low and it got purged

## Detection Commands

### listorphanedchannels
Lists channels in `CHANNELD_AWAITING_LOCKIN` state where the funding transaction is not in the mempool.

```bash
lightning-cli listorphanedchannels [timeout_hours=48]
```

Parameters:
- `timeout_hours` (optional): Only show channels stuck for at least this many hours (default: 48)

Returns:
- Array of orphaned channels with details including peer_id, channel_id, funding_txid, hours_stuck
- Total count of orphaned channels

### cleanuporphanedchannels
Safely removes orphaned channels that have been stuck for the specified time.

```bash
lightning-cli cleanuporphanedchannels [timeout_hours=48] [force=false]
```

Parameters:
- `timeout_hours` (optional): Only cleanup channels stuck for at least this many hours (default: 48)
- `force` (optional): Force cleanup even if safety checks fail (default: false)

Safety checks:
- Channel must not have any pending HTLCs
- Channel must be in `CHANNELD_AWAITING_LOCKIN` state

## Manual Cleanup Process

1. First, identify orphaned channels:
```bash
lightning-cli listorphanedchannels
```

2. Review each orphaned channel carefully:
- Check the funding transaction status on a block explorer
- Verify no funds are at risk

3. Clean up individual channels using dev-forget-channel:
```bash
lightning-cli dev-forget-channel <peer_id> [short_channel_id] [force=true]
```

4. Or clean up all orphaned channels at once:
```bash
lightning-cli cleanuporphanedchannels
```

## Monitoring

The node will log warnings when orphaned channels are detected:
```
UNUSUAL: Orphaned channel detected: funding_txid=xxx, outnum=0, stuck for 72 hours
```

## Prevention

To prevent orphaned channels:
1. Ensure funding transactions use appropriate fees
2. Monitor channel states after funding
3. Set up alerts for channels stuck in `CHANNELD_AWAITING_LOCKIN`
4. Consider implementing automatic cleanup policies

## Recovery

If you accidentally cleanup a channel with a valid funding transaction:
1. The funds remain safe in the funding output
2. You can spend the funding output using the commitment transaction
3. Contact support if you need assistance recovering funds
6 changes: 3 additions & 3 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1671,7 +1671,7 @@ bool peer_start_channeld(struct channel *channel,
u8 *initmsg;
int hsmfd;
const struct existing_htlc **htlcs;
struct short_channel_id scid;
struct short_channel_id *scid;
u64 num_revocations;
struct lightningd *ld = channel->peer->ld;
const struct config *cfg = &ld->config;
Expand Down Expand Up @@ -1727,10 +1727,10 @@ bool peer_start_channeld(struct channel *channel,
htlcs = peer_htlcs(tmpctx, channel);

if (channel->scid) {
scid = *channel->scid;
scid = channel->scid;
log_debug(channel->log, "Already have funding locked in");
} else {
memset(&scid, 0, sizeof(scid));
scid = NULL;
}

num_revocations = revocations_received(&channel->their_shachain.chain);
Expand Down
Loading