From 6289a2fb844dece81ae953d5f85ba5195af18d95 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 1 Feb 2018 20:49:34 -0800 Subject: [PATCH] lnd: move seed generation outside wallet to allow for user supplied entropy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this commit, we extend the initial wallet creation set up case with the goal of giving the user the ability to restore a prior wallet from seed, or obtain the mnemonic for a newly generated wallet. As the WalletUnlocker has been extended to allow passing a user source of entropy, if this is detected, then we’ll use BIP39 to covert it into an HD wallet seed. Otherwise, we’ll generate our own entropy, then convert that into the wallet seed. In order to make this change, we’ll now manually create the default wallet ourselves. In the case that the user didn’t provide their own seed, we’ll send the seed we generated back to the user. This will allow frontends to display the newly generated seed to the end user. --- lnd.go | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/lnd.go b/lnd.go index 295a277d..d88affda 100644 --- a/lnd.go +++ b/lnd.go @@ -39,12 +39,14 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/lnwallet/btcwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/macaroons" "github.com/lightningnetwork/lnd/walletunlocker" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" + "github.com/roasbeef/btcwallet/wallet" ) const ( @@ -820,14 +822,47 @@ func waitForWalletPassword(grpcEndpoints, restEndpoints []string, "Use `lncli create` to create wallet, or " + "`lncli unlock` to unlock already created wallet.") - // We currently don't distinguish between getting a password to - // be used for creation or unlocking, as a new wallet db will be - // created if none exists when creating the chain control. + // We currently don't distinguish between getting a password to be used + // for creation or unlocking, as a new wallet db will be created if + // none exists when creating the chain control. select { - case walletPw := <-pwService.CreatePasswords: - return walletPw, walletPw, nil + + // The wallet is being created for the first time, we'll check to see + // if the user provided any entropy for seed creation. If so, then + // we'll create the wallet early to load the seed. + case initMsg := <-pwService.InitMsgs: + password := initMsg.Passphrase + cipherSeed := initMsg.WalletSeed + + netDir := btcwallet.NetworkDir( + chainConfig.ChainDir, activeNetParams.Params, + ) + loader := wallet.NewLoader(activeNetParams.Params, netDir) + + // With the seed, we can now use the wallet loader to create + // the wallet, then unload it so it can be opened shortly + // after. + // + // TODO(roasbeef): extend loader to also accept birthday + // * also check with keychain version + _, err = loader.CreateNewWallet( + password, password, cipherSeed.Entropy[:], + ) + if err != nil { + return nil, nil, err + } + + if err := loader.UnloadWallet(); err != nil { + return nil, nil, err + } + + return password, password, nil + + // The wallet has already been created in the past, and is simply being + // unlocked. So we'll just return these passphrases. case walletPw := <-pwService.UnlockPasswords: return walletPw, walletPw, nil + case <-shutdownChannel: return nil, nil, fmt.Errorf("shutting down") }