Skip to content

Commit 27da365

Browse files
committed
Add removechannel command
1 parent 7eee3cd commit 27da365

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
+ [fixoldbackup](#fixoldbackup)
1717
+ [genimportscript](#genimportscript)
1818
+ [forceclose](#forceclose)
19+
+ [removechannel](#removechannel)
1920
+ [rescueclosed](#rescueclosed)
2021
+ [rescuefunding](#rescuefunding)
2122
+ [showrootkey](#showrootkey)
@@ -267,6 +268,7 @@ Available commands:
267268
fixoldbackup Fixes an old channel.backup file that is affected by the lnd issue #3881 (unable to derive shachain root key).
268269
forceclose Force-close the last state that is in the channel.db provided.
269270
genimportscript Generate a script containing the on-chain keys of an lnd wallet that can be imported into other software like bitcoind.
271+
removechannel Remove a single channel from the given channel DB.
270272
rescueclosed Try finding the private keys for funds that are in outputs of remotely force-closed channels.
271273
rescuefunding Rescue funds locked in a funding multisig output that never resulted in a proper channel. This is the command the initiator of the channel needs to run.
272274
showrootkey Extract and show the BIP32 HD root key from the 24 word lnd aezeed.
@@ -505,6 +507,26 @@ Example command:
505507
chantools genimportscript --format bitcoin-cli --recoverywindow 5000
506508
```
507509

510+
### removechannel
511+
512+
```text
513+
Usage:
514+
chantools [OPTIONS] removechannel [removechannel-OPTIONS]
515+
516+
[removechannel command options]
517+
--channeldb= The lnd channel.db file to remove the channel from.
518+
--channel= The channel to remove from the DB file, identified by its channel point (<txid>:<txindex>).
519+
```
520+
521+
Removes a single channel from the given channel DB.
522+
523+
Example command:
524+
525+
```bash
526+
chantools --channeldb ~/.lnd/data/graph/mainnet/channel.db \
527+
--channel 3149764effbe82718b280de425277e5e7b245a4573aa4a0203ac12cee1c37816:0
528+
```
529+
508530
### rescueclosed
509531

510532
```text

cmd/chantools/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ func runCommandParser() error {
156156
"-initiator) of the channel needs to run.", "",
157157
&signRescueFundingCommand{},
158158
)
159+
_, _ = parser.AddCommand(
160+
"removechannel", "Remove a single channel from the given "+
161+
"channel DB.", "", &removeChannelCommand{},
162+
)
159163

160164
_, err := parser.Parse()
161165
return err

cmd/chantools/removechannel.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/btcsuite/btcd/chaincfg/chainhash"
9+
"github.com/btcsuite/btcd/wire"
10+
"github.com/guggero/chantools/lnd"
11+
"github.com/lightningnetwork/lnd/channeldb"
12+
)
13+
14+
type removeChannelCommand struct {
15+
ChannelDB string `long:"channeldb" description:"The lnd channel.db file to remove the channel from."`
16+
Channel string `long:"channel" description:"The channel to remove from the DB file, identified by its channel point (<txid>:<txindex>)."`
17+
}
18+
19+
func (c *removeChannelCommand) Execute(_ []string) error {
20+
setupChainParams(cfg)
21+
22+
// Check that we have a channel DB.
23+
if c.ChannelDB == "" {
24+
return fmt.Errorf("channel DB is required")
25+
}
26+
db, err := lnd.OpenDB(c.ChannelDB, false)
27+
if err != nil {
28+
return fmt.Errorf("error opening channel DB: %v", err)
29+
}
30+
defer func() {
31+
if err := db.Close(); err != nil {
32+
log.Errorf("Error closing DB: %v", err)
33+
}
34+
}()
35+
36+
parts := strings.Split(c.Channel, ":")
37+
if len(parts) != 2 {
38+
return fmt.Errorf("invalid channel point format: %v", c.Channel)
39+
}
40+
hash, err := chainhash.NewHashFromStr(parts[0])
41+
if err != nil {
42+
return err
43+
}
44+
index, err := strconv.ParseUint(parts[1], 10, 64)
45+
if err != nil {
46+
return err
47+
}
48+
49+
return removeChannel(db, &wire.OutPoint{
50+
Hash: *hash,
51+
Index: uint32(index),
52+
})
53+
}
54+
55+
func removeChannel(db *channeldb.DB, chanPoint *wire.OutPoint) error {
56+
dbChan, err := db.FetchChannel(*chanPoint)
57+
if err != nil {
58+
return err
59+
}
60+
61+
if err := dbChan.MarkBorked(); err != nil {
62+
return err
63+
}
64+
65+
// Abandoning a channel is a three step process: remove from the open
66+
// channel state, remove from the graph, remove from the contract
67+
// court. Between any step it's possible that the users restarts the
68+
// process all over again. As a result, each of the steps below are
69+
// intended to be idempotent.
70+
return db.AbandonChannel(chanPoint, uint32(100000))
71+
}

0 commit comments

Comments
 (0)