Beispiel #1
0
    def check_nonce(cls, nonce, channel_name=''):
        """

        :param channel_name:
        :param nonce:
        :return:
        """
        new_nonce = Channel.new_nonce(channel_name)

        if not (TransactionBase._FOUNDER_NONCE < int(nonce) == new_nonce):
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_WITH_INCOMPATIBLE_NONCE,
                '{}::Channel<{}> has incompatible nonce<self: {}, peer: {}>'.
                format(cls.__name__, channel_name, new_nonce, nonce))
        else:
            return True, new_nonce
Beispiel #2
0
    def create(cls,
               channel_name,
               asset_type,
               sender,
               receiver,
               payment,
               hashcode,
               router,
               current_channel=None,
               comments=None):
        """

        :param channel_name:
        :param asset_type:
        :param sender:
        :param receiver:
        :param payment:
        :param hashcode:
        :param router:
        :param current_channel:
        :param comments:
        :return:
        """
        cls.check_channel_state(channel_name)
        cls.check_router(router, hashcode)
        cls.check_asset_type(asset_type)
        cls.check_both_urls(sender, receiver)

        payer_address, _, _ = uri_parser(sender)
        payee_address, _, _ = uri_parser(receiver)
        asset_type = asset_type.upper()
        channel = Channel(channel_name)

        # get nonce
        nonce = Channel.new_nonce(channel_name)
        if HtlcMessage._FOUNDER_NONCE > nonce:
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE,
                'HtlcMessage::create: Incorrect nonce<{}> for channel<{}>'.
                format(nonce, channel_name))

        # to check whether previous transaction need be resigned or not
        resign_body, valid_trade = HtlcMessage.create_resign_message_body(
            sender, channel_name, nonce)

        # there're one trade need resign, we need adjust the nonce value
        if valid_trade and valid_trade.state in [
                EnumTradeState.confirming.name
        ]:
            payer_balance = valid_trade.balance
            payee_balance = valid_trade.peer_balance
        else:
            # to get channel balance
            balance = channel.balance
            payer_balance = balance.get(payer_address).get(asset_type)
            payee_balance = balance.get(payee_address).get(asset_type)

        # To calculate the balance after payment
        _, payer_balance, payee_balance = HtlcMessage.calculate_balance_after_payment(
            payer_balance, payee_balance, payment, is_htlc_type=True)

        # exclude current router from the router
        end_block_height = cls.get_unlocked_block_height(len(router))

        # generate htlc transaction and record it into database later
        htlc_trade = Channel.htlc_trade(type=EnumTradeType.TRADE_TYPE_HTLC,
                                        role=EnumTradeRole.TRADE_ROLE_FOUNDER,
                                        asset_type=asset_type,
                                        balance=payer_balance,
                                        peer_balance=payee_balance,
                                        payment=payment,
                                        hashcode=hashcode,
                                        delay_block=end_block_height)

        # record the channel if RResponse is triggered
        if current_channel:
            htlc_trade.update({'channel': current_channel})

        # create message
        htlc_request = HtlcMessage.request(payer_balance, payee_balance,
                                           payment, hashcode, end_block_height)
        # has transaction which is needed to be resigned
        if resign_body:
            htlc_request.update({'ResignBody': resign_body})

        # start to create message  and send later
        message = HtlcMessage.create_message_header(sender, receiver,
                                                    HtlcMessage._message_name,
                                                    channel_name, asset_type,
                                                    nonce)
        message.update({'Router': router})
        message.update({'MessageBody': htlc_request})

        if comments:
            message.update({'Comments': comments})

        HtlcMessage.send(message)

        # record the transaction
        Channel.add_trade(channel_name, nonce=nonce, **htlc_trade)

        return None
Beispiel #3
0
    def create(channel_name,
               asset_type,
               sender,
               receiver,
               payment,
               hashcode=None,
               comments=None):
        """

        :param channel_name:
        :param asset_type:
        :param sender:
        :param receiver:
        :param payment:
        :param hashcode:
        :param comments:
        :param hlock_to_rsmc:
        :return:
        """
        # check channel state
        RsmcMessage.check_asset_type(asset_type)
        channel = RsmcMessage.check_channel_state(channel_name)

        # get nonce in the offline account book
        nonce = Channel.new_nonce(channel_name)
        if RsmcMessage._FOUNDER_NONCE > nonce:
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE,
                'RsmcMessage::create: Incorrect nonce<{}> for channel<{}>'.
                format(nonce, channel_name))

        # to get channel balance
        balance = channel.balance
        payer_address, _, _ = uri_parser(sender)
        payee_address, _, _ = uri_parser(receiver)
        asset_type = asset_type.upper()

        # judge whether it is htlc lock part to rsmc trade or not
        hlock_to_rsmc = RsmcMessage.is_hlock_to_rsmc(hashcode)
        _, payer_balance, payee_balance = RsmcBase.calculate_balance_after_payment(
            balance.get(payer_address).get(asset_type),
            balance.get(payee_address).get(asset_type),
            payment,
            hlock_to_rsmc=hlock_to_rsmc)

        # create message
        message_body = {
            'AssetType': asset_type.upper(),
            'PaymentCount': str(payment),
            'SenderBalance': str(payer_balance),
            'ReceiverBalance': str(payee_balance),
        }

        if hlock_to_rsmc:
            message_body.update({'HashR': hashcode})

        # start to create message
        message = RsmcMessage.create_message_header(sender, receiver,
                                                    RsmcMessage._message_name,
                                                    channel_name, asset_type,
                                                    nonce)
        message = message.message_header
        message.update({'MessageBody': message_body})
        if comments:
            message.update({'Comments': comments})

        RsmcMessage.send(message)

        return None
Beispiel #4
0
    def create(channel_name, asset_type, sender, receiver, payment, hashcode=None, comments=None):
        """

        :param channel_name:
        :param asset_type:
        :param sender:
        :param receiver:
        :param payment:
        :param hashcode:
        :param comments:
        :param hlock_to_rsmc:
        :return:
        """
        # check channel state
        RsmcMessage.check_asset_type(asset_type)
        channel = RsmcMessage.check_channel_state(channel_name)
        payer_address, _, _ = uri_parser(sender)
        payee_address, _, _ = uri_parser(receiver)
        asset_type = asset_type.upper()
        resign_body = None

        # get nonce in the offline account book
        nonce = Channel.new_nonce(channel_name)
        if RsmcMessage._FOUNDER_NONCE > nonce:
            raise GoTo(EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE,
                       'RsmcMessage::create: Incorrect nonce<{}> for channel<{}>'.format(nonce, channel_name))

        # to check whether there's a transaction which is needed to resign
        resign_body, valid_trade = RsmcMessage.create_resign_message_body(sender, channel_name, nonce)

        # there're one trade need resign, we need adjust the nonce value
        if valid_trade and valid_trade.state in [EnumTradeState.confirming.name]:
            payer_balance = valid_trade.balance
            payee_balance = valid_trade.peer_balance
        else:
            # to get channel balance
            balance = channel.balance
            payer_balance = balance.get(payer_address).get(asset_type)
            payee_balance = balance.get(payee_address).get(asset_type)

        # judge whether it is htlc lock part to rsmc trade or not
        hlock_to_rsmc = RsmcMessage.is_hlock_to_rsmc(hashcode)
        _, payer_balance, payee_balance = RsmcBase.calculate_balance_after_payment(
            payer_balance, payee_balance, payment, hlock_to_rsmc=hlock_to_rsmc
        )

        # sign the trade
        sign_hashcode, sign_rcode = RsmcMessage.get_rcode(channel_name, hashcode)
        rsmc_trade = Channel.rsmc_trade(
            type=EnumTradeType.TRADE_TYPE_RSMC, role=EnumTradeRole.TRADE_ROLE_FOUNDER, asset_type=asset_type,
            balance=payer_balance, peer_balance=payee_balance, payment=payment,
            hashcode=sign_hashcode, rcode=sign_rcode
        )

        # create message
        rsmc_request = RsmcMessage.request(asset_type, payment, payer_balance, payee_balance, hashcode)
        # has transaction which is needed to be resigned
        if resign_body:
            rsmc_request.update({'ResignBody': resign_body})

        # start to create message
        message = RsmcMessage.create_message_header(sender, receiver, RsmcMessage._message_name,
                                                    channel_name, asset_type, nonce)
        message.update({'MessageBody': rsmc_request})
        if comments:
            message.update({'Comments': comments})

        RsmcMessage.send(message)

        # record the transaction
        Channel.add_trade(channel_name, nonce=nonce, **rsmc_trade)
        APIStatistics.update_statistics(payer_address, rsmc='rsmc')

        return None
Beispiel #5
0
    def create(cls,
               wallet,
               channel_name,
               asset_type,
               sender,
               receiver,
               payment,
               hashcode,
               router,
               next_router,
               current_channel=None,
               comments=None):
        """

        :param channel_name:
        :param wallet:
        :param sender:
        :param receiver:
        :param asset_type:
        :param payment:
        :param nonce:
        :param hashcode:
        :param router:
        :param next_router:
        :param comments:
        :return:
        """
        cls.check_channel_state(channel_name)
        cls.check_router(router, hashcode)
        cls.check_asset_type(asset_type)
        cls.check_both_urls(sender, receiver)
        cls.check_router(router, hashcode)

        # get nonce
        nonce = Channel.new_nonce(channel_name)
        if HtlcMessage._FOUNDER_NONCE > nonce:
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE,
                'HtlcMessage::create: Incorrect nonce<{}> for channel<{}>'.
                format(nonce, channel_name))

        # get sender & receiver address from sender or receiver
        payer_address, _, _ = uri_parser(sender)
        payee_address, _, _ = uri_parser(receiver)
        asset_type = asset_type.upper()

        # check whether the balance is enough or not
        channel = Channel(channel_name)
        balance = channel.balance
        _, payer_balance, payee_balance = HtlcMessage.calculate_balance_after_payment(
            balance.get(payer_address, {}).get(asset_type),
            balance.get(payee_address, {}).get(asset_type),
            payment,
            is_htlc_type=True)

        # calculate the end block height
        jumps_index = HtlcMessage.this_jump(sender, router)
        end_block_height = cls.get_locked_block_height(len(router),
                                                       jumps_index)

        # Htlc is made up of 2 parts: rsmc and hlock part
        sign_hashcode, sign_rcode = cls.get_default_rcode()
        rsmc_commitment = HtlcMessage.sign_content(
            typeList=RsmcMessage._sign_type_list,
            valueList=[
                channel_name, nonce, payer_address, payer_balance,
                payee_address, payee_balance, sign_hashcode, sign_rcode
            ],
            privtKey=wallet._key.private_key_string)

        # hlock parts
        hlock_commitment = HtlcMessage.sign_content(
            start=5,
            typeList=HtlcMessage._sign_type_list,
            valueList=[
                channel_name, payer_address, payee_address, end_block_height,
                int(payment), hashcode
            ],
            privtKey=wallet._key.private_key_string)

        # # add trade to database
        htlc_trade = Channel.htlc_trade(type=EnumTradeType.TRADE_TYPE_HTLC,
                                        role=EnumTradeRole.TRADE_ROLE_FOUNDER,
                                        asset_type=asset_type,
                                        balance=payer_balance,
                                        peer_balance=payee_balance,
                                        payment=payment,
                                        hashcode=hashcode,
                                        delay_block=end_block_height,
                                        commitment=rsmc_commitment,
                                        delay_commitment=hlock_commitment)
        if current_channel:
            htlc_trade.update({'channel': current_channel})
        Channel.add_trade(channel_name, nonce=nonce, **htlc_trade)

        # generate the messages
        message_body = {
            'SenderBalance': payer_balance,
            'ReceiverBalance': payee_balance,
            'Commitment': rsmc_commitment,
            'Payment': payment,
            'DelayBlock': end_block_height,
            'DelayCommitment': hlock_commitment,
            'HashR': hashcode
        }

        message = HtlcMessage.create_message_header(sender, receiver,
                                                    HtlcMessage._message_name,
                                                    channel_name, asset_type,
                                                    nonce)
        message = message.message_header
        message.update({
            'Router': router,
            'Next': next_router,
        })
        message.update({'MessageBody': message_body})

        if comments:
            message.update({'Comments': comments})

        HtlcMessage.send(message)

        return None