def check_nonce(cls, nonce, channel_name=''): """ :param channel_name: :param nonce: :return: """ new_nonce = Channel.new_nonce(channel_name) if not (TransactionBase._FOUNDER_NONCE < int(nonce) == new_nonce): raise GoTo( EnumResponseStatus.RESPONSE_TRADE_WITH_INCOMPATIBLE_NONCE, '{}::Channel<{}> has incompatible nonce<self: {}, peer: {}>'. format(cls.__name__, channel_name, new_nonce, nonce)) else: return True, new_nonce
def create(cls, channel_name, asset_type, sender, receiver, payment, hashcode, router, current_channel=None, comments=None): """ :param channel_name: :param asset_type: :param sender: :param receiver: :param payment: :param hashcode: :param router: :param current_channel: :param comments: :return: """ cls.check_channel_state(channel_name) cls.check_router(router, hashcode) cls.check_asset_type(asset_type) cls.check_both_urls(sender, receiver) payer_address, _, _ = uri_parser(sender) payee_address, _, _ = uri_parser(receiver) asset_type = asset_type.upper() channel = Channel(channel_name) # get nonce nonce = Channel.new_nonce(channel_name) if HtlcMessage._FOUNDER_NONCE > nonce: raise GoTo( EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE, 'HtlcMessage::create: Incorrect nonce<{}> for channel<{}>'. format(nonce, channel_name)) # to check whether previous transaction need be resigned or not resign_body, valid_trade = HtlcMessage.create_resign_message_body( sender, channel_name, nonce) # there're one trade need resign, we need adjust the nonce value if valid_trade and valid_trade.state in [ EnumTradeState.confirming.name ]: payer_balance = valid_trade.balance payee_balance = valid_trade.peer_balance else: # to get channel balance balance = channel.balance payer_balance = balance.get(payer_address).get(asset_type) payee_balance = balance.get(payee_address).get(asset_type) # To calculate the balance after payment _, payer_balance, payee_balance = HtlcMessage.calculate_balance_after_payment( payer_balance, payee_balance, payment, is_htlc_type=True) # exclude current router from the router end_block_height = cls.get_unlocked_block_height(len(router)) # generate htlc transaction and record it into database later htlc_trade = Channel.htlc_trade(type=EnumTradeType.TRADE_TYPE_HTLC, role=EnumTradeRole.TRADE_ROLE_FOUNDER, asset_type=asset_type, balance=payer_balance, peer_balance=payee_balance, payment=payment, hashcode=hashcode, delay_block=end_block_height) # record the channel if RResponse is triggered if current_channel: htlc_trade.update({'channel': current_channel}) # create message htlc_request = HtlcMessage.request(payer_balance, payee_balance, payment, hashcode, end_block_height) # has transaction which is needed to be resigned if resign_body: htlc_request.update({'ResignBody': resign_body}) # start to create message and send later message = HtlcMessage.create_message_header(sender, receiver, HtlcMessage._message_name, channel_name, asset_type, nonce) message.update({'Router': router}) message.update({'MessageBody': htlc_request}) if comments: message.update({'Comments': comments}) HtlcMessage.send(message) # record the transaction Channel.add_trade(channel_name, nonce=nonce, **htlc_trade) return None
def create(channel_name, asset_type, sender, receiver, payment, hashcode=None, comments=None): """ :param channel_name: :param asset_type: :param sender: :param receiver: :param payment: :param hashcode: :param comments: :param hlock_to_rsmc: :return: """ # check channel state RsmcMessage.check_asset_type(asset_type) channel = RsmcMessage.check_channel_state(channel_name) # get nonce in the offline account book nonce = Channel.new_nonce(channel_name) if RsmcMessage._FOUNDER_NONCE > nonce: raise GoTo( EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE, 'RsmcMessage::create: Incorrect nonce<{}> for channel<{}>'. format(nonce, channel_name)) # to get channel balance balance = channel.balance payer_address, _, _ = uri_parser(sender) payee_address, _, _ = uri_parser(receiver) asset_type = asset_type.upper() # judge whether it is htlc lock part to rsmc trade or not hlock_to_rsmc = RsmcMessage.is_hlock_to_rsmc(hashcode) _, payer_balance, payee_balance = RsmcBase.calculate_balance_after_payment( balance.get(payer_address).get(asset_type), balance.get(payee_address).get(asset_type), payment, hlock_to_rsmc=hlock_to_rsmc) # create message message_body = { 'AssetType': asset_type.upper(), 'PaymentCount': str(payment), 'SenderBalance': str(payer_balance), 'ReceiverBalance': str(payee_balance), } if hlock_to_rsmc: message_body.update({'HashR': hashcode}) # start to create message message = RsmcMessage.create_message_header(sender, receiver, RsmcMessage._message_name, channel_name, asset_type, nonce) message = message.message_header message.update({'MessageBody': message_body}) if comments: message.update({'Comments': comments}) RsmcMessage.send(message) return None
def create(channel_name, asset_type, sender, receiver, payment, hashcode=None, comments=None): """ :param channel_name: :param asset_type: :param sender: :param receiver: :param payment: :param hashcode: :param comments: :param hlock_to_rsmc: :return: """ # check channel state RsmcMessage.check_asset_type(asset_type) channel = RsmcMessage.check_channel_state(channel_name) payer_address, _, _ = uri_parser(sender) payee_address, _, _ = uri_parser(receiver) asset_type = asset_type.upper() resign_body = None # get nonce in the offline account book nonce = Channel.new_nonce(channel_name) if RsmcMessage._FOUNDER_NONCE > nonce: raise GoTo(EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE, 'RsmcMessage::create: Incorrect nonce<{}> for channel<{}>'.format(nonce, channel_name)) # to check whether there's a transaction which is needed to resign resign_body, valid_trade = RsmcMessage.create_resign_message_body(sender, channel_name, nonce) # there're one trade need resign, we need adjust the nonce value if valid_trade and valid_trade.state in [EnumTradeState.confirming.name]: payer_balance = valid_trade.balance payee_balance = valid_trade.peer_balance else: # to get channel balance balance = channel.balance payer_balance = balance.get(payer_address).get(asset_type) payee_balance = balance.get(payee_address).get(asset_type) # judge whether it is htlc lock part to rsmc trade or not hlock_to_rsmc = RsmcMessage.is_hlock_to_rsmc(hashcode) _, payer_balance, payee_balance = RsmcBase.calculate_balance_after_payment( payer_balance, payee_balance, payment, hlock_to_rsmc=hlock_to_rsmc ) # sign the trade sign_hashcode, sign_rcode = RsmcMessage.get_rcode(channel_name, hashcode) rsmc_trade = Channel.rsmc_trade( type=EnumTradeType.TRADE_TYPE_RSMC, role=EnumTradeRole.TRADE_ROLE_FOUNDER, asset_type=asset_type, balance=payer_balance, peer_balance=payee_balance, payment=payment, hashcode=sign_hashcode, rcode=sign_rcode ) # create message rsmc_request = RsmcMessage.request(asset_type, payment, payer_balance, payee_balance, hashcode) # has transaction which is needed to be resigned if resign_body: rsmc_request.update({'ResignBody': resign_body}) # start to create message message = RsmcMessage.create_message_header(sender, receiver, RsmcMessage._message_name, channel_name, asset_type, nonce) message.update({'MessageBody': rsmc_request}) if comments: message.update({'Comments': comments}) RsmcMessage.send(message) # record the transaction Channel.add_trade(channel_name, nonce=nonce, **rsmc_trade) APIStatistics.update_statistics(payer_address, rsmc='rsmc') return None
def create(cls, wallet, channel_name, asset_type, sender, receiver, payment, hashcode, router, next_router, current_channel=None, comments=None): """ :param channel_name: :param wallet: :param sender: :param receiver: :param asset_type: :param payment: :param nonce: :param hashcode: :param router: :param next_router: :param comments: :return: """ cls.check_channel_state(channel_name) cls.check_router(router, hashcode) cls.check_asset_type(asset_type) cls.check_both_urls(sender, receiver) cls.check_router(router, hashcode) # get nonce nonce = Channel.new_nonce(channel_name) if HtlcMessage._FOUNDER_NONCE > nonce: raise GoTo( EnumResponseStatus.RESPONSE_TRADE_WITH_INCORRECT_NONCE, 'HtlcMessage::create: Incorrect nonce<{}> for channel<{}>'. format(nonce, channel_name)) # get sender & receiver address from sender or receiver payer_address, _, _ = uri_parser(sender) payee_address, _, _ = uri_parser(receiver) asset_type = asset_type.upper() # check whether the balance is enough or not channel = Channel(channel_name) balance = channel.balance _, payer_balance, payee_balance = HtlcMessage.calculate_balance_after_payment( balance.get(payer_address, {}).get(asset_type), balance.get(payee_address, {}).get(asset_type), payment, is_htlc_type=True) # calculate the end block height jumps_index = HtlcMessage.this_jump(sender, router) end_block_height = cls.get_locked_block_height(len(router), jumps_index) # Htlc is made up of 2 parts: rsmc and hlock part sign_hashcode, sign_rcode = cls.get_default_rcode() rsmc_commitment = HtlcMessage.sign_content( typeList=RsmcMessage._sign_type_list, valueList=[ channel_name, nonce, payer_address, payer_balance, payee_address, payee_balance, sign_hashcode, sign_rcode ], privtKey=wallet._key.private_key_string) # hlock parts hlock_commitment = HtlcMessage.sign_content( start=5, typeList=HtlcMessage._sign_type_list, valueList=[ channel_name, payer_address, payee_address, end_block_height, int(payment), hashcode ], privtKey=wallet._key.private_key_string) # # add trade to database htlc_trade = Channel.htlc_trade(type=EnumTradeType.TRADE_TYPE_HTLC, role=EnumTradeRole.TRADE_ROLE_FOUNDER, asset_type=asset_type, balance=payer_balance, peer_balance=payee_balance, payment=payment, hashcode=hashcode, delay_block=end_block_height, commitment=rsmc_commitment, delay_commitment=hlock_commitment) if current_channel: htlc_trade.update({'channel': current_channel}) Channel.add_trade(channel_name, nonce=nonce, **htlc_trade) # generate the messages message_body = { 'SenderBalance': payer_balance, 'ReceiverBalance': payee_balance, 'Commitment': rsmc_commitment, 'Payment': payment, 'DelayBlock': end_block_height, 'DelayCommitment': hlock_commitment, 'HashR': hashcode } message = HtlcMessage.create_message_header(sender, receiver, HtlcMessage._message_name, channel_name, asset_type, nonce) message = message.message_header message.update({ 'Router': router, 'Next': next_router, }) message.update({'MessageBody': message_body}) if comments: message.update({'Comments': comments}) HtlcMessage.send(message) return None