From e6fcb580a3eb6d346f7c7e1772d7a684cd9d28b1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Sun, 27 Dec 2020 01:40:51 +0100 Subject: [PATCH] doc+cmd: generate description from commands --- cmd/chantools/chanbackup.go | 7 ++++++- cmd/chantools/compactdb.go | 5 +++++ cmd/chantools/derivekey.go | 16 ++++++++++------ cmd/chantools/dumpbackup.go | 10 +++++++--- cmd/chantools/dumpchannels.go | 4 ++++ cmd/chantools/filterbackup.go | 5 +++++ cmd/chantools/fixoldbackup.go | 7 +++++++ cmd/chantools/forceclose.go | 16 ++++++++++++++++ cmd/chantools/genimportscript.go | 16 ++++++++++++++++ cmd/chantools/removechannel.go | 2 ++ cmd/chantools/rescueclosed.go | 14 ++++++++++++-- cmd/chantools/rescuefunding.go | 15 +++++++++++++++ cmd/chantools/root.go | 7 +++---- cmd/chantools/showrootkey.go | 6 +++++- cmd/chantools/signrescuefunding.go | 9 +++++++++ cmd/chantools/summary.go | 5 +++++ cmd/chantools/sweeptimelock.go | 15 +++++++++++++-- cmd/chantools/sweeptimelockmanual.go | 21 +++++++++++++++++++-- cmd/chantools/vanitygen.go | 16 ++++++++++++++++ cmd/chantools/walletinfo.go | 9 +++++++++ doc/chantools.md | 4 +--- doc/chantools_chanbackup.md | 13 +++++++++++++ doc/chantools_compactdb.md | 13 +++++++++++++ doc/chantools_derivekey.md | 12 ++++++++++++ doc/chantools_dumpbackup.md | 12 ++++++++++++ doc/chantools_dumpchannels.md | 12 ++++++++++++ doc/chantools_filterbackup.md | 13 +++++++++++++ doc/chantools_fixoldbackup.md | 15 +++++++++++++++ doc/chantools_forceclose.md | 24 ++++++++++++++++++++++++ doc/chantools_genimportscript.md | 24 ++++++++++++++++++++++++ doc/chantools_removechannel.md | 7 +++++++ doc/chantools_rescueclosed.md | 18 ++++++++++++++++++ doc/chantools_rescuefunding.md | 23 +++++++++++++++++++++++ doc/chantools_showrootkey.md | 12 ++++++++++++ doc/chantools_signrescuefunding.md | 17 +++++++++++++++++ doc/chantools_summary.md | 13 +++++++++++++ doc/chantools_sweeptimelock.md | 19 +++++++++++++++++++ doc/chantools_sweeptimelockmanual.md | 25 +++++++++++++++++++++++++ doc/chantools_vanitygen.md | 24 ++++++++++++++++++++++++ doc/chantools_walletinfo.md | 17 +++++++++++++++++ 40 files changed, 498 insertions(+), 24 deletions(-) diff --git a/cmd/chantools/chanbackup.go b/cmd/chantools/chanbackup.go index 0a447b2..e29b797 100644 --- a/cmd/chantools/chanbackup.go +++ b/cmd/chantools/chanbackup.go @@ -21,7 +21,12 @@ func newChanBackupCommand() *cobra.Command { cc.cmd = &cobra.Command{ Use: "chanbackup", Short: "Create a channel.backup file from a channel database", - RunE: cc.Execute, + Long: `This command creates a new channel.backup from a +channel.db file.`, + Example: `chantools chanbackup --rootkey xprvxxxxxxx \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --multi_file new_channel_backup.backup`, + RunE: cc.Execute, } cc.cmd.Flags().StringVar( &cc.ChannelDB, "channeldb", "", "lnd channel.db file to "+ diff --git a/cmd/chantools/compactdb.go b/cmd/chantools/compactdb.go index a57b950..2e3c200 100644 --- a/cmd/chantools/compactdb.go +++ b/cmd/chantools/compactdb.go @@ -26,6 +26,11 @@ func newCompactDBCommand() *cobra.Command { Use: "compactdb", Short: "Create a copy of a channel.db file in safe/read-only " + "mode", + Long: `This command opens a database in read-only mode and tries +to create a copy of it to a destination file, compacting it in the process.`, + Example: `chantools compactdb \ + --sourcedb ~/.lnd/data/graph/mainnet/channel.db \ + --destdb ./results/compacted.db`, RunE: cc.Execute, } cc.cmd.Flags().Int64Var( diff --git a/cmd/chantools/derivekey.go b/cmd/chantools/derivekey.go index 4346ad0..2e962ad 100644 --- a/cmd/chantools/derivekey.go +++ b/cmd/chantools/derivekey.go @@ -10,19 +10,23 @@ import ( ) type deriveKeyCommand struct { - BIP39 bool - Path string - Neuter bool + BIP39 bool + Path string + Neuter bool rootKey *rootKey - cmd *cobra.Command + cmd *cobra.Command } func newDeriveKeyCommand() *cobra.Command { cc := &deriveKeyCommand{} cc.cmd = &cobra.Command{ - Use: "derivekey", + Use: "derivekey", Short: "Derive a key with a specific derivation path", + Long: `This command derives a single key with the given BIP32 +derivation path from the root key and prints it to the console.`, + Example: `chantools derivekey --rootkey xprvxxxxxxxxxx \ + --path "m/1017'/0'/5'/0/0'" --neuter`, RunE: cc.Execute, } cc.cmd.Flags().BoolVar( @@ -40,7 +44,7 @@ func newDeriveKeyCommand() *cobra.Command { ) cc.rootKey = newRootKey(cc.cmd, "decrypting the backup") - + return cc.cmd } diff --git a/cmd/chantools/dumpbackup.go b/cmd/chantools/dumpbackup.go index 40ec84a..a7bd147 100644 --- a/cmd/chantools/dumpbackup.go +++ b/cmd/chantools/dumpbackup.go @@ -15,7 +15,7 @@ type dumpBackupCommand struct { MultiFile string rootKey *rootKey - cmd *cobra.Command + cmd *cobra.Command } func newDumpBackupCommand() *cobra.Command { @@ -23,7 +23,11 @@ func newDumpBackupCommand() *cobra.Command { cc.cmd = &cobra.Command{ Use: "dumpbackup", Short: "Dump the content of a channel.backup file", - RunE: cc.Execute, + Long: `This command dumps all information that is inside a +channel.backup file in a human readable format.`, + Example: `chantools dumpbackup --rootkey xprvxxxxxxxxxx \ + --multi_file ~/.lnd/data/chain/bitcoin/mainnet/channel.backup`, + RunE: cc.Execute, } cc.cmd.Flags().StringVar( &cc.MultiFile, "multi_file", "", "lnd channel.backup file to "+ @@ -31,7 +35,7 @@ func newDumpBackupCommand() *cobra.Command { ) cc.rootKey = newRootKey(cc.cmd, "decrypting the backup") - + return cc.cmd } diff --git a/cmd/chantools/dumpchannels.go b/cmd/chantools/dumpchannels.go index eb4d182..3e8185d 100644 --- a/cmd/chantools/dumpchannels.go +++ b/cmd/chantools/dumpchannels.go @@ -23,6 +23,10 @@ func newDumpChannelsCommand() *cobra.Command { Use: "dumpchannels", Short: "Dump all channel information from an lnd channel " + "database", + Long: `This command dumps all open and pending channels from the +given lnd channel.db gile in a human readable format.`, + Example: `chantools dumpchannels \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/filterbackup.go b/cmd/chantools/filterbackup.go index 5738224..a8c1ae6 100644 --- a/cmd/chantools/filterbackup.go +++ b/cmd/chantools/filterbackup.go @@ -26,6 +26,11 @@ func newFilterBackupCommand() *cobra.Command { Use: "filterbackup", Short: "Filter an lnd channel.backup file and remove certain " + "channels", + Long: `Filter an lnd channel.backup file by removing certain +channels (identified by their funding transaction outpoints).`, + Example: `chantools filterbackup --rootkey xprvxxxxxxxxxx \ + --multi_file ~/.lnd/data/chain/bitcoin/mainnet/channel.backup \ + --discard 2abcdef2b2bffaaa...db0abadd:1,4abcdef2b2bffaaa...db8abadd:0`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/fixoldbackup.go b/cmd/chantools/fixoldbackup.go index 15117d5..359b03b 100644 --- a/cmd/chantools/fixoldbackup.go +++ b/cmd/chantools/fixoldbackup.go @@ -25,6 +25,13 @@ func newFixOldBackupCommand() *cobra.Command { Short: "Fixes an old channel.backup file that is affected by " + "the lnd issue #3881 (unable to derive shachain root " + "key)", + Long: `Fixes an old channel.backup file that is affected by the +lnd issue [#3881](https://github.com/lightningnetwork/lnd/issues/3881) +([lncli] unable to restore chan backups: rpc error: code = Unknown desc = +unable to unpack chan backup: unable to derive shachain root key: unable to +derive private key).`, + Example: `chantools fixoldbackup --rootkey xprvxxxxxxxxxx \ + --multi_file ~/.lnd/data/chain/bitcoin/mainnet/channel.backup`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/forceclose.go b/cmd/chantools/forceclose.go index 8118b99..6a24f2a 100644 --- a/cmd/chantools/forceclose.go +++ b/cmd/chantools/forceclose.go @@ -35,6 +35,22 @@ func newForceCloseCommand() *cobra.Command { Use: "forceclose", Short: "Force-close the last state that is in the channel.db " + "provided", + Long: `If you are certain that a node is offline for good (AFTER +you've tried SCB!) and a channel is still open, you can use this method to +force-close your latest state that you have in your channel.db. + +**!!! WARNING !!! DANGER !!! WARNING !!!** + +If you do this and the state that you publish is *not* the latest state, then +the remote node *could* punish you by taking the whole channel amount *if* they +come online before you can sweep the funds from the time locked (144 - 2000 +blocks) transaction *or* they have a watch tower looking out for them. + +**This should absolutely be the last resort and you have been warned!**`, + Example: `chantools forceclose --rootkey xprvxxxxxxxxxx \ + --fromsummary results/summary-xxxx-yyyy.json + --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --publish`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/genimportscript.go b/cmd/chantools/genimportscript.go index 28e8980..ccbb3a6 100644 --- a/cmd/chantools/genimportscript.go +++ b/cmd/chantools/genimportscript.go @@ -33,6 +33,22 @@ func newGenImportScriptCommand() *cobra.Command { Short: "Generate a script containing the on-chain " + "keys of an lnd wallet that can be imported into " + "other software like bitcoind", + Long: `Generates a script that contains all on-chain private (or +public) keys derived from an lnd 24 word aezeed wallet. That script can then be +imported into other software like bitcoind. + +The following script formats are currently supported: +* bitcoin-cli: Creates a list of bitcoin-cli importprivkey commands that can + be used in combination with a bitcoind full node to recover the funds locked + in those private keys. +* bitcoin-cli-watchonly: Does the same as bitcoin-cli but with the + bitcoin-cli importpubkey command. That means, only the public keys are + imported into bitcoind to watch the UTXOs of those keys. The funds cannot be + spent that way as they are watch-only. +* bitcoin-importwallet: Creates a text output that is compatible with + bitcoind's importwallet command.`, + Example: `chantools genimportscript --format bitcoin-cli \ + --recoverywindow 5000`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/removechannel.go b/cmd/chantools/removechannel.go index 5abc9d8..dae7b86 100644 --- a/cmd/chantools/removechannel.go +++ b/cmd/chantools/removechannel.go @@ -24,6 +24,8 @@ func newRemoveChannelCommand() *cobra.Command { cc.cmd = &cobra.Command{ Use: "removechannel", Short: "Remove a single channel from the given channel DB", + Example: `chantools --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --channel 3149764effbe82718b280de425277e5e7b245a4573aa4a0203ac12cee1c37816:0`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/rescueclosed.go b/cmd/chantools/rescueclosed.go index 94c243e..ad77e10 100644 --- a/cmd/chantools/rescueclosed.go +++ b/cmd/chantools/rescueclosed.go @@ -35,8 +35,8 @@ type rescueClosedCommand struct { ChannelDB string rootKey *rootKey - inputs *inputFlags - cmd *cobra.Command + inputs *inputFlags + cmd *cobra.Command } func newRescueClosedCommand() *cobra.Command { @@ -45,6 +45,16 @@ func newRescueClosedCommand() *cobra.Command { Use: "rescueclosed", Short: "Try finding the private keys for funds that " + "are in outputs of remotely force-closed channels", + Long: `If channels have already been force-closed by the remote +peer, this command tries to find the private keys to sweep the funds from the +output that belongs to our side. This can only be used if we have a channel DB +that contains the latest commit point. Normally you would use SCB to get the +funds from those channels. But this method can help if the other node doesn't +know about the channels any more but we still have the channel.db from the +moment they force-closed.`, + Example: `chantools rescueclosed --rootkey xprvxxxxxxxxxx \ + --fromsummary results/summary-xxxxxx.json \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/rescuefunding.go b/cmd/chantools/rescuefunding.go index e355eac..f9ea9cc 100644 --- a/cmd/chantools/rescuefunding.go +++ b/cmd/chantools/rescuefunding.go @@ -51,6 +51,21 @@ func newRescueFundingCommand() *cobra.Command { Short: "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", + Long: `This is part 1 of a two phase process to rescue a channel +funding output that was created on chain by accident but never resulted in a +proper channel and no commitment transactions exist to spend the funds locked in +the 2-of-2 multisig. + +**You need the cooperation of the channel partner (remote node) for this to +work**! They need to run the second command of this process: signrescuefunding + +If successful, this will create a PSBT that then has to be sent to the channel +partner (remote node operator).`, + Example: `chantools rescuefunding --rootkey xprvxxxxxxxxxx \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --channelpoint xxxxxxx:xx \ + --sweepaddr bc1qxxxxxxxxx \ + --feerate 10`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/root.go b/cmd/chantools/root.go index 9c1e7d5..00b7a3e 100644 --- a/cmd/chantools/root.go +++ b/cmd/chantools/root.go @@ -42,10 +42,9 @@ var ( var rootCmd = &cobra.Command{ Use: "chantools", Short: "Chantools helps recover funds from lightning channels", - Long: "This tool provides helper functions that can be used rescue\n" + - "funds locked in lnd channels in case lnd itself cannot run\n" + - "properly anymore.\n\nComplete documentation is available at " + - "https://github.com/guggero/chantools/.", + Long: `This tool provides helper functions that can be used rescue +funds locked in lnd channels in case lnd itself cannot run properly anymore. +Complete documentation is available at https://github.com/guggero/chantools/.`, Version: fmt.Sprintf("v%s, commit %s", version, Commit), PreRun: func(cmd *cobra.Command, args []string) { switch { diff --git a/cmd/chantools/showrootkey.go b/cmd/chantools/showrootkey.go index 576bb66..6a553ec 100644 --- a/cmd/chantools/showrootkey.go +++ b/cmd/chantools/showrootkey.go @@ -21,7 +21,11 @@ func newShowRootKeyCommand() *cobra.Command { Use: "showrootkey", Short: "Extract and show the BIP32 HD root key from the 24 " + "word lnd aezeed", - RunE: cc.Execute, + Long: `This command converts the 24 word lnd aezeed phrase and +password to the BIP32 HD root key that is used as the --rootkey flag in other +commands of this tool.`, + Example: `chantools showrootkey`, + RunE: cc.Execute, } cc.cmd.Flags().BoolVar( &cc.BIP39, "bip39", false, "read a classic BIP39 seed and "+ diff --git a/cmd/chantools/signrescuefunding.go b/cmd/chantools/signrescuefunding.go index 811ee10..7dc609b 100644 --- a/cmd/chantools/signrescuefunding.go +++ b/cmd/chantools/signrescuefunding.go @@ -27,6 +27,15 @@ func newSignRescueFundingCommand() *cobra.Command { "never resulted in a proper channel; this is the " + "command the remote node (the non-initiator) of the " + "channel needs to run", + Long: `This is part 2 of a two phase process to rescue a channel +funding output that was created on chain by accident but never resulted in a +proper channel and no commitment transactions exist to spend the funds locked in +the 2-of-2 multisig. + +If successful, this will create a final on-chain transaction that can be +broadcast by any Bitcoin node.`, + Example: `chantools signrescuefunding --rootkey xprvxxxxxxxxxx \ + --psbt `, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/summary.go b/cmd/chantools/summary.go index 2fc0747..8415049 100644 --- a/cmd/chantools/summary.go +++ b/cmd/chantools/summary.go @@ -24,6 +24,11 @@ func newSummaryCommand() *cobra.Command { Use: "summary", Short: "Compile a summary about the current state of " + "channels", + Long: `From a list of channels, find out what their state is by +querying the funding transaction on a block explorer API.`, + Example: `lncli listchannels | chantools summary --listchannels - + +chantools summary --fromchanneldb ~/.lnd/data/graph/mainnet/channel.db`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/sweeptimelock.go b/cmd/chantools/sweeptimelock.go index 34aee22..4a28ec1 100644 --- a/cmd/chantools/sweeptimelock.go +++ b/cmd/chantools/sweeptimelock.go @@ -31,8 +31,8 @@ type sweepTimeLockCommand struct { FeeRate uint16 rootKey *rootKey - inputs *inputFlags - cmd *cobra.Command + inputs *inputFlags + cmd *cobra.Command } func newSweepTimeLockCommand() *cobra.Command { @@ -41,6 +41,17 @@ func newSweepTimeLockCommand() *cobra.Command { Use: "sweeptimelock", Short: "Sweep the force-closed state after the time lock has " + "expired", + Long: `Use this command to sweep the funds from channels that +you force-closed with the forceclose command. You **MUST** use the result file +that was created with the forceclose command, otherwise it won't work. You also +have to wait until the highest time lock (can be up to 2016 blocks which is more +than two weeks) of all the channels has passed. If you only want to sweep +channels that have the default CSV limit of 1 day, you can set the --maxcsvlimit +parameter to 144.`, + Example: `chantools sweeptimelock --rootkey xprvxxxxxxxxxx \ + --fromsummary results/forceclose-xxxx-yyyy.json \ + --sweepaddr bc1q..... + --publish`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/sweeptimelockmanual.go b/cmd/chantools/sweeptimelockmanual.go index b6f553c..5d88690 100644 --- a/cmd/chantools/sweeptimelockmanual.go +++ b/cmd/chantools/sweeptimelockmanual.go @@ -35,8 +35,8 @@ type sweepTimeLockManualCommand struct { RemoteRevocationBasePoint string rootKey *rootKey - inputs *inputFlags - cmd *cobra.Command + inputs *inputFlags + cmd *cobra.Command } func newSweepTimeLockManualCommand() *cobra.Command { @@ -45,6 +45,23 @@ func newSweepTimeLockManualCommand() *cobra.Command { Use: "sweeptimelockmanual", Short: "Sweep the force-closed state of a single channel " + "manually if only a channel backup file is available", + Long: `Sweep the locally force closed state of a single channel +manually if only a channel backup file is available. This can only be used if a +channel is force closed from the local node but then that node's state is lost +and only the channel.backup file is available. + +To get the value for --remoterevbasepoint you must use the dumpbackup command, +then look up the value for RemoteChanCfg -> RevocationBasePoint -> PubKey. + +To get the value for --timelockaddr you must look up the channel's funding +output on chain, then follow it to the force close output. The time locked +address is always the one that's longer (because it's P2WSH and not P2PKH).`, + Example: `chantools sweeptimelockmanual --rootkey xprvxxxxxxxx \ + --sweepaddr bc1q..... \ + --timelockaddr bc1q............ \ + --remoterevbasepoint 03xxxxxxx \ + --feerate 10 \ + --publish`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/vanitygen.go b/cmd/chantools/vanitygen.go index 41fc8f8..21c3aba 100644 --- a/cmd/chantools/vanitygen.go +++ b/cmd/chantools/vanitygen.go @@ -35,6 +35,22 @@ func newVanityGenCommand() *cobra.Command { Use: "vanitygen", Short: "Generate a seed with a custom lnd node identity " + "public key that starts with the given prefix", + Long: `Try random lnd compatible seeds until one is found that +produces a node identity public key that starts with the given prefix. + +Example output: + +
+Running vanitygen on 8 threads. Prefix bit length is 17, expecting to approach
+probability p=1.0 after 131,072 seeds.
+Tested 185k seeds, p=1.41296, speed=14k/s, elapsed=13s                          
+Looking for 022222, found pubkey: 022222f015540ddde9bdf7c95b24f1d44f7ea6ab69bec83d6fbe622296d64b51d6
+with seed: [ability roast pear stomach wink cable tube trumpet shy caught hunt
+someone border organ spoon only prepare calm silent million tobacco chaos normal
+phone]
+
+`, + Example: `chantools vanitygen --prefix 022222 --threads 8`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/cmd/chantools/walletinfo.go b/cmd/chantools/walletinfo.go index efff43d..8e8c47f 100644 --- a/cmd/chantools/walletinfo.go +++ b/cmd/chantools/walletinfo.go @@ -58,6 +58,15 @@ func newWalletInfoCommand() *cobra.Command { Use: "walletinfo", Short: "Shows info about an lnd wallet.db file and optionally " + "extracts the BIP32 HD root key", + Long: `Shows some basic information about an lnd wallet.db file, +like the node identity the wallet belongs to, how many on-chain addresses are +used and, if enabled with --withrootkey the BIP32 HD root key of the wallet. The +latter can be useful to recover funds from a wallet if the wallet password is +still known but the seed was lost. **The 24 word seed phrase itself cannot be +extracted** because it is hashed into the extended HD root key before storing it +in the wallet.db.`, + Example: `chantools walletinfo --withrootkey \ + --walletdb ~/.lnd/data/chain/bitcoin/mainnet/wallet.db`, RunE: cc.Execute, } cc.cmd.Flags().StringVar( diff --git a/doc/chantools.md b/doc/chantools.md index c04940d..b5ce26e 100644 --- a/doc/chantools.md +++ b/doc/chantools.md @@ -5,9 +5,7 @@ Chantools helps recover funds from lightning channels ### Synopsis This tool provides helper functions that can be used rescue -funds locked in lnd channels in case lnd itself cannot run -properly anymore. - +funds locked in lnd channels in case lnd itself cannot run properly anymore. Complete documentation is available at https://github.com/guggero/chantools/. ### Options diff --git a/doc/chantools_chanbackup.md b/doc/chantools_chanbackup.md index 2be0662..54282f1 100644 --- a/doc/chantools_chanbackup.md +++ b/doc/chantools_chanbackup.md @@ -2,10 +2,23 @@ Create a channel.backup file from a channel database +### Synopsis + +This command creates a new channel.backup from a +channel.db file. + ``` chantools chanbackup [flags] ``` +### Examples + +``` +chantools chanbackup --rootkey xprvxxxxxxx \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --multi_file new_channel_backup.backup +``` + ### Options ``` diff --git a/doc/chantools_compactdb.md b/doc/chantools_compactdb.md index c6d6af9..21ebf17 100644 --- a/doc/chantools_compactdb.md +++ b/doc/chantools_compactdb.md @@ -2,10 +2,23 @@ Create a copy of a channel.db file in safe/read-only mode +### Synopsis + +This command opens a database in read-only mode and tries +to create a copy of it to a destination file, compacting it in the process. + ``` chantools compactdb [flags] ``` +### Examples + +``` +chantools compactdb \ + --sourcedb ~/.lnd/data/graph/mainnet/channel.db \ + --destdb ./results/compacted.db +``` + ### Options ``` diff --git a/doc/chantools_derivekey.md b/doc/chantools_derivekey.md index 3194d73..a52f563 100644 --- a/doc/chantools_derivekey.md +++ b/doc/chantools_derivekey.md @@ -2,10 +2,22 @@ Derive a key with a specific derivation path +### Synopsis + +This command derives a single key with the given BIP32 +derivation path from the root key and prints it to the console. + ``` chantools derivekey [flags] ``` +### Examples + +``` +chantools derivekey --rootkey xprvxxxxxxxxxx \ + --path "m/1017'/0'/5'/0/0'" --neuter +``` + ### Options ``` diff --git a/doc/chantools_dumpbackup.md b/doc/chantools_dumpbackup.md index 443369b..66f0faf 100644 --- a/doc/chantools_dumpbackup.md +++ b/doc/chantools_dumpbackup.md @@ -2,10 +2,22 @@ Dump the content of a channel.backup file +### Synopsis + +This command dumps all information that is inside a +channel.backup file in a human readable format. + ``` chantools dumpbackup [flags] ``` +### Examples + +``` +chantools dumpbackup --rootkey xprvxxxxxxxxxx \ + --multi_file ~/.lnd/data/chain/bitcoin/mainnet/channel.backup +``` + ### Options ``` diff --git a/doc/chantools_dumpchannels.md b/doc/chantools_dumpchannels.md index 3e31444..9eeaa42 100644 --- a/doc/chantools_dumpchannels.md +++ b/doc/chantools_dumpchannels.md @@ -2,10 +2,22 @@ Dump all channel information from an lnd channel database +### Synopsis + +This command dumps all open and pending channels from the +given lnd channel.db gile in a human readable format. + ``` chantools dumpchannels [flags] ``` +### Examples + +``` +chantools dumpchannels \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db +``` + ### Options ``` diff --git a/doc/chantools_filterbackup.md b/doc/chantools_filterbackup.md index 1788097..bdf3a09 100644 --- a/doc/chantools_filterbackup.md +++ b/doc/chantools_filterbackup.md @@ -2,10 +2,23 @@ Filter an lnd channel.backup file and remove certain channels +### Synopsis + +Filter an lnd channel.backup file by removing certain +channels (identified by their funding transaction outpoints). + ``` chantools filterbackup [flags] ``` +### Examples + +``` +chantools filterbackup --rootkey xprvxxxxxxxxxx \ + --multi_file ~/.lnd/data/chain/bitcoin/mainnet/channel.backup \ + --discard 2abcdef2b2bffaaa...db0abadd:1,4abcdef2b2bffaaa...db8abadd:0 +``` + ### Options ``` diff --git a/doc/chantools_fixoldbackup.md b/doc/chantools_fixoldbackup.md index 09fcb82..679570e 100644 --- a/doc/chantools_fixoldbackup.md +++ b/doc/chantools_fixoldbackup.md @@ -2,10 +2,25 @@ Fixes an old channel.backup file that is affected by the lnd issue #3881 (unable to derive shachain root key) +### Synopsis + +Fixes an old channel.backup file that is affected by the +lnd issue [#3881](https://github.com/lightningnetwork/lnd/issues/3881) +([lncli] unable to restore chan backups: rpc error: code = Unknown desc = +unable to unpack chan backup: unable to derive shachain root key: unable to +derive private key). + ``` chantools fixoldbackup [flags] ``` +### Examples + +``` +chantools fixoldbackup --rootkey xprvxxxxxxxxxx \ + --multi_file ~/.lnd/data/chain/bitcoin/mainnet/channel.backup +``` + ### Options ``` diff --git a/doc/chantools_forceclose.md b/doc/chantools_forceclose.md index 48933c0..f5e4494 100644 --- a/doc/chantools_forceclose.md +++ b/doc/chantools_forceclose.md @@ -2,10 +2,34 @@ Force-close the last state that is in the channel.db provided +### Synopsis + +If you are certain that a node is offline for good (AFTER +you've tried SCB!) and a channel is still open, you can use this method to +force-close your latest state that you have in your channel.db. + +**!!! WARNING !!! DANGER !!! WARNING !!!** + +If you do this and the state that you publish is *not* the latest state, then +the remote node *could* punish you by taking the whole channel amount *if* they +come online before you can sweep the funds from the time locked (144 - 2000 +blocks) transaction *or* they have a watch tower looking out for them. + +**This should absolutely be the last resort and you have been warned!** + ``` chantools forceclose [flags] ``` +### Examples + +``` +chantools forceclose --rootkey xprvxxxxxxxxxx \ + --fromsummary results/summary-xxxx-yyyy.json + --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --publish +``` + ### Options ``` diff --git a/doc/chantools_genimportscript.md b/doc/chantools_genimportscript.md index f0e5fa9..1c3726d 100644 --- a/doc/chantools_genimportscript.md +++ b/doc/chantools_genimportscript.md @@ -2,10 +2,34 @@ Generate a script containing the on-chain keys of an lnd wallet that can be imported into other software like bitcoind +### Synopsis + +Generates a script that contains all on-chain private (or +public) keys derived from an lnd 24 word aezeed wallet. That script can then be +imported into other software like bitcoind. + +The following script formats are currently supported: +* bitcoin-cli: Creates a list of bitcoin-cli importprivkey commands that can + be used in combination with a bitcoind full node to recover the funds locked + in those private keys. +* bitcoin-cli-watchonly: Does the same as bitcoin-cli but with the + bitcoin-cli importpubkey command. That means, only the public keys are + imported into bitcoind to watch the UTXOs of those keys. The funds cannot be + spent that way as they are watch-only. +* bitcoin-importwallet: Creates a text output that is compatible with + bitcoind's importwallet command. + ``` chantools genimportscript [flags] ``` +### Examples + +``` +chantools genimportscript --format bitcoin-cli \ + --recoverywindow 5000 +``` + ### Options ``` diff --git a/doc/chantools_removechannel.md b/doc/chantools_removechannel.md index 1f62875..09ccd4f 100644 --- a/doc/chantools_removechannel.md +++ b/doc/chantools_removechannel.md @@ -6,6 +6,13 @@ Remove a single channel from the given channel DB chantools removechannel [flags] ``` +### Examples + +``` +chantools --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --channel 3149764effbe82718b280de425277e5e7b245a4573aa4a0203ac12cee1c37816:0 +``` + ### Options ``` diff --git a/doc/chantools_rescueclosed.md b/doc/chantools_rescueclosed.md index 35ae27f..8335e90 100644 --- a/doc/chantools_rescueclosed.md +++ b/doc/chantools_rescueclosed.md @@ -2,10 +2,28 @@ Try finding the private keys for funds that are in outputs of remotely force-closed channels +### Synopsis + +If channels have already been force-closed by the remote +peer, this command tries to find the private keys to sweep the funds from the +output that belongs to our side. This can only be used if we have a channel DB +that contains the latest commit point. Normally you would use SCB to get the +funds from those channels. But this method can help if the other node doesn't +know about the channels any more but we still have the channel.db from the +moment they force-closed. + ``` chantools rescueclosed [flags] ``` +### Examples + +``` +chantools rescueclosed --rootkey xprvxxxxxxxxxx \ + --fromsummary results/summary-xxxxxx.json \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db +``` + ### Options ``` diff --git a/doc/chantools_rescuefunding.md b/doc/chantools_rescuefunding.md index 1eaadd3..b356779 100644 --- a/doc/chantools_rescuefunding.md +++ b/doc/chantools_rescuefunding.md @@ -2,10 +2,33 @@ 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 +### Synopsis + +This is part 1 of a two phase process to rescue a channel +funding output that was created on chain by accident but never resulted in a +proper channel and no commitment transactions exist to spend the funds locked in +the 2-of-2 multisig. + +**You need the cooperation of the channel partner (remote node) for this to +work**! They need to run the second command of this process: signrescuefunding + +If successful, this will create a PSBT that then has to be sent to the channel +partner (remote node operator). + ``` chantools rescuefunding [flags] ``` +### Examples + +``` +chantools rescuefunding --rootkey xprvxxxxxxxxxx \ + --channeldb ~/.lnd/data/graph/mainnet/channel.db \ + --channelpoint xxxxxxx:xx \ + --sweepaddr bc1qxxxxxxxxx \ + --feerate 10 +``` + ### Options ``` diff --git a/doc/chantools_showrootkey.md b/doc/chantools_showrootkey.md index bc0b875..b4be2ac 100644 --- a/doc/chantools_showrootkey.md +++ b/doc/chantools_showrootkey.md @@ -2,10 +2,22 @@ Extract and show the BIP32 HD root key from the 24 word lnd aezeed +### Synopsis + +This command converts the 24 word lnd aezeed phrase and +password to the BIP32 HD root key that is used as the --rootkey flag in other +commands of this tool. + ``` chantools showrootkey [flags] ``` +### Examples + +``` +chantools showrootkey +``` + ### Options ``` diff --git a/doc/chantools_signrescuefunding.md b/doc/chantools_signrescuefunding.md index 1539654..975fcb0 100644 --- a/doc/chantools_signrescuefunding.md +++ b/doc/chantools_signrescuefunding.md @@ -2,10 +2,27 @@ Rescue funds locked in a funding multisig output that never resulted in a proper channel; this is the command the remote node (the non-initiator) of the channel needs to run +### Synopsis + +This is part 2 of a two phase process to rescue a channel +funding output that was created on chain by accident but never resulted in a +proper channel and no commitment transactions exist to spend the funds locked in +the 2-of-2 multisig. + +If successful, this will create a final on-chain transaction that can be +broadcast by any Bitcoin node. + ``` chantools signrescuefunding [flags] ``` +### Examples + +``` +chantools signrescuefunding --rootkey xprvxxxxxxxxxx \ + --psbt +``` + ### Options ``` diff --git a/doc/chantools_summary.md b/doc/chantools_summary.md index d111c67..68e95f5 100644 --- a/doc/chantools_summary.md +++ b/doc/chantools_summary.md @@ -2,10 +2,23 @@ Compile a summary about the current state of channels +### Synopsis + +From a list of channels, find out what their state is by +querying the funding transaction on a block explorer API. + ``` chantools summary [flags] ``` +### Examples + +``` +lncli listchannels | chantools summary --listchannels - + +chantools summary --fromchanneldb ~/.lnd/data/graph/mainnet/channel.db +``` + ### Options ``` diff --git a/doc/chantools_sweeptimelock.md b/doc/chantools_sweeptimelock.md index 9d0099e..f845c23 100644 --- a/doc/chantools_sweeptimelock.md +++ b/doc/chantools_sweeptimelock.md @@ -2,10 +2,29 @@ Sweep the force-closed state after the time lock has expired +### Synopsis + +Use this command to sweep the funds from channels that +you force-closed with the forceclose command. You **MUST** use the result file +that was created with the forceclose command, otherwise it won't work. You also +have to wait until the highest time lock (can be up to 2016 blocks which is more +than two weeks) of all the channels has passed. If you only want to sweep +channels that have the default CSV limit of 1 day, you can set the --maxcsvlimit +parameter to 144. + ``` chantools sweeptimelock [flags] ``` +### Examples + +``` +chantools sweeptimelock --rootkey xprvxxxxxxxxxx \ + --fromsummary results/forceclose-xxxx-yyyy.json \ + --sweepaddr bc1q..... + --publish +``` + ### Options ``` diff --git a/doc/chantools_sweeptimelockmanual.md b/doc/chantools_sweeptimelockmanual.md index e44660d..b28a6b4 100644 --- a/doc/chantools_sweeptimelockmanual.md +++ b/doc/chantools_sweeptimelockmanual.md @@ -2,10 +2,35 @@ Sweep the force-closed state of a single channel manually if only a channel backup file is available +### Synopsis + +Sweep the locally force closed state of a single channel +manually if only a channel backup file is available. This can only be used if a +channel is force closed from the local node but then that node's state is lost +and only the channel.backup file is available. + +To get the value for --remoterevbasepoint you must use the dumpbackup command, +then look up the value for RemoteChanCfg -> RevocationBasePoint -> PubKey. + +To get the value for --timelockaddr you must look up the channel's funding +output on chain, then follow it to the force close output. The time locked +address is always the one that's longer (because it's P2WSH and not P2PKH). + ``` chantools sweeptimelockmanual [flags] ``` +### Examples + +``` +chantools sweeptimelockmanual --rootkey xprvxxxxxxxx \ + --sweepaddr bc1q..... \ + --timelockaddr bc1q............ \ + --remoterevbasepoint 03xxxxxxx \ + --feerate 10 \ + --publish +``` + ### Options ``` diff --git a/doc/chantools_vanitygen.md b/doc/chantools_vanitygen.md index 6badbd1..41b7441 100644 --- a/doc/chantools_vanitygen.md +++ b/doc/chantools_vanitygen.md @@ -2,10 +2,34 @@ Generate a seed with a custom lnd node identity public key that starts with the given prefix +### Synopsis + +Try random lnd compatible seeds until one is found that +produces a node identity public key that starts with the given prefix. + +Example output: + +
+Running vanitygen on 8 threads. Prefix bit length is 17, expecting to approach
+probability p=1.0 after 131,072 seeds.
+Tested 185k seeds, p=1.41296, speed=14k/s, elapsed=13s                          
+Looking for 022222, found pubkey: 022222f015540ddde9bdf7c95b24f1d44f7ea6ab69bec83d6fbe622296d64b51d6
+with seed: [ability roast pear stomach wink cable tube trumpet shy caught hunt
+someone border organ spoon only prepare calm silent million tobacco chaos normal
+phone]
+
+ + ``` chantools vanitygen [flags] ``` +### Examples + +``` +chantools vanitygen --prefix 022222 --threads 8 +``` + ### Options ``` diff --git a/doc/chantools_walletinfo.md b/doc/chantools_walletinfo.md index b3bd155..31e9203 100644 --- a/doc/chantools_walletinfo.md +++ b/doc/chantools_walletinfo.md @@ -2,10 +2,27 @@ Shows info about an lnd wallet.db file and optionally extracts the BIP32 HD root key +### Synopsis + +Shows some basic information about an lnd wallet.db file, +like the node identity the wallet belongs to, how many on-chain addresses are +used and, if enabled with --withrootkey the BIP32 HD root key of the wallet. The +latter can be useful to recover funds from a wallet if the wallet password is +still known but the seed was lost. **The 24 word seed phrase itself cannot be +extracted** because it is hashed into the extended HD root key before storing it +in the wallet.db. + ``` chantools walletinfo [flags] ``` +### Examples + +``` +chantools walletinfo --withrootkey \ + --walletdb ~/.lnd/data/chain/bitcoin/mainnet/wallet.db +``` + ### Options ```