def _save(claim_id, name, tx, n, encoded_meta):
     try:
         decoded = json.loads(base64.b64decode(encoded_meta))
         verify_name_characters(name)
         meta = Metadata(decoded, process_now=False)
         ver = meta.get('ver', '0.0.1')
         log.debug("lbry://%s conforms to metadata version %s" %
                   (name, ver))
         self._claims.update({
             tx: {
                 'name': name,
                 'claim_id': claim_id,
                 'nout': n,
                 'metadata': meta
             }
         })
         sd_hash = meta['sources']['lbry_sd_hash']
         self._check_name_at_height(self._chain_height, name)
         if claim_id in self.non_complying_claims:
             self.non_complying_claims.remove(claim_id)
         d = self._load_sd_attempts(sd_hash)
         d.addCallback(lambda _: self._load_stream_size(sd_hash))
         return d
     except:
         if claim_id not in self.non_complying_claims:
             self.non_complying_claims.append(claim_id)
         self._claims.update(
             {txid: {
                 'name': name,
                 'claim_id': claim_id,
                 'nout': n
             }})
         return self._notify_bad_metadata(name, txid)
Beispiel #2
0
    def _get_stream_info_from_value(self, result, name):
        def _check_result_fields(r):
            for k in ['value', 'txid', 'n', 'height', 'amount']:
                assert k in r, "getvalueforname response missing field %s" % k

        def _log_success(claim_id):
            log.debug("lbry://%s complies with %s, claimid: %s", name,
                      metadata.version, claim_id)
            return defer.succeed(None)

        if 'error' in result:
            log.warning("Got an error looking up a name: %s", result['error'])
            return Failure(UnknownNameError(name))
        _check_result_fields(result)
        try:
            metadata = Metadata(json.loads(result['value']))
        except (TypeError, ValueError, ValidationError):
            return Failure(InvalidStreamInfoError(name, result['value']))
        sd_hash = metadata['sources']['lbry_sd_hash']
        claim_outpoint = ClaimOutpoint(result['txid'], result['n'])
        d = self._save_name_metadata(name, claim_outpoint, sd_hash)
        d.addCallback(
            lambda _: self.get_claimid(name, result['txid'], result['n']))
        d.addCallback(lambda cid: _log_success(cid))
        d.addCallback(lambda _: metadata)
        return d
Beispiel #3
0
 def _get_dict_for_return(self, name):
     meta = Metadata(self.updater.metadata[name], process_now=True)
     r = {
         'name': name,
         'value': meta,
         'cost': self.updater.cost_and_availability[name]['cost'],
         'available': self.updater.cost_and_availability[name]['available'],
     }
     return r
Beispiel #4
0
    def _claim_name(self):
        log.debug('Claiming name')
        self._update_metadata()
        m = Metadata(self.metadata)

        def set_tx_hash(txid):
            log.debug('Name claimed using txid: %s', txid)
            self.txid = txid

        d = self.wallet.claim_name(self.publish_name, self.bid_amount, m)
        d.addCallback(set_tx_hash)
        return d
    def _update_claim_database(self, block_hash, height, name, claim, txid):
        if 'supported claimId' in claim:
            log.info("Skipping claim support %s for lbry://%s, claimid: %s",
                     txid, name, claim['supported claimId'])
            return defer.succeed(None)

        claim_value = base64.b64encode(claim['value'])
        nout = claim['nOut']
        claim_id = claim['claimId']
        try:
            claim_info = {
                'name': name,
                'claim_id': claim_id,
                'nout': nout,
                'metadata': Metadata(json.loads(claim['value']),
                                     process_now=False)
            }
            self._claims.update({txid: claim_info})
            if claim_id in self.non_complying_claims:
                self.non_complying_claims.remove(claim_id)
        except ValueError:
            log.info("Claim %s has invalid metadata json", claim_id)
            if claim_id not in self.non_complying_claims:
                self.non_complying_claims.append(claim_id)
            self._claims.update(
                {txid: {
                    'name': name,
                    'claim_id': claim_id,
                    'nout': nout
                }})
        except AssertionError:
            log.info("Claim %s has non conforming metadata", claim_id)
            if claim_id not in self.non_complying_claims:
                self.non_complying_claims.append(claim_id)
            self._claims.update(
                {txid: {
                    'name': name,
                    'claim_id': claim_id,
                    'nout': nout
                }})

        log.info("Add claim for lbry://%s, id: %s, tx: %s", name, claim_id,
                 txid)

        d = self.db.runQuery("insert into blocks values (?, ?, ?)",
                             (height, block_hash, txid))
        d.addCallback(lambda _: self.db.runQuery(
            "insert into claims values (?, ?, ?, ?)",
            (claim_id, name, txid, nout)))
        d.addCallback(
            lambda _: self.db.runQuery("insert into metadata values (?, ?, ?)",
                                       (claim_id, txid, claim_value)))
        return d
Beispiel #6
0
    def claim_name(self, name, bid, metadata):
        """
        Claim a name, or update if name already claimed by user

        @param name: str, name to claim
        @param bid: float, bid amount
        @param metadata: Metadata compliant dict

        @return: Deferred which returns a dict containing below items
            txid - txid of the resulting transaction
            nout - nout of the resulting claim
            fee - transaction fee paid to make claim
            claim_id -  claim id of the claim
        """

        _metadata = Metadata(metadata)
        my_claim = yield self.get_my_claim(name)

        if my_claim:
            log.info("Updating claim")
            if self.get_balance() < Decimal(bid) - Decimal(my_claim['amount']):
                raise InsufficientFundsError()
            new_metadata = yield self.update_metadata(_metadata,
                                                      my_claim['value'])
            old_claim_outpoint = ClaimOutpoint(my_claim['txid'],
                                               my_claim['nout'])
            claim = yield self._send_name_claim_update(name,
                                                       my_claim['claim_id'],
                                                       old_claim_outpoint,
                                                       new_metadata, bid)
            claim['claim_id'] = my_claim['claim_id']
        else:
            log.info("Making a new claim")
            if self.get_balance() < bid:
                raise InsufficientFundsError()
            claim = yield self._send_name_claim(name, _metadata, bid)

        if not claim['success']:
            msg = 'Claim to name {} failed: {}'.format(name, claim['reason'])
            raise Exception(msg)

        claim = self._process_claim_out(claim)
        claim_outpoint = ClaimOutpoint(claim['txid'], claim['nout'])
        log.info("Saving metadata for claim %s %d", claim['txid'],
                 claim['nout'])

        yield self._save_name_metadata(name, claim_outpoint,
                                       _metadata['sources']['lbry_sd_hash'])
        defer.returnValue(claim)
Beispiel #7
0
        def _build_response(claim):
            try:
                metadata = Metadata(json.loads(claim['value']))
                meta_ver = metadata.version
                sd_hash = metadata['sources']['lbry_sd_hash']
                d = self._save_name_metadata(name, claim_outpoint, sd_hash)
            except (TypeError, ValueError, ValidationError):
                metadata = claim['value']
                meta_ver = "Non-compliant"
                d = defer.succeed(None)

            d.addCallback(lambda _: self._format_claim_for_return(
                name, claim, metadata=metadata, meta_version=meta_ver))
            log.info("get claim info lbry://%s metadata: %s, claimid: %s",
                     name, meta_ver, claim['claimId'])
            return d
 def _initialize_metadata(self):
     log.info("initializing metadata")
     nametrie = self.api.get_nametrie()
     for c in nametrie:
         name = c['name']
         txid = c['txid']
         claim = self._claims.get(txid, {})
         if 'metadata' in claim:
             try:
                 meta = Metadata(claim['metadata'], process_now=False)
                 self.metadata[name] = meta
             except AssertionError:
                 log.info("Bad metadata for lbry://%s", name)
         else:
             log.debug("Missing metadata for lbry://%s", name)
             if 'claim_id' in claim:
                 self._handle_bad_new_claim(name, claim['claim_id'])
Beispiel #9
0
    def _claim_name(self):
        log.debug('Claiming name')
        self._update_metadata()
        m = Metadata(self.metadata)

        def set_txid_nout(claim_out):
            if not claim_out['success']:
                msg = 'Failed to claim name:{}'.format(claim_out['reason'])
                defer.fail(Exception(msg))
            txid = claim_out['txid']
            nout = claim_out['nout'] 
            log.debug('Name claimed using txid: %s, nout: %d', txid, nout)
            self.txid = txid
            self.nout = nout 

        d = self.wallet.claim_name(self.publish_name, self.bid_amount, m)
        d.addCallback(set_txid_nout)
        return d
Beispiel #10
0
    def _claim_name(self):
        log.debug('Claiming name')
        self._update_metadata()
        m = Metadata(self.metadata)

        def set_claim_out(claim_out):
            log.debug(
                'Name claimed using txid: %s, nout: %d, claim_id: %s, fee :%f',
                claim_out['txid'], claim_out['nout'], claim_out['claim_id'],
                claim_out['fee'])
            self.txid = claim_out['txid']
            self.nout = claim_out['nout']
            self.claim_id = claim_out['claim_id']
            self.fee = claim_out['fee']

        d = self.wallet.claim_name(self.publish_name, self.bid_amount, m)
        d.addCallback(set_claim_out)
        return d
Beispiel #11
0
    def claim_name(self, name, bid, m):
        def _save_metadata(claim_out, metadata):
            if not claim_out['success']:
                msg = 'Claim to name {} failed: {}'.format(
                    name, claim_out['reason'])
                raise Exception(msg)
            claim_out = self._process_claim_out(claim_out)
            claim_outpoint = ClaimOutpoint(claim_out['txid'],
                                           claim_out['nout'])
            log.info("Saving metadata for claim %s %d", claim_outpoint['txid'],
                     claim_outpoint['nout'])
            d = self._save_name_metadata(name, claim_outpoint,
                                         metadata['sources']['lbry_sd_hash'])
            d.addCallback(lambda _: claim_out)
            return d

        def _claim_or_update(claim, metadata, _bid):
            if not claim:
                log.debug("No own claim yet, making a new one")
                if self.get_balance() < _bid:
                    raise InsufficientFundsError()
                return self._send_name_claim(name, metadata, _bid)
            else:
                log.debug("Updating over own claim")
                if self.get_balance() < _bid - claim['amount']:
                    raise InsufficientFundsError()
                d = self.update_metadata(metadata, claim['value'])
                claim_outpoint = ClaimOutpoint(claim['txid'], claim['nOut'])
                d.addCallback(
                    lambda new_metadata: self._send_name_claim_update(
                        name, claim['claim_id'], claim_outpoint, new_metadata,
                        _bid))
                d.addCallback(lambda claim_out: claim_out.update(
                    {'claim_id': claim['claim_id']}))
                return d

        meta = Metadata(m)
        d = self.get_my_claim(name)
        d.addCallback(lambda claim: _claim_or_update(claim, meta, bid))
        d.addCallback(lambda claim_out: _save_metadata(claim_out, meta))
        return d
Beispiel #12
0
 def update_metadata(self, new_metadata, old_metadata):
     meta_for_return = old_metadata if isinstance(old_metadata, dict) else {}
     for k in new_metadata:
         meta_for_return[k] = new_metadata[k]
     return defer.succeed(Metadata(meta_for_return))
Beispiel #13
0
 def make_claim(self, name, bid, metadata):
     validated_metadata = Metadata(metadata)
     claim_out = yield self.wallet.claim_name(name, bid, validated_metadata)
     defer.returnValue(claim_out)