@ -402,7 +402,7 @@ class Daemon(Logger):
if not self . config . NETWORK_OFFLINE :
if not self . config . NETWORK_OFFLINE :
self . network = Network ( config , daemon = self )
self . network = Network ( config , daemon = self )
self . fx = FxThread ( config = config )
self . fx = FxThread ( config = config )
# path -> wallet; make sure path is standardized.
# wallet_key -> wallet
self . _wallets = { } # type: Dict[str, Abstract_Wallet]
self . _wallets = { } # type: Dict[str, Abstract_Wallet]
self . _wallet_lock = threading . RLock ( )
self . _wallet_lock = threading . RLock ( )
daemon_jobs = [ ]
daemon_jobs = [ ]
@ -452,6 +452,17 @@ class Daemon(Logger):
if self . config . LIGHTNING_USE_GOSSIP :
if self . config . LIGHTNING_USE_GOSSIP :
self . network . start_gossip ( )
self . network . start_gossip ( )
@staticmethod
def _wallet_key_from_path ( path ) - > str :
""" This does stricter path standardization than ' standardize_path ' .
It is used for keying the _wallets dict , but not for the actual filesystem operations . ( see #8495)
"""
path = standardize_path ( path )
# also resolve symlinks and windows network mounts/etc:
path = os . path . realpath ( path )
path = os . path . normcase ( path )
return str ( path )
def with_wallet_lock ( func ) :
def with_wallet_lock ( func ) :
def func_wrapper ( self : ' Daemon ' , * args , * * kwargs ) :
def func_wrapper ( self : ' Daemon ' , * args , * * kwargs ) :
with self . _wallet_lock :
with self . _wallet_lock :
@ -461,9 +472,9 @@ class Daemon(Logger):
@with_wallet_lock
@with_wallet_lock
def load_wallet ( self , path , password , * , manual_upgrades = True ) - > Optional [ Abstract_Wallet ] :
def load_wallet ( self , path , password , * , manual_upgrades = True ) - > Optional [ Abstract_Wallet ] :
path = standardize_path ( path )
path = standardize_path ( path )
wallet_key = self . _wallet_key_from_path ( path )
# wizard will be launched if we return
# wizard will be launched if we return
if path in self . _wallets :
if wallet := self . _wallets . get ( wallet_key ) :
wallet = self . _wallets [ path ]
return wallet
return wallet
wallet = self . _load_wallet ( path , password , manual_upgrades = manual_upgrades , config = self . config )
wallet = self . _load_wallet ( path , password , manual_upgrades = manual_upgrades , config = self . config )
if wallet is None :
if wallet is None :
@ -503,13 +514,13 @@ class Daemon(Logger):
@with_wallet_lock
@with_wallet_lock
def add_wallet ( self , wallet : Abstract_Wallet ) - > None :
def add_wallet ( self , wallet : Abstract_Wallet ) - > None :
path = wallet . storage . path
path = wallet . storage . path
path = standardize _path( path )
wallet_key = self . _wallet_key_from _path( path )
self . _wallets [ path ] = wallet
self . _wallets [ wallet_key ] = wallet
run_hook ( ' daemon_wallet_loaded ' , self , wallet )
run_hook ( ' daemon_wallet_loaded ' , self , wallet )
def get_wallet ( self , path : str ) - > Optional [ Abstract_Wallet ] :
def get_wallet ( self , path : str ) - > Optional [ Abstract_Wallet ] :
path = standardize _path( path )
wallet_key = self . _wallet_key_from _path( path )
return self . _wallets . get ( path )
return self . _wallets . get ( wallet_key )
@with_wallet_lock
@with_wallet_lock
def get_wallets ( self ) - > Dict [ str , Abstract_Wallet ] :
def get_wallets ( self ) - > Dict [ str , Abstract_Wallet ] :
@ -531,8 +542,8 @@ class Daemon(Logger):
@with_wallet_lock
@with_wallet_lock
async def _stop_wallet ( self , path : str ) - > bool :
async def _stop_wallet ( self , path : str ) - > bool :
""" Returns True iff a wallet was found. """
""" Returns True iff a wallet was found. """
path = standardize _path( path )
wallet_key = self . _wallet_key_from _path( path )
wallet = self . _wallets . pop ( path , None )
wallet = self . _wallets . pop ( wallet_key , None )
if not wallet :
if not wallet :
return False
return False
await wallet . stop ( )
await wallet . stop ( )