Esempio n. 1
0
    def notify_rcode_to_next_peer(self, next_channel):
        """

        :param next_channel:
        :return:
        """
        peer = None
        try:
            # original payer is found
            if not next_channel:
                LOG.info('HTLC Founder with HashR<{}> received the R-code<{}>'.
                         format(self.hashcode, self.rcode))
                return

            htlc_trade = self.get_htlc_trade_by_hashr(next_channel,
                                                      self.hashcode)
            if next_channel != htlc_trade.channel:
                LOG.error('Why the channel is different. next_channel<{}>, stored channel<{}>' \
                          .format(next_channel, htlc_trade.channel))

            # notify the previous node the R-code
            LOG.debug('Payment get channel {}/{}'.format(
                next_channel, self.hashcode))
            channel = Channel(next_channel)
            peer = channel.peer_uri(self.wallet.url)
            nonce = channel.latest_nonce(next_channel)
            LOG.info("Next peer: {}".format(peer))
            self.create(next_channel, self.asset_type, nonce, self.wallet.url,
                        peer, self.hashcode, self.rcode, self.comments)
        except Exception as error:
            LOG.error('Failed to notify RCode<{}> to peer<{}>'.format(
                self.rcode, peer))
Esempio n. 2
0
    def notify_rcode_to_next_peer(self, next_channel):
        """

        :param next_channel:
        :return:
        """
        peer = None
        try:
            # original payer is found
            if not next_channel or next_channel == self.channel_name:
                LOG.info('HTLC Founder with HashR<{}> received the R-code<{}>'.
                         format(self.hashcode, self.rcode))
                return

            htlc_trade = self.get_htlc_trade_by_hashr(next_channel,
                                                      self.hashcode)
            if htlc_trade.role == EnumTradeRole.TRADE_ROLE_PARTNER.name and next_channel != htlc_trade.channel:
                LOG.warning(
                    'Why the channel is different. next_channel<{}>, stored channel<{}>'
                    .format(next_channel, htlc_trade.channel))

            # notify the previous node the R-code
            LOG.debug('Payment get channel {}/{}'.format(
                next_channel, self.hashcode))
            channel = Channel(next_channel)
            channel.update_trade(next_channel,
                                 htlc_trade.nonce,
                                 rcode=self.rcode)
            peer = channel.peer_uri(self.wallet.url)
            nonce = channel.latest_nonce(next_channel)
            LOG.info("Next peer: {}".format(peer))
            self.create(next_channel, self.asset_type, nonce, self.wallet.url,
                        peer, self.hashcode, self.rcode, self.comments)

            APIStatistics.update_statistics(self.wallet.address,
                                            htlc_rcode=True)
        except Exception as error:
            LOG.error('Failed to notify RCode<{}> to peer<{}>'.format(
                self.rcode, peer))
Esempio n. 3
0
    def handle_resign_body(cls, wallet, channel_name, resign_body):
        """"""
        if not resign_body:
            return None

        if not (wallet and channel_name):
            raise GoTo(
                EnumResponseStatus.RESPONSE_ILLEGAL_INPUT_PARAMETER,
                'Void wallet<{}> or Illegal channel name<{}>'.format(
                    wallet, channel_name))

        resign_nonce = int(resign_body.get('Nonce'))
        update_channel_db = {}
        update_trade_db = {}

        # get transaction by the resign_nonce
        resign_trade = Channel.query_trade(channel_name, resign_nonce)
        asset_type = resign_trade.asset_type

        channel = Channel(channel_name)
        self_address, _, _ = uri_parser(wallet.url)
        peer_address, _, _ = uri_parser(channel.peer_uri(wallet.url))

        # Is this wallet sender side of this trade ?????
        if EnumTradeRole.TRADE_ROLE_PARTNER.name == resign_trade.role:
            payer_address = peer_address
            payee_address = self_address
            payer_balance = resign_trade.peer_balance
            payee_balance = resign_trade.balance
        elif EnumTradeRole.TRADE_ROLE_FOUNDER.name == resign_trade.role:
            payer_address = self_address
            payee_address = peer_address
            payer_balance = resign_trade.balance
            payee_balance = resign_trade.peer_balance
        else:
            raise GoTo(
                EnumResponseStatus.RESPONSE_DATABASE_ERROR_TRADE_ROLE,
                'Error trade role<{}> for nonce<{}>'.format(
                    resign_trade.role, resign_nonce))

        if EnumTradeType.TRADE_TYPE_HTLC.name == resign_trade.type:
            rsmc_sign_hashcode, rsmc_sign_rcode = cls.get_default_rcode()
        elif EnumTradeType.TRADE_TYPE_RSMC.name == resign_trade.type:
            rsmc_sign_hashcode, rsmc_sign_rcode = resign_trade.hashcode, resign_trade.rcode
        else:
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_RESIGN_NOT_SUPPORTED_TYPE,
                'Only support HTLC and RSMC resign. Current transaction type: {}'
                .format(resign_trade.type))

        rsmc_list = [
            channel_name, resign_nonce, payer_address,
            int(payer_balance), payee_address,
            int(payee_balance), rsmc_sign_hashcode, rsmc_sign_rcode
        ]

        # self commitment is None
        if not resign_trade.commitment:
            commitment = cls.sign_content(wallet, cls._rsmc_sign_type_list,
                                          rsmc_list)
            update_trade_db.update({'commitment': commitment})

        # self lock commitment is none
        htlc_list = None
        if EnumTradeType.TRADE_TYPE_HTLC.name == resign_trade.type:
            htlc_list = [
                channel_name, payer_address, payee_address,
                int(resign_trade.delay_block),
                int(resign_trade.payment), resign_trade.hashcode
            ]
            delay_commitment = cls.sign_content(wallet,
                                                cls._htlc_sign_type_list,
                                                htlc_list)
            update_trade_db.update({'delay_commitment': delay_commitment})

        # check whether the trade need update or not
        if resign_trade.state not in [
                EnumTradeState.confirmed.name,
                EnumTradeState.confirmed_onchain.name
        ]:
            peer_commitment = resign_body.get('Commitment')
            peer_delay_commitment = resign_body.get('DelayCommitment')

            # check peer signature
            cls.check_signature(wallet, peer_address, cls._rsmc_sign_type_list,
                                rsmc_list, peer_commitment)

            # update transaction and channel balance
            update_trade_db.update({'peer_commitment': peer_commitment})
            update_channel_db = {
                'balance': {
                    payer_address: {
                        asset_type: payer_balance
                    },
                    payee_address: {
                        asset_type: payee_balance
                    }
                }
            }

            # check the htlc part signature
            if EnumTradeType.TRADE_TYPE_HTLC.name == resign_trade.type:
                cls.check_signature(wallet, peer_address,
                                    cls._htlc_sign_type_list, htlc_list,
                                    peer_delay_commitment)
                update_trade_db.update(
                    {'peer_delay_commitment': peer_delay_commitment})
                update_trade_db.update(
                    {'state': EnumTradeState.confirming.name})

                # need update the hlock part
                if payer_address == self_address:
                    channel = Channel(channel_name)
                    channel_hlock = channel.hlock
                    if channel_hlock and channel_hlock.get(payer_address):
                        payer_hlock = int(resign_trade.payment) + int(
                            channel_hlock.get(payer_address).get(asset_type))
                        channel_hlock.update(
                            {payer_address: {
                                asset_type: str(payer_hlock)
                            }})
                        update_channel_db.update({'hlock': channel_hlock})
            else:  # RSMC type transaction
                update_trade_db.update(
                    {'state': EnumTradeState.confirmed.name})

            # update transaction
            Channel.update_trade(channel_name, resign_nonce, **update_trade_db)

            # update Channel balance to new one
            Channel.update_channel(channel_name, **update_channel_db)

        # return resign message body
        return cls.create_resign_message_body(wallet.url, channel_name,
                                              resign_nonce, True)