def digest(self): return remove_0x_prefix( encode_hex( hash_array([ decode_hex(self.terms_of_service_digest), decode_hex(self.privacy_policy_digest) ])))
def normalize_tokens(transactions): return normalize_size(transactions, { 'left': 0, 'merkle_root': '0x0000000000000000000000000000000000000000', 'right': 0, 'hash': crypto.decode_hex(ZERO_CHECKSUM) })
def normalize_transfers(transfers, upper_bound): return normalize_size( transfers, { 'wallet': '0x0000000000000000000000000000000000000000', 'left': int(upper_bound), 'right': int(upper_bound), 'nonce': 0, 'hash': crypto.decode_hex(ZERO_CHECKSUM) })
def normalize_transactions(transactions): return normalize_size( transactions, { 'wallet': '0x0000000000000000000000000000000000000000', 'amount': 0, 'recipient_trail_identifier': 0, 'nonce': 0, 'hash': crypto.decode_hex(ZERO_CHECKSUM) })
def checksum(self): representation = [ keccak(crypto.address(settings.HUB_LQD_CONTRACT_ADDRESS)), keccak(crypto.address(self.wallet.token.address)), keccak(crypto.address(self.wallet.address)), crypto.uint64(self.wallet.trail_identifier if self.wallet. trail_identifier is not None else 0), crypto.uint256(self.eon_number), crypto.decode_hex(self.tx_set_hash), crypto.uint256(self.updated_spendings), crypto.uint256(self.updated_gains) ] return crypto.hash_array(representation)
def build_stack_from_cache(merkle_hash_cache, merkle_height_cache): if merkle_hash_cache == '' or merkle_hash_cache is None: return [] merkle_hash_stack = merkle_hash_cache.split(',') merkle_height_stack = merkle_height_cache.split(',') assert (len(merkle_hash_stack) == len(merkle_height_stack)) merkle_hash_stack = [crypto.decode_hex(item) for item in merkle_hash_stack] merkle_height_stack = [int(item) for item in merkle_height_stack] return [{ 'hash': hash_value, 'height': height_value } for hash_value, height_value in zip(merkle_hash_stack, merkle_height_stack)]
def is_valid(self): return crypto.verify_message_signature(crypto.address(self.wallet.address), crypto.decode_hex( self.checksum), self.vrs())
def place_parallel_withdrawals(test_case: RPCTestCase, token, wallet_address, current_eon, dishonest=False): token_commitment = TokenCommitment.objects.get( token=token, root_commitment__eon_number=current_eon - 1) wallet = Wallet.objects.get(token=token, address=remove_0x_prefix(wallet_address)) wallet_transfer_context = WalletTransferContext(wallet=wallet, transfer=None) allotment = wallet_transfer_context.balance_as_of_eon( eon_number=current_eon - 1) passive_checksum, passive_amount, passive_marker = wallet_transfer_context.get_passive_values( eon_number=current_eon - 1) available_balance = wallet_transfer_context.loosely_available_funds_at_eon( eon_number=current_eon, current_eon_number=current_eon, is_checkpoint_created=True, only_appended=True) overdraw = dishonest and available_balance < allotment.amount() if overdraw: total_draw = max(available_balance, allotment.amount()) // 4 else: total_draw = min(available_balance, allotment.amount()) // 4 total_amount = 0 if (total_draw == 0): return (total_amount, [], False) withdrawal_amounts = [total_draw // 4, total_draw // 2, total_draw // 4] for withdrawal_amount in withdrawal_amounts: cyan([ wallet.address, wallet.token.address, withdrawal_amount, available_balance ]) test_case.contract_interface.withdraw( token_address=wallet.token.address, wallet=wallet.address, active_state_checksum=crypto.zfill( allotment.active_state_checksum()), trail=int(allotment.merkle_proof_trail), allotment_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( allotment.merkle_proof_hashes, 64) ], membership_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( token_commitment.membership_hashes, 64) ], values=csf_to_list(allotment.merkle_proof_values, int), exclusive_allotment_interval=[ int(allotment.left), int(allotment.right) ], withdrawal_amount=int(withdrawal_amount), passive_checksum=passive_checksum, passive_amount=passive_amount, passive_marker=passive_marker) total_amount += int(withdrawal_amount) return (total_amount, withdrawal_amounts, overdraw)
def respond_to_challenges(): contract_interface = NOCUSTContractInterface() contract_interface.get_current_eon_number() latest_root_commitment = RootCommitment.objects\ .all()\ .order_by('eon_number')\ .last() if latest_root_commitment is None: return with Challenge.global_lock(): challenges = Challenge.objects\ .filter(rebuted=False, eon_number__lte=latest_root_commitment.eon_number)\ .order_by('block') for challenge in challenges: token = challenge.wallet.token challenge_entry_token = token.address if challenge.wallet.token != challenge.recipient.token: try: tp = TokenPair.objects.get( token_from=challenge.wallet.token, token_to=challenge.recipient.token) except TokenPair.DoesNotExist: logger.warning( "Skipping challenge for {}. token pair not found!". format(challenge.wallet.address)) continue token = challenge.recipient.token challenge_entry_token = to_checksum_address(tp.conduit) challenge_entry = contract_interface.get_challenge_record( token_address=challenge_entry_token, recipient=challenge.recipient.address, sender=challenge.wallet.address) if not challenge_entry.challengeStage: logger.warning( "Skipping answered challenge for {}. Where is the answer tx_id?" .format(challenge.wallet.address)) continue try: recipient_balance = ExclusiveBalanceAllotment.objects.get( wallet=challenge.recipient, eon_number=challenge.eon_number) except ExclusiveBalanceAllotment.DoesNotExist: logger.error("Could not find balance for {} at eon {}.".format( challenge.wallet.address, challenge.eon_number)) send_admin_email(subject='DISPUTE! NO BALANCE!', content='{}'.format(challenge.wallet.address)) return token_commitment = TokenCommitment.objects.get( token=token, root_commitment__eon_number=challenge.eon_number) # state update challenge if challenge.wallet.token == challenge.recipient.token and challenge.wallet.address == challenge.recipient.address: v_0, r_0, s_0 = recipient_balance.wallet_v_r_s() v_1, r_1, s_1 = recipient_balance.operator_v_r_s() recipient_transfer_context = WalletTransferContext( wallet=challenge.recipient, transfer=None) passive_checksum, passive_amount, passive_marker = recipient_transfer_context.get_passive_values( eon_number=challenge_entry.initialStateEon) logger.info( "Answering challenge for {} with balance {}.".format( challenge.wallet.address, recipient_balance.amount())) logger.info("{}{}{}, {}{}{}".format(v_0, r_0, s_0, v_1, r_1, s_1)) send_admin_email(subject='DISPUTE! Sate Update.', content='{}'.format(challenge.wallet.address)) # TODO signal critical failure if this does not succeed! transaction = contract_interface.queue_answer_state_update_challenge( challenge=challenge, allotment_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( recipient_balance.merkle_proof_hashes, 64) ], membership_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( token_commitment.membership_hashes, 64) ], values=csf_to_list(recipient_balance.merkle_proof_values, int), l_r=[ int(recipient_balance.left), int(recipient_balance.right) ], tx_set_root=crypto.zfill( crypto.decode_hex( recipient_balance.transaction_set_root())), deltas=[d for d in recipient_balance.deltas()], r=[crypto.uint256(r_0), crypto.uint256(r_1)], s=[crypto.uint256(s_0), crypto.uint256(s_1)], v=[v_0, v_1], passive_checksum=passive_checksum, passive_amount=passive_amount, passive_marker=passive_marker) # transfer challenge elif challenge.wallet.token == challenge.recipient.token and challenge.wallet.address != challenge.recipient.address: try: transfer = Transfer.objects.get( recipient=challenge.recipient, eon_number=challenge_entry.initialStateEon, nonce=challenge_entry.deliveredTxNonce) except Transfer.DoesNotExist: logger.error( "Could not find transfer for {} at eon {} with nonce {}." .format(challenge.recipient.address, challenge.eon_number, challenge_entry.deliveredTxNonce)) send_admin_email( subject='DISPUTE! NO TRANSFER!', content= "Could not find transfer for {} at eon {} with nonce {}." .format(challenge.recipient.address, challenge.eon_number, challenge_entry.deliveredTxNonce)) return recipient_transfer_context = WalletTransferContext( wallet=challenge.recipient, transfer=None) transfers_list_nonce_index_map = {} transfers_list = recipient_transfer_context.authorized_transfers_list_shorthand( only_appended=True, force_append=False, eon_number=challenge_entry.initialStateEon, last_transfer_is_finalized=False, index_map=transfers_list_nonce_index_map) transfer_tree = TransactionMerkleTree(transfers_list) transfer_index = transfers_list_nonce_index_map.get( transfer.nonce) transfer_node = transfer_tree.merkle_tree_leaf_map.get( transfer_index) transfer_proof = [ node.get('hash') for node in calculate_merkle_proof( transfer_index, transfer_node) ] passive_checksum, passive_amount, passive_marker = recipient_transfer_context.get_passive_values( eon_number=challenge_entry.initialStateEon) send_admin_email(subject='DISPUTE! Transfer Delivery.', content='{} {} {}'.format( challenge.wallet.address, challenge.recipient.address, transfer_index)) # TODO signal critical failure if this does not succeed! transaction = contract_interface.queue_answer_delivery_challenge( challenge=challenge, tx_trail=transfer_index, allotment_chain=[ crypto.zfill(crypto.decode_hex(v)) for v in long_string_to_list( recipient_balance.merkle_proof_hashes, 64) ], membership_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( token_commitment.membership_hashes, 64) ], values=csf_to_list(recipient_balance.merkle_proof_values, int), l_r=[ int(recipient_balance.left), int(recipient_balance.right) ], deltas=[d for d in recipient_balance.deltas()], tx_set_root=crypto.decode_hex( recipient_balance.transaction_set_root()), tx_chain=[crypto.zfill(x) for x in transfer_proof], passive_checksum=passive_checksum, passive_amount=passive_amount, passive_marker=passive_marker) # swap challenge elif challenge.wallet.token != challenge.recipient.token and challenge.wallet.address == challenge.recipient.address: try: transfer = Transfer.objects.get( recipient=challenge.recipient, eon_number=challenge_entry.initialStateEon, nonce=challenge_entry.deliveredTxNonce) except Transfer.DoesNotExist: logger.error( "Could not find transfer for {} at eon {} with nonce {}." .format(challenge.recipient.address, challenge.eon_number, challenge_entry.deliveredTxNonce)) send_admin_email( subject='DISPUTE! NO SWAP!', content= "Could not find transfer for {} at eon {} with nonce {}." .format(challenge.recipient.address, challenge.eon_number, challenge_entry.deliveredTxNonce)) return recipient_transfer_context = WalletTransferContext( wallet=challenge.recipient, transfer=None) # if not initial transfer in a multi eon swap # override starting balance to cached starting balance if Transfer.objects.filter(eon_number=transfer.eon_number - 1, tx_id=transfer.tx_id).exists(): starting_balance = int(transfer.recipient_starting_balance) else: starting_balance = int( recipient_transfer_context.starting_balance_in_eon( challenge_entry.initialStateEon)) transfers_list_nonce_index_map = {} transfers_list = recipient_transfer_context.authorized_transfers_list_shorthand( only_appended=True, force_append=False, eon_number=challenge_entry.initialStateEon, last_transfer_is_finalized=True, index_map=transfers_list_nonce_index_map, starting_balance=starting_balance) transfer_tree = TransactionMerkleTree(transfers_list) transfer_index = transfers_list_nonce_index_map.get( transfer.nonce) transfer_node = transfer_tree.merkle_tree_leaf_map.get( transfer_index) transfer_proof = [ node.get('hash') for node in calculate_merkle_proof( transfer_index, transfer_node) ] passive_checksum, passive_amount, passive_marker = recipient_transfer_context.get_passive_values( eon_number=challenge_entry.initialStateEon) send_admin_email(subject='DISPUTE! Swap Delivery.', content='{} {} {}'.format( challenge.wallet.address, challenge.recipient.address, transfer_index)) is_cancelled = transfer.cancelled and transfer.recipient_cancellation_active_state is not None if transfer.complete or is_cancelled: starting_balance = 2**256 - 1 # TODO signal critical failure if this does not succeed! transaction = contract_interface.queue_answer_swap_challenge( challenge=challenge, token_pair=[ challenge.wallet.token.address, challenge.recipient.token.address ], balance_at_start_of_eon=starting_balance, tx_trail=int(transfer_index), allotment_chain=[ crypto.zfill(crypto.decode_hex(v)) for v in long_string_to_list( recipient_balance.merkle_proof_hashes, 64) ], membership_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( token_commitment.membership_hashes, 64) ], values=csf_to_list(recipient_balance.merkle_proof_values, int), l_r=[ int(recipient_balance.left), int(recipient_balance.right) ], deltas=[d for d in recipient_balance.deltas()], tx_set_root=crypto.zfill( crypto.decode_hex( recipient_balance.transaction_set_root())), tx_chain=[crypto.zfill(x) for x in transfer_proof], passive_checksum=passive_checksum, passive_amount=passive_amount, passive_marker=passive_marker) challenge.rebuted = True challenge.save() logger.warning(transaction)
def init_swap_challenge(test_case: RPCTestCase, swap: Transfer, eon_number): sender_transfer_context = WalletTransferContext(wallet=swap.wallet, transfer=None) if Transfer.objects.filter(eon_number=swap.eon_number - 1, tx_id=swap.tx_id).exists(): starting_balance = int(swap.sender_starting_balance) else: starting_balance = int( sender_transfer_context.starting_balance_in_eon(eon_number)) transfers_list_nonce_index_map = {} transfers_list = sender_transfer_context.authorized_transfers_list_shorthand( only_appended=True, force_append=False, eon_number=eon_number, last_transfer_is_finalized=True, index_map=transfers_list_nonce_index_map, starting_balance=starting_balance) sender_active_state = sender_transfer_context.last_appended_active_state( eon_number=eon_number) transfer_tree = TransactionMerkleTree(transfers_list) transfer_index = transfers_list_nonce_index_map.get(int(swap.nonce)) transfer_node = transfer_tree.merkle_tree_leaf_map.get(transfer_index) transfer_proof = [ node.get('hash') for node in calculate_merkle_proof(transfer_index, transfer_node) ] test_case.assertEqual(sender_active_state.tx_set_hash, crypto.hex_value(transfer_tree.root_hash())) tx_set_root = crypto.zfill( crypto.decode_hex(sender_active_state.tx_set_hash)) deltas = [ int(sender_active_state.updated_spendings), int(sender_active_state.updated_gains) ] test_case.assertTrue( test_case.contract_interface.check_merkle_membership_proof( trail=int(transfer_index), chain=[crypto.zfill(x) for x in transfer_proof], node=transfer_node.get('hash'), merkle_root=tx_set_root)) token_commitment = TokenCommitment.objects.get( token=swap.wallet.token, root_commitment__eon_number=eon_number + 1) v, r, s = sender_active_state.operator_signature.vrs() # swap_sender_balance = sender_transfer_context.balance_as_of_eon( # eon_number) sender_balance = sender_transfer_context.balance_as_of_eon(eon_number + 1) passive_checksum, passive_amount, passive_marker = sender_transfer_context.get_passive_values( eon_number=eon_number + 1) swap_order = [ int(swap.amount), # sell int(swap.amount_swapped), # buy # int(swap_sender_balance.right - swap_sender_balance.left), starting_balance, # balance int(swap.nonce) ] # nonce chain_transition_checksum = test_case.contract_interface.check_proof_of_transition_agreement( token_address=swap.wallet.token.address, holder=swap.wallet.address, trail_identifier=swap.wallet.trail_identifier, eon_number=eon_number, tx_set_root=tx_set_root, deltas=deltas, attester=settings.HUB_OWNER_ACCOUNT_ADDRESS, r=crypto.uint256(r), s=crypto.uint256(s), v=v) test_case.assertEqual(crypto.hex_value(sender_active_state.checksum()), crypto.hex_value(chain_transition_checksum)) node_hash = merkle_tree.leaf_hash( merkle_tree.wallet_leaf_inner_hash, { 'contract': settings.HUB_LQD_CONTRACT_ADDRESS, 'token': swap.wallet.token.address, 'wallet': swap.wallet.address, 'left': sender_balance.left, 'right': sender_balance.right, 'active_state_checksum': sender_active_state.checksum(), 'passive_checksum': passive_checksum, 'passive_amount': passive_amount, 'passive_marker': passive_marker, }) checkpoint = RootCommitment.objects.get(eon_number=eon_number + 1) test_case.contract_interface.check_exclusive_allotment_proof( allotment_trail=int(sender_balance.merkle_proof_trail), membership_trail=swap.wallet.token.trail, node=node_hash, merkle_root=crypto.decode_hex(checkpoint.merkle_root), allotment_chain=[ crypto.zfill(crypto.decode_hex(v)) for v in long_string_to_list( sender_balance.merkle_proof_hashes, 64) ], membership_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( token_commitment.membership_hashes, 64) ], value=csf_to_list(sender_balance.merkle_proof_values, int), left=int(sender_balance.left), right=int(sender_balance.right)) test_case.contract_interface.issue_swap_challenge( token_pair=[swap.wallet.token.address, swap.recipient.token.address], wallet=swap.wallet.address, swap_order=swap_order, sender_tx_recipient_trails=[ swap.wallet.trail_identifier, int(transfer_index), swap.recipient.trail_identifier ], allotment_chain=[ crypto.zfill(crypto.decode_hex(v)) for v in long_string_to_list( sender_balance.merkle_proof_hashes, 64) ], membership_chain=[ crypto.zfill(crypto.decode_hex(checksum)) for checksum in long_string_to_list( token_commitment.membership_hashes, 64) ], tx_chain=[crypto.zfill(x) for x in transfer_proof], values=csf_to_list(sender_balance.merkle_proof_values, int), l_r=[int(sender_balance.left), int(sender_balance.right)], tx_set_root=tx_set_root, deltas=deltas, passive_checksum=passive_checksum, passive_amount=passive_amount, passive_marker=passive_marker)