Browse Source

Ensure coinjoin state is reset if wallet switches.

Prior to this commit, a lock of one wallet followed by
an unlock of another, or an unlock of a new wallet, overriding
the old one, if it occurred during a running taker-side
coinjoin, would not reset the coinjoin_state to CJ_NOT_RUNNING,
resulting in an inability of the newly loaded wallet to function
correctly.
After this commit, all subservices, including the quasi-service
of taker-side coinjoin, are fully shut down whenever a wallet is
locked, or a new wallet is unlocked. This may be suboptimal (see
TODO) but is logical for now.
The main effect is to ensure that a new wallet will always start
in the correct coinjoin state (CJ_NOT_RUNNING).
Also worth noting, a running Taker will have its abort parameter
set to True on the wallet lock event, meaning that it will not
proceed to the next step on the next asynchronous message coming
from counterparties.
master
Adam Gibson 4 years ago
parent
commit
d493343858
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 41
      jmclient/jmclient/wallet_rpc.py

41
jmclient/jmclient/wallet_rpc.py

@ -217,19 +217,40 @@ class JMWalletDaemon(Service):
return (listener_rpc, listener_ws)
def stopService(self):
""" Encapsulates shut down actions.
""" Top-level service (JMWalletDaemon itself) shutdown.
"""
self.stopSubServices()
super().stopService()
def stopSubServices(self):
""" This:
- shuts down the wallet service, and deletes its name.
- removes the currently valid auth token.
- shuts down any other running sub-services, such as yieldgenerator.
- shuts down (aborts) any taker-side coinjoining happening.
"""
# Currently valid authorization tokens must be removed
# from the daemon:
self.cookie = None
if self.wss_factory:
self.wss_factory.valid_token = None
self.wallet_name = None
# if the wallet-daemon is shut down, all services
# it encapsulates must also be shut down.
for name, service in self.services.items():
if service:
service.stopService()
super().stopService()
# these Services cannot be guaranteed to be
# re-startable (the WalletService for example,
# is explicitly not). So we remove these references
# after stopping.
for n in self.services:
self.services[n] = None
# taker is not currently encapsulated with a Service;
# if it is running, shut down:
if self.coinjoin_state == CJ_TAKER_RUNNING:
self.taker.aborted = True
self.taker_finished(False)
def err(self, request, message):
""" Return errors in a standard format.
@ -370,7 +391,7 @@ class JMWalletDaemon(Service):
# are any.
# This will stop all supporting services and wipe
# state (so wallet, maker service and cookie/token):
self.stopService()
self.stopSubServices()
self.services["wallet"] = WalletService(wallet)
# restart callback needed, otherwise wallet creation will
@ -656,11 +677,12 @@ class JMWalletDaemon(Service):
# lock multiple times:
already_locked = True
else:
self.services["wallet"].stopService()
self.cookie = None
self.wss_factory.valid_token = None
self.services["wallet"] = None
self.wallet_name = None
# notice that here a wallet locking event shuts down
# everything.
# TODO: changing this so a maker can run in the background
# while locked, will require auto-detection of coinjoin
# state on future unlock.
self.stopSubServices()
already_locked = False
return make_jmwalletd_response(request, walletname=walletname,
already_locked=already_locked)
@ -926,6 +948,9 @@ class JMWalletDaemon(Service):
raise InvalidRequestFormat()
if not self.coinjoin_state == CJ_TAKER_RUNNING:
raise ServiceNotStarted()
# prevent the next step, responding to AMP messages
# from jmdaemon backend, from continuing:
self.taker.aborted = True
self.taker_finished(False)
return make_jmwalletd_response(request, status=202)

Loading…
Cancel
Save