diff --git a/CHANGELOG.md b/CHANGELOG.md index 73edd1610..337f7d6b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,18 +9,18 @@ at anytime. ## [Unreleased] ### Added - * - * - * - + * Add `claim_id` parameter to `claim_show` + * Add `hex` field to claim responses for the raw claim value + * Add an `error` field to to file responses if an error occurs + ### Changed * * * ### Fixed - * - * + * `file_list` for files with bad signatures + * return None from resolve commands when nothing is found * ## [0.9.2rc9] - 2017-04-08 diff --git a/lbrynet/core/Wallet.py b/lbrynet/core/Wallet.py index 32cf56364..1126ef752 100644 --- a/lbrynet/core/Wallet.py +++ b/lbrynet/core/Wallet.py @@ -17,11 +17,12 @@ from lbryum.commands import known_commands, Commands from lbryschema.uri import parse_lbry_uri from lbryschema.claim import ClaimDict from lbryschema.error import DecodeError +from lbryschema.decode import smart_decode from lbrynet.core.sqlite_helpers import rerun_if_locked from lbrynet.interfaces import IRequestCreator, IQueryHandlerFactory, IQueryHandler, IWallet from lbrynet.core.client.ClientRequest import ClientRequest -from lbrynet.core.Error import RequestCanceledError, InsufficientFundsError +from lbrynet.core.Error import RequestCanceledError, InsufficientFundsError, UnknownNameError from lbrynet.db_migrator.migrate1to2 import UNSET_NOUT log = logging.getLogger(__name__) @@ -450,8 +451,20 @@ class Wallet(object): ###### + @defer.inlineCallbacks def get_claim(self, claim_id): - return self._get_claim_by_claimid(claim_id) + claim = yield self._get_claim_by_claimid(claim_id) + try: + decoded = smart_decode(claim['value']) + claim['value'] = decoded.claim_dict + claim['hex'] = decoded.serialized.encode('hex') + except DecodeError: + claim['hex'] = claim['value'] + claim['value'] = None + claim['error'] = "Failed to decode" + log.warning("Failed to decode claim value for lbry://%s#%s", claim['name'], + claim['claim_id']) + defer.returnValue(claim) def get_claimid(self, name, txid, nout): def _get_id_for_return(claim_id): @@ -484,48 +497,82 @@ class Wallet(object): break defer.returnValue(my_claim) - def get_claim_info(self, name, txid=None, nout=None): - if txid is None or nout is None: - return self.get_claim_by_name(name) + @defer.inlineCallbacks + def get_claim_info(self, name, txid=None, nout=None, claim_id=None): + if claim_id is not None: + results = yield self.get_claim(claim_id) + if results['name'] != name: + raise Exception("Name does not match claim referenced by id") + elif txid is None or nout is None: + results = yield self.get_claim_by_name(name) else: - return self.get_claim_by_outpoint(ClaimOutpoint(txid, nout)) + results = yield self.get_claim_by_outpoint(ClaimOutpoint(txid, nout)) + defer.returnValue(results) @defer.inlineCallbacks def _handle_claim_result(self, results): + if not results: + raise UnknownNameError("No results to return") + if 'error' in results: - raise Exception(results['error']) - elif 'claim' in results: + if results['error'] == 'name is not claimed': + raise UnknownNameError(results['error']) + else: + raise Exception(results['error']) + + if 'claim' in results: claim = results['claim'] if 'has_signature' in claim and claim['has_signature']: if not claim['signature_is_valid']: - raise Exception("Claim has invalid signature") + log.warning("lbry://%s#%s has an invalid signature", + claim['name'], claim['claim_id']) + decoded = ClaimDict.load_dict(claim['value']) + claim_dict = decoded.claim_dict + claim['value'] = claim_dict + defer.returnValue(claim) try: decoded = ClaimDict.load_dict(claim['value']) claim_dict = decoded.claim_dict outpoint = ClaimOutpoint(claim['txid'], claim['nout']) name = claim['name'] claim['value'] = claim_dict + claim['hex'] = decoded.serialized.encode('hex') yield self._save_name_metadata(name, outpoint, decoded.source_hash) yield self._update_claimid(claim['claim_id'], name, outpoint) - except (TypeError, ValueError, KeyError, DecodeError): - claim = claim['value'] - log.warning(results) + except DecodeError: + claim['hex'] = claim['value'] + claim['value'] = None + claim['error'] = "Failed to decode value" + results = claim + elif 'value' in results: if 'has_signature' in results and results['has_signature']: if not results['signature_is_valid']: - raise Exception("Claim has invalid signature") + log.warning("lbry://%s#%s has an invalid signature", + results['name'], results['claim_id']) + decoded = ClaimDict.load_dict(results['value']) + claim_dict = decoded.claim_dict + results['value'] = claim_dict + defer.returnValue(results) try: decoded = ClaimDict.load_dict(results['value']) claim_dict = decoded.claim_dict + claim_hex = decoded.serialized.encode('hex') + claim_err = None outpoint = ClaimOutpoint(results['txid'], results['nout']) name = results['name'] yield self._save_name_metadata(name, outpoint, decoded.source_hash) yield self._update_claimid(results['claim_id'], name, outpoint) - except (TypeError, ValueError, KeyError, DecodeError): - claim_dict = results['value'] - log.warning(results) + except DecodeError: + claim_dict = None + claim_hex = results['value'] + claim_err = "Failed to decode value" + if claim_err: + results['error'] = claim_err + results['hex'] = claim_hex results['value'] = claim_dict + log.info("get claim info lbry://%s#%s", results['name'], results['claim_id']) defer.returnValue(results) @@ -565,8 +612,19 @@ class Wallet(object): claims = result['claims'] claims_for_return = [] for claim in claims: - claim['value'] = ClaimDict.load_dict(claim['value']).claim_dict - claims_for_return.append(claim) + try: + decoded = smart_decode(claim['value']) + claim['value'] = decoded.claim_dict + claim['hex'] = decoded.serialized.encode('hex') + claims_for_return.append(claim) + except DecodeError: + claim['hex'] = claim['value'] + claim['value'] = None + claim['error'] = "Failed to decode" + log.warning("Failed to decode claim value for lbry://%s#%s", claim['name'], + claim['claim_id']) + claims_for_return.append(claim) + result['claims'] = claims_for_return defer.returnValue(result) @@ -1070,7 +1128,7 @@ class LBRYumWallet(Wallet): def _get_claim_by_outpoint(self, txid, nout): return self._run_cmd_as_defer_to_thread('getclaimbyoutpoint', txid, nout) - def get_claim_by_claimid(self, claim_id): + def _get_claim_by_claimid(self, claim_id): return self._run_cmd_as_defer_to_thread('getclaimbyid', claim_id) def _get_balance_for_address(self, address): diff --git a/lbrynet/lbrynet_daemon/Daemon.py b/lbrynet/lbrynet_daemon/Daemon.py index aea0bc009..0c5844eae 100644 --- a/lbrynet/lbrynet_daemon/Daemon.py +++ b/lbrynet/lbrynet_daemon/Daemon.py @@ -908,9 +908,13 @@ class Daemon(AuthJSONRPCServer): else: size = None message = None - claim = yield self.session.wallet.get_claim_info(lbry_file.name, - lbry_file.txid, - lbry_file.nout) + + if lbry_file.claim_id: + claim = yield self.session.wallet.get_claim(lbry_file.claim_id) + else: + claim = yield self.session.wallet.get_claim_info(lbry_file.name, + lbry_file.txid, + lbry_file.nout) try: metadata = claim['value'] except: @@ -920,7 +924,16 @@ class Daemon(AuthJSONRPCServer): except TypeError: outpoint = None - defer.returnValue({ + if claim and 'has_signature' in claim: + has_signature = claim['has_signature'] + else: + has_signature = None + if claim and 'signature_is_valid' in claim: + signature_is_valid = claim['signature_is_valid'] + else: + signature_is_valid = None + + result = { 'completed': lbry_file.completed, 'file_name': lbry_file.file_name, 'download_directory': lbry_file.download_directory, @@ -940,7 +953,12 @@ class Daemon(AuthJSONRPCServer): 'written_bytes': written_bytes, 'message': message, 'metadata': metadata - }) + } + if has_signature is not None: + result['has_signature'] = has_signature + if signature_is_valid is not None: + result['signature_is_valid'] = signature_is_valid + defer.returnValue(result) @defer.inlineCallbacks def _get_lbry_file(self, search_by, val, return_json=False, full_status=False): @@ -1374,7 +1392,7 @@ class Daemon(AuthJSONRPCServer): """ return self.jsonrpc_claim_show(**kwargs) - def jsonrpc_claim_show(self, name, txid=None, nout=None): + def jsonrpc_claim_show(self, name, txid=None, nout=None, claim_id=None): """ Resolve claim info from a LBRY name @@ -1383,6 +1401,7 @@ class Daemon(AuthJSONRPCServer): 'name': (str) name to look up, do not include lbry:// prefix 'txid'(optional): (str) if specified, look for claim with this txid 'nout'(optional): (int) if specified, look for claim with this nout + 'claim_id'(optional): (str) if specified, look for claim with this claim_id Returns: (dict) Dictionary contaning claim info, (bool) false if claim is not resolvable @@ -1398,7 +1417,7 @@ class Daemon(AuthJSONRPCServer): } """ - d = self.session.wallet.get_claim_info(name, txid, nout) + d = self.session.wallet.get_claim_info(name, txid, nout, claim_id) d.addCallback(format_json_out_amount_as_float) d.addCallback(lambda r: self._render_response(r)) return d diff --git a/setup.py b/setup.py index bfbed8050..048075e83 100644 --- a/setup.py +++ b/setup.py @@ -19,8 +19,8 @@ requires = [ 'envparse', 'jsonrpc', 'jsonschema', - 'lbryum>=2.7.6', - 'lbryschema', + 'lbryum>=2.7.14', + 'lbryschema>=0.0.2', 'miniupnpc', 'pycrypto', 'pyyaml',