-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Closed
Labels
SCBRelated to static channel backupRelated to static channel backupbugUnintended code behaviourUnintended code behaviour
Description
On the following scenario:
- Alice <-> Bob channel
- Bob goes offline
- Some time passes
- Alice force-closes the channel
- Some time passes
- Bob restores its node and applies SCB file during wallet init
Bob ends up with a pending_force_close channel with negative blocks_til_maturity that never resolves itself automatically.
How should such channels be handled?
Some options:
- Leave channel there forever
- Gonna have a channel on pending channels query forever
- Node operator needs to always remember to ignore this channel
- Restore again, but skip SCB
- Could further interfere with other ongoing operations
- More work for the node operator
- (Optionally) filter when listing pending channels
- Node operator will have to remember to specify the filter condition
- If the filtering isn't optional, node operator may want to actually know about the channel
- Add an RPC to remove this pending channel
- Risky if user doesn't know what it's doing
- Requires node operator intervention
- Detect and remove such pending channels automatically
- How to detect (which conditions apply here that don't conflict with other issues)?
- Less work for node operator
- May remove data before operator actually wants it gone
NOTE: Bob finds the on-chain funds correctly in this case, the issue is the extraneous entry in the pending_foce_close list.
Example itest that demonstrates issue
package itest
import (
"github.com/btcsuite/btcd/btcutil"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntest"
)
func testRestoreWithSCBAfterLongForceClosed(ht *lntest.HarnessTest) {
chanAmt := btcutil.Amount(100000)
alice := ht.Alice
// Create bob and track seed.
password := []byte("El Psy Kongroo")
bob, mnemonic, _ := ht.NewNodeWithSeed(
"dave", nil, password, false,
)
ht.EnsureConnected(alice, bob)
// Open alice <> bob channel.
cp := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// Advance channel state.
const paymentAmt = 1000
payReqs, _, _ := ht.CreatePayReqs(bob, paymentAmt, 1)
ht.CompletePaymentRequests(alice, payReqs)
// Save bob's backup.
chanBackup := bob.RPC.ExportAllChanBackups()
// Bob goes offline.
ht.Shutdown(bob)
// Alice force-closes the channel while Bob is offline.
ht.ForceCloseChannel(alice, cp)
// Mine a few blocks for good measure.
ht.MineBlocks(64)
// Bob restores its node from seed, applying the SCB.
backupSnapshot := &lnrpc.ChanBackupSnapshot{
MultiChanBackup: chanBackup.MultiChanBackup,
}
bob2 := ht.RestoreNodeWithSeed("bob2", nil, password, mnemonic, "",
revocationWindow, backupSnapshot)
// Mine a few blocks for good measure.
ht.MineBlocks(64)
// Channel was closed long ago, how to handle the pending force close
// channel?
resp := bob2.RPC.PendingChannels()
ht.Logf(spew.Sdump(resp))
ht.AssertNumPendingForceClose(bob, 0) // This fails.
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
SCBRelated to static channel backupRelated to static channel backupbugUnintended code behaviourUnintended code behaviour