wallet: (fix) get_receiving_address must always return an addr

- also, disallow deleting last address from an imported wallet (fixes #3254, fixes #4833)
- also, set LNBackups.sweep_address lazily, as during fresh wallet creation
  there are no addresses in the wallet at that point yet! see trace below.

Traceback (most recent call last):
  [...]
  File "...\electrum\electrum\tests\test_commands.py", line 112, in test_export_private_key_deterministic
    wallet = restore_wallet_from_text('bitter grass shiver impose acquire brush forget axis eager alone wine silver',
  File "...\electrum\electrum\wallet.py", line 2575, in restore_wallet_from_text
    wallet = Wallet(db, storage, config=config)
  File "...\electrum\electrum\wallet.py", line 2502, in __new__
    wallet = WalletClass(db, storage, config=config)
  File "...\electrum\electrum\wallet.py", line 2346, in __init__
    Deterministic_Wallet.__init__(self, db, storage, config=config)
  File "...\electrum\electrum\wallet.py", line 2147, in __init__
    Abstract_Wallet.__init__(self, db, storage, config=config)
  File "...\electrum\electrum\wallet.py", line 261, in __init__
    self.lnbackups = LNBackups(self)
  File "...\electrum\electrum\lnworker.py", line 1401, in __init__
    self.sweep_address = wallet.get_receiving_address()
  File "...\electrum\electrum\wallet.py", line 1498, in wrapper
    addr = func(self, *args, **kwargs)
  File "...\electrum\electrum\wallet.py", line 1520, in get_receiving_address
    raise Exception("no receiving addresses in wallet?!")
Exception: no receiving addresses in wallet?!
This commit is contained in:
SomberNight 2020-05-22 16:25:33 +02:00
parent 9657e927a7
commit f8c574b699
No known key found for this signature in database
GPG key ID: B33B5F232C6271E9
2 changed files with 8 additions and 3 deletions

View file

@ -1398,11 +1398,14 @@ class LNBackups(Logger):
self.lock = threading.RLock() self.lock = threading.RLock()
self.wallet = wallet self.wallet = wallet
self.db = wallet.db self.db = wallet.db
self.sweep_address = wallet.get_receiving_address()
self.channel_backups = {} self.channel_backups = {}
for channel_id, cb in self.db.get_dict("channel_backups").items(): for channel_id, cb in self.db.get_dict("channel_backups").items():
self.channel_backups[bfh(channel_id)] = ChannelBackup(cb, sweep_address=self.sweep_address, lnworker=self) self.channel_backups[bfh(channel_id)] = ChannelBackup(cb, sweep_address=self.sweep_address, lnworker=self)
@property
def sweep_address(self) -> str:
return self.wallet.get_receiving_address()
def channel_state_changed(self, chan): def channel_state_changed(self, chan):
util.trigger_callback('channel', chan) util.trigger_callback('channel', chan)

View file

@ -1513,11 +1513,11 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
return addrs[0] return addrs[0]
@check_returned_address @check_returned_address
def get_receiving_address(self): def get_receiving_address(self) -> str:
# always return an address # always return an address
domain = self.get_receiving_addresses() domain = self.get_receiving_addresses()
if not domain: if not domain:
return raise Exception("no receiving addresses in wallet?!")
choice = domain[0] choice = domain[0]
for addr in domain: for addr in domain:
if not self.is_used(addr): if not self.is_used(addr):
@ -2030,6 +2030,8 @@ class Imported_Wallet(Simple_Wallet):
def delete_address(self, address: str) -> None: def delete_address(self, address: str) -> None:
if not self.db.has_imported_address(address): if not self.db.has_imported_address(address):
return return
if len(self.get_addresses()) <= 1:
raise Exception("cannot delete last remaining address from wallet")
transactions_to_remove = set() # only referred to by this address transactions_to_remove = set() # only referred to by this address
transactions_new = set() # txs that are not only referred to by address transactions_new = set() # txs that are not only referred to by address
with self.lock: with self.lock: