diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 99e5417ed..75a71e1c0 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -1,9 +1,11 @@ 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.sqlite_helpers import rerun_if_locked from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException from twisted.internet import threads, reactor, defer, task from twisted.python.failure import Failure +from twisted.enterprise import adbapi from collections import defaultdict, deque from zope.interface import implements from decimal import Decimal @@ -15,7 +17,6 @@ import socket import time import os - log = logging.getLogger(__name__) alert = logging.getLogger("lbryalert." + __name__) @@ -40,8 +41,10 @@ class LBRYcrdWallet(object): """This class implements the LBRYWallet interface for the LBRYcrd payment system""" implements(ILBRYWallet) - def __init__(self, rpc_user, rpc_pass, rpc_url, rpc_port, wallet_dir=None, wallet_conf=None, + def __init__(self, db_dir, rpc_user, rpc_pass, rpc_url, rpc_port, wallet_dir=None, wallet_conf=None, lbrycrdd_path=None): + self.db_dir = db_dir + self.db = None self.rpc_conn_string = "http://%s:%s@%s:%s" % (rpc_user, rpc_pass, rpc_url, str(rpc_port)) self.next_manage_call = None self.wallet_balance = Decimal(0.0) @@ -76,7 +79,8 @@ class LBRYcrdWallet(object): self.manage() return True - d = threads.deferToThread(make_connection) + d = self._open_db() + d.addCallback(lambda _: threads.deferToThread(make_connection)) d.addCallback(lambda _: start_manage()) return d @@ -269,7 +273,12 @@ class LBRYcrdWallet(object): for field in known_fields: if field in value_dict: r_dict[field] = value_dict[field] - return r_dict + if 'stream_hash' in r_dict and 'txid' in result: + d = self._save_name_metadata(name, r_dict['stream_hash'], str(result['txid'])) + else: + d = defer.succeed(True) + d.addCallback(lambda _: r_dict) + return d return Failure(UnknownNameError(name)) d = threads.deferToThread(self._get_value_for_name, name) @@ -286,6 +295,18 @@ class LBRYcrdWallet(object): if key_fee_address is not None: value['key_fee_address'] = key_fee_address d = threads.deferToThread(self._claim_name, name, json.dumps(value), amount) + + def _save_metadata(txid): + d = self._save_name_metadata(name, sd_hash, txid) + d.addCallback(lambda _: txid) + return d + + d.addCallback(_save_metadata) + return d + + def get_name_and_validity_for_sd_hash(self, sd_hash): + d = self._get_claim_metadata_for_sd_hash(sd_hash) + d.addCallback(lambda name_txid: self._get_status_of_claim(name_txid[1], name_txid[0], sd_hash) if name_txid is not None else None) return d def get_available_balance(self): @@ -446,6 +467,28 @@ class LBRYcrdWallet(object): rpc_conn = self._get_rpc_conn() return str(rpc_conn.claimname(name, value, amount)) + @_catch_connection_error + def _get_status_of_claim(self, txhash, name, sd_hash): + rpc_conn = self._get_rpc_conn() + claims = rpc_conn.getclaimsfortx(txhash) + for claim in claims: + if 'in claim trie' in claim: + if 'name' in claim and str(claim['name']) == name and 'value' in claim: + try: + value_dict = json.loads(claim['value']) + except ValueError: + return None + if 'stream_hash' in value_dict and str(value_dict['stream_hash']) == sd_hash: + if 'is controlling' in claim and claim['is controlling']: + return name, "valid" + if claim['in claim trie']: + return name, "invalid" + if 'in queue' in claim and claim['in queue']: + return name, "pending" + return name, "unconfirmed" + return None + + @_catch_connection_error def _rpc_stop(self): # check if our lbrycrdd is actually running, or if we connected to one that was already @@ -455,6 +498,24 @@ class LBRYcrdWallet(object): rpc_conn.stop() self.lbrycrdd.wait() + def _open_db(self): + self.db = adbapi.ConnectionPool('sqlite3', os.path.join(self.db_dir, "blockchainname.db"), + check_same_thread=False) + return self.db.runQuery("create table if not exists name_metadata (" + + " name text, " + + " txid text, " + + " sd_hash text)") + + def _save_name_metadata(self, name, sd_hash, txid): + d = self.db.runQuery("insert into name_metadata values (?, ?, ?)", + (name, txid, sd_hash)) + return d + + def _get_claim_metadata_for_sd_hash(self, sd_hash): + d = self.db.runQuery("select name, txid from name_metadata where sd_hash=?", (sd_hash,)) + d.addCallback(lambda r: r[0] if len(r) else None) + return d + class LBRYcrdAddressRequester(object): implements([IRequestCreator]) diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index 3ae6adf4a..171da8983 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -2219,14 +2219,15 @@ class LBRYFileStatusModifier(CommandHandler): class Status(CommandHandler): - lbry_file_status_format = "[%d] %s - %s bytes - %s%% - %s" + lbry_file_status_format = "[%d] %s - %s bytes - %s - %s - %s%% - %s" - def __init__(self, console, lbry_service, rate_limiter, lbry_file_manager, blob_manager): + def __init__(self, console, lbry_service, rate_limiter, lbry_file_manager, blob_manager, wallet=None): CommandHandler.__init__(self, console) self.lbry_service = lbry_service self.rate_limiter = rate_limiter self.lbry_file_manager = lbry_file_manager self.blob_manager = blob_manager + self.wallet = wallet self.chosen_lbry_file = None self.current_handler = None @@ -2279,6 +2280,13 @@ class Status(CommandHandler): #self.console.sendLine("Server port: %s" % str(self.lbry_service.peer_port)) return defer.succeed(True) + def _get_name_and_validity_for_lbry_file(self, lbry_file): + if self.wallet is None: + return defer.succeed(None) + d = self.lbry_file_manager.stream_info_manager.get_sd_blob_hashes_for_stream(lbry_file.stream_hash) + d.addCallback(lambda sd_blob_hashes: self.wallet.get_name_and_validity_for_sd_hash(sd_blob_hashes[0]) if len(sd_blob_hashes) else None) + return d + def _show_lbry_file_status(self): self.lbry_files = self.lbry_file_manager.lbry_files status_ds = map(lambda lbry_file: lbry_file.status(), self.lbry_files) @@ -2287,14 +2295,27 @@ class Status(CommandHandler): size_ds = map(lambda lbry_file: lbry_file.get_total_bytes(), self.lbry_files) size_dl = defer.DeferredList(size_ds) - dl = defer.DeferredList([status_dl, size_dl]) + name_validity_ds = map(self._get_name_and_validity_for_lbry_file, self.lbry_files) + name_validity_dl = defer.DeferredList(name_validity_ds) + + dl = defer.DeferredList([status_dl, size_dl, name_validity_dl]) def show_statuses(statuses): status_reports = statuses[0][1] sizes = statuses[1][1] - for i, (lbry_file, (succ1, status), (succ2, size)) in enumerate(zip(self.lbry_files, status_reports, sizes)): + name_validities = statuses[2][1] + for i, (lbry_file, (succ1, status), (succ2, size), (succ3, name_validity)) in enumerate(zip(self.lbry_files, status_reports, sizes, name_validities)): percent_done = "unknown" name = lbry_file.file_name + claimed_name = "" + claimed_name_valid = "" + if succ3 and name_validity: + validity = name_validity[1] + if validity == "valid": + claimed_name_valid = "" + else: + claimed_name_valid = "(" + validity + ")" + claimed_name = name_validity[0] total_bytes = "unknown" running_status = "unknown" if succ1: @@ -2305,10 +2326,10 @@ class Status(CommandHandler): running_status = status.running_status if succ2: total_bytes = "%d" % size - self.console.sendLine(self.lbry_file_status_format % (i, str(name), - total_bytes, - percent_done, - str(running_status))) + self.console.sendLine(self.lbry_file_status_format % (i, str(name), total_bytes, + str(claimed_name_valid), + str(claimed_name), + percent_done, str(running_status))) dl.addCallback(show_statuses) return dl diff --git a/lbrynet/lbrynet_console/LBRYConsole.py b/lbrynet/lbrynet_console/LBRYConsole.py index 91800dce9..ee7521591 100644 --- a/lbrynet/lbrynet_console/LBRYConsole.py +++ b/lbrynet/lbrynet_console/LBRYConsole.py @@ -247,8 +247,8 @@ class LBRYConsole(): lbrycrdd_path = self.lbrycrdd_path if not lbrycrdd_path: lbrycrdd_path = self.default_lbrycrdd_path - return LBRYcrdWallet(lbrycrd_options['username'], lbrycrd_options['password'], "127.0.0.1", - lbrycrd_options['rpc_port'], wallet_dir=self.lbrycrd_dir, + return LBRYcrdWallet(self.db_dir, lbrycrd_options['username'], lbrycrd_options['password'], + "127.0.0.1", lbrycrd_options['rpc_port'], wallet_dir=self.lbrycrd_dir, wallet_conf=self.lbrycrd_conf, lbrycrdd_path=lbrycrdd_path) def get_wallet(): @@ -331,13 +331,13 @@ class LBRYConsole(): ModifyLBRYFileOptionsChooserFactory(self.lbry_file_manager), AddStreamFromHashFactory(self.sd_identifier, self.session), StatusFactory(self, self.session.rate_limiter, self.lbry_file_manager, - self.session.blob_manager) + self.session.blob_manager, self.session.wallet if self.wallet_type == 'lbrycrd' else None) ] self.add_control_handlers(handlers) if self.wallet_type == 'lbrycrd': lbrycrd_handlers = [ AddStreamFromLBRYcrdNameFactory(self.sd_identifier, self.session, - self.session.wallet), + self.session.wallet), ClaimNameFactory(self.session. wallet, self.lbry_file_manager, self.session.blob_manager), GetNewWalletAddressFactory(self.session.wallet), diff --git a/lbrynet/lbrynet_gui/LBRYGui.py b/lbrynet/lbrynet_gui/LBRYGui.py index c7aa6ed23..3b97ecbb4 100644 --- a/lbrynet/lbrynet_gui/LBRYGui.py +++ b/lbrynet/lbrynet_gui/LBRYGui.py @@ -292,7 +292,7 @@ class LBRYDownloader(object): lbrycrdd_path = None if self.start_lbrycrdd is True: lbrycrdd_path = self.lbrycrdd_path - wallet = LBRYcrdWallet(self.wallet_user, self.wallet_password, "127.0.0.1", + wallet = LBRYcrdWallet(self.db_dir, self.wallet_user, self.wallet_password, "127.0.0.1", self.wallet_rpc_port, wallet_dir=self.wallet_dir, wallet_conf=self.wallet_conf, lbrycrdd_path=lbrycrdd_path) peer_port = None