@@ -391,7 +391,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
391391 """
392392
393393 max_change_outputs = 3
394- gap_limit_for_change = 10
394+ gap_limit_for_change = None # type: int | None
395395
396396 txin_type : str
397397 wallet_type : str
@@ -1840,19 +1840,7 @@ def get_change_addresses_for_new_transaction(
18401840 else :
18411841 change_addrs = [preferred_change_addr ]
18421842 elif self .use_change :
1843- # Recalc and get unused change addresses
1844- addrs = self .calc_unused_change_addresses ()
1845- # New change addresses are created only after a few
1846- # confirmations.
1847- if addrs :
1848- # if there are any unused, select all
1849- change_addrs = addrs
1850- else :
1851- # if there are none, take one randomly from the last few
1852- if not allow_reusing_used_change_addrs :
1853- return []
1854- addrs = self .get_change_addresses (slice_start = - self .gap_limit_for_change )
1855- change_addrs = [random .choice (addrs )] if addrs else []
1843+ change_addrs = self ._get_change_addresses_we_can_use_now (allow_reuse = allow_reusing_used_change_addrs )
18561844 for addr in change_addrs :
18571845 assert is_address (addr ), f"not valid bitcoin address: { addr } "
18581846 # note that change addresses are not necessarily ismine
@@ -1872,21 +1860,38 @@ def get_single_change_address_for_new_transaction(
18721860 return addrs [0 ]
18731861 return None
18741862
1875- @check_returned_address_for_corruption
18761863 def get_new_sweep_address_for_channel (self ) -> str :
1864+ addrs = self ._get_change_addresses_we_can_use_now (allow_reuse = True )
1865+ if addrs :
1866+ return addrs [0 ]
1867+ # fallback for e.g. imported wallets
1868+ return self .get_receiving_address ()
1869+
1870+ def _get_change_addresses_we_can_use_now (
1871+ self ,
1872+ * ,
1873+ allow_reuse : bool = True ,
1874+ ) -> Sequence [str ]:
18771875 # Recalc and get unused change addresses
18781876 addrs = self .calc_unused_change_addresses ()
1877+ # New change addresses are created only after a few
1878+ # confirmations.
18791879 if addrs :
1880- selected_addr = addrs [0 ]
1880+ # if there are any unused, select all
1881+ change_addrs = addrs
18811882 else :
18821883 # if there are none, take one randomly from the last few
1883- addrs = self .get_change_addresses (slice_start = - self .gap_limit_for_change )
1884- if addrs :
1885- selected_addr = random .choice (addrs )
1886- else : # fallback for e.g. imported wallets
1887- selected_addr = self .get_receiving_address ()
1888- assert is_address (selected_addr ), f"not valid bitcoin address: { selected_addr } "
1889- return selected_addr
1884+ if not allow_reuse :
1885+ return []
1886+ gap_limit = self .gap_limit_for_change or 0
1887+ addrs = self .get_change_addresses (slice_start = - gap_limit )
1888+ change_addrs = [random .choice (addrs )] if addrs else []
1889+ for addr in change_addrs :
1890+ assert is_address (addr ), f"not valid bitcoin address: { addr } "
1891+ # note that change addresses are not necessarily ismine
1892+ # in which case this is a no-op
1893+ self .check_address_for_corruption (addr )
1894+ return change_addrs
18901895
18911896 def should_keep_reserve_utxo (
18921897 self ,
@@ -3805,11 +3810,13 @@ def decrypt_message(self, pubkey: str, message, password) -> bytes:
38053810
38063811
38073812class Deterministic_Wallet (Abstract_Wallet ):
3813+ gap_limit_for_change : int
38083814
38093815 def __init__ (self , db , * , config ):
38103816 self ._ephemeral_addr_to_addr_index = {} # type: Dict[str, Sequence[int]]
38113817 Abstract_Wallet .__init__ (self , db , config = config )
38123818 self .gap_limit = db .get ('gap_limit' , 20 )
3819+ self .gap_limit_for_change = db .get ('gap_limit_for_change' , 10 )
38133820 # generate addresses now. note that without libsecp this might block
38143821 # for a few seconds!
38153822 self .synchronize ()
@@ -4228,7 +4235,8 @@ def create_new_wallet(
42284235 password : Optional [str ] = None ,
42294236 encrypt_file : bool = True ,
42304237 seed_type : Optional [str ] = None ,
4231- gap_limit : Optional [int ] = None
4238+ gap_limit : Optional [int ] = None ,
4239+ gap_limit_for_change : Optional [int ] = None ,
42324240) -> dict :
42334241 """Create a new wallet"""
42344242 storage = WalletStorage (path , allow_partial_writes = config .WALLET_PARTIAL_WRITES )
@@ -4244,6 +4252,8 @@ def create_new_wallet(
42444252 db .put ('lightning_xprv' , k .get_lightning_xprv (None ))
42454253 if gap_limit is not None :
42464254 db .put ('gap_limit' , gap_limit )
4255+ if gap_limit_for_change is not None :
4256+ db .put ('gap_limit_for_change' , gap_limit_for_change )
42474257 wallet = Wallet (db , config = config )
42484258 wallet .update_password (old_pw = None , new_pw = password , encrypt_storage = encrypt_file )
42494259 wallet .synchronize ()
@@ -4261,6 +4271,7 @@ def restore_wallet_from_text(
42614271 password : Optional [str ] = None ,
42624272 encrypt_file : Optional [bool ] = None ,
42634273 gap_limit : Optional [int ] = None ,
4274+ gap_limit_for_change : Optional [int ] = None ,
42644275) -> dict :
42654276 """Restore a wallet from text. Text can be a seed phrase, a master
42664277 public key, a master private key, a list of bitcoin addresses
@@ -4304,6 +4315,8 @@ def restore_wallet_from_text(
43044315 db .put ('wallet_type' , 'standard' )
43054316 if gap_limit is not None :
43064317 db .put ('gap_limit' , gap_limit )
4318+ if gap_limit_for_change is not None :
4319+ db .put ('gap_limit_for_change' , gap_limit_for_change )
43074320 wallet = Wallet (db , config = config )
43084321 if db .storage :
43094322 assert not db .storage .file_exists (), "file was created too soon! plaintext keys might have been written to disk"
0 commit comments