From ac8b1735087bde95d239a386fcf2c93c16813cd8 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Thu, 13 Jan 2022 15:39:10 +0000 Subject: [PATCH] Ensure all displayed addresses are imported Fixes #1143 (and possibly others). Before this commit, (index plus gap limit) addresses are imported on sync, and addresses used by maker/taker in coinjoin are imported, but when a deposit occurred, bumping the index, further addresses were not imported. The effect was that it was possible, if doing a series of deposits to multiple external addresses in a Qt session, to end up depositing to an address that was not yet imported. And this results in the user needing to rescan for Core+JM to recognize the coins. After this commit, we ensure all 'gap limit forwards' addresses, which are displayed as potential deposit addresses in Joinmarket-Qt, are imported before the display. --- jmclient/jmclient/wallet_service.py | 16 ++++++++-------- jmclient/jmclient/wallet_utils.py | 12 ++++++++++++ test/ygrunner.py | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/jmclient/jmclient/wallet_service.py b/jmclient/jmclient/wallet_service.py index 22046b159..47c9abdae 100644 --- a/jmclient/jmclient/wallet_service.py +++ b/jmclient/jmclient/wallet_service.py @@ -887,11 +887,13 @@ def get_balance_by_mixdepth(self, verbose=True, include_disabled=include_disabled, maxheight=maxheight) - def get_internal_addr(self, mixdepth): + def import_addr(self, addr): if self.bci is not None and hasattr(self.bci, 'import_addresses'): - addr = self.wallet.get_internal_addr(mixdepth) - self.bci.import_addresses([addr], - self.wallet.get_wallet_name()) + self.bci.import_addresses([addr], self.wallet.get_wallet_name()) + + def get_internal_addr(self, mixdepth): + addr = self.wallet.get_internal_addr(mixdepth) + self.import_addr(addr) return addr def collect_addresses_init(self): @@ -944,10 +946,8 @@ def collect_addresses_gap(self, gap_limit=None): return addresses def get_external_addr(self, mixdepth): - if self.bci is not None and hasattr(self.bci, 'import_addresses'): - addr = self.wallet.get_external_addr(mixdepth) - self.bci.import_addresses([addr], - self.wallet.get_wallet_name()) + addr = self.wallet.get_external_addr(mixdepth) + self.import_addr(addr) return addr def __getattr__(self, attr): diff --git a/jmclient/jmclient/wallet_utils.py b/jmclient/jmclient/wallet_utils.py index c70109785..ff4356fe1 100644 --- a/jmclient/jmclient/wallet_utils.py +++ b/jmclient/jmclient/wallet_utils.py @@ -494,9 +494,12 @@ def get_addr_status(addr_path, utxos, is_new, is_internal): xpub_key = "" unused_index = wallet_service.get_next_unused_index(m, address_type) + gap_addrs = [] for k in range(unused_index + wallet_service.gap_limit): path = wallet_service.get_path(m, address_type, k) addr = wallet_service.get_address_from_path(path) + if k >= unused_index: + gap_addrs.append(addr) label = wallet_service.get_address_label(addr) balance, status = get_addr_status( path, utxos[m], k >= unused_index, address_type) @@ -509,6 +512,15 @@ def get_addr_status(addr_path, utxos, is_new, is_internal): entrylist.append(WalletViewEntry( wallet_service.get_path_repr(path), m, address_type, k, addr, [balance, balance], priv=privkey, status=status, label=label)) + # ensure that we never display un-imported addresses (this will generally duplicate + # the import of each new address gap limit times, but one importmulti call + # per mixdepth is cheap enough. + # This only applies to the external branch, because it only applies to addresses + # displayed for user deposit. + # It also does not apply to fidelity bond addresses which are created manually. + if address_type == BaseWallet.ADDRESS_TYPE_EXTERNAL: + wallet_service.bci.import_addresses(gap_addrs, + wallet_service.get_wallet_name()) wallet_service.set_next_index(m, address_type, unused_index) path = wallet_service.get_path_repr(wallet_service.get_path(m, address_type)) branchlist.append(WalletViewBranch(path, m, address_type, entrylist, diff --git a/test/ygrunner.py b/test/ygrunner.py index 861ac1577..88ef65b97 100644 --- a/test/ygrunner.py +++ b/test/ygrunner.py @@ -217,7 +217,7 @@ def get_addr_and_fund(yg): return if yg.wallet_service.timelock_funded: return - addr = wallet_gettimelockaddress(yg.wallet_service.wallet, "2021-11") + addr = wallet_gettimelockaddress(yg.wallet_service.wallet, "2023-11") print("Got timelockaddress: {}".format(addr)) # pay into it; amount is randomized for now.