def __init__(self, message): self.message = message self.sender = message.get('Sender') self.sender_address, _, _ = uri_parser(self.sender) self.receiver = message.get('Receiver') self.receiver_address, _, _, = uri_parser(self.receiver) self.message_type = message.get('MessageType', '') self.message_body = message.get('MessageBody') self.resign_body = self.message_body.get('ResignBody') self.channel_name = message.get('ChannelName') self.asset_type = message.get('AssetType', 'INVALID_ASSET').upper() self.net_magic = message.get('NetMagic') self.status = message.get('Status') self.comments = self.message.get('Comments') self.nonce = int(message.get('TxNonce')) try: self.nego_nonce = int(message.get('ResetTxNonce')) except: self.nego_nonce = None # transaction is triggered by command cline trigger_by_cli = int(self.message_body.get('TriggeredByCLI', 0)) self.trigger_by_cli = True if trigger_by_cli else False
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)
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
def __init__(self, message): self.message = message self.sender = message.get('Sender') self.sender_address, _, _ = uri_parser(self.sender) self.receiver = message.get('Receiver') self.receiver_address, _, _, = uri_parser(self.receiver) self.message_type = message.get('MessageType') self.message_body = message.get('MessageBody') self.channel_name = message.get('ChannelName') self.asset_type = message.get('AssetType', 'INVALID_ASSET').upper() self.nonce = int(message.get('TxNonce')) self.net_magic = message.get('NetMagic') self.status = message.get('Status') self.comments = self.message.get('Comments')
def create(channel_name, asset_type, nonce, sender, receiver, hashcode, rcode, comments=None): """ :param channel_name: :param asset_type: :param nonce: :param sender: :param receiver: :param hashcode: :param value: :param comments: :return: """ htlc_trade = RResponse.get_htlc_trade_by_hashr(channel_name, hashcode) asset_type = asset_type.upper() payer_address, _, _ = uri_parser(receiver) payment = htlc_trade.payment message = RResponse.create_message_header(sender, receiver, RResponse._message_name, channel_name, asset_type, nonce) message = message.message_header message_body = { "HashR": hashcode, "R": rcode, "PaymentCount": payment, } message.update({'MessageBody': message_body}) if comments: message.update({'Comments': comments}) RResponse.send(message)
def create(wallet, channel_name, asset_type, founder, founder_deposit, partner, partner_deposit, founder_commitment, comments=None): """ :param wallet: :param channel_name: :param asset_type: :param founder: :param founder_deposit: :param partner: :param partner_deposit: :param founder_commitment: :param comments: :return: """ # check the deposit founder_deposit = int(founder_deposit) partner_deposit = int(partner_deposit) FounderResponsesMessage.check_deposit(founder_deposit, partner_deposit) nonce = FounderResponsesMessage._FOUNDER_NONCE # start to sign content founder_address, _, _ = uri_parser(founder) partner_address, _, _ = uri_parser(partner) # Sign this data to the commitment = FounderResponsesMessage.sign_content( wallet, FounderResponsesMessage._sign_type_list, [ channel_name, nonce, founder_address, founder_deposit, partner_address, partner_deposit ]) # start add channel deposit = { founder_address: { asset_type: str(founder_deposit) }, partner_address: { asset_type: str(partner_deposit) } } hlock = { founder_address: { asset_type: '0' }, partner_address: { asset_type: '0' } } Channel.add_channel(channel=channel_name, src_addr=founder, dest_addr=partner, state=EnumChannelState.INIT.name, deposit=deposit, hlock=hlock, magic=get_magic()) APIStatistics.update_statistics(wallet.address, state=EnumChannelState.INIT.name) # add trade to database founder_trade = Channel.founder_trade( type=EnumTradeType.TRADE_TYPE_FOUNDER, role=EnumTradeRole.TRADE_ROLE_PARTNER, asset_type=asset_type, balance=partner_deposit, peer_balance=founder_deposit, commitment=commitment, peer_commitment=founder_commitment, state=EnumTradeState.confirming) Channel.add_trade(channel_name, nonce=nonce, **founder_trade) # create messages asset_type = asset_type.upper() message = FounderResponsesMessage.create_message_header( partner, founder, FounderResponsesMessage._message_name, channel_name, asset_type, nonce) message_body = {"Commitment": commitment} message.update({"MessageBody": message_body}) # Add comments in the messages if comments: message.update({"Comments": comments}) # fill message status message.update({'Status': EnumResponseStatus.RESPONSE_OK.name}) # send message to peer FounderResponsesMessage.send(message) return
def create(wallet, channel_name, asset_type, founder, founder_deposit, partner, partner_deposit=None, comments=None): """ :param wallet: :param channel_name: :param asset_type: :param founder: :param founder_deposit: :param partner: :param partner_deposit: :param comments: :return: """ founder_deposit = int(founder_deposit) if partner_deposit is None: partner_deposit = founder_deposit partner_deposit = int(partner_deposit) # check the deposit FounderMessage.check_deposit(founder_deposit, partner_deposit) # get addresses of peers nonce = FounderMessage._FOUNDER_NONCE founder_address, _, _ = uri_parser(founder) partner_address, _, _ = uri_parser(partner) # Sign this data to hash value commitment = FounderMessage.sign_content( wallet, FounderMessage._sign_type_list, [ channel_name, nonce, founder_address, founder_deposit, partner_address, partner_deposit ]) # add channel asset_type = asset_type.upper() deposit = { founder_address: { asset_type: str(founder_deposit) }, partner_address: { asset_type: str(partner_deposit) } } hlock = { founder_address: { asset_type: '0' }, partner_address: { asset_type: '0' } } Channel.add_channel(channel=channel_name, src_addr=founder, dest_addr=partner, state=EnumChannelState.INIT.name, deposit=deposit, magic=get_magic(), hlock=hlock) APIStatistics.update_statistics(wallet.address, state=EnumChannelState.INIT.name) # record the transaction founder_trade = Channel.founder_trade( type=EnumTradeType.TRADE_TYPE_FOUNDER, role=EnumTradeRole.TRADE_ROLE_FOUNDER, asset_type=asset_type, balance=founder_deposit, peer_balance=partner_deposit, commitment=commitment) Channel.add_trade(channel_name, nonce=nonce, **founder_trade) # create founder request message message = FounderMessage.create_message_header( founder, partner, FounderMessage._message_name, channel_name, asset_type, nonce) message_body = { "FounderDeposit": str(founder_deposit), "PartnerDeposit": str(partner_deposit), "Commitment": commitment, } message.update({'MessageBody': message_body}) # Add comments in the messages if comments: message.update({"Comments": comments}) FounderMessage.send(message) return
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) 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 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)
def force_release_htlc(cls, uri='', channel_name='', hashcode='', rcode='', sign_key='', gwei_coef=1, trigger=None, is_debug=False, is_pubnishment=False, htcl_to_rsmc=False): """ :param uri: :param channel_name: :param hashcode: :param rcode: :param sign_key: :param gwei_coef: :param trigger: :param is_debug: :param htcl_to_rsmc: :return: """ # some internal function here # ToDo: not a good way, could be optimized later def common_kwargs_for_trigger(invoker, channel_id, lock_hash, lock_secret, invoker_key, gwei_coef=1): # makeup the parameters for callback return { 'invoker': invoker, 'channel_id': channel_id, 'lock_hash': lock_hash, 'lock_secret': lock_secret, 'invoker_key': invoker_key, 'gwei_coef': gwei_coef } def unlock_htlc_kwargs(trade, address, peer_address, is_debug): """""" trigger_kwargs = { 'lock_period': trade.delay_block, 'lock_amount': trade.payment } # is debug by test engineer if not is_debug: trigger_kwargs.update({'lock_secret': htlc_trade.rcode}) # what role is played by this wallet if EnumTradeRole.TRADE_ROLE_FOUNDER.name == trade.role: trigger_kwargs.update({ 'founder': address, 'founder_signature': trade.delay_commitment, 'partner': peer_address, 'partner_signature': trade.peer_delay_commitment }) else: trigger_kwargs.update({ 'founder': peer_address, 'founder_signature': trade.peer_delay_commitment, 'partner': address, 'partner_signature': trade.delay_commitment }) return trigger_kwargs def punishment_htlc_kwargs(trade, address, peer_address): """""" trigger_kwargs = { 'nonce': trade.nonce, 'lock_secret': htlc_trade.rcode } # what role is played by this wallet if EnumTradeRole.TRADE_ROLE_FOUNDER.name == trade.role: trigger_kwargs.update({ 'founder': address, 'partner': peer_address, 'founder_balance': trade.balance, 'partner_balance': trade.peer_balance, 'founder_signature': trade.commitment, 'partner_signature': trade.peer_commitment }) else: trigger_kwargs.update({ 'founder': peer_address, 'partner': address, 'founder_balance': trade.peer_balance, 'partner_balance': trade.balance, 'founder_signature': trade.peer_commitment, 'partner_signature': trade.commitment }) return trigger_kwargs # start to unlock the payment of htlc-locked part try: # get the htlc record by hashcode htlc_trade = cls.batch_query_trade( channel_name, filters={ 'type': EnumTradeType.TRADE_TYPE_HTLC.name, 'hashcode': hashcode })[0] # if the state of this trasaction is confirming, no need to update transaction rsmc_trade = None if is_pubnishment: rsmc_trade = cls.batch_query_trade( channel_name, filters={ 'type': EnumTradeType.TRADE_TYPE_RSMC.name, 'hashcode': hashcode }) rsmc_trade = rsmc_trade[0] if rsmc_trade else None # no action Rsmc trade with this HashR has already existed and the state of trade is confirmed if rsmc_trade and rsmc_trade.state in [ EnumTradeState.confirmed.name ]: # to trigger the htlc punishment and close the channel pass else: # Below actions are needed: # step 1 : validate the R-code # step 2 : update the R-code to htlc trade LOG.info( 'No need to punish hlock transaction with HashR<{}>'. format(hashcode)) # to record this rcode if rcode is correct one if Payment.verify_hr(hashcode, rcode): cls.update_trade(channel_name, htlc_trade.nonce, rcode=rcode) # here, we need to notify the rcode to next wallet if htcl_to_rsmc: cls.notify_rcode_to_next_peer(htlc_trade, rcode) return {'result': 'success'} except Exception as error: LOG.error('No Htlc trade was found or rcode is error. channel<{}>, HashR<{}>. Exception: {}' \ .format(channel_name, hashcode, error)) else: channel = cls(channel_name) peer_uri = channel.peer_uri(uri) self_address, _, _ = uri_parser(uri) peer_address, _, _ = uri_parser(peer_uri) LOG.debug('Unlock Htlc payment: channel<{}>, HashR<{}>'.format( channel_name, hashcode)) # makeup the parameters for callback function trigger_kwargs = common_kwargs_for_trigger(self_address, channel_name, hashcode, rcode, sign_key, gwei_coef) # is withdraw update topic of the contract if is_pubnishment: trigger_kwargs.update( punishment_htlc_kwargs(rsmc_trade, self_address, peer_address)) else: trigger_kwargs.update( unlock_htlc_kwargs(htlc_trade, self_address, peer_address, is_debug)) # start trigger the callback and return the result. LOG.debug('Force to unlock htlc with aruments: {}'.format( trigger_kwargs)) return trigger(**trigger_kwargs) return None
def force_release_rsmc(cls, uri=None, channel_name=None, nonce=None, sign_key=None, gwei_coef=1, trigger=None, is_debug=False): """ :param uri: :param channel_name: :param nonce: :param sign_key: :param gwei_coef: :param trigger: :return: """ if not (uri and channel_name and sign_key and trigger): LOG.warn( 'uri<{}>, channel_name<{}>, trigger<{}> and sign_key should not be none' .format(uri, channel_name, trigger)) return None try: # get records by nonce from the trade history if is_debug and nonce is not None: trade = cls.query_trade(channel_name, int(nonce)) else: trade = cls.latest_confirmed_trade(channel_name) latest_nonce = int(trade.nonce) if nonce is not None and (latest_nonce == int(nonce) or int(nonce) > latest_nonce + 1): LOG.debug( 'No need update transaction. nonce<{}>, latest_nonce<{}>' .format(nonce, latest_nonce)) # update the channel to settling state Channel.update_channel( channel_name, state=EnumChannelState.SETTLING.name) return None nonce = latest_nonce except Exception as error: LOG.error('No trade record could be forced to release. channel<{}>, nonce<{}>. Exception: {}' \ .format(channel_name, nonce, error)) else: channel = cls(channel_name) peer_uri = channel.peer_uri(uri) self_address, _, _ = uri_parser(uri) peer_address, _, _ = uri_parser(peer_uri) LOG.debug('Force to close channel<{}> with nonce<{}>'.format( channel_name, nonce)) LOG.debug('Trade nonce: {}'.format(trade.nonce)) # get hashcode and rcode hashcode = None rcode = None if trade.nonce not in [0, 1]: hashcode = trade.hashcode rcode = trade.rcode trade_role = trade.role if EnumTradeRole.TRADE_ROLE_FOUNDER.name == trade_role: result = trigger(self_address, channel_name, nonce, self_address, trade.balance, peer_address, trade.peer_balance, hashcode, rcode, trade.commitment, trade.peer_commitment, sign_key, gwei_coef) else: result = trigger(self_address, channel_name, nonce, peer_address, trade.peer_balance, self_address, trade.balance, hashcode, rcode, trade.peer_commitment, trade.commitment, sign_key, gwei_coef) return result return None
def rsmc_sign(cls, wallet, channel_name, asset_type, nonce, sender, receiver, payment, sender_balance, receiver_balance, role_index=0, hashcode=None, comments=None): """ Descriptions: create and send RsmcSign messages. :param wallet: :param channel_name: :param asset_type: :param nonce: :param sender: :param receiver: :param payment: :param sender_balance: :param receiver_balance: :param role_index: :param comments: :param hashcode: :return: """ asset_type = asset_type.upper() # different ROLE by role index role_index = int(role_index) payer, payee = RsmcMessage.get_payer_and_payee(role_index, sender, receiver) payer_address, _, _ = uri_parser(payer) payee_address, _, _ = uri_parser(payee) # check balance is_hlock_to_rsmc = RsmcResponsesMessage.is_hlock_to_rsmc(hashcode) _, payer_balance, payee_balance = RsmcResponsesMessage.check_balance( channel_name, asset_type, payer_address, sender_balance, payee_address, receiver_balance, hlock_to_rsmc=is_hlock_to_rsmc, payment=payment) # sign the trade sign_hashcode, sign_rcode = cls.get_rcode(channel_name, hashcode) commitment = RsmcResponsesMessage.sign_content( typeList=RsmcResponsesMessage._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) # add trade to database if 0 == role_index: trade_role = EnumTradeRole.TRADE_ROLE_PARTNER self_balance = payee_balance peer_balance = payer_balance else: trade_role = EnumTradeRole.TRADE_ROLE_FOUNDER self_balance = payer_balance peer_balance = payee_balance # ToDo: need re-sign all unconfirmed htlc message later rsmc_trade = Channel.rsmc_trade(type=EnumTradeType.TRADE_TYPE_RSMC, role=trade_role, asset_type=asset_type, balance=self_balance, peer_balance=peer_balance, payment=payment, hashcode=sign_hashcode, rcode=sign_rcode, commitment=commitment) Channel.add_trade(channel_name, nonce=nonce, **rsmc_trade) # update message body message_body = { 'AssetType': asset_type.upper(), 'PaymentCount': str(payment), 'SenderBalance': str(payer_balance), 'ReceiverBalance': str(payee_balance), 'Commitment': commitment, 'RoleIndex': str(role_index), } if hashcode: message_body.update({'HashR': hashcode}) # generate the message header message = RsmcResponsesMessage.create_message_header( receiver, sender, RsmcResponsesMessage._message_name, channel_name, asset_type, nonce) message = message.message_header # to send response OK message message.update({'MessageBody': message_body}) message.update({'Status': EnumResponseStatus.RESPONSE_OK.name}) if comments: message.update({'Comments': comments}) # send RsmcSign message RsmcResponsesMessage.send(message) return
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(cls, wallet, channel_name, asset_type, tx_nonce, sender, receiver, payment, sender_balance, receiver_balance, hashcode, delay_block, peer_commitment, peer_hlock_commitment, router, next_router, comments=None): """ :param wallet: :param channel_name: :param asset_type: :param tx_nonce: :param sender: :param receiver: :param payment: :param sender_balance: :param receiver_balance: :param hashcode: :param delay_block: :param peer_commitment: :param peer_hlock_commitment: :param router: :param next_router: :param comments: :return: """ # get nonce from latest trade _, nonce = HtlcResponsesMessage.check_nonce(tx_nonce, channel_name) # start to verify balance payer_address, _, _ = uri_parser(sender) payee_address, _, _ = uri_parser(receiver) asset_type = asset_type.upper() # check balance _, payer_balance, payee_balance = HtlcResponsesMessage.check_balance( channel_name, asset_type, payer_address, sender_balance, payee_address, receiver_balance, is_htcl_type=True, payment=payment) # 2 parts in htlc message: conclusive and inconclusive part sign_hashcode, sign_rcode = cls.get_default_rcode() rsmc_commitment = HtlcResponsesMessage.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_commitment = HtlcResponsesMessage.sign_content( start=5, typeList=HtlcResponsesMessage._sign_type_list, valueList=[ channel_name, payer_address, payee_address, delay_block, int(payment), hashcode ], privtKey=wallet._key.private_key_string) # # ToDo: need re-sign all unconfirmed htlc message later htlc_trade = Channel.htlc_trade( type=EnumTradeType.TRADE_TYPE_HTLC, role=EnumTradeRole.TRADE_ROLE_PARTNER, asset_type=asset_type, balance=payee_balance, peer_balance=payer_balance, payment=payment, hashcode=hashcode, delay_block=delay_block, commitment=rsmc_commitment, peer_commitment=peer_commitment, delay_commitment=hlock_commitment, peer_delay_commitment=peer_hlock_commitment, channel=channel_name) Channel.add_trade(channel_name, nonce=nonce, **htlc_trade) # create message message = HtlcResponsesMessage.create_message_header( receiver, sender, HtlcResponsesMessage._message_name, channel_name, asset_type, tx_nonce) message = message.message_header message.update({ 'Router': router, 'Next': next_router, }) message_body = { 'SenderBalance': payer_balance, 'ReceiverBalance': payee_balance, 'Commitment': rsmc_commitment, 'Payment': payment, 'DelayBlock': delay_block, 'DelayCommitment': hlock_commitment, 'HashR': hashcode } # orgnize the message message.update({'MessageBody': message_body}) message.update({'Status': EnumResponseStatus.RESPONSE_OK.name}) if comments: message.update({'Comments': comments}) # Before the response ok, we could update the channel balance HtlcResponsesMessage.update_balance_for_channel(channel_name, asset_type, payer_address, payee_address, payment, is_htlc_type=True) # send response ok message to peer HtlcResponsesMessage.send(message) return
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