diff --git a/electrum/gui/kivy/main_window.py b/electrum/gui/kivy/main_window.py index 57c824361..ba5d668ec 100644 --- a/electrum/gui/kivy/main_window.py +++ b/electrum/gui/kivy/main_window.py @@ -1421,23 +1421,26 @@ class ElectrumWindow(App, Logger): "This means that you must save a backup of your wallet everytime you create a new channel.\n\n" "If you want to have recoverable channels, you must create a new wallet with an Electrum seed") self.show_info(msg) - else: - if self.wallet.can_have_lightning(): - root.dismiss() + elif self.wallet.can_have_lightning(): + root.dismiss() + if self.wallet.can_have_deterministic_lightning(): + msg = messages.MSG_LIGHTNING_SCB_WARNING + "\n" + _("Create lightning keys?") + else: msg = _( "Warning: this wallet type does not support channel recovery from seed. " "You will need to backup your wallet everytime you create a new wallet. " "Create lightning keys?") - d = Question(msg, self._enable_lightning, title=_('Enable Lightning?')) - d.open() - else: - pass + d = Question(msg, self._enable_lightning, title=_('Enable Lightning?')) + d.open() def _enable_lightning(self, b): if not b: return + self.protected(_("Create lightning keys?"), self.__enable_lightning, ()) + + def __enable_lightning(self, password): wallet_path = self.get_wallet_path() - self.wallet.init_lightning() + self.wallet.init_lightning(password=password) self.show_info(_('Lightning keys have been initialized.')) self.stop_wallet() self.load_wallet_by_name(wallet_path) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index 5f5debc98..481cd5adf 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -2386,12 +2386,21 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): self.set_contact(line2.text(), line1.text()) def init_lightning_dialog(self): - if self.question(_( + assert not self.wallet.has_lightning() + if self.wallet.can_have_deterministic_lightning(): + msg = messages.MSG_LIGHTNING_SCB_WARNING + "\n" + _("Create lightning keys?") + else: + msg = _( "Warning: this wallet type does not support channel recovery from seed. " "You will need to backup your wallet everytime you create a new wallet. " - "Create lightning keys?")): - self.wallet.init_lightning() - self.show_message("Lightning keys created. Please restart Electrum") + "Create lightning keys?") + if self.question(msg): + self._init_lightning_dialog() + + @protected + def _init_lightning_dialog(self, *, password): + self.wallet.init_lightning(password=password) + self.show_message("Lightning keys created. Please restart Electrum") def show_wallet_info(self): dialog = WindowModalDialog(self, _("Wallet Information")) diff --git a/electrum/wallet.py b/electrum/wallet.py index 5cce149a6..3175601ed 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -333,24 +333,34 @@ class Abstract_Wallet(AddressSynchronizer, ABC): new_db.write(new_storage) return new_path - def has_lightning(self): + def has_lightning(self) -> bool: return bool(self.lnworker) - def can_have_lightning(self): + def can_have_lightning(self) -> bool: # we want static_remotekey to be a wallet address return self.txin_type == 'p2wpkh' - def init_lightning(self): + def can_have_deterministic_lightning(self) -> bool: + if not self.can_have_lightning(): + return False + if not self.keystore: + return False + return self.keystore.can_have_deterministic_lightning_xprv() + + def init_lightning(self, *, password) -> None: assert self.can_have_lightning() assert self.db.get('lightning_xprv') is None - if self.db.get('lightning_privkey2'): - return - # TODO derive this deterministically from wallet.keystore at keystore generation time - # probably along a hardened path ( lnd-equivalent would be m/1017'/coinType'/ ) - seed = os.urandom(32) - node = BIP32Node.from_rootseed(seed, xtype='standard') - ln_xprv = node.to_xprv() - self.db.put('lightning_privkey2', ln_xprv) + assert self.db.get('lightning_privkey2') is None + + if self.can_have_deterministic_lightning(): + ks = self.keystore + assert isinstance(ks, keystore.BIP32_KeyStore) + self.db.put('lightning_xprv', ks.get_lightning_xprv(password)) + else: + seed = os.urandom(32) + node = BIP32Node.from_rootseed(seed, xtype='standard') + ln_xprv = node.to_xprv() + self.db.put('lightning_privkey2', ln_xprv) async def stop(self): """Stop all networking and save DB to disk."""