Exemple #1
0
 def to_representation(self, instance: ExclusiveBalanceAllotment):
     wallet_context = WalletTransferContext(
         wallet=instance.wallet, transfer=None)
     passive_checksum, passive_amount, passive_marker = wallet_context.get_passive_values(
         eon_number=instance.eon_number - 1)
     return {
         'eon_number': int(instance.eon_number),
         'left': str_int(instance.left),
         'right': str_int(instance.right),
         'allotment_chain': long_string_to_list(instance.merkle_proof_hashes, 64),
         'membership_chain': long_string_to_list(instance.merkle_membership_chain(), 64),
         'values': csf_to_list(instance.merkle_proof_values, str_int),
         'trail': int(instance.merkle_proof_trail),
         'active_state_checksum':
             encode_hex(instance.active_state.checksum()) if instance.active_state else
             encode_hex(b'\0'*32),
         'active_state':
             ConciseActiveStateSerializer(
                 instance.active_state, read_only=True).data if instance.active_state else None,
         'passive_checksum': encode_hex(passive_checksum),
         'passive_amount': str_int(passive_amount),
         'passive_marker': str_int(passive_marker)
     }
Exemple #2
0
def create_token_commitment_for_eon(token: Token, eon_number):
    logger.info('Creating Token Commitment for {} at {}'.format(
        token.address, eon_number))
    last_eon_number = eon_number - 1

    with transaction.atomic():
        wallets = Wallet.objects\
            .filter(
                token=token,
                registration_operator_authorization__isnull=False,
                trail_identifier__isnull=False)\
            .order_by('trail_identifier')

        new_balances = []
        left, right = 0, 0

        for wallet in wallets:
            with wallet.lock(auto_renewal=True):
                wallet_transfer_context = WalletTransferContext(
                    wallet=wallet, transfer=None)

                last_transfer, last_transfer_is_outgoing = wallet_transfer_context.last_appended_active_transfer(
                    eon_number=last_eon_number)

                last_transfer_active_state = None
                if last_transfer is not None and last_transfer.is_open_swap():
                    last_transfer.retire_swap()

                if last_transfer is not None:
                    last_transfer_active_state = WalletTransferContext.appropriate_transfer_active_state(
                        transfer=last_transfer,
                        is_outgoing=last_transfer_is_outgoing)

                available_funds = wallet_transfer_context.available_funds_at_eon(
                    eon_number=last_eon_number,
                    only_appended=True)

                right = left + available_funds
                assert right >= left, 'Wallet {} Token {} Balance {}'.format(
                    wallet.address, token.address, available_funds)

                passive_checksum, passive_amount, passive_marker = wallet_transfer_context.get_passive_values(
                    eon_number=last_eon_number)

                new_balances.append({
                    'contract': settings.HUB_LQD_CONTRACT_ADDRESS,
                    'token': token.address,
                    'wallet': wallet.address,
                    'left': left,
                    'right': right,
                    'active_state_checksum': last_transfer_active_state.checksum() if last_transfer_active_state is not None else b'\0'*32,
                    'active_state': last_transfer_active_state,
                    'passive_checksum': passive_checksum,
                    'passive_amount': passive_amount,
                    'passive_marker': passive_marker,
                })
                left = right

                last_incoming_passive_transfer = wallet_transfer_context.last_appended_incoming_passive_transfer(
                    eon_number=last_eon_number)
                if last_incoming_passive_transfer:
                    wallet_transfer_context = WalletTransferContext(
                        wallet=wallet, transfer=last_incoming_passive_transfer)

                    passive_eon_transfers_list = wallet_transfer_context.incoming_passive_transfers_list(
                        only_appended=True,
                        force_append=False)
                    passive_transfers_merkle_tree = wallet_transfer_context.incoming_passive_transfers_tree(
                        only_appended=True,
                        force_append=False)

                    for index, incoming_passive_transfer in enumerate(passive_eon_transfers_list):

                        final_transfer_index = index
                        final_transfer_membership_proof = passive_transfers_merkle_tree.proof(
                            final_transfer_index)
                        final_transfer_membership_proof_chain = final_transfer_membership_proof.get(
                            "chain")
                        final_transfer_membership_proof_values = final_transfer_membership_proof.get(
                            "values")

                        assert incoming_passive_transfer.final_receipt_hashes is None
                        assert incoming_passive_transfer.final_receipt_index is None
                        assert incoming_passive_transfer.final_receipt_values is None

                        incoming_passive_transfer.final_receipt_hashes = final_transfer_membership_proof_chain
                        incoming_passive_transfer.final_receipt_index = final_transfer_index
                        incoming_passive_transfer.final_receipt_values = final_transfer_membership_proof_values

                        incoming_passive_transfer.save()

                if last_transfer_active_state is None:
                    continue

                wallet_transfer_context = WalletTransferContext(
                    wallet=wallet, transfer=last_transfer)
                starting_balance = int(
                    wallet_transfer_context.starting_balance_in_eon(last_eon_number))

                # if last active transfer is a multi eon swap
                # starting balance included in every tx checksum should be set to the cached starting balance
                # this way checkpoint state will match signed active state
                if last_transfer.is_swap() and not last_transfer.cancelled:
                    if Transfer.objects.filter(eon_number=last_transfer.eon_number-1, tx_id=last_transfer.tx_id).exists():
                        matched_out, matched_in = last_transfer.matched_amounts(
                            all_eons=True)
                        current_matched_out, current_matched_in = last_transfer.matched_amounts(
                            all_eons=False)
                        if last_transfer_is_outgoing:
                            sender_starting_balance = last_transfer.sender_starting_balance

                            # current eon's starting balance should be equal to
                            # cached starting balance - committed matched out amount in past rounds
                            assert(starting_balance == sender_starting_balance -
                                   matched_out + current_matched_out)
                            starting_balance = sender_starting_balance
                        else:
                            recipient_starting_balance = last_transfer.recipient_starting_balance

                            # current eon's starting balance should be equal to
                            # cached starting balance + committed matched in amount in past rounds
                            assert(
                                starting_balance == recipient_starting_balance + matched_in - current_matched_in)
                            starting_balance = recipient_starting_balance

                confirmed_eon_transfers_list = wallet_transfer_context.authorized_transfers_list(
                    only_appended=True,
                    force_append=False)
                confirmed_eon_transfers_list_shorthand = wallet_transfer_context.authorized_transfers_list_shorthand(
                    only_appended=True,
                    force_append=False,
                    last_transfer_is_finalized=False,
                    starting_balance=starting_balance)
                transaction_merkle_tree = TransactionMerkleTree(
                    confirmed_eon_transfers_list_shorthand)
                transaction_merkle_tree_root = hex_value(
                    transaction_merkle_tree.root_hash())

                assert transaction_merkle_tree_root == last_transfer_active_state.tx_set_hash,\
                    '{}/{}'.format(transaction_merkle_tree_root,
                                   last_transfer_active_state.tx_set_hash)

                for confirmed_incoming_transfer in confirmed_eon_transfers_list:
                    if confirmed_incoming_transfer.recipient != wallet:
                        continue

                    final_transfer_index = transaction_merkle_tree.merkle_tree_nonce_map.get(
                        confirmed_incoming_transfer.nonce)
                    final_transfer_membership_proof_chain = transaction_merkle_tree.proof(
                        final_transfer_index)

                    assert confirmed_incoming_transfer.final_receipt_hashes is None
                    assert confirmed_incoming_transfer.final_receipt_index is None

                    confirmed_incoming_transfer.final_receipt_hashes = final_transfer_membership_proof_chain
                    confirmed_incoming_transfer.final_receipt_index = final_transfer_index

                    confirmed_incoming_transfer.save()

        managed_funds = 0
        if eon_number > 1:
            last_eon = LocalViewInterface.confirmed(eon_number=last_eon_number)
            pending_withdrawals_until_last_eon = \
                WithdrawalRequest.objects\
                .filter(wallet__token=token, eon_number__lte=last_eon_number, slashed=False)\
                .filter(Q(withdrawal__isnull=True) | Q(withdrawal__block__gt=last_eon.block))

            if not pending_withdrawals_until_last_eon.exists():
                last_eon_pending_withdrawals = 0
            else:
                last_eon_pending_withdrawals = pending_withdrawals_until_last_eon\
                    .aggregate(Sum('amount')) \
                    .get('amount__sum')

            total_token_balance = last_eon.contractledgerstate_set.get(
                token=token).total_balance
            managed_funds = total_token_balance - last_eon_pending_withdrawals

        if right < managed_funds:
            logger.warning('UNCLAIMED FUNDS: {} in {}'.format(
                managed_funds - right, token.address))
            send_admin_email(
                subject='Soft TokenCommitment Warning: Extra funds',
                content='There are some additional funds in the balance pool that belong to no one: {} of {}'
                .format(managed_funds - right, token.address))
            altered_balances = new_balances + [{
                'contract': settings.HUB_LQD_CONTRACT_ADDRESS,
                'token': token.address,
                'wallet': settings.HUB_OWNER_ACCOUNT_ADDRESS,
                'left': left,
                'right': managed_funds,
                'active_state_checksum': b'\0'*32,
                'active_state': None,
                'passive_checksum': b'\0'*32,
                'passive_amount': 0,
                'passive_marker': 0,
            }]
            new_merkle_tree = MerkleTree(altered_balances, managed_funds)
            right = managed_funds
        else:
            if right > managed_funds:
                logger.error('OVERCLAIMING FUNDS!! {} > {} in {}'.format(
                    right, managed_funds, token.address))
                send_admin_email(
                    subject='HARD Checkpoint Error: OVERCLAIMING!',
                    content='OVERCLAIMING FUNDS!! {} > {} in {}'.format(right, managed_funds, token.address))
            new_merkle_tree = MerkleTree(new_balances, right)

        bulk_manager = BulkCreateManager(chunk_size=500)
        for index, balance in enumerate(new_balances):
            if not balance.get('wallet') or balance.get('wallet') == '0x0000000000000000000000000000000000000000':
                continue

            merkle_proof = new_merkle_tree.proof(index)

            wallet = Wallet.objects.get(
                token=token,
                address=remove_0x_prefix(balance.get('wallet')))

            # TODO verify validity through RPC prior to insertion

            assert(wallet.trail_identifier == index)

            # create records in batches
            bulk_manager.add(
                ExclusiveBalanceAllotment(
                    wallet=wallet,
                    eon_number=eon_number,
                    left=balance.get('left'),
                    right=balance.get('right'),
                    merkle_proof_hashes=merkle_proof.get('chain'),
                    merkle_proof_values=merkle_proof.get('values'),
                    merkle_proof_trail=index,
                    active_state=balance.get('active_state')
                )
            )
        # make sure remaining batch is added
        bulk_manager.done()

        token_commitment = TokenCommitment.objects.create(
            token=token,
            merkle_root=hex_value(new_merkle_tree.root_hash()),
            upper_bound=right)

        return token_commitment
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
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)