Пример #1
0
    def handle(self):
        super(FounderResponsesMessage, self).handle()

        # check response status
        if not self.check_response_status(self.status):
            return

        try:
            # some checks and verification for founder message
            self.verify()
            self.check_nonce(self.nonce)
            founder_trade = Channel.query_trade(self.channel_name, self.nonce)
            self.check_signature(self.wallet,
                                 type_list=self._sign_type_list,
                                 value_list=[
                                     self.channel_name, self.nonce,
                                     self.receiver_address,
                                     int(founder_trade.balance),
                                     self.sender_address,
                                     int(founder_trade.peer_balance)
                                 ],
                                 signature=self.commitment)

            # update the trade
            Channel.update_trade(self.channel_name,
                                 self.nonce,
                                 peer_commitment=self.commitment)
        except GoTo as error:
            LOG.error(error)
        except Exception as error:
            LOG.error(
                'Exception occurred during creating channel<{}>. Exception: {}'
                .format(self.channel_name, error))
        else:
            self.register_deposit_event()
Пример #2
0
    def execute(self,
                block_height,
                invoker='',
                channel_name='',
                invoker_key=''):
        """

        :param block_height:
        :param invoker_uri:
        :param channel_name:
        :param trade:
        :param invoker_key:
        :param gwei:
        :return:
        """
        super(ChannelEndSettleEvent, self).execute(block_height)

        # close channel event
        result = self.contract_event_api.end_close_channel(
            invoker, channel_name, invoker_key, gwei_coef=self.gwei_coef)

        # set channel settling
        if result is not None and 'success' in result.values():
            Channel.update_channel(self.channel_name,
                                   state=EnumChannelState.SETTLED.name)
        self.next_stage()
Пример #3
0
    def create(sender,
               receiver,
               channel_name,
               asset_type,
               payment,
               nonce,
               comments=''):
        message = PaymentLinkAck.create_message_header(
            sender, receiver, PaymentLinkAck._message_name, channel_name,
            asset_type, nonce)

        hashcode, rcode = Payment.create_hr()
        Channel.add_payment(channel_name,
                            hashcode=hashcode,
                            rcode=rcode,
                            payment=payment)
        pycode = Payment.generate_payment_code(sender, asset_type, payment,
                                               hashcode, comments)

        message = message.message_header
        message_body = {'PaymentLink': pycode}
        message.update({'MessageBody': message_body})
        message.update({'Status': EnumResponseStatus.RESPONSE_OK.name})
        if comments:
            message.update({'Comments': comments})
        Message.send(message)
        pass
Пример #4
0
    def prepare(self, block_height, address='', deposit=0.0, key=''):
        super(ChannelDepositEvent, self).prepare(block_height)

        # if this transaction id is approved, it means successful by eth block chain
        if self.approved_tx_id:
            checked = self.check_transaction_success(self.approved_tx_id)
            if checked:
                LOG.debug('Approved asset by address<{}:{}>'.format(address, deposit))
                Channel.update_channel(self.channel_name, state=EnumChannelState.OPENING.name)
                LOG.info('Start to create channel<{}>. State: OPENING.'.format(self.channel_name))
                console_log.info('Channel<{}> is opening'.format(self.channel_name))
                # go to next stage
                self.next_stage()
                return True
            elif checked is False:
                return False
            else:
                # new transaction is pushed to chain
                self.approved_tx_id = None
        else:
            approved_deposit = self.contract_event_api.get_approved_asset(address)
            if approved_deposit >= int(deposit):
                LOG.debug('Has already approved: {}'.format(approved_deposit))
                # go to next stage
                self.next_stage()
                return True
            
        # make transaction to chain
        result = self.contract_event_api.approve(address, int(deposit), key, gwei_coef=self.gwei_coef)
        if result:
            self.approved_tx_id = '0x'+result.strip()

        return False
Пример #5
0
    def execute(self,
                block_height,
                invoker='',
                channel_name='',
                hashcode='',
                invoker_key=''):
        """

        :param block_height:
        :param invoker:
        :param channel_name:
        :param hashcode:
        :param invoker_key:
        :return:
        """
        super(ChannelSettleHtlcUnlockEvent, self).execute(block_height)

        # close channel event
        result = self.contract_event_api.settle_after_htlc_unlock_payment(
            invoker_key, channel_name, hashcode, invoker_key)

        # set channel settling
        if result is not None and 'success' in result.values():
            Channel.update_channel(self.channel_name,
                                   state=EnumChannelState.SETTLED.name)
        self.next_stage()
Пример #6
0
    def validate_transaction(self):
        """

        :return:
        """
        # check the trade with nonce existed or not
        try:
            pre_trade = Channel.query_trade(self.channel_name, self.nonce - 1)
        except Exception as error:
            # should never go here
            raise (
                EnumResponseStatus.RESPONSE_TRADE_NOT_FOUND,
                'Transaction with nonce<{}> is not found'.format(self.nonce -
                                                                 1))
        else:
            if pre_trade.state in [
                    EnumTradeState.confirmed.name
                    or EnumTradeState.confirmed_onchain.name
            ]:
                return True
            elif pre_trade.state in [EnumTradeState.confirming.name] \
                    and EnumTradeType.TRADE_TYPE_HTLC.name == pre_trade.type \
                    and pre_trade.peer_commitment and pre_trade.peer_delay_commitment:
                return True

            raise GoTo(
                EnumResponseStatus.
                RESPONSE_TRADE_RESIGN_REQUEST_NOT_IMPLEMENTED,
                'Wait for next resign. current confirmed nonce<{}>, request nonce<{}>'
                .format(Channel.latest_confirmed_nonce(), self.nonce))
Пример #7
0
    def check_nonce(cls, nonce, channel_name='', is_founder=False):
        """

        :param channel_name:
        :param nonce:
        :return:
        """
        nonce = int(nonce)
        nego_trade = Channel.query_trade(channel_name, nonce)
        pre_trade = Channel.query_trade(channel_name, nonce - 1)

        # to check whether the nonce is legal one or not
        if not (TransactionBase._FOUNDER_NONCE < nonce and pre_trade.state in [
                EnumTradeState.confirmed.name,
                EnumTradeState.confirmed_onchain.name
        ] and (
            (nego_trade.state in [EnumTradeState.init.state] and is_founder) or
            (nego_trade.state in [EnumTradeState.confirming.state]
             and not is_founder))):
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_WITH_INCOMPATIBLE_NONCE,
                '{}::Channel<{}> has incompatible nonce<{}>, state<previous:{}, negotiated: {}>' \
                    .format(cls.__name__, channel_name, nonce, pre_trade.state, nego_trade.state))
        else:
            return True, nego_trade
Пример #8
0
    def execute(self, block_height, channel_name='', hashcode=''):
        """

        :param block_height:
        :param channel_name:
        :param kwargs:
        :return:
        """
        super(ChannelHtlcUnlockedEvent, self).execute(block_height)

        # if monitor this event, update the htlc trade state to confirmed
        if channel_name and hashcode:
            try:
                htlc_trade = Channel.batch_query_trade(
                    channel_name,
                    filters={
                        'type': EnumTradeType.TRADE_TYPE_HTLC.name,
                        'hashcode': hashcode
                    })[0]
            except Exception as error:
                LOG.error('Htlc trade with HashR<{}> not found for channel<{}>. Exception: {}'\
                          .format(hashcode, channel_name, error))
            else:
                Channel.update_trade(
                    channel_name,
                    htlc_trade.nonce,
                    state=EnumTradeState.confirmed_onchain.name)
        else:
            LOG.error(
                'Error input parameters: channel <{}>, hashcode<{}>.'.format(
                    channel_name, hashcode))
Пример #9
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))
Пример #10
0
    def error_handler(self, block_height, *args, **kwargs):
        super(ChannelQuickSettleEvent, self).error_handler(block_height, *args, **kwargs)

        # if running here, it means the channel is still OPENED
        total_deposit = self.contract_event_api.get_channel_total_balance(self.channel_name)
        if 0 < total_deposit:
            Channel.update_channel(self.channel_name, state=EnumChannelState.OPENED.name)
            sync_channel_info_to_gateway(self.channel_name, 'AddChannel', self.asset_type)
Пример #11
0
    def create(wallet, receiver, channel_name, asset_type):
        """

        :param channel_name:
        :param wallet:
        :param sender:
        :param receiver:
        :param asset_type:
        :return:
        """
        sender = wallet.url
        channel = Channel(channel_name)
        nonce = SettleMessage._SETTLE_NONCE
        asset_type = asset_type.upper()

        sender_address, _, _, = uri_parser(sender)
        receiver_address, _, _, = uri_parser(receiver)

        balance = channel.balance
        sender_balance = balance.get(sender_address, {}).get(asset_type)
        receiver_balance = balance.get(receiver_address, {}).get(asset_type)

        commitment = SettleMessage.sign_content(
            typeList=SettleMessage._sign_type_list,
            valueList=[
                channel_name, nonce, sender_address,
                int(sender_balance), receiver_address,
                int(receiver_balance)
            ],
            privtKey=wallet._key.private_key_string)

        # add trade to database
        settle_trade = Channel.settle_trade(
            type=EnumTradeType.TRADE_TYPE_QIUCK_SETTLE,
            role=EnumTradeRole.TRADE_ROLE_FOUNDER,
            asset_type=asset_type,
            balance=sender_balance,
            peer_balance=receiver_balance,
            commitment=commitment)
        SettleMessage.add_or_update_quick_settle_trade(
            channel_name, EnumTradeRole.TRADE_ROLE_FOUNDER, **settle_trade)

        # create settle request message
        message = SettleMessage.create_message_header(
            sender, receiver, SettleMessage._message_name, channel_name,
            asset_type, nonce)
        message = message.message_header
        message_body = {
            "Commitment": commitment,
            "SenderBalance": sender_balance,
            "ReceiverBalance": receiver_balance
        }
        message.update({'MessageBody': message_body})

        Message.send(message)

        return
Пример #12
0
    def handle(self):
        super(RsmcResponsesMessage, self).handle()

        status = EnumResponseStatus.RESPONSE_OK
        try:
            # check the response status
            if not self.check_response_status(self.status):
                self.rollback_resource(self.channel_name, self.nonce, self.payment, self.status)
                return
            # common check
            self.check_channel_state(self.channel_name)
            self.verify()
            self.check_role(self.role_index)

            if 0 == self.role_index:
                need_update_balance, rsmc_sign_body = self.handle_partner_response()
            elif 1 == self.role_index:
                need_update_balance, rsmc_sign_body = self.handle_founder_response()
            else:
                raise GoTo(EnumResponseStatus.RESPONSE_FAIL, 'Invalid Role<{}> of RsmcResponse'.format(self.role_index))

            # send RsmcSign to peer
            if rsmc_sign_body:
                response_message = self.create_message_header(self.receiver, self.sender, self._message_name,
                                                              self.channel_name, self.asset_type, self.nego_nonce or self.nonce)
                response_message.update({'MessageBody': rsmc_sign_body})
                response_message.update({'Status': status.name})
                self.send(response_message)

            is_htlc_to_rsmc = self.is_hlock_to_rsmc(self.hashcode)
            if is_htlc_to_rsmc:
                # update the htlc transaction state.
                Channel.confirm_payment(self.channel_name, self.hashcode, is_htlc_to_rsmc)

            # update the channel balance
            if need_update_balance:
                APIStatistics.update_statistics(self.wallet.address, payment=self.payment, payer=(0==self.role_index))
                self.update_balance_for_channel(self.channel_name, self.asset_type, self.payer_address,
                                                self.payee_address, self.payment, is_htlc_to_rsmc)
        except GoTo as error:
            LOG.exception(error)
            status = error.reason
        except Exception as error:
            status = EnumResponseStatus.RESPONSE_EXCEPTION_HAPPENED
            LOG.exception('Failed to handle RsmcSign for channel<{}> nonce<{}>, role_index<{}>.Exception: {}' \
                      .format(self.channel_name, self.nonce, self.role_index, error))
        finally:
            # send error response
            if EnumResponseStatus.RESPONSE_OK != status:
                if 0 == self.role_index:
                    self.send_error_response(self.sender, self.receiver, self.channel_name,
                                             self.asset_type, self.nonce, status, kwargs={'RoleIndex': '1'})

                # need rollback some resources
                self.rollback_resource(self.channel_name, self.nonce, self.payment, status=self.status)

        return
Пример #13
0
    def terminate(self, block_height, *args, asset_type='TNC'):
        super(ChannelQuickSettleEvent, self).terminate(block_height)

        # to check the total deposit of the channel
        total_deposit = self.contract_event_api.get_channel_total_balance(self.channel_name)
        if 0 >= total_deposit:
            Channel.update_channel(self.channel_name, state=EnumChannelState.CLOSED.name)
            APIStatistics.update_statistics(self.wallet_address, state=EnumChannelState.CLOSED.name)
            console_log.info('Channel {} state is {}'.format(self.channel_name, EnumChannelState.CLOSED.name))
            self.next_stage()
Пример #14
0
    def handle_founder_response(self):
        """

        :return:
        """
        need_update_balance = False
        # handle the resign body firstly
        if self.resign_body:
            resign_ack, _ = self.handle_resign_body(self.wallet, self.channel_name, self.resign_body)

        sign_hashcode, sign_rcode = self.get_rcode(self.channel_name, self.hashcode)
        # has already signed by peer
        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, self.nonce, self.payer_address, int(self.sender_balance),
                            self.payee_address, int(self.receiver_balance), sign_hashcode, sign_rcode],
                signature=self.commitment
            )
            # Just update current transaction confirmed:
            Channel.update_trade(self.channel_name, self.nonce, peer_commitment=self.commitment,
                                 state=EnumTradeState.confirmed.name)
            need_update_balance = True

            if self.comments:
                self.notify_peer_payment_finished()
        else:
            # to check the latest confirmed nonce
            self.validate_transaction()

            # if running here, it means that the transaction has been succeeded to resign
            is_htlc_to_rsmc = self.is_hlock_to_rsmc(self.hashcode)
            self.check_balance(self.channel_name, self.asset_type, self.payer_address, self.sender_balance,
                               self.payee_address, self.receiver_balance, hlock_to_rsmc=is_htlc_to_rsmc, payment=self.payment)

            # sign this transaction
            commitment = RsmcResponsesMessage.sign_content(
                self.wallet, self._sign_type_list, [self.channel_name, self.nonce, self.payer_address, int(self.sender_balance),
                                                    self.payee_address, int(self.receiver_balance), sign_hashcode, sign_rcode]
            )

            # update the transaction confirming state
            Channel.update_trade(self.channel_name, self.nonce, balance=self.receiver_balance,
                                 peer_balance=self.sender_balance, commitment=commitment,
                                 state=EnumTradeState.confirming.name)

            rsmc_sign_body = self.response(self.asset_type, self.payment, self.sender_balance, self.receiver_balance,
                                           0, self.hashcode)
            rsmc_sign_body.update({'Commitment': commitment})

            return need_update_balance, rsmc_sign_body

        return need_update_balance, None
Пример #15
0
    def prepare(self, block_height, *args, **kwargs):
        super(ChannelQuickSettleEvent, self).prepare(block_height, *args, **kwargs)

        # update the channel OPENING State after trigger the deposit event, wait for OPENED
        if self.retry is False:
            Channel.update_channel(self.channel_name, state=EnumChannelState.CLOSING.name)
            LOG.info('Start to quick-close channel<{}>. State: CLOSING.'.format(self.channel_name))
            console_log.info('Channel<{}> is closing'.format(self.channel_name))

        # go to next stage
        self.next_stage()
Пример #16
0
    def rollback_resource(cls, channel_name, nonce, payment=None, status=None):
        """

        :param channel_name:
        :param nonce:
        :param payment:
        :return:
        """
        if status is not None and status != EnumResponseStatus.RESPONSE_OK.name:
            trade = Channel.query_trade(channel_name, nonce)
            if trade:
                Channel.delete_trade(channel_name, int(nonce))
Пример #17
0
    def handle(self):
        super(RResponse, self).handle()

        status = EnumResponseStatus.RESPONSE_OK
        try:
            self.check_channel_state(self.channel_name)
            self.check_rcode(self.hashcode, self.rcode)

            htlc_trade = self.get_htlc_trade_by_hashr(self.channel_name,
                                                      self.hashcode)
            Channel.update_trade(self.channel_name,
                                 htlc_trade.nonce,
                                 rcode=self.rcode)
            # check payment:
            stored_payment = int(htlc_trade.payment)
            if stored_payment != self.payment:
                raise GoTo(
                    EnumResponseStatus.RESPONSE_TRADE_UNMATCHED_PAYMENT,
                    'Unmatched payment. self stored payment<{}>, peer payment<{}>'
                    .format(stored_payment, self.payment))

            # send response OK message
            RResponseAck.create(self.channel_name, self.asset_type, self.nonce,
                                self.sender, self.receiver, self.hashcode,
                                self.rcode, self.payment, self.comments,
                                status)
        except TrinityException as error:
            LOG.error(error)
            status = error.reason
        except Exception as error:
            status = EnumResponseStatus.RESPONSE_EXCEPTION_HAPPENED
            LOG.error(
                'Failed to handle RResponse with HashR<{}>. Exception: {}'.
                format(self.hashcode, error))
            pass
        else:
            # trigger rsmc
            self.trigger_pay_by_rsmc()

            # notify rcode to next peer
            LOG.debug(
                'notify the RResponse to next channel<{}>, current channel<{}>'
                .format(htlc_trade.channel, self.channel_name))
            self.notify_rcode_to_next_peer(htlc_trade.channel)
        finally:
            if EnumResponseStatus.RESPONSE_OK != status:
                RResponseAck.send_error_response(self.sender, self.receiver,
                                                 self.channel_name,
                                                 self.asset_type, self.nonce,
                                                 status)

        return None
Пример #18
0
    def execute(self, block_height, channel_name='', **kwargs):
        """

        :param block_height:
        :param channel_name:
        :param kwargs:
        :return:
        """
        super(ChannelSettledEvent, self).execute(block_height)

        # if monitor this event, close channel directly
        if channel_name:
            Channel.update_channel(channel_name,
                                   state=EnumChannelState.SETTLED.name)
Пример #19
0
    def register_quick_close_event(self, is_founder=True):
        """

        :param is_founder:
        :return:
        """
        try:
            channel_event = ChannelQuickSettleEvent(self.channel_name,
                                                    is_founder)

            if is_founder:
                settle_trade = Channel.query_trade(self.channel_name,
                                                   SettleBase._SETTLE_NONCE)

                # register arguments for execution action
                channel_event.register_args(
                    EnumEventAction.EVENT_EXECUTE, self.receiver_address,
                    self.channel_name, self.nonce, self.receiver_address,
                    settle_trade.balance, self.sender_address,
                    settle_trade.peer_balance, settle_trade.commitment,
                    self.commitment, self.wallet._key.private_key_string)

            # register arguments for termination action
            channel_event.register_args(EnumEventAction.EVENT_TERMINATE,
                                        asset_type=self.asset_type)
        except Exception as error:
            LOG.error(
                'Failed to regiser quick close channel event since {}'.format(
                    error))
        else:
            # register and trigger the event
            event_machine.register_event(self.channel_name, channel_event)
            event_machine.trigger_start_event(self.channel_name)
Пример #20
0
    def channel_close(self, arguments):
        """

        :param arguments:
        :return:
        """
        channel_name = get_arg(arguments, 1)

        console_log.console("Closing channel {}".format(channel_name))
        if channel_name:
            Channel.quick_close(channel_name,
                                wallet=self.Wallet,
                                cli=True,
                                trigger=SettleMessage.create)
        else:
            console_log.warn("No Channel Create")
Пример #21
0
    def create(wallet,
               channel_name,
               asset_type,
               nonce,
               sender,
               sender_balance,
               receiver,
               receiver_balance,
               peer_commitment,
               comments=None):
        """

        :param wallet:
        :param channel_name:
        :param asset_type:
        :param sender:
        :param receiver:
        :param sender_balance:
        :param receiver_balance:
        :param peer_commitment:
        :param status:
        :return:
        """
        sender_address, _, _ = uri_parser(sender)
        receiver_address, _, _ = uri_parser(receiver)
        asset_type = asset_type.upper()

        # sign the contents
        commitment = SettleResponseMessage.sign_content(
            wallet, SettleResponseMessage._sign_type_list, [
                channel_name, nonce, sender_address,
                int(sender_balance), receiver_address,
                int(receiver_balance)
            ])

        # finally, add the transaction information to database
        settle_trade = Channel.settle_trade(
            type=EnumTradeType.TRADE_TYPE_QIUCK_SETTLE,
            role=EnumTradeRole.TRADE_ROLE_PARTNER,
            asset_type=asset_type,
            balance=receiver_balance,
            peer_balance=sender_balance,
            commitment=commitment,
            peer_commitment=peer_commitment)
        SettleResponseMessage.add_or_update_quick_settle_trade(
            channel_name, EnumTradeRole.TRADE_ROLE_PARTNER, **settle_trade)

        message = SettleResponseMessage.create_message_header(
            receiver, sender, SettleResponseMessage._message_name,
            channel_name, asset_type, nonce)

        message.update({"MessageBody": {"Commitment": commitment}})

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

        # send response OK message
        message.update({'Status': EnumResponseStatus.RESPONSE_OK.name})
        Message.send(message)
Пример #22
0
    def check_channel_state(cls, channel_name):
        channel = Channel(channel_name)

        if not channel.is_opened:
            raise GoTo(
                EnumResponseStatus.RESPONSE_CHANNEL_NOT_OPENED,
                'Channel is not OPENED. Current tate<{}>'.format(
                    channel.state))

        return channel
Пример #23
0
    def register_deposit_event(self, is_founder=True):
        """

        :param is_founder:
        :return:
        """
        try:
            channel_event = ChannelDepositEvent(self.channel_name,
                                                self.wallet.address,
                                                is_founder)

            # get the transaction record of founder message
            founder_trade = Channel.query_trade(self.channel_name,
                                                FounderBase._FOUNDER_NONCE)

            # set some arguments by the role type
            self_address = self.receiver_address
            self_deposit = founder_trade.balance
            if is_founder:
                founder_address = self.receiver_address
                founder_deposit = founder_trade.balance
                founder_commitment = founder_trade.commitment
                partner_address = self.sender_address
                partner_deposit = founder_trade.peer_balance
                partner_commitment = founder_trade.peer_commitment
            else:
                founder_address = self.sender_address
                founder_deposit = founder_trade.peer_balance
                founder_commitment = founder_trade.peer_commitment
                partner_address = self.receiver_address
                partner_deposit = founder_trade.balance
                partner_commitment = founder_trade.commitment

            # register the preparation action for deposit event
            channel_event.register_args(EnumEventAction.EVENT_PREPARE,
                                        self_address, self_deposit,
                                        self.wallet._key.private_key_string)

            # add execution action for deposit event
            channel_event.register_args(
                EnumEventAction.EVENT_EXECUTE, self_address, self.channel_name,
                FounderBase._FOUNDER_NONCE, founder_address, founder_deposit,
                partner_address, partner_deposit, founder_commitment,
                partner_commitment, self.wallet._key.private_key_string)
            channel_event.register_args(EnumEventAction.EVENT_TERMINATE,
                                        asset_type=self.asset_type)
        except Exception as error:
            LOG.exception(
                'Failed to register deposit event since {}'.format(error))
        else:
            # register and trigger event
            event_machine.register_event(self.channel_name, channel_event)
            event_machine.trigger_start_event(self.channel_name)

        return
Пример #24
0
    def channel_payment(self, arguments):
        """

        :param arguments:
        :return:
        """
        asset_type = get_arg(arguments, 1)
        if not check_support_asset_type(asset_type):
            console_log.error(
                "No support asset, current just support {}".format(
                    SupportAssetType.SupportAssetType))
            return None
        value = TrinityNumber(get_arg(arguments, 2).strip()).number
        if not value:
            console_log.error("command not give the count")
            return None
        try:
            if 0 >= value or not check_float_decimals(value, asset_type):
                console_log.error("value should not be less than 0")
                return None
        except ValueError:
            console_log.error("value format error")
            return None
        comments = " ".join(arguments[3:])
        comments = comments if comments else "None"
        if len(comments) > 128:
            console_log.error("comments length should be less than 128")
            return None
        try:
            hash_r, rcode = Payment.create_hr()
            Channel.add_payment(None, hash_r, rcode, value)
            paycode = Payment.generate_payment_code(self.Wallet.url,
                                                    asset_type, value, hash_r,
                                                    comments, True)
        except Exception as e:
            LOG.error(e)
            console_log.error("Get payment link error, please check the log")
            return None
        if self.qrcode:
            qrcode_terminal.draw(paycode, version=4)
        console_log.console(paycode)
        return None
Пример #25
0
    def check_payment(cls, channel_name, address, asset_type, payment):
        """

        :param channel_name:
        :param address:
        :param asset_type:
        :param payment:
        :return:
        """
        channel_balance = Channel(channel_name).balance
        balance = channel_balance.get(address).get(asset_type.upper())

        if not 0 < int(payment) <= int(balance):
            raise GoTo(
                EnumResponseStatus.
                RESPONSE_TRADE_NO_ENOUGH_BALANCE_FOR_PAYMENT,
                'Invalid payment<{}>, payer balance<{}>'.format(
                    payment, balance))

        return True, int(balance)
Пример #26
0
 def check_hashcode_used(cls, channel_name, hashcode):
     try:
         trade_record = Channel.batch_query_trade(
             channel_name, filters={'hashcode': hashcode})[0]
     except Exception as error:
         return True
     else:
         raise GoTo(
             EnumResponseStatus.RESPONSE_TRADE_HASHR_ALREADY_EXISTED,
             'HashR<{}> already used by trade with nonce<{}>'.format(
                 hashcode, trade_record.nonce))
Пример #27
0
    def record_transaction(self, nonce, **update_args):
        """
        
        :param nonce:
        :param update_args:
        :return:
        """
        # check the trade with nonce existed or not
        try:
            new_trade = Channel.query_trade(self.channel_name, nonce)
        except Exception as error:
            new_trade = None

        # add new transaction
        if new_trade:
            Channel.update_trade(self.channel_name, nonce=nonce, **update_args)
        else:
            Channel.add_trade(self.channel_name, nonce=nonce, **update_args)

        return
Пример #28
0
    def terminate(self, block_height, *args, asset_type='TNC'):
        super(ChannelDepositEvent, self).terminate(block_height, *args)

        # check the deposit of the contract address
        total_deposit = self.contract_event_api.get_channel_total_balance(self.channel_name)
        if total_deposit >= self.deposit + self.partner_deposit:
            Channel.update_channel(self.channel_name, state=EnumChannelState.OPENED.name)
            Channel.update_trade(self.channel_name, self.nonce, state=EnumTradeState.confirmed.name)
            sync_channel_info_to_gateway(self.channel_name, 'AddChannel', asset_type)
            console_log.info('Channel {} state is {}'.format(self.channel_name, EnumChannelState.OPENED.name))

            # to trigger monitor event for closing channel
            event_monitor_close_channel(self.channel_name)
            event_monitor_settle(self.channel_name)

            # to trigger monitor event for unlocking htlc locked payment
            event_monitor_withdraw(self.channel_name)
            event_monitor_withdraw_update(self.channel_name)
            event_monitor_withdraw_settle(self.channel_name)

            self.next_stage()
Пример #29
0
    def notify_peer_payment_finished(self,):
        try:
            payment_record = Channel.query_payment(self.channel_name, self.comments)[0]
            receiver = payment_record.receiver
        except:
            LOG.warning('No payment record with code<{}> is found'.format(self.comments))
            pass
        else:
            PaymentAck.create(self.wallet.url, receiver, self.channel_name, self.asset_type, self.nonce,
                              self.comments)

        return
Пример #30
0
    def execute(self,
                block_height,
                invoker_uri='',
                channel_name='',
                invoker_key='',
                nonce=None):
        """

        :param block_height:
        :param invoker_uri:
        :param channel_name:
        :param trade:
        :param invoker_key:
        :param gwei:
        :return:
        """
        super(ChannelUpdateSettleEvent, self).execute(block_height)

        # close channel event
        # ToDo uncomment below codes in future
        # latest_trade = Channel.latest_confirmed_trade()
        # if isinstance(nonce, int) and int(nonce) == latest_trade.nonce: # or check balance:
        #     self.next_stage()
        #     return

        result = Channel.force_release_rsmc(
            invoker_uri,
            channel_name,
            nonce,
            invoker_key,
            gwei_coef=self.gwei_coef,
            trigger=self.contract_event_api.update_close_channel)

        # set channel settling
        if result is not None and 'success' in result.values():
            Channel.update_channel(self.channel_name,
                                   state=EnumChannelState.SETTLED.name)
            APIStatistics.update_statistics(
                self.wallet_address, state=EnumChannelState.SETTLED.name)
        self.next_stage()