def trigger_htlc_to_next_jump(self): """""" self.router, _ = self.exclude_wallet_from_router( self.wallet.url, self.router) if not self.check_if_the_last_router(): next_router = self.next_jump LOG.debug('Get Next Router {} from {}'.format( str(next_router), self.router)) if not next_router: raise GoTo( EnumResponseStatus.RESPONSE_ROUTER_WITH_ILLEGAL_NEXT_JUMP, 'Illegal next jump<{}> in router<{}>'.format( next_router, self.router)) # to get channel between current wallet and next jump channel_set = Channel.get_channel(self.wallet.url, next_router, state=EnumChannelState.OPENED) if not (channel_set and channel_set[0]): raise GoTo( EnumResponseStatus.RESPONSE_CHANNEL_NOT_FOUND, 'No OPENED channel is found between {} and {}.'.format( self.wallet.url, next_router)) channel_set = channel_set[0] if channel_set.channel == self.channel_name: LOG.warn('Has reached receiver of HTLC transaction.') return # calculate fee and transfer to next jump fee = TrinityNumber(str(self.get_fee(self.wallet.url))).number payment = self.big_number_calculate(self.payment, fee, False) receiver = next_router HtlcMessage.create(channel_set.channel, self.asset_type, self.wallet.url, receiver, payment, self.hashcode, self.router, current_channel=self.channel_name, comments=self.comments) # record channel of next jump in current htlc trade Channel.update_trade(self.channel_name, self.nonce, channel=channel_set.channel) APIStatistics.update_statistics(self.wallet.address, htlc_free=fee) else: # trigger RResponse Channel.update_payment(self.channel_name, self.hashcode) payment_trade = Channel.query_payment(self.channel_name, self.hashcode) if not (payment_trade and payment_trade[0]): raise GoTo( EnumResponseStatus.RESPONSE_TRADE_HASHR_NOT_FOUND, 'Rcode not found for hashcode<{}>'.format(self.hashcode)) payment_trade = payment_trade[0] try: RResponse.create(self.channel_name, self.asset_type, self.nonce, self.wallet.url, self.sender, self.hashcode, payment_trade.rcode, self.comments) # update the htlc trade history Channel.update_trade(self.channel_name, self.nonce, rcode=payment_trade.rcode) except Exception as error: LOG.exception( 'Failed triggerring to send RResponse for HashR<{}>. Exception: {}' .format(self.hashcode, error))
def handle(self): super(HtlcMessage, self).handle() trigger_rresponse = False status = EnumResponseStatus.RESPONSE_OK try: self.check_hashcode_used(self.channel_name, self.hashcode) self.check_channel_state(self.channel_name) self.check_router(self.router, self.hashcode) self.verify() _, nonce = self.check_nonce(self.nonce, self.channel_name) _, payer_balance, payee_balance = self.check_balance( self.channel_name, self.asset_type, self.sender_address, self.sender_balance, self.receiver_address, self.receiver_balance, is_htcl_type=True, payment=self.payment) sign_hashcode, sign_rcode = self.get_default_rcode() self.check_signature(self.wallet, type_list=RsmcMessage._sign_type_list, value_list=[ self.channel_name, self.nonce, self.sender_address, int(self.sender_balance), self.receiver_address, int(self.receiver_balance), sign_hashcode, sign_rcode ], signature=self.commitment) self.check_signature(self.wallet, type_list=self._sign_type_list, value_list=[ self.channel_name, self.sender_address, self.receiver_address, int(self.delay_block), int(self.payment), self.hashcode ], signature=self.delay_commitment) # transform the message to the next router if not last router node next_router = self.next_router if not self.check_if_the_last_router(): next_router = self.get_next_router() LOG.debug('Get Next Router {}'.format(str(next_router))) # to get channel channel_set = Channel.get_channel( self.wallet.url, next_router, state=EnumChannelState.OPENED) if not (channel_set and channel_set[0]): status = EnumResponseStatus.RESPONSE_CHANNEL_NOT_FOUND raise GoTo( EnumResponseStatus.RESPONSE_CHANNEL_NOT_FOUND, 'No OPENED channel is found between {} and {}.'.format( self.wallet.url, next_router)) channel_set = channel_set[0] # calculate fee and transfer to next jump fee = TrinityNumber(str(self.get_fee(self.wallet.url))).number payment = self.big_number_calculate(self.payment, fee, False) receiver = next_router self.create(self.wallet, channel_set.channel, self.asset_type, self.wallet.url, receiver, payment, self.hashcode, self.router, next_router, current_channel=self.channel_name, comments=self.comments) else: Channel.update_payment(self.channel_name, self.hashcode) payment_trade = Channel.query_payment(self.channel_name, self.hashcode) if not (payment_trade and payment_trade[0]): raise GoTo( EnumResponseStatus.RESPONSE_TRADE_HASHR_NOT_FOUND, 'Rcode not found for hashcode<{}>'.format( self.hashcode)) payment_trade = payment_trade[0] # trigger RResponse trigger_rresponse = True # send response to receiver HtlcResponsesMessage.create( self.wallet, self.channel_name, self.asset_type, self.nonce, self.sender, self.receiver, self.payment, self.sender_balance, self.receiver_balance, self.hashcode, self.delay_block, self.commitment, self.delay_commitment, self.router, next_router, self.comments) # means last receiver has received this htlc message, then update this trade record. if trigger_rresponse: try: RResponse.create(self.channel_name, self.asset_type, self.nonce, self.wallet.url, self.sender, self.hashcode, payment_trade.rcode, self.comments) # update the htlc trade history Channel.update_trade(self.channel_name, self.nonce, rcode=payment_trade.rcode) except Exception as error: LOG.error('Failed triggerring to send RResponse for HashR<{}>. Exception: {}'\ .format(self.hashcode, error)) except TrinityException as error: LOG.error(error) status = error.reason except Exception as error: LOG.error( 'Failed to handle Htlc message for channel<{}>, HashR<{}>. Exception:{}' .format(self.channel_name, self.hashcode, error)) status = EnumResponseStatus.RESPONSE_EXCEPTION_HAPPENED finally: # failed operation if EnumResponseStatus.RESPONSE_OK != status: # send error response HtlcResponsesMessage.send_error_response( self.sender, self.receiver, self.channel_name, self.asset_type, self.nonce, status) # delete some related resources self.rollback_resource(self.channel_name, self.nonce, self.payment, status.name) return