Chantools
A loose collection of tools all somehow related to lnd and Lightning Network channels.
Install / Use
/learn @lightninglabs/ChantoolsREADME
Channel tools
Index
This tool provides helper functions that can be used to rescue funds locked in
lnd channels in case lnd itself cannot run properly anymore (some commands
also support Core Lightning (CLN), check command overview below
for a list of compatible commands).
WARNING: This tool was specifically built for a certain rescue operation and might not be well-suited for your use case. Or not all edge cases for your needs are coded properly. Please look at the code to understand what it does before you use it for anything serious.
WARNING 2: This tool will query public block explorer APIs for some
commands, your privacy might not be preserved. Use at your own risk or supply
a private API URL with --apiurl.
Installation
The easiest way to install chantools is to download a pre-built binary for
your operating system and
architecture.
Example (make sure you always use the latest version!):
$ cd /tmp
$ wget -O chantools.tar.gz https://github.com/lightninglabs/chantools/releases/download/v0.14.2/chantools-linux-amd64-v0.14.2.tar.gz
$ tar -zxvf chantools.tar.gz
$ sudo mv chantools-*/chantools /usr/local/bin/
Compile from source
If there isn't a pre-built binary for your operating system or architecture
available, or you want to build chantools from source for another reason, you
need to make sure you have go 1.24.0 (or later) and make installed and can
then run the following commands:
git clone https://github.com/lightninglabs/chantools.git
cd chantools
make install
How to use
There is a helper GUI
available that
guides you through the most common (and safest to use) commands of chantools.
For any other, more advanced, use cases either check out the available commands or the legacy channel recovery scenario guide below.
When should I use what command?
This list contains a list of scenarios that users seem to run into sometimes.
Before you start running any chantools command, you MUST read the
"What should I NEVER do?" section below!
Scenarios:
-
My node/disk/database crashed and I only have the seed and
channel.backupfile.This is the "normal" recovery scenario for which you don't need
chantools. Just follow the [lndrecovery guide][recovery]. All channels will be closed to recover funds, so you should still try to avoid This scenario. You only needchantoolsif you had [zombie channels][safety-zombie] or a channel that did not confirm in time (see below). -
My node/disk/database crashed and I only have the seed.
This is very bad and recovery will take manual steps and might not be successful for private channels. If you do not have any data left from your node, you need to follow the
chantools fakechanbackupcommand help text. If you do have an old version of yourchannel.dbfile, DO NOT UNDER ANY CIRCUMSTANCES start your node with it. Instead, try to extract achannel.backupfrom it using thechantools chanbackupcommand. If that is successful, follow the steps in the [lndrecovery guide][recovery]. This will not cover new channels opened after the backup of thechannel.dbfile was created. You might still need to create the fake channel backup. -
I suspect my channel.db file to be corrupt.
This can happen due to unclean shutdowns or power outages. Try running
chantools compactdb. If there are NO ERRORS during the execution of that command, things should be back to normal, and you can continue running your node. If you get errors, you should probably follow the recovery scenario described below to avoid future issues. This will close all channels, however. -
I don't have a
channel.backupfile but all my peers force closed my channels, why don't I see the funds with just my seed?When a channel is force closed by the remote party, the funds don't automatically go to a normal on-chain address. You need to sweep those funds using the
chantools sweepremoteclosedcommand. -
My channel peer is online, but they don't force close a channel when using a
channel.backupfile.This can have many reasons. Often it means the channels is a legacy channel type (not an anchor output channel) and the force close transaction the peer has doesn't have enough fees to make it into the mempool. In that case waiting for an empty mempool might be the only option. Another reason might be that the peer is a CLN node with a specific version that doesn't react to force close requests normally. You can use the
chantools triggerforceclosecommand in that case (should work with CLN peers of a certain version that don't respond to normal force close requests).
What should I NEVER do?
- You should never panic. There are extremely few situations in which doing
nothing makes things worse. On the contrary, most cases where users actually
lost funds it was due to them running commands they did not understand in a
rush of panic. So stay calm, try to find out what the reason for the problem
is, ask for help (see [Slack][slack], [
lnddiscussions][discussions]) or use Google. Create a backup of all your files in thelnddata directory (just in case, but never [start a node from a file based backup][safety-file-backup]) before running any command. Also read the [lndOperational Safety Guidelines][safety]. - Whatever you might read in any issue, you should never use
lncli abandonchannelon a channel that was confirmed on chain. Even if you have an SCB (Static Channel Backup, unfortunately poorly named) file (channel.backup) or export fromlncli exportchanbackup. Those files DO NOT contain enough information to close a channel if your peer does not have the channel data either (which might happen if the channel took longer than 2 weeks to confirm). If the channel confirmed on chain, you need to force close it from your node if it does not operate normally. Runningabandonchanneldeletes the information needed to be able to force close. - When running Umbrel, NEVER just uninstall the Lightning App when encountering a problem. Uninstalling the app deletes important data that might be needed for recovery in edge cases. The channel backup (SCB) in the cloud does NOT cover "expired" channels (channels that took longer than 2 weeks to confirm) or [zombie channels][safety-zombie].
- The term "backup" in SCB (Static Channel Backup) or the
channel.backupfile or the output oflncli exportchanbackupis not optimal as it implies the channels can be fully restored or brought back to an operational state. But the content of those files are for absolute emergencies only. Channels are always closed when using such a file (by asking the remote peer to issue their latest force close transaction they have). So chain fees occur. And there are some edge cases where funds are not covered by those files, for example when a channel funding transaction is not confirmed in time. Or for channels where the peer is no longer online. So deleting yourlnddata directory should never ever be something to be done lightly (see Umbrel above).
Seed and passphrase input
All commands that require the seed (and, if set, the seed's passphrase) offer three distinct possibilities to specify it:
- Enter manually on the terminal: This is the safest option as it makes sure that the seed isn't stored in the terminal's command history.
- Pass the extened master root key as parameter: This is added as an option
for users who don't have the full seed anymore, possibly because they used
lnd's--noseedbackupflag and extracted thexprvfrom the wallet database with thewalletinfocommand. Those users can specify the master root key by passing the--rootkeycommand line flag to each command that requires the seed. - Use environment variables: This option makes it easy to automate usage of
chantoolsby removing the need to type into the terminal. There are three environment variables that can be set to skip entering values through the terminal:AEZEED_MNEMONIC: Specifies the 24 wordlndaezeed.AEZEED_PASSPHRASE: Specifies the passphrase for the aezeed. If no passphrase was used during the creation of the seed, the special valueAEZEED_PASSPHRASE="-"needs to be passed to indicate no passphrase should be used or read from the terminal.WALLET_PASSWORD: Specifies the encryption password that is needed to access awallet.dbfile. This is currently only used by thewalletinfocommand.
Example using environment variables:
# We add a space in front of each command to tell bash we don't want this
# command stored in the history.
$ export AEZEED_MNEMONIC="abandon able ... ... ..."
# We didn't set a passphrase for this example seed, we need to indicate this by
# passing in a single dash character.
$ export AEZEED_PASSPHRASE="-"
$ chantools showrootkey
2020-10-29 20:22:42.329 [INF] CHAN: chantools version v0.12.0 commit v0.12.0
Your BIP32 HD root key is: xprv9s21ZrQH1...
Are my funds safe?
Some commands require the seed. But your seed will never leave your computer.
Most commands don't require an internet connection: you can and should
