-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Summary
A channel was force-closed during migration from RN due to the bug fixed in #760. The channel monitor was silently dropped by .mapNotNull() in fetchRNRemoteLdkData(), causing LDK to not recognize the channel on restart. The counterparty force-closed the channel, and the client's to_local output was never swept because the monitor data was missing.
376,523 sats are still sitting unclaimed on-chain.
Channel Details
| Field | Value |
|---|---|
| Channel ID | 7c9f614b82e0917924e2925284bc6ba9f8932055e57225ffeb804cde35b96c08 |
| Funding Txid | 086cb935de4c80ebff2572e5552093f8a96bbc845292e2247991e0824b619f7c |
| Funding Output | 0 |
| Channel Capacity | 441,826 sats |
| Counterparty | 03816141f1dce7782ec32b66a300783b1d436b19777e7c686ed00115bd4b88ff4b (Blocktank LSP lnd3) |
Force Close Transaction
| Field | Value |
|---|---|
| Close Txid | b41cb9e5e562014ea2535c193496c099a59086c22ddafaae32c0fd9ba1b4c0d3 |
| Block Height | 934,477 |
Outputs
| # | Value | Status | Purpose |
|---|---|---|---|
| 0 | 330 sats | Spent (block 934,493) | Anchor |
| 1 | 330 sats | Spent (block 934,493) | Anchor |
| 2 | 64,046 sats | Spent (block 934,623) | LSP's to_remote (swept by lnd3) |
| 3 | 376,523 sats | Unspent | Client's to_local — never claimed |
Root Cause
MigrationService.fetchRNRemoteLdkData() (before #760 fix):
}.mapNotNull { it.await() }If any channel monitor retrieval failed, it was silently dropped. The monitor was lost, LDK sent a bogus ChannelReestablish, and the counterparty force-closed.
Proposed Solution
The RN remote backup is not wiped after migration — cleanupAfterMigration() only clears local DataStore preferences. Channel monitors should still be on the RN backup server.
One-time recovery check for all affected users
On app startup (post-migration), perform a one-time check against the RN remote backup:
- List channel monitors on the RN backup server via
rnBackupClient.listFiles(fileGroup = "ldk") - Compare with the monitors LDK Node currently knows about
- If there are orphaned monitors on the remote that LDK doesn't have, retrieve them
- For each recovered monitor, check if the corresponding funding output has an unswept
to_localoutput on-chain - If claimable funds are found, feed the monitor to LDK to reconstruct state and sweep
This would recover funds for any user affected by the #760 bug, not just this specific case. The check should be gated behind a flag so it only runs once.