multi: add migrate-wallet-to-watch-only flag

To enable converting an existing wallet with private key material into a
watch-only wallet on first startup with remote signing enabled, we add a
new flag. Since the conversion is a destructive process, this shouldn't
happen automatically just because remote signing is enabled.
This commit is contained in:
Oliver Gugger committed 2022-01-06 14:35:26 +01:00
1 parent afc53d1c52
commit bab807a57d
6 files changed
+93 -25

No files matched your search

+41 -1
View File
@@ -287,15 +287,38 @@ func (b *BtcWallet) InternalWallet() *base.Wallet {
//
// This is a part of the WalletController interface.
func (b *BtcWallet) Start() error {
// Is the wallet (according to its database) currently watch-only
// already? If it is, we won't need to convert it later.
walletIsWatchOnly := b.wallet.Manager.WatchOnly()
// If the wallet is watch-only, but we don't expect it to be, then we
// are in an unexpected state and cannot continue.
if walletIsWatchOnly && !b.cfg.WatchOnly {
return fmt.Errorf("wallet is watch-only but we expect it " +
"not to be; check if remote signing was disabled by " +
"accident")
}
// We'll start by unlocking the wallet and ensuring that the KeyScope:
// (1017, 1) exists within the internal waddrmgr. We'll need this in
// order to properly generate the keys required for signing various
// contracts. If this is a watch-only wallet, we don't have any private
// keys and therefore unlocking is not necessary.
if !b.cfg.WatchOnly {
if !walletIsWatchOnly {
if err := b.wallet.Unlock(b.cfg.PrivatePass, nil); err != nil {
return err
}
// If the wallet isn't about to be converted, we need to inform
// the user that this wallet still contains all private key
// material and that they need to migrate the existing wallet.
if b.cfg.WatchOnly && !b.cfg.MigrateWatchOnly {
log.Warnf("Wallet is expected to be in watch-only " +
"mode but hasn't been migrated to watch-only " +
"yet, it still contains private keys; " +
"consider turning on the watch-only wallet " +
"migration in remote signing mode")
}
}
scope, err := b.wallet.Manager.FetchScopedKeyManager(b.chainKeyScope)
@@ -343,6 +366,23 @@ func (b *BtcWallet) Start() error {
}
}
// If this is the first startup with remote signing and wallet
// migration turned on and the wallet wasn't previously
// migrated, we can do that now that we made sure all accounts
// that we need were derived correctly.
if !walletIsWatchOnly && b.cfg.WatchOnly &&
b.cfg.MigrateWatchOnly {
log.Infof("Migrating wallet to watch-only mode, " +
"purging all private key material")
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
err = b.wallet.Manager.ConvertToWatchingOnly(ns)
if err != nil {
return err
}
}
return nil
})
if err != nil {
+7
View File
@@ -76,6 +76,13 @@ type Config struct {
// WatchOnly indicates that the wallet was initialized with public key
// material only and does not contain any private keys.
WatchOnly bool
// MigrateWatchOnly indicates that if a wallet with private key material
// already exists, it should be attempted to be converted into a
// watch-only wallet on first startup. This flag has no effect if no
// wallet exists and a watch-only one is created directly, or, if the
// wallet was previously converted to a watch-only already.
MigrateWatchOnly bool
}
// NetworkDir returns the directory name of a network directory to hold wallet