Пример #1
0
    def handle_partner_response(self):
        """

        :return: response to send to peer
        """
        # local variables
        need_update_balance = False
        is_htlc_to_rsmc = self.is_hlock_to_rsmc(self.hashcode)

        # handle the resign body firstly
        resign_ack = None
        if self.resign_body:
            resign_ack, resign_trade = self.handle_resign_body(self.wallet, self.channel_name, self.resign_body)

            # here if the peer not provide the signature, we need re-calculate the balance
            if not self.commitment:
                _, self.sender_balance, self.receiver_balance = self.calculate_balance_after_payment(
                    resign_trade.balance, resign_trade.peer_balance, self.payment, is_htlc_to_rsmc
                )

        # to check whether the negotiated nonce is legal or not
        self.validate_negotiated_nonce()

        # create RSMC response message with RoleIndex==1
        rsmc_sign_body = self.response(self.asset_type, self.payment, self.sender_balance, self.receiver_balance,
                                       1, self.hashcode)

        # get some common local variables
        sign_hashcode, sign_rcode = self.get_rcode(self.channel_name, self.hashcode)
        payer_balance = int(self.sender_balance)
        payee_balance = int(self.receiver_balance)
        payment = int(self.payment)
        # use this nonce for following message of current transaction
        nonce = self.nego_nonce or self.nonce

        # if negotiated nonce by peer, delete the transaction with self.nonce
        if nonce != self.nonce:
            # generate the rsmc trade part
            rsmc_trade = Channel.rsmc_trade(
                type=EnumTradeType.TRADE_TYPE_RSMC, role=EnumTradeRole.TRADE_ROLE_FOUNDER,
                asset_type=self.asset_type, balance=payer_balance, peer_balance=payee_balance, payment=payment,
                hashcode=sign_hashcode, rcode=sign_rcode
            )
            self.record_transaction(nonce, **rsmc_trade)

            if nonce < self.nonce:
                Channel.delete_trade(self.channel_name, self.nonce)

        # query the trade by nonce
        current_trade = Channel.query_trade(self.channel_name, nonce)
        if current_trade.commitment:
            # It means that the transaction is already signed during resign
            # previous transaction record.
            commitment = current_trade.commitment
        else:
            # start to sign this new transaction and save it
            # check balance
            self.check_balance(self.channel_name, self.asset_type, self.payer_address, payer_balance,
                               self.payee_address, payee_balance, hlock_to_rsmc=is_htlc_to_rsmc, payment=payment)

            # sign the transaction
            commitment = RsmcResponsesMessage.sign_content(
                self.wallet, self._sign_type_list, [self.channel_name, nonce, self.payer_address, payer_balance,
                                                    self.payee_address, payee_balance, sign_hashcode, sign_rcode]
            )

            # update the transaction
            Channel.update_trade(self.channel_name, nonce, commitment=commitment)

        # peer has already sign the new transaction with nonce
        if self.commitment:
            # check the signature
            self.check_signature(
                self.wallet, self.sender_address,
                type_list=self._sign_type_list,
                value_list=[self.channel_name, nonce, self.payer_address, int(self.sender_balance),
                            self.payee_address, int(self.receiver_balance), sign_hashcode, sign_rcode],
                signature=self.commitment
            )

            # update this trade confirmed state
            Channel.update_trade(
                self.channel_name, nonce, peer_commitment=self.commitment,
                state=EnumTradeState.confirmed.name
            )
            need_update_balance = True

            rsmc_sign_body.update({'Commitment': commitment})

        # has resign response ??
        if resign_ack:
            rsmc_sign_body.update({'ResignBody': resign_ack})

        return need_update_balance, rsmc_sign_body
Пример #2
0
    def handle(self):
        super(RsmcMessage, self).handle()

        status = EnumResponseStatus.RESPONSE_OK
        resign_ack = None
        resign_request = None
        try:
            # common check
            self.check_channel_state(self.channel_name)
            self.verify()

            # resign request by peer ??
            if self.resign_body:
                resign_ack, nego_trade = self.handle_resign_body(self.wallet, self.channel_name, self.resign_body)
            else:
                # check whether need resign previous transaction
                resign_request, nego_trade = self.create_resign_message_body(self.wallet.url, self.channel_name, self.nonce)

            # real nonce
            nego_nonce = nego_trade and (nego_trade.nonce+1)
            nonce = nego_nonce or self.nonce

            rsmc_sign_body = self.response(self.asset_type, self.payment, self.sender_balance, self.receiver_balance,
                                           self.rsmc_sign_role, self.hashcode)

            # record the transaction without any signature
            sign_hashcode, sign_rcode = self.get_rcode(self.channel_name, self.hashcode)
            rsmc_trade = Channel.rsmc_trade(
                type=EnumTradeType.TRADE_TYPE_RSMC, role=EnumTradeRole.TRADE_ROLE_PARTNER, asset_type=self.asset_type,
                balance=self.receiver_balance, peer_balance=self.sender_balance, payment=self.payment,
                hashcode=sign_hashcode, rcode=sign_rcode
            )

            # if need resign, just send resign message body
            if resign_request:
                # add resign body to message body
                rsmc_sign_body.update({'ResignBody': resign_request})
            else:
                # check the balance
                htlc_to_rsmc = self.is_hlock_to_rsmc(self.hashcode)
                _, payer_balance, payee_balance = self.check_balance(
                    self.channel_name, self.asset_type, self.payer_address, self.sender_balance,
                    self.payee_address, self.receiver_balance, hlock_to_rsmc=htlc_to_rsmc, payment=self.payment
                )

                # sign the trade
                commitment = RsmcResponsesMessage.sign_content(
                    self.wallet, RsmcMessage._sign_type_list, [self.channel_name, nonce, self.payer_address,
                                                               payer_balance, self.payee_address, payee_balance,
                                                               sign_hashcode, sign_rcode]
                )

                # update the rsmc_trade
                rsmc_trade.update({'commitment': commitment, 'state':EnumTradeState.confirming.name})

                # update the message body with signature
                rsmc_sign_body.update({'Commitment': commitment})

                # add resign ack
                if resign_ack:
                    rsmc_sign_body.update({'ResignBody': resign_ack})

            # Response message header
            response_message = RsmcResponsesMessage.create_message_header(
                self.receiver, self.sender, RsmcResponsesMessage._message_name, self.channel_name, self.asset_type,
                self.nonce, nonce
            )
            response_message.update({'MessageBody': rsmc_sign_body})
            response_message.update({'Status': status.name})
            self.send(response_message)

            # record the transaction
            self.record_transaction(nonce, **rsmc_trade)
            APIStatistics.update_statistics(self.wallet.address, rsmc='rsmc')
        except TrinityException as error:
            status = error.reason
            LOG.exception(error)
        except Exception as error:
            status = EnumResponseStatus.RESPONSE_EXCEPTION_HAPPENED
            LOG.exception('Failed to handle RsmcMessage. Exception: {}'.format(error))
        finally:
            if EnumResponseStatus.RESPONSE_OK != status:
                # nofify error response
                RsmcResponsesMessage.send_error_response(self.sender, self.receiver, self.channel_name, self.asset_type,
                                                         self.nonce, status)

        return
Пример #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)
        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
Пример #4
0
    def rsmc_sign(cls,
                  wallet,
                  channel_name,
                  asset_type,
                  nonce,
                  sender,
                  receiver,
                  payment,
                  sender_balance,
                  receiver_balance,
                  role_index=0,
                  hashcode=None,
                  comments=None):
        """
        Descriptions: create and send RsmcSign messages.
        :param wallet:
        :param channel_name:
        :param asset_type:
        :param nonce:
        :param sender:
        :param receiver:
        :param payment:
        :param sender_balance:
        :param receiver_balance:
        :param role_index:
        :param comments:
        :param hashcode:
        :return:
        """
        asset_type = asset_type.upper()

        # different ROLE by role index
        role_index = int(role_index)
        payer, payee = RsmcMessage.get_payer_and_payee(role_index, sender,
                                                       receiver)
        payer_address, _, _ = uri_parser(payer)
        payee_address, _, _ = uri_parser(payee)

        # check balance
        is_hlock_to_rsmc = RsmcResponsesMessage.is_hlock_to_rsmc(hashcode)
        _, payer_balance, payee_balance = RsmcResponsesMessage.check_balance(
            channel_name,
            asset_type,
            payer_address,
            sender_balance,
            payee_address,
            receiver_balance,
            hlock_to_rsmc=is_hlock_to_rsmc,
            payment=payment)

        # sign the trade
        sign_hashcode, sign_rcode = cls.get_rcode(channel_name, hashcode)
        commitment = RsmcResponsesMessage.sign_content(
            typeList=RsmcResponsesMessage._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)

        # add trade to database
        if 0 == role_index:
            trade_role = EnumTradeRole.TRADE_ROLE_PARTNER
            self_balance = payee_balance
            peer_balance = payer_balance
        else:
            trade_role = EnumTradeRole.TRADE_ROLE_FOUNDER
            self_balance = payer_balance
            peer_balance = payee_balance

        # ToDo: need re-sign all unconfirmed htlc message later
        rsmc_trade = Channel.rsmc_trade(type=EnumTradeType.TRADE_TYPE_RSMC,
                                        role=trade_role,
                                        asset_type=asset_type,
                                        balance=self_balance,
                                        peer_balance=peer_balance,
                                        payment=payment,
                                        hashcode=sign_hashcode,
                                        rcode=sign_rcode,
                                        commitment=commitment)
        Channel.add_trade(channel_name, nonce=nonce, **rsmc_trade)

        # update message body
        message_body = {
            'AssetType': asset_type.upper(),
            'PaymentCount': str(payment),
            'SenderBalance': str(payer_balance),
            'ReceiverBalance': str(payee_balance),
            'Commitment': commitment,
            'RoleIndex': str(role_index),
        }

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

        # generate the message header
        message = RsmcResponsesMessage.create_message_header(
            receiver, sender, RsmcResponsesMessage._message_name, channel_name,
            asset_type, nonce)
        message = message.message_header

        # to send response OK message
        message.update({'MessageBody': message_body})
        message.update({'Status': EnumResponseStatus.RESPONSE_OK.name})
        if comments:
            message.update({'Comments': comments})

        # send RsmcSign message
        RsmcResponsesMessage.send(message)

        return