Пример #1
0
 def _pay_key_fee(self, address, fee_lbc, name):
     log.info("Pay key fee %s --> %s", dewies_to_lbc(fee_lbc), address)
     reserved_points = self.wallet.reserve_points(address, fee_lbc)
     if reserved_points is None:
         raise InsufficientFundsError(
             'Unable to pay the key fee of %s for %s' % (dewies_to_lbc(fee_lbc), name)
         )
     return self.wallet.send_points_to_address(reserved_points, fee_lbc)
Пример #2
0
    async def parse_and_validate_claim_result(self,
                                              claim_result,
                                              certificate=None):
        if not claim_result or 'value' not in claim_result:
            return claim_result
        claim_result = _decode_claim_result(claim_result)

        if claim_result['value']:
            claim_result['has_signature'] = False
            if claim_result['value'].is_signed:
                claim_result['has_signature'] = True
                claim_tx = await self._fetch_tx(claim_result['txid'])
                if certificate is None:
                    log.info("fetching certificate to check claim signature")
                    channel_id = claim_result['value'].signing_channel_id
                    certificate = (await
                                   self.network.get_claims_by_ids(channel_id)
                                   ).get(channel_id)
                    if not certificate:
                        log.warning('Certificate %s not found', channel_id)
                claim_result['channel_name'] = certificate[
                    'name'] if certificate else None
                cert_tx = await self._fetch_tx(certificate['txid']
                                               ) if certificate else None
                claim_result[
                    'signature_is_valid'] = validate_claim_signature_and_get_channel_name(
                        claim_result,
                        certificate,
                        self.ledger,
                        claim_tx=claim_tx,
                        cert_tx=cert_tx)
                # fixme: workaround while json encoder isnt used here
                if cert_tx:
                    channel_txo = cert_tx.outputs[certificate['nout']]
                    claim_result['signing_channel'] = {
                        'name': channel_txo.claim_name,
                        'claim_id': channel_txo.claim_id,
                        'value': channel_txo.claim
                    }
                    claim_result['is_channel_signature_valid'] = claim_result[
                        'signature_is_valid']

        if 'amount' in claim_result:
            claim_result['amount'] = dewies_to_lbc(claim_result['amount'])
            claim_result['effective_amount'] = dewies_to_lbc(
                claim_result['effective_amount'])
            claim_result['supports'] = [{
                'txid': txid,
                'nout': nout,
                'amount': dewies_to_lbc(amount)
            } for (txid, nout, amount) in claim_result['supports']]

        claim_result['height'] = claim_result.get('height', -1) or -1
        claim_result[
            'permanent_url'] = f"lbry://{claim_result['name']}#{claim_result['claim_id']}"

        return claim_result
Пример #3
0
 def encode_transaction(self, tx):
     return {
         'txid': tx.id,
         'height': tx.height,
         'inputs': [self.encode_input(txo) for txo in tx.inputs],
         'outputs': [self.encode_output(txo) for txo in tx.outputs],
         'total_input': dewies_to_lbc(tx.input_sum),
         'total_output': dewies_to_lbc(tx.input_sum - tx.fee),
         'total_fee': dewies_to_lbc(tx.fee),
         'hex': hexlify(tx.raw).decode(),
     }
Пример #4
0
    def encode_output(self, txo):
        output = {
            'txid': txo.tx_ref.id,
            'nout': txo.position,
            'amount': dewies_to_lbc(txo.amount),
            'address': txo.get_address(self.ledger),
        }
        if txo.is_change is not None:
            output['is_change'] = txo.is_change
        if txo.is_my_account is not None:
            output['is_mine'] = txo.is_my_account

        if txo.script.is_claim_involved:
            output.update({
                'name': txo.claim_name,
                'claim_id': txo.claim_id,
                'permanent_url': txo.permanent_url,
                'is_claim': txo.script.is_claim_name,
                'is_support': txo.script.is_support_claim,
                'is_update': txo.script.is_update_claim
            })

            if txo.script.is_claim_name or txo.script.is_update_claim:
                output['value'] = txo.claim.claim_dict
                if txo.claim_name.startswith('@'):
                    output['has_signature'] = txo.has_signature

            if txo.script.is_claim_name:
                output['category'] = 'claim'
            elif txo.script.is_update_claim:
                output['category'] = 'update'
            elif txo.script.is_support_claim:
                output['category'] = 'support'

        return output
Пример #5
0
def format_amount_value(obj):
    if isinstance(obj, dict):
        for k, v in obj.items():
            if k in ('amount', 'effective_amount'):
                if not isinstance(obj[k], float):
                    obj[k] = dewies_to_lbc(obj[k])
            elif k == 'supports' and isinstance(v, list):
                obj[k] = [{
                    'txid': txid,
                    'nout': nout,
                    'amount': dewies_to_lbc(amount)
                } for (txid, nout, amount) in v]
            elif isinstance(v, (list, dict)):
                obj[k] = format_amount_value(v)
    elif isinstance(obj, list):
        obj = [format_amount_value(o) for o in obj]
    return obj
Пример #6
0
 def _format_support(outpoint, supported_id, amount, address):
     return {
         "txid": outpoint.split(":")[0],
         "nout": int(outpoint.split(":")[1]),
         "claim_id": supported_id,
         "amount": dewies_to_lbc(amount),
         "address": address,
     }
Пример #7
0
    def encode_output(self, txo, check_signature=True):
        tx_height = txo.tx_ref.height
        best_height = self.ledger.headers.height
        output = {
            'txid':
            txo.tx_ref.id,
            'nout':
            txo.position,
            'amount':
            dewies_to_lbc(txo.amount),
            'address':
            txo.get_address(self.ledger),
            'height':
            tx_height,
            'confirmations':
            (best_height + 1) - tx_height if tx_height > 0 else tx_height
        }
        if txo.is_change is not None:
            output['is_change'] = txo.is_change
        if txo.is_my_account is not None:
            output['is_mine'] = txo.is_my_account

        if txo.script.is_claim_involved:
            output.update({
                'name': txo.claim_name,
                'claim_id': txo.claim_id,
                'permanent_url': txo.permanent_url,
            })

            if txo.script.is_claim_name or txo.script.is_update_claim:
                claim = txo.claim
                output['value'] = claim
                if claim.is_signed:
                    output['valid_signature'] = None
                    if check_signature and txo.channel is not None:
                        output['channel_name'] = txo.channel.claim_name
                        try:
                            output['valid_signature'] = txo.is_signed_by(
                                txo.channel, self.ledger)
                        except BadSignatureError:
                            output['valid_signature'] = False
                        except ValueError:
                            log.exception(
                                'txo.id: %s, txo.channel.id:%s, output: %s',
                                txo.id, txo.channel.id, output)
                            output['valid_signature'] = False

            if txo.script.is_claim_name:
                output['type'] = 'claim'
            elif txo.script.is_update_claim:
                output['type'] = 'update'
            elif txo.script.is_support_claim:
                output['type'] = 'support'
            else:
                output['type'] = 'basic'

        return output
Пример #8
0
 def encode_claim_meta(self, meta):
     for key, value in meta.items():
         if key.endswith('_amount'):
             if isinstance(value, int):
                 meta[key] = dewies_to_lbc(value)
     if meta.get('creation_height', 0) > 0:
         meta['creation_timestamp'] = self.ledger.headers[
             meta['creation_height']]['timestamp']
     return meta
Пример #9
0
 def encode_output(self, txo):
     output = {
         'txid': txo.tx_ref.id,
         'nout': txo.position,
         'amount': dewies_to_lbc(txo.amount),
         'address': txo.get_address(self.ledger),
         'is_claim': txo.script.is_claim_name,
         'is_support': txo.script.is_support_claim,
         'is_update': txo.script.is_update_claim,
     }
     if txo.is_change is not None:
         output['is_change'] = txo.is_change
     return output
Пример #10
0
 async def _report_state(self):
     for account in self.accounts:
         total_receiving = len((await account.receiving.get_addresses()))
         total_change = len((await account.change.get_addresses()))
         channel_count = await account.get_channel_count()
         claim_count = await account.get_claim_count()
         balance = dewies_to_lbc(await account.get_balance())
         log.info(
             "Loaded account %s with %s LBC, %d receiving addresses (gap: %d), "
             "%d change addresses (gap: %d), %d channels, %d certificates and %d claims. ",
             account.id, balance, total_receiving, account.receiving.gap,
             total_change, account.change.gap, channel_count,
             len(account.channel_keys), claim_count)
Пример #11
0
 def as_dict(self) -> typing.Dict:
     return {
         "name": self.claim_name,
         "claim_id": self.claim_id,
         "address": self.claim_address,
         "claim_sequence": self.claim_sequence,
         "value": self.claim,
         "height": self.height,
         "amount": dewies_to_lbc(self.amount),
         "nout": self.nout,
         "txid": self.txid,
         "channel_claim_id": self.channel_claim_id,
         "channel_name": self.channel_name
     }
Пример #12
0
    def encode_output(self, txo):
        tx_height = txo.tx_ref.height
        best_height = self.ledger.headers.height
        output = {
            'txid': txo.tx_ref.id,
            'nout': txo.position,
            'amount': dewies_to_lbc(txo.amount),
            'address': txo.get_address(self.ledger),
            'height': tx_height,
            'confirmations': best_height - tx_height if tx_height > 0 else tx_height
        }
        if txo.is_change is not None:
            output['is_change'] = txo.is_change
        if txo.is_my_account is not None:
            output['is_mine'] = txo.is_my_account

        if txo.script.is_claim_involved:
            output.update({
                'name': txo.claim_name,
                'claim_id': txo.claim_id,
                'permanent_url': txo.permanent_url,
            })

            if txo.script.is_claim_name or txo.script.is_update_claim:
                claim = txo.claim
                output['value'] = claim.claim_dict
                if claim.has_signature:
                    output['valid_signature'] = None
                    if txo.channel is not None:
                        output['valid_signature'] = claim.validate_signature(
                            txo.get_address(self.ledger), txo.channel.claim
                        )

            if txo.script.is_claim_name:
                output['type'] = 'claim'
            elif txo.script.is_update_claim:
                output['type'] = 'update'
            elif txo.script.is_support_claim:
                output['type'] = 'support'
            else:
                output['type'] = 'basic'

            # deprecated, will be removed after 0.30 release
            output['category'] = output['type']

        return output
Пример #13
0
def calculate_effective_amount(
        amount: str,
        supports: typing.Optional[typing.List[typing.Dict]] = None) -> str:
    return dewies_to_lbc(
        lbc_to_dewies(amount) +
        sum([lbc_to_dewies(support['amount']) for support in supports]))
Пример #14
0
    def encode_output(self, txo, check_signature=True, include_meta=True):
        tx_height = txo.tx_ref.height
        best_height = self.ledger.headers.height
        output = {
            'txid':
            txo.tx_ref.id,
            'nout':
            txo.position,
            'height':
            tx_height,
            'amount':
            dewies_to_lbc(txo.amount),
            'address':
            txo.get_address(self.ledger),
            'confirmations':
            (best_height + 1) - tx_height if tx_height > 0 else tx_height,
            'timestamp':
            self.ledger.headers[tx_height]['timestamp']
            if tx_height > 0 else None
        }
        if txo.is_change is not None:
            output['is_change'] = txo.is_change
        if txo.is_my_account is not None:
            output['is_mine'] = txo.is_my_account

        if txo.script.is_claim_name:
            output['type'] = 'claim'
            output['claim_op'] = 'create'
        elif txo.script.is_update_claim:
            output['type'] = 'claim'
            output['claim_op'] = 'update'
        elif txo.script.is_support_claim:
            output['type'] = 'support'
        else:
            output['type'] = 'payment'

        if txo.script.is_claim_involved:
            output.update({
                'name': txo.claim_name,
                'normalized': txo.normalized_name,
                'claim_id': txo.claim_id,
                'permanent_url': txo.permanent_url
            })
            if include_meta:
                output['meta'] = self.encode_claim_meta(txo.meta)
            if txo.script.is_claim_name or txo.script.is_update_claim:
                try:
                    output['value'] = txo.claim
                    output['value_type'] = txo.claim.claim_type
                    if self.include_protobuf:
                        output['protobuf'] = hexlify(txo.claim.to_bytes())
                    if txo.channel is not None:
                        output['signing_channel'] = self.encode_output(
                            txo.channel, include_meta=False)
                        if check_signature and txo.claim.is_signed:
                            output['is_channel_signature_valid'] = False
                            if txo.channel:
                                output[
                                    'is_channel_signature_valid'] = txo.is_signed_by(
                                        txo.channel, self.ledger)
                except DecodeError:
                    pass
        return output
Пример #15
0
    def encode_output(self, txo, check_signature=True):
        tx_height = txo.tx_ref.height
        best_height = self.ledger.headers.height
        output = {
            'txid':
            txo.tx_ref.id,
            'nout':
            txo.position,
            'height':
            tx_height,
            'amount':
            dewies_to_lbc(txo.amount),
            'address':
            txo.get_address(self.ledger),
            'confirmations':
            (best_height + 1) - tx_height if tx_height > 0 else tx_height
        }
        if txo.is_change is not None:
            output['is_change'] = txo.is_change
        if txo.is_my_account is not None:
            output['is_mine'] = txo.is_my_account

        if txo.script.is_claim_name:
            output['type'] = 'claim'
            output['claim_op'] = 'create'
        elif txo.script.is_update_claim:
            output['type'] = 'claim'
            output['claim_op'] = 'update'
        elif txo.script.is_support_claim:
            output['type'] = 'support'
        else:
            output['type'] = 'payment'

        if txo.script.is_claim_involved:
            output.update({
                'name': txo.claim_name,
                'claim_id': txo.claim_id,
                'permanent_url': txo.permanent_url,
            })
            if txo.script.is_claim_name or txo.script.is_update_claim:
                output['value'] = txo.claim
                output['value_type'] = txo.claim.claim_type
                if self.include_protobuf:
                    output['protobuf'] = hexlify(txo.claim.to_bytes())
                if txo.channel is not None:
                    output['signing_channel'] = {
                        'name': txo.channel.claim_name,
                        'claim_id': txo.channel.claim_id,
                        'value': txo.channel.claim
                    }
                    if check_signature and txo.claim.is_signed:
                        output['is_channel_signature_valid'] = False
                        try:
                            output[
                                'is_channel_signature_valid'] = txo.is_signed_by(
                                    txo.channel, self.ledger)
                        except BadSignatureError:
                            pass
                        except ValueError:
                            log.exception(
                                'txo.id: %s, txo.channel.id:%s, output: %s',
                                txo.id, txo.channel.id, output)
        return output
Пример #16
0
 def encode_claim_meta(self, meta):
     for key, value in meta.items():
         if key.endswith('_amount'):
             if isinstance(value, int):
                 meta[key] = dewies_to_lbc(value)
     return meta
Пример #17
0
 async def get_history(account: BaseAccount, **constraints):
     headers = account.ledger.headers
     txs = await account.get_transactions(**constraints)
     history = []
     for tx in txs:
         ts = headers[tx.height]['timestamp'] if tx.height > 0 else None
         item = {
             'txid':
             tx.id,
             'timestamp':
             ts,
             'date':
             datetime.fromtimestamp(ts).isoformat(' ')[:-3]
             if tx.height > 0 else None,
             'confirmations':
             (headers.height + 1) - tx.height if tx.height > 0 else 0,
             'claim_info': [],
             'update_info': [],
             'support_info': [],
             'abandon_info': []
         }
         is_my_inputs = all([txi.is_my_account for txi in tx.inputs])
         if is_my_inputs:
             # fees only matter if we are the ones paying them
             item['value'] = dewies_to_lbc(tx.net_account_balance + tx.fee)
             item['fee'] = dewies_to_lbc(-tx.fee)
         else:
             # someone else paid the fees
             item['value'] = dewies_to_lbc(tx.net_account_balance)
             item['fee'] = '0.0'
         for txo in tx.my_claim_outputs:
             item['claim_info'].append({
                 'address':
                 txo.get_address(account.ledger),
                 'balance_delta':
                 dewies_to_lbc(-txo.amount),
                 'amount':
                 dewies_to_lbc(txo.amount),
                 'claim_id':
                 txo.claim_id,
                 'claim_name':
                 txo.claim_name,
                 'nout':
                 txo.position
             })
         for txo in tx.my_update_outputs:
             if is_my_inputs:  # updating my own claim
                 previous = None
                 for txi in tx.inputs:
                     if txi.txo_ref.txo is not None:
                         other_txo = txi.txo_ref.txo
                         if (other_txo.is_claim or other_txo.script.is_support_claim) \
                                 and other_txo.claim_id == txo.claim_id:
                             previous = other_txo
                             break
                 if previous is not None:
                     item['update_info'].append({
                         'address':
                         txo.get_address(account.ledger),
                         'balance_delta':
                         dewies_to_lbc(previous.amount - txo.amount),
                         'amount':
                         dewies_to_lbc(txo.amount),
                         'claim_id':
                         txo.claim_id,
                         'claim_name':
                         txo.claim_name,
                         'nout':
                         txo.position
                     })
             else:  # someone sent us their claim
                 item['update_info'].append({
                     'address':
                     txo.get_address(account.ledger),
                     'balance_delta':
                     dewies_to_lbc(0),
                     'amount':
                     dewies_to_lbc(txo.amount),
                     'claim_id':
                     txo.claim_id,
                     'claim_name':
                     txo.claim_name,
                     'nout':
                     txo.position
                 })
         for txo in tx.my_support_outputs:
             item['support_info'].append({
                 'address':
                 txo.get_address(account.ledger),
                 'balance_delta':
                 dewies_to_lbc(
                     txo.amount if not is_my_inputs else -txo.amount),
                 'amount':
                 dewies_to_lbc(txo.amount),
                 'claim_id':
                 txo.claim_id,
                 'claim_name':
                 txo.claim_name,
                 'is_tip':
                 not is_my_inputs,
                 'nout':
                 txo.position
             })
         if is_my_inputs:
             for txo in tx.other_support_outputs:
                 item['support_info'].append({
                     'address':
                     txo.get_address(account.ledger),
                     'balance_delta':
                     dewies_to_lbc(-txo.amount),
                     'amount':
                     dewies_to_lbc(txo.amount),
                     'claim_id':
                     txo.claim_id,
                     'claim_name':
                     txo.claim_name,
                     'is_tip':
                     is_my_inputs,
                     'nout':
                     txo.position
                 })
         for txo in tx.my_abandon_outputs:
             item['abandon_info'].append({
                 'address':
                 txo.get_address(account.ledger),
                 'balance_delta':
                 dewies_to_lbc(txo.amount),
                 'amount':
                 dewies_to_lbc(txo.amount),
                 'claim_id':
                 txo.claim_id,
                 'claim_name':
                 txo.claim_name,
                 'nout':
                 txo.position
             })
         history.append(item)
     return history