diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c76daa53..ea22fb466 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ at anytime. * Add `peer_port` to settings configurable using `settings_set` * Added an option to disable max key fee check. * Add `wallet_unlock`, a command available during startup to unlock an encrypted wallet + * Added a new startup stage to indicate if the daemon is waiting for the `wallet_unlock` command. * Add `--conf` CLI flag to specify an alternate config file * Added `blockchain_name` and `lbryum_servers` to the adjustable settings diff --git a/lbrynet/core/Wallet.py b/lbrynet/core/Wallet.py index 501c0d959..06156091c 100644 --- a/lbrynet/core/Wallet.py +++ b/lbrynet/core/Wallet.py @@ -1193,6 +1193,9 @@ class LBRYumWallet(Wallet): self.blocks_behind = 0 self.catchup_progress = 0 + # fired when the wallet actually unlocks (wallet_unlocked_d can be called multiple times) + self.wallet_unlock_success = defer.Deferred() + def _is_first_run(self): return (not self.printed_retrieving_headers and self.network.blockchain.retrieving_headers) @@ -1203,12 +1206,33 @@ class LBRYumWallet(Wallet): return self._cmd_runner + def check_locked(self): + if not self.wallet.use_encryption: + log.info("Wallet is not encrypted") + self.wallet_unlock_success.callback(True) + elif not self._cmd_runner: + raise Exception("Command runner hasn't been initialized yet") + elif self._cmd_runner.locked: + log.info("Waiting for wallet password") + self.wallet_unlocked_d.addCallback(self.unlock) + return self.wallet_unlock_success + + def unlock(self, password): + if self._cmd_runner and self._cmd_runner.locked: + try: + self._cmd_runner.unlock_wallet(password) + self.wallet_unlock_success.callback(True) + log.info("Unlocked the wallet!") + except InvalidPassword: + log.warning("Incorrect password, try again") + self.wallet_unlocked_d = defer.Deferred() + self.wallet_unlocked_d.addCallback(self.unlock) + return defer.succeed(False) + return defer.succeed(True) + def _start(self): network_start_d = defer.Deferred() - # fired when the wallet actually unlocks (wallet_unlocked_d can be called multiple times) - wallet_unlock_success = defer.Deferred() - def setup_network(): self.network = Network(self.config) log.info("Loading the wallet") @@ -1227,30 +1251,6 @@ class LBRYumWallet(Wallet): else: network_start_d.errback(ValueError("Failed to connect to network.")) - def unlock(password): - if self._cmd_runner and self._cmd_runner.locked: - try: - self._cmd_runner.unlock_wallet(password) - wallet_unlock_success.callback(True) - log.info("Unlocked the wallet!") - except InvalidPassword: - log.warning("Incorrect password, try again") - self.wallet_unlocked_d = defer.Deferred() - self.wallet_unlocked_d.addCallback(unlock) - return defer.succeed(False) - return defer.succeed(True) - - def check_locked(): - if not self.wallet.use_encryption: - log.info("Wallet is not encrypted") - wallet_unlock_success.callback(True) - elif not self._cmd_runner: - raise Exception("Command runner hasn't been initialized yet") - elif self._cmd_runner.locked: - log.info("Waiting for wallet password") - self.wallet_unlocked_d.addCallback(unlock) - return wallet_unlock_success - self._start_check = task.LoopingCall(check_started) d = setup_network() @@ -1263,7 +1263,6 @@ class LBRYumWallet(Wallet): d.addCallback(lambda _: log.info("Synchronized wallet")) d.addCallback(lambda _: self.get_cmd_runner()) d.addCallbacks(lambda _: log.info("Set up lbryum command runner")) - d.addCallbacks(lambda _: check_locked()) return d def _stop(self): diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index da2439a41..c9c4528fe 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -60,6 +60,7 @@ LOADING_FILE_MANAGER_CODE = 'loading_file_manager' LOADING_SERVER_CODE = 'loading_server' STARTED_CODE = 'started' WAITING_FOR_FIRST_RUN_CREDITS = 'waiting_for_credits' +WAITING_FOR_UNLOCK = 'waiting_for_wallet_unlock' STARTUP_STAGES = [ (INITIALIZING_CODE, 'Initializing'), (LOADING_DB_CODE, 'Loading databases'), @@ -68,6 +69,7 @@ STARTUP_STAGES = [ (LOADING_SERVER_CODE, 'Starting lbrynet'), (STARTED_CODE, 'Started lbrynet'), (WAITING_FOR_FIRST_RUN_CREDITS, 'Waiting for first run credits'), + (WAITING_FOR_UNLOCK, 'Waiting for user to unlock the wallet using the wallet_unlock command') ] # TODO: make this consistent with the stages in Downloader.py @@ -248,6 +250,7 @@ class Daemon(AuthJSONRPCServer): yield threads.deferToThread(self._setup_data_directory) yield self._check_db_migration() yield self._get_session() + yield self._check_wallet_locked() yield self._get_analytics() yield add_lbry_file_to_sd_identifier(self.sd_identifier) yield self._setup_stream_identifier() @@ -588,6 +591,14 @@ class Daemon(AuthJSONRPCServer): d.addCallback(lambda _: self.session.setup()) return d + @defer.inlineCallbacks + def _check_wallet_locked(self): + wallet = self.session.wallet + if wallet.wallet.use_encryption: + self.startup_status = STARTUP_STAGES[7] + + yield wallet.check_locked() + def _setup_stream_identifier(self): file_saver_factory = EncryptedFileSaverFactory( self.session.peer_finder,