From 9a7c71394e95f364325c9143451439e8262eb6e3 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Mon, 14 Dec 2015 22:35:16 -0500 Subject: [PATCH 1/3] make welcome messages more friendly --- lbrynet/lbrynet_console/ConsoleControl.py | 9 ++++++++- lbrynet/lbrynet_console/LBRYConsole.py | 9 ++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lbrynet/lbrynet_console/ConsoleControl.py b/lbrynet/lbrynet_console/ConsoleControl.py index 4d49fd6d4..9c0bea6dc 100644 --- a/lbrynet/lbrynet_console/ConsoleControl.py +++ b/lbrynet/lbrynet_console/ConsoleControl.py @@ -29,7 +29,14 @@ class ConsoleControl(basic.LineReceiver): def send_initial_prompt(self): self.sendLine("") - self.sendLine("Welcome to lbrynet-console!") + self.sendLine("In this early release of LBRY, some functions will not work\n" + "until you have downloaded a full copy of our blockchain. To\n" + "check whether you've caught up with the blockchain, use the\n" + "command 'get-blockchain-status'.\n\n" + "If, for example, you are unable to download some files or\n" + "your balance is showing 0 when you know it shouldn't be, it\n" + "is likely that the culprit is the blockchain.\n\n" + "Welcome to lbrynet-console!") self.sendLine("") self.sendLine("Enter a command. Try 'get wonderfullife' or 'help' to see more options.") self.show_prompt() diff --git a/lbrynet/lbrynet_console/LBRYConsole.py b/lbrynet/lbrynet_console/LBRYConsole.py index 834cfc355..2b284597b 100644 --- a/lbrynet/lbrynet_console/LBRYConsole.py +++ b/lbrynet/lbrynet_console/LBRYConsole.py @@ -320,11 +320,10 @@ class LBRYConsole(): if credits_received != 0.0: points_string = locale.format_string("%.2f LBC", (round(credits_received, 2),), grouping=True) - alert.info("Thank you for using LBRY! You have been given %s for free because we " - "love you. Please give them a few minutes to show up while you catch up " - "with our blockchain.\nTo check whether you've caught up with the blockchain, " - "use the command 'get-blockchain-status'.\nDownloading some files " - "may not work until you have downloaded the LBC blockchain.", points_string) + alert.info("\n\nThank you for testing the alpha version of LBRY!\n\n" + "You have been given %s for free because we love you.\n" + "Please give them a few minutes to show up while you\n" + "catch up with our blockchain.\n", points_string) def _setup_lbry_file_manager(self): self.lbry_file_metadata_manager = DBLBRYFileMetadataManager(self.db_dir) From 6d2e5af6bc12e7d37bd0c28bcd2f6499d43637c0 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Mon, 14 Dec 2015 23:49:27 -0500 Subject: [PATCH 2/3] Inform user that they are behind on the blockchain if they get certain errors --- lbrynet/lbrynet_console/ControlHandlers.py | 69 +++++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index 77a9562c6..f8c5a4d6e 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -269,6 +269,33 @@ class GetWalletBalances(CommandHandler): # assert line is None, "Show wallet balances should not be passed any arguments" # return True, self._get_wallet_balances() + def _show_time_behind_blockchain(self, best_block_time): + best_time = datetime.datetime.utcfromtimestamp(best_block_time) + diff = datetime.datetime.utcnow() - best_time + unit = None + val = None + if diff.days > 0: + if diff.days >= 7: + val = diff.days // 7 + unit = "week" + else: + val = diff.days + unit = "day" + elif diff.seconds >= 60 * 90: + if diff.seconds >= 60 * 60: + val = diff.seconds // (60 * 60) + unit = "hour" + if unit is not None: + if val != 1: + unit += "s" + self.console.sendLine("\n\nYour balance may be out of date. This application\n" + "is %d %s behind the LBC blockchain.\n\n" % (val, unit)) + else: + self.console.sendLine("\n\n") + + def _log_recent_blocktime_error(self, err): + log.error("An error occurred looking up the most recent blocktime: %s", err.getTraceback()) + def _get_wallet_balances(self): d = self.wallet.get_balance() @@ -277,6 +304,10 @@ class GetWalletBalances(CommandHandler): balance = 0 balance_string = "balance: " + str(balance) + " LBC\n" self.console.sendLine(balance_string) + d = self.wallet.get_most_recent_blocktime() + d.addCallback(self._show_time_behind_blockchain) + d.addErrback(self._log_recent_blocktime_error) + d.chainDeferred(self.finished_deferred) d.addCallback(format_balance) return d @@ -763,6 +794,34 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): d.addCallback(get_name_from_info) return d + def _show_time_behind_blockchain(self, best_block_time): + best_time = datetime.datetime.utcfromtimestamp(best_block_time) + diff = datetime.datetime.utcnow() - best_time + unit = None + val = None + if diff.days > 0: + if diff.days >= 7: + val = diff.days // 7 + unit = "week" + else: + val = diff.days + unit = "day" + elif diff.seconds >= 60 * 90: + if diff.seconds >= 60 * 60: + val = diff.seconds // (60 * 60) + unit = "hour" + if unit is not None: + if val != 1: + unit += "s" + self.console.sendLine("\nThis application is %d %s behind the LBC blockchain, which may be\n" + "preventing this name from being resolved. Use 'get-blockchain-status'\n" + "to check if your application is up to date with the blockchain.\n\n" % (val, unit)) + else: + self.console.sendLine("\n\n") + + def _log_recent_blockchain_time_error(self, err): + log.error("An error occurred trying to look up the most recent blocktime: %s", err.getTraceback()) + def _handle_load_failed(self, err): self.loading_failed = True if err.check(UnknownNameError): @@ -772,8 +831,11 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): AddStreamFromHash.start(self, self.name) return else: - self.console.sendLine("The name %s could not be found.\n\n" % err.getErrorMessage()) - self.finished_deferred.callback(None) + self.console.sendLine("The name %s could not be found." % err.getErrorMessage()) + d = self.wallet.get_most_recent_blocktime() + d.addCallback(self._show_time_behind_blockchain) + d.addErrback(self._log_recent_blockchain_time_error) + d.chainDeferred(self.finished_deferred) return elif err.check(InvalidBlobHashError): self.console.sendLine("The metadata for this name is invalid. The stream cannot be downloaded.\n\n") @@ -1709,6 +1771,7 @@ class Publish(CommandHandler): def _show_publish_error(self, err): message = "An error occurred publishing %s to %s. Error: %s." self.console.sendLine(message % (str(self.file_name), str(self.publish_name), err.getErrorMessage())) + log.error(message, str(self.file_name), str(self.publish_name), err.getTraceback()) def _do_publish(self): d = create_lbry_file(self.session, self.lbry_file_manager, self.file_name, open(self.file_path)) @@ -1722,7 +1785,7 @@ class Publish(CommandHandler): class PublishFactory(CommandHandlerFactory): control_handler_class = Publish priority = 90 - command = 'publish' + command = "publish" short_help = "Publish a file to lbrynet" full_help = "Publish a file to lbrynet.\n\n" \ "Usage: publish [file_name]\n\n" \ From a948335cb9c8a04f54467a7487c6e79be2f4d7cf Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Tue, 15 Dec 2015 14:42:29 -0500 Subject: [PATCH 3/3] show if the application is behind on the blockchain if an error occurs that could be caused by that --- lbrynet/core/LBRYcrdWallet.py | 11 +- lbrynet/lbrynet_console/ConsoleControl.py | 2 + lbrynet/lbrynet_console/ControlHandlers.py | 194 ++++++++++++--------- lbrynet/lbrynet_console/LBRYConsole.py | 5 +- 4 files changed, 129 insertions(+), 83 deletions(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 982eebf10..4a1cc1c7f 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -1,6 +1,7 @@ from lbrynet.interfaces import IRequestCreator, IQueryHandlerFactory, IQueryHandler, ILBRYWallet from lbrynet.core.client.ClientRequest import ClientRequest from lbrynet.core.Error import UnknownNameError, InvalidStreamInfoError, RequestCanceledError +from lbrynet.core.Error import InsufficientFundsError from lbrynet.core.sqlite_helpers import rerun_if_locked from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException from twisted.internet import threads, reactor, defer, task @@ -498,12 +499,20 @@ class LBRYcrdWallet(object): @_catch_connection_error def _claim_name(self, name, value, amount): rpc_conn = self._get_rpc_conn() - return str(rpc_conn.claimname(name, value, amount)) + try: + return str(rpc_conn.claimname(name, value, amount)) + except JSONRPCException as e: + if 'message' in e.error and e.error['message'] == "Insufficient funds": + raise InsufficientFundsError() + elif 'message' in e.error: + raise ValueError(e.error['message']) @_catch_connection_error def _get_status_of_claim(self, txhash, name, sd_hash): rpc_conn = self._get_rpc_conn() claims = rpc_conn.getclaimsfortx(txhash) + if claims is None: + claims = [] for claim in claims: if 'in claim trie' in claim: if 'name' in claim and str(claim['name']) == name and 'value' in claim: diff --git a/lbrynet/lbrynet_console/ConsoleControl.py b/lbrynet/lbrynet_console/ConsoleControl.py index 9c0bea6dc..0477154bd 100644 --- a/lbrynet/lbrynet_console/ConsoleControl.py +++ b/lbrynet/lbrynet_console/ConsoleControl.py @@ -36,6 +36,8 @@ class ConsoleControl(basic.LineReceiver): "If, for example, you are unable to download some files or\n" "your balance is showing 0 when you know it shouldn't be, it\n" "is likely that the culprit is the blockchain.\n\n" + "You should have received 1000 LBC the first time you ran\n" + "this program. If you did not, let us know!\n\n" "Welcome to lbrynet-console!") self.sendLine("") self.sendLine("Enter a command. Try 'get wonderfullife' or 'help' to see more options.") diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index f8c5a4d6e..9b2941f1c 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -54,6 +54,49 @@ class InvalidValueError(Exception): # prompt_description = None +class RoundedTime(object): + SECOND = 0 + MINUTE = 1 + HOUR = 2 + DAY = 3 + WEEK = 4 + units = ['second', 'minute', 'hour', 'day', 'week'] + + def __init__(self, unit, val): + assert unit < len(self.units) + self.unit = unit + self.val = val + + def __str__(self): + assert self.unit < len(self.units) + unit_str = self.units[self.unit] + if self.val != 1: + unit_str += "s" + return "%d %s" % (self.val, unit_str) + + +def get_time_behind_blockchain(best_block_time): + best_time = datetime.datetime.utcfromtimestamp(best_block_time) + diff = datetime.datetime.utcnow() - best_time + if diff.days > 0: + if diff.days >= 7: + val = diff.days // 7 + unit = RoundedTime.WEEK + else: + val = diff.days + unit = RoundedTime.DAY + elif diff.seconds >= 60 * 60: + val = diff.seconds // (60 * 60) + unit = RoundedTime.HOUR + elif diff.seconds >= 60: + val = diff.seconds // 60 + unit = RoundedTime.MINUTE + else: + val = diff.seconds + unit = RoundedTime.SECOND + return RoundedTime(unit, val) + + class CommandHandlerFactory(object): implements(ICommandHandlerFactory) priority = 0 @@ -269,32 +312,16 @@ class GetWalletBalances(CommandHandler): # assert line is None, "Show wallet balances should not be passed any arguments" # return True, self._get_wallet_balances() - def _show_time_behind_blockchain(self, best_block_time): - best_time = datetime.datetime.utcfromtimestamp(best_block_time) - diff = datetime.datetime.utcnow() - best_time - unit = None - val = None - if diff.days > 0: - if diff.days >= 7: - val = diff.days // 7 - unit = "week" - else: - val = diff.days - unit = "day" - elif diff.seconds >= 60 * 90: - if diff.seconds >= 60 * 60: - val = diff.seconds // (60 * 60) - unit = "hour" - if unit is not None: - if val != 1: - unit += "s" + def _show_time_behind_blockchain(self, rounded_time): + if rounded_time.unit >= RoundedTime.HOUR: self.console.sendLine("\n\nYour balance may be out of date. This application\n" - "is %d %s behind the LBC blockchain.\n\n" % (val, unit)) + "is %s behind the LBC blockchain.\n\n" % str(rounded_time)) else: - self.console.sendLine("\n\n") + self.console.sendLine("") def _log_recent_blocktime_error(self, err): log.error("An error occurred looking up the most recent blocktime: %s", err.getTraceback()) + self.console.sendLine("") def _get_wallet_balances(self): d = self.wallet.get_balance() @@ -302,12 +329,13 @@ class GetWalletBalances(CommandHandler): def format_balance(balance): if balance == 0: balance = 0 - balance_string = "balance: " + str(balance) + " LBC\n" + balance_string = "balance: " + str(balance) + " LBC" self.console.sendLine(balance_string) d = self.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) d.addCallback(self._show_time_behind_blockchain) d.addErrback(self._log_recent_blocktime_error) - d.chainDeferred(self.finished_deferred) + return d d.addCallback(format_balance) return d @@ -429,9 +457,10 @@ class AddStream(CommandHandler): cancel_prompt = "Trying to locate the stream's metadata. Type \"cancel\" to cancel..." canceled_message = "Canceled downloading." - def __init__(self, console, sd_identifier, base_payment_rate_manager): + def __init__(self, console, sd_identifier, base_payment_rate_manager, wallet): CommandHandler.__init__(self, console) self.sd_identifier = sd_identifier + self.wallet = wallet self.loading_metadata_deferred = None self.metadata = None self.factory = None @@ -690,6 +719,10 @@ class AddStream(CommandHandler): def _handle_download_error(self, err): if err.check(InsufficientFundsError): self.console.sendLine("Download stopped due to insufficient funds.") + d = self.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) + d.addCallback(self._show_time_behind_blockchain_download) + d.addErrback(self._log_recent_blockchain_time_error_download) else: log.error("An unexpected error has caused the download to stop: %s" % err.getTraceback()) self.console.sendLine("An unexpected error has caused the download to stop. See console.log for details.") @@ -698,6 +731,15 @@ class AddStream(CommandHandler): return self.factory.make_downloader(self.metadata, self.options_chosen, self.payment_rate_manager) + def _show_time_behind_blockchain_download(self, rounded_time): + if rounded_time.unit >= RoundedTime.HOUR: + self.console.sendLine("\nThis application is %s behind the LBC blockchain, so some of your\n" + "funds may not be available. Use 'get-blockchain-status' to check if\n" + "your application is up to date with the blockchain." % str(rounded_time)) + + def _log_recent_blockchain_time_error_download(self, err): + log.error("An error occurred trying to look up the most recent blocktime: %s", err.getTraceback()) + class AddStreamFromSD(AddStream): #prompt_description = "Add a stream from a stream descriptor file" @@ -721,8 +763,8 @@ class AddStreamFromHash(AddStream): #prompt_description = "Add a stream from a hash" #line_prompt = "Stream descriptor hash:" - def __init__(self, console, sd_identifier, session): - AddStream.__init__(self, console, sd_identifier, session.base_payment_rate_manager) + def __init__(self, console, sd_identifier, session, wallet): + AddStream.__init__(self, console, sd_identifier, session.base_payment_rate_manager, wallet) self.session = session def start(self, sd_hash): @@ -739,8 +781,13 @@ class AddStreamFromHash(AddStream): self.finished_deferred.callback(None) return if err.check(InsufficientFundsError): - self.console.sendLine("Insufficient funds to download the metadata blob.\n\n") - self.finished_deferred.callback(None) + self.console.sendLine("Insufficient funds to download the metadata blob.") + d = self.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) + d.addCallback(self._show_time_behind_blockchain_download) + d.addErrback(self._log_recent_blockchain_time_error_download) + d.addCallback(lambda _: self.console.sendLine("\n")) + d.chainDeferred(self.finished_deferred) return return AddStream._handle_load_failed(self, err) @@ -760,7 +807,7 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): #line_prompt = "Short name:" def __init__(self, console, sd_identifier, session, wallet): - AddStreamFromHash.__init__(self, console, sd_identifier, session) + AddStreamFromHash.__init__(self, console, sd_identifier, session, wallet) self.wallet = wallet self.resolved_name = None self.description = None @@ -790,36 +837,23 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): self.key_fee = None self.key_fee_address = stream_info.get('key_fee_address', None) return stream_info['stream_hash'] - d = self.wallet.get_stream_info_for_name(name) + d = self.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) + d.addCallback(self._show_time_behind_blockchain_resolve) + d.addErrback(self._log_recent_blockchain_time_error_resolve) + d.addCallback(lambda _: self.wallet.get_stream_info_for_name(name)) d.addCallback(get_name_from_info) return d - def _show_time_behind_blockchain(self, best_block_time): - best_time = datetime.datetime.utcfromtimestamp(best_block_time) - diff = datetime.datetime.utcnow() - best_time - unit = None - val = None - if diff.days > 0: - if diff.days >= 7: - val = diff.days // 7 - unit = "week" - else: - val = diff.days - unit = "day" - elif diff.seconds >= 60 * 90: - if diff.seconds >= 60 * 60: - val = diff.seconds // (60 * 60) - unit = "hour" - if unit is not None: - if val != 1: - unit += "s" - self.console.sendLine("\nThis application is %d %s behind the LBC blockchain, which may be\n" - "preventing this name from being resolved. Use 'get-blockchain-status'\n" - "to check if your application is up to date with the blockchain.\n\n" % (val, unit)) + def _show_time_behind_blockchain_resolve(self, rounded_time): + if rounded_time.unit >= RoundedTime.HOUR: + self.console.sendLine("\nThis application is %s behind the LBC blockchain, which may be\n" + "preventing this name from being resolved correctly. Use 'get-blockchain-status'\n" + "to check if your application is up to date with the blockchain.\n\n" % str(rounded_time)) else: - self.console.sendLine("\n\n") + self.console.sendLine("\n") - def _log_recent_blockchain_time_error(self, err): + def _log_recent_blockchain_time_error_resolve(self, err): log.error("An error occurred trying to look up the most recent blocktime: %s", err.getTraceback()) def _handle_load_failed(self, err): @@ -832,10 +866,7 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): return else: self.console.sendLine("The name %s could not be found." % err.getErrorMessage()) - d = self.wallet.get_most_recent_blocktime() - d.addCallback(self._show_time_behind_blockchain) - d.addErrback(self._log_recent_blockchain_time_error) - d.chainDeferred(self.finished_deferred) + self.finished_deferred.callback(True) return elif err.check(InvalidBlobHashError): self.console.sendLine("The metadata for this name is invalid. The stream cannot be downloaded.\n\n") @@ -1768,10 +1799,29 @@ class Publish(CommandHandler): message = "Finished publishing %s to %s. The txid of the LBRYcrd claim is %s." self.console.sendLine(message % (str(self.file_name), str(self.publish_name), str(self.tx_hash))) + def _show_time_behind_blockchain(self, rounded_time): + if rounded_time.unit >= RoundedTime.HOUR: + self.console.sendLine("This application is %s behind the LBC blockchain\n" + "and therefore may not have all of the funds you expect\n" + "available at this time." % str(rounded_time)) + + def _log_best_blocktime_error(self, err): + log.error("An error occurred checking the best time of the blockchain: %s", err.getTraceback()) + def _show_publish_error(self, err): message = "An error occurred publishing %s to %s. Error: %s." - self.console.sendLine(message % (str(self.file_name), str(self.publish_name), err.getErrorMessage())) + if err.check(InsufficientFundsError): + d = self.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) + d.addCallback(self._show_time_behind_blockchain) + d.addErrback(self._log_best_blocktime_error) + error_message = "Insufficient funds" + else: + d = defer.succeed(True) + error_message = err.getErrorMessage() + self.console.sendLine(message % (str(self.file_name), str(self.publish_name), error_message)) log.error(message, str(self.file_name), str(self.publish_name), err.getTraceback()) + return d def _do_publish(self): d = create_lbry_file(self.session, self.lbry_file_manager, self.file_name, open(self.file_path)) @@ -2480,35 +2530,19 @@ class BlockchainStatus(CommandHandler): def start(self): d = self.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) d.addCallbacks(self._show_time_behind_blockchain, self._show_error) d.chainDeferred(self.finished_deferred) return d - def _show_time_behind_blockchain(self, best_block_time): - best_time = datetime.datetime.utcfromtimestamp(best_block_time) - diff = datetime.datetime.utcnow() - best_time - unit = None - val = None - if diff.days > 0: - if diff.days >= 7: - val = diff.days // 7 - unit = "week" - else: - val = diff.days - unit = "day" - elif diff.seconds >= 60 * 90: - if diff.seconds >= 60 * 60: - val = diff.seconds // (60 * 60) - unit = "hour" - if unit is not None: - if val != 1: - unit += "s" - self.console.sendLine("This application is %d %s behind the LBC blockchain." % (val, unit)) + def _show_time_behind_blockchain(self, rounded_time): + if rounded_time.unit >= RoundedTime.HOUR: + self.console.sendLine("This application is %s behind the LBC blockchain." % str(rounded_time)) else: self.console.sendLine("This application is up to date with the LBC blockchain.") def _show_error(self, err): - logging.error(err.getTraceback()) + log.error(err.getTraceback()) self.console.sendLine("Unable to determine the status of the blockchain.") diff --git a/lbrynet/lbrynet_console/LBRYConsole.py b/lbrynet/lbrynet_console/LBRYConsole.py index 2b284597b..dc4af02d8 100644 --- a/lbrynet/lbrynet_console/LBRYConsole.py +++ b/lbrynet/lbrynet_console/LBRYConsole.py @@ -353,7 +353,8 @@ class LBRYConsole(): ShutDownFactory(self), PeerStatsAndSettingsChooserFactory(self.session.peer_manager), LBRYFileStatusFactory(self.lbry_file_manager), - AddStreamFromSDFactory(self.sd_identifier, self.session.base_payment_rate_manager), + AddStreamFromSDFactory(self.sd_identifier, self.session.base_payment_rate_manager, + self.session.wallet), DeleteLBRYFileChooserFactory(self.lbry_file_metadata_manager, self.session.blob_manager, self.lbry_file_manager), ToggleLBRYFileRunningChooserFactory(self.lbry_file_manager), @@ -365,7 +366,7 @@ class LBRYConsole(): CreatePlainStreamDescriptorChooserFactory(self.lbry_file_manager), ShowLBRYFileStreamHashChooserFactory(self.lbry_file_manager), ModifyLBRYFileOptionsChooserFactory(self.lbry_file_manager), - AddStreamFromHashFactory(self.sd_identifier, self.session), + AddStreamFromHashFactory(self.sd_identifier, self.session, self.session.wallet), StatusFactory(self, self.session.rate_limiter, self.lbry_file_manager, self.session.blob_manager, self.session.wallet if self.wallet_type == 'lbrycrd' else None), # AutoFetcherStartFactory(self.autofetcher),