genimportscript: add Electrum format, write result to file

pull/32/head v0.9.3
Oliver Gugger 3 years ago
parent 0821c35442
commit ce3cc2ceef
No known key found for this signature in database
GPG Key ID: 8E4256593F177720

@ -3,6 +3,7 @@ package btc
import ( import (
"fmt" "fmt"
"io" "io"
"strings"
"time" "time"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
@ -16,6 +17,7 @@ const (
FormatCli = "bitcoin-cli" FormatCli = "bitcoin-cli"
FormatCliWatchOnly = "bitcoin-cli-watchonly" FormatCliWatchOnly = "bitcoin-cli-watchonly"
FormatImportwallet = "bitcoin-importwallet" FormatImportwallet = "bitcoin-importwallet"
FormatElectrum = "electrum"
) )
type KeyExporter interface { type KeyExporter interface {
@ -40,6 +42,9 @@ func ParseFormat(format string) KeyExporter {
case FormatImportwallet: case FormatImportwallet:
return &ImportWallet{} return &ImportWallet{}
case FormatElectrum:
return &Electrum{}
} }
} }
@ -215,3 +220,35 @@ func (i *ImportWallet) Format(hdKey *hdkeychain.ExtendedKey,
func (i *ImportWallet) Trailer(_ uint32) string { func (i *ImportWallet) Trailer(_ uint32) string {
return "" return ""
} }
type Electrum struct{}
func (p *Electrum) Header() string {
return "# Copy the content of this file (without this line) into " +
"Electrum."
}
func (p *Electrum) Format(hdKey *hdkeychain.ExtendedKey,
params *chaincfg.Params, path string, branch, index uint32) (string,
error) {
privKey, err := hdKey.ECPrivKey()
if err != nil {
return "", fmt.Errorf("could not derive private key: %v", err)
}
wif, err := btcutil.NewWIF(privKey, params, true)
if err != nil {
return "", fmt.Errorf("could not encode WIF: %v", err)
}
prefix := "p2wpkh"
if strings.HasPrefix(path, lnd.WalletBIP49DerivationPath) {
prefix = "p2wpkh-p2sh"
}
return fmt.Sprintf("%s:%s", prefix, wif.String()), nil
}
func (p *Electrum) Trailer(_ uint32) string {
return ""
}

@ -21,6 +21,7 @@ type genImportScriptCommand struct {
DerivationPath string DerivationPath string
RecoveryWindow uint32 RecoveryWindow uint32
RescanFrom uint32 RescanFrom uint32
Stdout bool
rootKey *rootKey rootKey *rootKey
cmd *cobra.Command cmd *cobra.Command
@ -46,7 +47,9 @@ The following script formats are currently supported:
imported into bitcoind to watch the UTXOs of those keys. The funds cannot be imported into bitcoind to watch the UTXOs of those keys. The funds cannot be
spent that way as they are watch-only. spent that way as they are watch-only.
* bitcoin-importwallet: Creates a text output that is compatible with * bitcoin-importwallet: Creates a text output that is compatible with
bitcoind's importwallet command.`, bitcoind's importwallet command.
* electrum: Creates a text output that contains one private key per line with
the address type as the prefix, the way Electrum expects them.`,
Example: `chantools genimportscript --format bitcoin-cli \ Example: `chantools genimportscript --format bitcoin-cli \
--recoverywindow 5000`, --recoverywindow 5000`,
RunE: cc.Execute, RunE: cc.Execute,
@ -54,8 +57,8 @@ The following script formats are currently supported:
cc.cmd.Flags().StringVar( cc.cmd.Flags().StringVar(
&cc.Format, "format", "bitcoin-importwallet", "format of the "+ &cc.Format, "format", "bitcoin-importwallet", "format of the "+
"generated import script; currently supported are: "+ "generated import script; currently supported are: "+
"bitcoin-importwallet, bitcoin-cli and "+ "bitcoin-importwallet, bitcoin-cli, "+
"bitcoin-cli-watchonly", "bitcoin-cli-watchonly and electrum",
) )
cc.cmd.Flags().BoolVar( cc.cmd.Flags().BoolVar(
&cc.LndPaths, "lndpaths", false, "use all derivation paths "+ &cc.LndPaths, "lndpaths", false, "use all derivation paths "+
@ -79,6 +82,9 @@ The following script formats are currently supported:
"from the wallet birthday if the lnd 24 word aezeed "+ "from the wallet birthday if the lnd 24 word aezeed "+
"is entered", "is entered",
) )
cc.cmd.Flags().BoolVar(
&cc.Stdout, "stdout", false, "write generated import script "+
"to standard out instead of writing it to a file")
cc.rootKey = newRootKey(cc.cmd, "decrypting the backup") cc.rootKey = newRootKey(cc.cmd, "decrypting the backup")
@ -137,10 +143,25 @@ func (c *genImportScriptCommand) Execute(_ *cobra.Command, _ []string) error {
} }
} }
writer := os.Stdout
if !c.Stdout {
fileName := fmt.Sprintf("results/genimportscript-%s.txt",
time.Now().Format("2006-01-02-15-04-05"))
log.Infof("Writing import script with format '%s' to %s",
c.Format, fileName)
var err error
writer, err = os.Create(fileName)
if err != nil {
return fmt.Errorf("error creating result file %s: %v",
fileName, err)
}
}
exporter := btc.ParseFormat(c.Format) exporter := btc.ParseFormat(c.Format)
err = btc.ExportKeys( err = btc.ExportKeys(
extendedKey, strPaths, paths, chainParams, c.RecoveryWindow, extendedKey, strPaths, paths, chainParams, c.RecoveryWindow,
c.RescanFrom, exporter, os.Stdout, c.RescanFrom, exporter, writer,
) )
if err != nil { if err != nil {
return fmt.Errorf("error exporting keys: %v", err) return fmt.Errorf("error exporting keys: %v", err)

@ -26,7 +26,7 @@ import (
const ( const (
defaultAPIURL = "https://blockstream.info/api" defaultAPIURL = "https://blockstream.info/api"
version = "0.9.2" version = "0.9.3"
na = "n/a" na = "n/a"
Commit = "" Commit = ""

@ -61,7 +61,7 @@ chantools fakechanbackup --from_channel_graph lncli_describegraph.json \
--channelpoint string funding transaction outpoint of the channel to rescue (<txid>:<txindex>) as it is displayed on 1ml.com --channelpoint string funding transaction outpoint of the channel to rescue (<txid>:<txindex>) as it is displayed on 1ml.com
--from_channel_graph string the full LN channel graph in the JSON format that the 'lncli describegraph' returns --from_channel_graph string the full LN channel graph in the JSON format that the 'lncli describegraph' returns
-h, --help help for fakechanbackup -h, --help help for fakechanbackup
--multi_file string the fake channel backup file to create (default "results/fake-2021-08-29-18-21-11.backup") --multi_file string the fake channel backup file to create (default "results/fake-2021-08-29-22-04-34.backup")
--remote_node_addr string the remote node connection information in the format pubkey@host:port --remote_node_addr string the remote node connection information in the format pubkey@host:port
--rootkey string BIP32 HD root key of the wallet to use for encrypting the backup; leave empty to prompt for lnd 24 word aezeed --rootkey string BIP32 HD root key of the wallet to use for encrypting the backup; leave empty to prompt for lnd 24 word aezeed
--short_channel_id string the short channel ID in the format <blockheight>x<transactionindex>x<outputindex> --short_channel_id string the short channel ID in the format <blockheight>x<transactionindex>x<outputindex>

@ -18,6 +18,8 @@ The following script formats are currently supported:
spent that way as they are watch-only. spent that way as they are watch-only.
* bitcoin-importwallet: Creates a text output that is compatible with * bitcoin-importwallet: Creates a text output that is compatible with
bitcoind's importwallet command. bitcoind's importwallet command.
* electrum: Creates a text output that contains one private key per line with
the address type as the prefix, the way Electrum expects them.
``` ```
chantools genimportscript [flags] chantools genimportscript [flags]
@ -35,12 +37,13 @@ chantools genimportscript --format bitcoin-cli \
``` ```
--bip39 read a classic BIP39 seed and passphrase from the terminal instead of asking for lnd seed format or providing the --rootkey flag --bip39 read a classic BIP39 seed and passphrase from the terminal instead of asking for lnd seed format or providing the --rootkey flag
--derivationpath string use one specific derivation path; specify the first levels of the derivation path before any internal/external branch; Cannot be used in conjunction with --lndpaths --derivationpath string use one specific derivation path; specify the first levels of the derivation path before any internal/external branch; Cannot be used in conjunction with --lndpaths
--format string format of the generated import script; currently supported are: bitcoin-importwallet, bitcoin-cli and bitcoin-cli-watchonly (default "bitcoin-importwallet") --format string format of the generated import script; currently supported are: bitcoin-importwallet, bitcoin-cli, bitcoin-cli-watchonly and electrum (default "bitcoin-importwallet")
-h, --help help for genimportscript -h, --help help for genimportscript
--lndpaths use all derivation paths that lnd used; results in a large number of results; cannot be used in conjunction with --derivationpath --lndpaths use all derivation paths that lnd used; results in a large number of results; cannot be used in conjunction with --derivationpath
--recoverywindow uint32 number of keys to scan per internal/external branch; output will consist of double this amount of keys (default 2500) --recoverywindow uint32 number of keys to scan per internal/external branch; output will consist of double this amount of keys (default 2500)
--rescanfrom uint32 block number to rescan from; will be set automatically from the wallet birthday if the lnd 24 word aezeed is entered (default 500000) --rescanfrom uint32 block number to rescan from; will be set automatically from the wallet birthday if the lnd 24 word aezeed is entered (default 500000)
--rootkey string BIP32 HD root key of the wallet to use for decrypting the backup; leave empty to prompt for lnd 24 word aezeed --rootkey string BIP32 HD root key of the wallet to use for decrypting the backup; leave empty to prompt for lnd 24 word aezeed
--stdout write generated import script to standard out instead of writing it to a file
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

@ -157,19 +157,9 @@ func AllDerivationPaths(params *chaincfg.Params) ([]string, [][]uint32, error) {
) )
} }
pathStrings := []string{ pathStrings := []string{
"m/44'/0'/0'", WalletBIP49DerivationPath,
"m/49'/0'/0'",
WalletDefaultDerivationPath, WalletDefaultDerivationPath,
mkPath(keychain.KeyFamilyMultiSig),
mkPath(keychain.KeyFamilyRevocationBase),
mkPath(keychain.KeyFamilyHtlcBase),
mkPath(keychain.KeyFamilyPaymentBase), mkPath(keychain.KeyFamilyPaymentBase),
mkPath(keychain.KeyFamilyDelayBase),
mkPath(keychain.KeyFamilyRevocationRoot),
mkPath(keychain.KeyFamilyNodeKey),
mkPath(keychain.KeyFamilyStaticBackup),
mkPath(keychain.KeyFamilyTowerSession),
mkPath(keychain.KeyFamilyTowerID),
} }
paths := make([][]uint32, len(pathStrings)) paths := make([][]uint32, len(pathStrings))
for idx, path := range pathStrings { for idx, path := range pathStrings {

Loading…
Cancel
Save