Пример #1
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()
Пример #2
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
Пример #3
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()
Пример #4
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)
Пример #5
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()
Пример #6
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()
Пример #7
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)
Пример #8
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()
Пример #9
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()
Пример #10
0
    def execute(self,
                block_height,
                invoker_uri='',
                channel_name='',
                nonce=None,
                invoker_key='',
                is_debug=False):
        """

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

        LOG.debug('parameter: {}, {}, {}, {}'.format(invoker_uri, channel_name,
                                                     nonce, invoker_key))
        LOG.debug('event args: {}, kwargs'.format(self.event_arguments.args,
                                                  self.event_arguments.kwargs))

        # close channel event
        result = Channel.force_release_rsmc(
            invoker_uri,
            channel_name,
            nonce,
            invoker_key,
            gwei_coef=self.gwei_coef,
            trigger=self.contract_event_api.close_channel,
            is_debug=is_debug)

        # 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()
Пример #11
0
    def execute(self,
                block_height,
                invoker_uri='',
                channel_name='',
                hashcode='',
                rcode='',
                invoker_key=''):
        """

        :param block_height:
        :param invoker_uri:
        :param channel_name:
        :param hashcode:
        :param rcode:
        :param invoker_key:
        :return:
        """
        super(ChannelPunishHtlcUnlockEvent, self).execute(block_height)

        # punishment when other want to release the htlc-locked payment
        result = Channel.force_release_htlc(
            invoker_uri,
            channel_name,
            hashcode,
            rcode,
            invoker_key,
            gwei_coef=self.gwei_coef,
            trigger=self.contract_event_api.punish_when_htlc_unlock_payment,
            is_debug=False,
            is_pubnishment=True,
            htcl_to_rsmc=self.transfer_htlc_to_rsmc)
        self.transfer_htlc_to_rsmc = False

        # 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()
Пример #12
0
    def execute(self, block_height, channel_name='', **kwargs):
        """

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

        # check whether the contract asset
        try:
            if channel_name:
                balance_of_channel = self.contract_event_api.get_channel_total_balance(
                    channel_name)
                if 0 >= balance_of_channel:
                    Channel.update_channel(channel_name,
                                           state=EnumChannelState.SETTLED.name)
        except Exception as error:
            LOG.exception(
                'Keep the channel current state because of exception: {}'.
                format(error))

        return
Пример #13
0
    def update_balance_for_channel(cls,
                                   channel_name,
                                   asset_type,
                                   payer_address,
                                   payee_address,
                                   payment,
                                   is_hlock_to_rsmc=False,
                                   is_htlc_type=False):
        """

        :param channel_name:
        :param payer_address:
        :param payee_address:
        :param asset_type:
        :param payment:
        :param is_hlock_to_rsmc:
        :return:
        """
        channel = Channel(channel_name)

        try:
            asset_type = asset_type.upper()
            channel_balance = channel.balance
            channel_hlock = channel.hlock

            # calculate the left balance
            payer_balance = channel_balance.get(payer_address).get(asset_type)
            payee_balance = channel_balance.get(payee_address).get(asset_type)

            if is_hlock_to_rsmc:
                payer_hlock = channel_hlock.get(payer_address).get(asset_type)
                payer_hlock = cls.big_number_calculate(payer_hlock, payment,
                                                       False)
                if 0 > payer_hlock:
                    raise GoTo(
                        EnumResponseStatus.
                        RESPONSE_TRADE_LOCKED_ASSET_LESS_THAN_PAYMENT,
                        'Why here? Payment<{}> should less than locked asset'.
                        format(payment))
                channel_hlock.update(
                    {payer_address: {
                        asset_type: str(payer_hlock)
                    }})
                payee_balance = cls.big_number_calculate(
                    payee_balance, payment)
            elif is_htlc_type:
                payer_hlock = channel_hlock.get(payer_address).get(asset_type)
                payer_hlock = cls.big_number_calculate(payer_hlock, payment)
                channel_hlock.update(
                    {payer_address: {
                        asset_type: str(payer_hlock)
                    }})
                payer_balance = cls.big_number_calculate(
                    payer_balance, payment, False)
            else:
                payer_balance = cls.big_number_calculate(
                    payer_balance, payment, False)
                payee_balance = cls.big_number_calculate(
                    payee_balance, payment)

            if int(payer_balance) >= 0 and int(payee_balance) >= 0:
                Channel.update_channel(channel_name,
                                       balance={
                                           payer_address: {
                                               asset_type: str(payer_balance)
                                           },
                                           payee_address: {
                                               asset_type: str(payee_balance)
                                           }
                                       },
                                       hlock=channel_hlock)
            else:
                raise GoTo(
                    EnumResponseStatus.
                    RESPONSE_TRADE_NO_ENOUGH_BALANCE_FOR_PAYMENT,
                    'Payer has not enough balance for this payment<{}>'.format(
                        payment))

        except Exception as error:
            raise GoTo(
                EnumResponseStatus.RESPONSE_TRADE_BALANCE_UPDATE_FAILED,
                'Update channel<{}> balance error. payment<{}>. Exception: {}'.
                format(channel_name, payment, error))
Пример #14
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)