Ejemplo n.º 1
0
 def htlc_unlock_payment(cls,
                         invoker,
                         channel_id,
                         founder,
                         partner,
                         lock_period,
                         lock_amount,
                         lock_hash,
                         founder_signature,
                         partner_signature,
                         lock_secret,
                         invoker_key,
                         gwei_coef=1):
     try:
         result = cls._eth_interface.withdraw(invoker,
                                              channel_id,
                                              founder,
                                              partner,
                                              int(lock_period),
                                              int(lock_amount),
                                              lock_hash,
                                              founder_signature,
                                              partner_signature,
                                              lock_secret,
                                              invoker_key,
                                              gwei_coef=gwei_coef)
         LOG.debug('htlc_unlock_payment result: {}'.format(result))
         return result
     except Exception as error:
         LOG.exception('htlc_unlock_payment error: {}'.format(error))
         return None
Ejemplo n.º 2
0
    def approve(cls, address, deposit, private_key, gwei_coef=1):
        """

        :param address:
        :param deposit:
        :param private_key:
        :param gwei_coef:
        :return:
        """
        deposit = int(deposit)
        # approved_asset = cls.get_approved_asset(address)
        #
        # if approved_asset >= deposit:
        #     LOG.info('Has been approved asset count: {}'.format(approved_asset))
        #     return True

        try:
            # return tx_id
            tx_id = cls._eth_interface.approve(address,
                                               deposit,
                                               private_key,
                                               gwei_coef=gwei_coef)
            LOG.debug(
                'ContractEventInterface::approve: txId: {}'.format(tx_id))
            return tx_id
        except Exception as error:
            LOG.exception('authorized deposit error: {}'.format(error))

        return False
Ejemplo n.º 3
0
    def handle(self):
        """

        :return:
        """
        old_block = get_block_count() - 1
        _event_coroutine = self.timer_event()
        next(_event_coroutine)
        self.prepare_handle_event()

        while WebSocketConnection._websocket_listening:
            try:
                response = self.receive()
                block_height = get_block_count()

                # handle response
                self.handle_event(block_height, response)

                # handle timer event
                if old_block != block_height:
                    for block in range(old_block + 1, block_height + 1):
                        ucoro_event(_event_coroutine, block)

                    # set new value to old_block
                    old_block = block_height

                time.sleep(0.5)
            except Exception as error:
                LOG.exception('websocket handle: {}'.format(error))
                time.sleep(1)

        ucoro_event(_event_coroutine, None)
Ejemplo n.º 4
0
def ucoro_event(coro, iter_data):
    try:
        coro.send(iter_data)
    except StopIteration as error:
        LOG.debug('Co-routine has been killed.')
    except Exception as error:
        LOG.exception('Error occurred during using co-routine. error: {}'.format(error))
Ejemplo n.º 5
0
 def approve_deposit(cls,
                     address,
                     channel_id,
                     nonce,
                     founder,
                     founder_amount,
                     partner,
                     partner_amount,
                     founder_sign,
                     partner_sign,
                     private_key,
                     gwei_coef=1):
     try:
         return cls._eth_interface.deposit(address,
                                           channel_id,
                                           nonce,
                                           founder,
                                           int(founder_amount),
                                           partner,
                                           int(partner_amount),
                                           founder_sign,
                                           partner_sign,
                                           private_key,
                                           gwei_coef=gwei_coef)
     except Exception as error:
         LOG.exception('approve_deposit error: {}'.format(error))
         return None
Ejemplo n.º 6
0
    def register_quick_close_event(self, is_founder=True):
        """

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

            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.exception(
                '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)
Ejemplo n.º 7
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.exception('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))
Ejemplo n.º 8
0
 def get_transaction_receipt(cls, tx_id):
     try:
         result = cls._eth_interface.get_transaction_receipt(tx_id)
         if result:
             print(result)
         return result
     except Exception as error:
         LOG.exception('get_approved_asset error: {}'.format(error))
         return None
Ejemplo n.º 9
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
Ejemplo n.º 10
0
    def monitorCloseChannel(self, message):
        """

        :param message:
        :return:

        message like below format:
            {
                'playload': '0xabf328663edff39bfa3f157556afa52bdcb14fda32d35c70e6e3386e954e7995',
                'txId': '0xc0461c9a92a295eec4dd1060e4abd34bbb1c8139e2b9bc5e35e7c2daa1dccfc5',
                'channelId': '0xabf328663edff39bfa3f157556afa52bdcb14fda32d35c70e6e3386e954e7995',
                'invoker': '0x23cca051bfedb5e17d3aad2038ba0a5155d1b1b7',
                'nonce': 5,
                'blockNumber': 3924231,
                'messageType': 'monitorCloseChannel'
            }

        """
        if not message:
            LOG.error('Invalid message: {}'.format(message))
            return

        try:
            invoker = message.get('invoker').strip()
            channel_name = message.get('channelId')
            nonce = message.get('nonce')
            end_time = int(message.get('blockNumber'))
        except Exception as error:
            LOG.exception('Invalid message: {}. Exception: {}'.format(
                message, error))
        else:
            if not (self.wallet_address and invoker):
                LOG.error(
                    'Wallet address<{}> or invoker<{}> should not be none'.
                    format(self.wallet_address, invoker))
                return

            if invoker != self.wallet_address.lower():
                channel_event = ChannelUpdateSettleEvent(
                    channel_name, self.wallet_address)
                channel_event.register_args(
                    EnumEventAction.EVENT_EXECUTE, self.wallet.url,
                    channel_name, self.wallet._key.private_key_string, nonce)
                event_machine.register_event(channel_name, channel_event)
                event_machine.trigger_start_event(channel_name)
            else:
                LOG.debug('register ChannelEndSettleEvent at block<{}>'.format(
                    end_time))
                channel_event = ChannelEndSettleEvent(channel_name,
                                                      self.wallet_address)
                channel_event.register_args(
                    EnumEventAction.EVENT_EXECUTE, invoker, channel_name,
                    self.wallet._key.private_key_string)
                self.register_event(channel_event, end_time)

        return
Ejemplo n.º 11
0
 def register_event(self, name, event):
     try:
         self.event_lock.acquire()
         self.__event_queue.update({name: event})
     except Exception as error:
         LOG.exception(
             'event machine register_event<{}> exception: {}'.format(
                 name, error))
     finally:
         self.event_lock.release()
Ejemplo n.º 12
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
Ejemplo n.º 13
0
 def trigger_start_event(self, name):
     try:
         self.event_lock.acquire()
         if name not in self.__event_ordered_list:
             self.__event_ordered_list.append(name)
     except Exception as error:
         LOG.exception(
             'event machine trigger_start_event<{}> exception: {}'.format(
                 name, error))
     finally:
         self.event_lock.release()
Ejemplo n.º 14
0
 def end_close_channel(cls, invoker, channel_id, invoker_key, gwei_coef=1):
     try:
         result = cls._eth_interface.settle_transaction(invoker,
                                                        channel_id,
                                                        invoker_key,
                                                        gwei_coef=gwei_coef)
         LOG.debug('end_close_channel result: {}'.format(result))
         return result
     except Exception as error:
         LOG.exception('end force_settle error: {}'.format(error))
         return None
Ejemplo n.º 15
0
    def get_event(self, key):
        try:
            self.event_lock.acquire()
            event = self.__monitor_queue.pop(key, [])
        except Exception as error:
            event = None
            LOG.exception('websocket get_event exception: {}'.format(error))
        finally:
            self.event_lock.release()

        return event
Ejemplo n.º 16
0
 def send(self, payload):
     try:
         self._conn.send(payload)
     except WebSocketConnectionClosedException as error:
         LOG.exception('send: Websocket was closed: {}'.format(error))
         self.reconnect()
         # re-send this payload
         if self._conn:
             self._conn.send(payload)
     except Exception as error:
         LOG.exception('send: Websocket exception: {}'.format(error))
Ejemplo n.º 17
0
    def get_approved_asset(cls, address):
        try:
            result = cls._eth_interface.get_approved_asset(
                settings.TNC, settings.TNC_abi, address,
                settings.ETH_Data_Contract_address)

            if result:
                result = TrinityNumber(str(result)).number

            return result
        except Exception as error:
            LOG.exception('get_approved_asset error: {}'.format(error))
            return 0
Ejemplo n.º 18
0
    def unregister_event(self, name):
        try:
            self.event_lock.acquire()
            if name in self.__event_ordered_list:
                self.__event_ordered_list.remove(name)

            if name in self.__event_queue.keys():
                self.__event_queue.pop(name)
        except Exception as error:
            LOG.exception(
                'event machine unregister_event<{}> exception: {}'.format(
                    name, error))
        finally:
            self.event_lock.release()
Ejemplo n.º 19
0
    def insert_event_back_into_queue(self, name, event):
        try:
            self.event_lock.acquire()
            if not self.has_event(name):
                self.__event_queue.update({name: event})
                self.__event_ordered_list.append(name)
        except Exception as error:
            LOG.exception(
                'event machine insert_event_back_into_queue<{}> exception: {}'.
                format(name, error))
        finally:
            self.event_lock.release()

        return
Ejemplo n.º 20
0
    def execute(self, block_height, address='', channel_id='', nonce='',
                founder='', deposit=0, partner='', partner_deposit=0,
                founder_sign='', partner_sign='', private_key=''):
        super(ChannelDepositEvent, self).execute(block_height)

        # update the founder and partner deposit
        self.deposit = int(deposit)
        self.partner_deposit = int(partner_deposit)
        
        # execute stage of channel event
        try:
            # if this wallet is not the event founder, go to next step directly.
            if not self.is_event_founder:
                self.next_stage()
                return True

            # below codes is just executed by the founder
            # check whether deposit is success or not
            if self.deposit_tx_id:
                checked = self.check_transaction_success(self.deposit_tx_id)
                if checked:
                    # go to next stage
                    self.next_stage()
                    return True
                elif checked is False:
                    return False
                else:
                    # new transaction is pushed to chain
                    self.deposit_tx_id = None

            # get approved asset of both partners
            peer_approved_deposit = self.contract_event_api.get_approved_asset(partner)
            approved_deposit = self.contract_event_api.get_approved_asset(founder)
            LOG.debug('Approved asset in wallet<{}>: founder<{}:{}>, partner<{}:{}>' \
                      .format(address, founder, approved_deposit, partner, peer_approved_deposit))
            # check approved asset of both side for event founder.
            if not (approved_deposit >= self.deposit and peer_approved_deposit >= self.partner_deposit):
                return False

            # Trigger deposit action if is_event_founder is True
            result = self.deposit_tx_id = self.contract_event_api.approve_deposit(
                    address, channel_id, nonce, founder, deposit, partner, partner_deposit,
                    founder_sign, partner_sign, private_key, gwei_coef=self.gwei_coef)
            if result:
                self.deposit_tx_id = '0x'+result.strip()

        except Exception as error:
            LOG.exception('Failed to approve deposit of Channel<{}>. Exception: {}'.format(self.channel_name, error))

        return False
Ejemplo n.º 21
0
    def get_event(self):
        try:
            self.event_lock.acquire()
            name = self.__event_ordered_list.pop(0)
            event = self.__event_queue.pop(name)
        except Exception as error:
            name = None
            event = None
            LOG.exception(
                'event machine get_event exception: {}'.format(error))
        finally:
            self.event_lock.release()

        return name, event
Ejemplo n.º 22
0
    def monitorWithdrawUpdate(self, message):
        if not message:
            LOG.error('Invalid message: {}'.format(message))
            return

        try:
            invoker = message.get('invoker').strip()
            channel_name = message.get('channelId')
        except Exception as error:
            LOG.exception('Invalid message: {}. Exception: {}'.format(
                message, error))
        else:
            if invoker.lower() != self.wallet_address.lower() and channel_name:
                ChannelStateManageEvent(channel_name).execute(
                    get_block_count(), channel_name)
Ejemplo n.º 23
0
    def receive(self):
        try:
            return self._conn.recv()
        except WebSocketConnectionClosedException as error:
            LOG.exception('receive: Websocket was closed: {}'.format(error))
            self.reconnect()

            return self._conn.recv() if self._conn else None
        except WebSocketTimeoutException as error:
            pass
        except Exception as error:
            if not self._conn:
                self.reconnect()
            LOG.exception('receive: Websocket exception: {}'.format(error))

        return None
Ejemplo n.º 24
0
 def create_client(self, retry=False):
     try:
         self._conn = create_connection(self.__ws_url,
                                        sockopt=(
                                            (socket.SOL_SOCKET,
                                             socket.SO_KEEPALIVE, 1),
                                            (socket.IPPROTO_TCP,
                                             socket.TCP_NODELAY, 1),
                                        ),
                                        timeout=self.timeout)
     except Exception as error:
         LOG.exception('Connect to server error. {}'.format(error))
     else:
         if self.wallet_address and retry:
             self.notify_wallet_info()
             pass
Ejemplo n.º 25
0
    def quick_settle(cls,
                     invoker,
                     channel_id,
                     nonce,
                     founder,
                     founder_balance,
                     partner,
                     partner_balance,
                     founder_signature,
                     partner_signature,
                     invoker_key,
                     gwei_coef=1):
        """

        :param invoker:
        :param channel_id:
        :param nonce:
        :param founder:
        :param founder_balance:
        :param partner:
        :param partner_balance:
        :param founder_signature:
        :param partner_signature:
        :param invoker_key:
        :return:
        """
        try:
            return cls._eth_interface.quick_close_channel(invoker,
                                                          channel_id,
                                                          nonce,
                                                          founder,
                                                          int(founder_balance),
                                                          partner,
                                                          int(partner_balance),
                                                          founder_signature,
                                                          partner_signature,
                                                          invoker_key,
                                                          gwei_coef=gwei_coef)
        except Exception as error:
            LOG.exception('quick_settle error: {}'.format(error))
            LOG.error('quick_settle parameters: '
                      'channel<{}>, nonce<{}>, '
                      'founder<{}>, founder_balance<{}>, founder_signature<{}>, '
                      'partner<{}>, partner_balance<{}>, partner_signature<{}>' \
                      .format(channel_id, nonce, founder, founder_balance, founder_signature,
                              partner, partner_balance, partner_signature))
            return None
Ejemplo n.º 26
0
    def handle(self):
        super(SettleMessage, self).handle()
        status = EnumResponseStatus.RESPONSE_OK
        nonce = self.nonce

        try:
            # common check arguments
            self.verify()
            self.check_nonce(self.nonce)
            self.check_balance(self.channel_name, self.asset_type,
                               self.sender_address, self.sender_balance,
                               self.receiver_address, self.receiver_balance)
            self.check_signature(self.wallet,
                                 self.sender_address,
                                 type_list=self._sign_type_list,
                                 value_list=[
                                     self.channel_name, self.nonce,
                                     self.sender_address,
                                     int(self.sender_balance),
                                     self.receiver_address,
                                     int(self.receiver_balance)
                                 ],
                                 signature=self.commitment)

            # To create settle response message
            SettleResponseMessage.create(self.wallet, self.channel_name,
                                         self.asset_type, self.nonce,
                                         self.sender, self.sender_balance,
                                         self.receiver, self.receiver_balance,
                                         self.commitment)
        except GoTo as error:
            LOG.exception(error)
            status = error.reason
        except Exception as error:
            LOG.exception(error)
            status = EnumResponseStatus.RESPONSE_EXCEPTION_HAPPENED
        finally:
            if EnumResponseStatus.RESPONSE_OK != status:
                SettleResponseMessage.send_error_response(
                    self.sender, self.receiver, self.channel_name,
                    self.asset_type, nonce, status)
            else:
                # register the settle event
                self.register_quick_close_event(False)

            return
Ejemplo n.º 27
0
    def monitorWithdraw(self, message):
        """

        :param message:
        :return:
        """
        if not message:
            LOG.error('Invalid message: {}'.format(message))
            return

        try:
            invoker = message.get('invoker').strip()
            channel_name = message.get('channelId')
            hashcode = message.get('lockHash')
            rcode = message.get('secret')
            end_time = int(message.get('blockNumber'))
        except Exception as error:
            LOG.exception('Invalid message: {}. Exception: {}'.format(
                message, error))
        else:
            if not (self.wallet_address and invoker):
                LOG.error('monitorWithdraw: Wallet address<{}> or invoker<{}> should not be none' \
                          .format(self.wallet_address, invoker))
                return

            if invoker != self.wallet_address.lower():
                channel_event = ChannelPunishHtlcUnlockEvent(channel_name)
                channel_event.register_args(
                    EnumEventAction.EVENT_EXECUTE, self.wallet.url,
                    channel_name, hashcode, rcode,
                    self.wallet._key.private_key_string)
                event_machine.register_event(channel_name, channel_event)
                event_machine.trigger_start_event(channel_name)
            else:
                LOG.debug(
                    'monitorWithdraw: register ChannelEndSettleEvent at next block'
                )
                channel_event = ChannelSettleHtlcUnlockEvent(channel_name)
                channel_event.register_args(
                    EnumEventAction.EVENT_EXECUTE, invoker, channel_name,
                    hashcode, self.wallet._key.private_key_string)
                self.register_event(channel_event, end_time)

        return
Ejemplo n.º 28
0
        def wrapper(*args, **kwargs):
            received = None
            # use such mode to modulate blocking-mode to received
            while True:
                try:
                    received = yield
                    if received in ['exit', None]:
                        break

                    kwargs.update({'received': received})
                    callback(*args, **kwargs)
                except Exception as error:
                    LOG.exception('Co-routine received<{}>, error: {}'.format(received, error))
                finally:
                    # only run once time
                    if once:
                        break

                    time.sleep(timeout)
Ejemplo n.º 29
0
    def register_event(self, event, end_block=None):

        if not end_block:
            block_height = get_block_count() + 1
        else:
            block_height = end_block

        try:
            self.event_lock.acquire()
            event_list = self.__monitor_queue.get(block_height, [])
            event_list.append(event)
            self.__monitor_queue.update({block_height: event_list})
        except Exception as error:
            LOG.exception(
                'websocket register_event exception: {}'.format(error))
        finally:
            self.event_lock.release()

        return
Ejemplo n.º 30
0
    def monitorWithdrawSettle(self, message):
        """

        :param message:
        :return:
        """
        try:
            channel_name = message.get('channelId')
            hashcode = message.get('lockHash')

            # update the channel to settled state
            if channel_name:
                channel_event = ChannelHtlcUnlockedEvent(channel_name)
                channel_event.execute(get_block_count(), channel_name,
                                      hashcode)
        except Exception as error:
            LOG.exception('Invalid message: {}. Exception: {}'.format(
                message, error))

        return