You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chantools/cmd/chantools/genimportscript.go

135 lines
3.4 KiB
Go

package main
import (
"fmt"
"os"
"time"
"github.com/guggero/chantools/btc"
"github.com/guggero/chantools/lnd"
"github.com/spf13/cobra"
)
const (
defaultRecoveryWindow = 2500
defaultRescanFrom = 500000
)
type genImportScriptCommand struct {
Format string
LndPaths bool
DerivationPath string
RecoveryWindow uint32
RescanFrom uint32
rootKey *rootKey
cmd *cobra.Command
}
func newGenImportScriptCommand() *cobra.Command {
cc := &genImportScriptCommand{}
cc.cmd = &cobra.Command{
Use: "genimportscript",
Short: "Generate a script containing the on-chain " +
"keys of an lnd wallet that can be imported into " +
"other software like bitcoind",
RunE: cc.Execute,
}
cc.cmd.Flags().StringVar(
&cc.Format, "format", "bitcoin-importwallet", "format of the "+
"generated import script; currently supported are: "+
"bitcoin-importwallet, bitcoin-cli and "+
"bitcoin-cli-watchonly",
)
cc.cmd.Flags().BoolVar(
&cc.LndPaths, "lndpaths", false, "use all derivation paths "+
"that lnd used; results in a large number of results; "+
"cannot be used in conjunction with --derivationpath",
)
cc.cmd.Flags().StringVar(
&cc.DerivationPath, "derivationpath", "", "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",
)
cc.cmd.Flags().Uint32Var(
&cc.RecoveryWindow, "recoverywindow", defaultRecoveryWindow,
"number of keys to scan per internal/external branch; output "+
"will consist of double this amount of keys",
)
cc.cmd.Flags().Uint32Var(
&cc.RescanFrom, "rescanfrom", defaultRescanFrom, "block "+
"number to rescan from; will be set automatically "+
"from the wallet birthday if the lnd 24 word aezeed "+
"is entered",
)
cc.rootKey = newRootKey(cc.cmd, "decrypting the backup")
return cc.cmd
}
func (c *genImportScriptCommand) Execute(_ *cobra.Command, _ []string) error {
var (
strPaths []string
paths [][]uint32
)
extendedKey, birthday, err := c.rootKey.readWithBirthday()
if err != nil {
return fmt.Errorf("error reading root key: %v", err)
}
// The btcwallet gives the birthday a slack of 48 hours, let's do the
// same.
if !birthday.IsZero() {
c.RescanFrom = btc.SeedBirthdayToBlock(
chainParams, birthday.Add(-48*time.Hour),
)
}
// Set default values.
if c.RecoveryWindow == 0 {
c.RecoveryWindow = defaultRecoveryWindow
}
if c.RescanFrom == 0 {
c.RescanFrom = defaultRescanFrom
}
// Decide what derivation path(s) to use.
switch {
default:
c.DerivationPath = lnd.WalletDefaultDerivationPath
fallthrough
case c.DerivationPath != "":
derivationPath, err := lnd.ParsePath(c.DerivationPath)
if err != nil {
return fmt.Errorf("error parsing path: %v", err)
}
strPaths = []string{c.DerivationPath}
paths = [][]uint32{derivationPath}
case c.LndPaths && c.DerivationPath != "":
return fmt.Errorf("cannot use --lndpaths and --derivationpath " +
"at the same time")
case c.LndPaths:
strPaths, paths, err = lnd.AllDerivationPaths(chainParams)
if err != nil {
return fmt.Errorf("error getting lnd paths: %v", err)
}
}
exporter := btc.ParseFormat(c.Format)
err = btc.ExportKeys(
extendedKey, strPaths, paths, chainParams, c.RecoveryWindow,
c.RescanFrom, exporter, os.Stdout,
)
if err != nil {
return fmt.Errorf("error exporting keys: %v", err)
}
return nil
}