Example #1
0
def handle_unlock(mediator_state, state_change: ReceiveUnlock, channelidentifiers_to_channels):
    """ Handle a ReceiveUnlock state change. """
    events = list()
    balance_proof_sender = state_change.balance_proof.sender
    channel_identifier = state_change.balance_proof.channel_address

    for pair in mediator_state.transfers_pair:
        if pair.payer_transfer.balance_proof.sender == balance_proof_sender:
            channel_state = channelidentifiers_to_channels.get(channel_identifier)

            if channel_state:
                is_valid, channel_events, _ = channel.handle_unlock(
                    channel_state,
                    state_change,
                )
                events.extend(channel_events)

                if is_valid:
                    unlock = EventUnlockClaimSuccess(
                        pair.payee_transfer.payment_identifier,
                        pair.payee_transfer.lock.secrethash,
                    )
                    events.append(unlock)

                    send_processed = SendProcessed(
                        balance_proof_sender,
                        b'global',
                        state_change.message_identifier,
                    )
                    events.append(send_processed)

                    pair.payer_state = 'payer_balance_proof'

    iteration = TransitionResult(mediator_state, events)
    return iteration
Example #2
0
def handle_unlock(target_state, state_change: ReceiveUnlock, channel_state):
    """ Handles a ReceiveUnlock state change. """
    iteration = TransitionResult(target_state, list())
    balance_proof_sender = state_change.balance_proof.sender

    if balance_proof_sender == target_state.route.node_address:
        is_valid, events, _ = channel.handle_unlock(
            channel_state,
            state_change,
        )

        if is_valid:
            transfer = target_state.transfer
            transfer_success = EventTransferReceivedSuccess(
                transfer.payment_identifier,
                transfer.lock.amount,
                transfer.initiator,
            )

            unlock_success = EventUnlockClaimSuccess(
                transfer.payment_identifier,
                transfer.lock.secrethash,
            )

            send_processed = SendProcessed(
                balance_proof_sender,
                b'global',
                state_change.message_identifier,
            )

            events.extend([transfer_success, unlock_success, send_processed])
            iteration = TransitionResult(None, events)

    return iteration
Example #3
0
def claim_lock(app_chain, identifier, token, secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token)
        partner_channel = get_channelstate(to_, from_, token)

        unlock_lock = channel.send_unlock(
            from_channel,
            identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            unlock_lock.identifier,
            unlock_lock.balance_proof.nonce,
            unlock_lock.balance_proof.channel_address,
            unlock_lock.balance_proof.transferred_amount,
            unlock_lock.balance_proof.locksroot,
            unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            unlock_lock.secret,
            balance_proof,
        )

        is_valid, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
Example #4
0
def handle_unlock(target_state, state_change, channel_state):
    """ Handles a ReceiveUnlock state change. """
    iteration = TransitionResult(target_state, list())
    balance_proof_sender = state_change.balance_proof.sender

    if balance_proof_sender == target_state.route.node_address:
        is_valid, events, _ = channel.handle_unlock(
            channel_state,
            state_change,
        )

        if is_valid:
            transfer = target_state.transfer
            transfer_success = EventTransferReceivedSuccess(
                transfer.payment_identifier,
                transfer.lock.amount,
                transfer.initiator,
            )

            unlock_success = EventUnlockClaimSuccess(
                transfer.payment_identifier,
                transfer.lock.secrethash,
            )

            send_processed = SendProcessed(
                balance_proof_sender,
                b'global',
                state_change.message_identifier,
            )

            events.extend([transfer_success, unlock_success, send_processed])
            iteration = TransitionResult(None, events)

    return iteration
Example #5
0
def handle_unlock(mediator_state, state_change, channelidentifiers_to_channels):
    """ Handle a ReceiveUnlock state change. """
    events = list()
    balance_proof_sender = state_change.balance_proof.sender
    channel_identifier = state_change.balance_proof.channel_address

    for pair in mediator_state.transfers_pair:
        if pair.payer_transfer.balance_proof.sender == balance_proof_sender:
            channel_state = channelidentifiers_to_channels.get(channel_identifier)

            if channel_state:
                is_valid, channel_events, _ = channel.handle_unlock(
                    channel_state,
                    state_change,
                )
                events.extend(channel_events)

                if is_valid:
                    unlock = EventUnlockClaimSuccess(
                        pair.payee_transfer.payment_identifier,
                        pair.payee_transfer.lock.secrethash,
                    )
                    events.append(unlock)

                    send_processed = SendProcessed(
                        balance_proof_sender,
                        b'global',
                        state_change.message_identifier,
                    )
                    events.append(send_processed)

                    pair.payer_state = 'payer_balance_proof'

    iteration = TransitionResult(mediator_state, events)
    return iteration
Example #6
0
def handle_unlock(mediator_state, state_change, channelidentifiers_to_channels):
    """ Handle a ReceiveUnlock state change. """
    events = list()
    balance_proof_sender = state_change.balance_proof.sender
    channel_identifier = state_change.balance_proof.channel_address

    for pair in mediator_state.transfers_pair:
        if pair.payer_transfer.balance_proof.sender == balance_proof_sender:
            channel_state = channelidentifiers_to_channels.get(channel_identifier)

            if channel_state:
                is_valid, _ = channel.handle_unlock(
                    channel_state,
                    state_change,
                )

                if is_valid:
                    withdraw = EventWithdrawSuccess(
                        pair.payee_transfer.payment_identifier,
                        pair.payee_transfer.lock.secrethash,
                    )
                    events.append(withdraw)

                    pair.payer_state = 'payer_balance_proof'

    iteration = TransitionResult(mediator_state, events)
    return iteration
Example #7
0
def handle_unlock(
    target_state: TargetTransferState,
    state_change: ReceiveUnlock,
    channel_state: NettingChannelState,
) -> TransitionResult[TargetTransferState]:
    """ Handles a ReceiveUnlock state change. """
    balance_proof_sender = state_change.balance_proof.sender

    is_valid, events, _ = channel.handle_unlock(channel_state, state_change)
    next_target_state: Optional[TargetTransferState] = target_state

    if is_valid:
        transfer = target_state.transfer
        payment_received_success = EventPaymentReceivedSuccess(
            payment_network_identifier=channel_state.payment_network_identifier,
            token_network_identifier=TokenNetworkID(channel_state.token_network_identifier),
            identifier=transfer.payment_identifier,
            amount=TokenAmount(transfer.lock.amount),
            initiator=transfer.initiator,
        )

        unlock_success = EventUnlockClaimSuccess(
            transfer.payment_identifier, transfer.lock.secrethash
        )

        send_processed = SendProcessed(
            recipient=balance_proof_sender,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=state_change.message_identifier,
        )

        events.extend([payment_received_success, unlock_success, send_processed])
        next_target_state = None

    return TransitionResult(next_target_state, events)
Example #8
0
def handle_unlock(
    target_state: TargetTransferState,
    state_change: ReceiveUnlock,
    channel_state: NettingChannelState,
):
    """ Handles a ReceiveUnlock state change. """
    iteration = TransitionResult(target_state, list())
    balance_proof_sender = state_change.balance_proof.sender

    if balance_proof_sender == target_state.route.node_address:
        is_valid, events, _ = channel.handle_unlock(
            channel_state,
            state_change,
        )

        if is_valid:
            transfer = target_state.transfer
            payment_received_success = EventPaymentReceivedSuccess(
                payment_network_identifier=channel_state.
                payment_network_identifier,
                token_network_identifier=channel_state.
                token_network_identifier,
                identifier=transfer.payment_identifier,
                amount=transfer.lock.amount,
                initiator=transfer.initiator,
            )

            unlock_success = EventUnlockClaimSuccess(
                transfer.payment_identifier,
                transfer.lock.secrethash,
            )

            send_processed = SendProcessed(
                recipient=balance_proof_sender,
                channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
                message_identifier=state_change.message_identifier,
            )

            events.extend(
                [payment_received_success, unlock_success, send_processed])
            iteration = TransitionResult(None, events)

    return iteration
Example #9
0
def claim_lock(app_chain, payment_identifier, token_network_identifier,
               secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token_network_identifier)
        partner_channel = get_channelstate(to_, from_,
                                           token_network_identifier)

        unlock_lock = channel.send_unlock(
            from_channel,
            random.randint(0, UINT64_MAX),
            payment_identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            chain_id=unlock_lock.balance_proof.chain_id,
            message_identifier=unlock_lock.message_identifier,
            payment_identifier=unlock_lock.payment_identifier,
            nonce=unlock_lock.balance_proof.nonce,
            token_network_address=partner_channel.token_network_identifier,
            channel_identifier=unlock_lock.balance_proof.channel_identifier,
            transferred_amount=unlock_lock.balance_proof.transferred_amount,
            locked_amount=unlock_lock.balance_proof.locked_amount,
            locksroot=unlock_lock.balance_proof.locksroot,
            secret=unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            message_identifier=random.randint(0, UINT64_MAX),
            secret=unlock_lock.secret,
            balance_proof=balance_proof,
        )

        is_valid, _, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
Example #10
0
def claim_lock(app_chain, payment_identifier, token_network_identifier, secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token_network_identifier)
        partner_channel = get_channelstate(to_, from_, token_network_identifier)

        unlock_lock = channel.send_unlock(
            from_channel,
            random.randint(0, UINT64_MAX),
            payment_identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            unlock_lock.balance_proof.chain_id,
            unlock_lock.message_identifier,
            unlock_lock.payment_identifier,
            unlock_lock.balance_proof.nonce,
            partner_channel.token_network_identifier,
            unlock_lock.balance_proof.channel_address,
            unlock_lock.balance_proof.transferred_amount,
            unlock_lock.balance_proof.locked_amount,
            unlock_lock.balance_proof.locksroot,
            unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            message_identifier=random.randint(0, UINT64_MAX),
            secret=unlock_lock.secret,
            balance_proof=balance_proof,
        )

        is_valid, _, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
Example #11
0
def handle_unlock(
        target_state: TargetTransferState,
        state_change: ReceiveUnlock,
        channel_state: NettingChannelState,
):
    """ Handles a ReceiveUnlock state change. """
    balance_proof_sender = state_change.balance_proof.sender

    is_valid, events, _ = channel.handle_unlock(
        channel_state,
        state_change,
    )

    if is_valid:
        transfer = target_state.transfer
        payment_received_success = EventPaymentReceivedSuccess(
            payment_network_identifier=channel_state.payment_network_identifier,
            token_network_identifier=channel_state.token_network_identifier,
            identifier=transfer.payment_identifier,
            amount=transfer.lock.amount,
            initiator=transfer.initiator,
        )

        unlock_success = EventUnlockClaimSuccess(
            transfer.payment_identifier,
            transfer.lock.secrethash,
        )

        send_processed = SendProcessed(
            recipient=balance_proof_sender,
            channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE,
            message_identifier=state_change.message_identifier,
        )

        events.extend([payment_received_success, unlock_success, send_processed])
        target_state = None

    return TransitionResult(target_state, events)
Example #12
0
def test_interwoven_transfers():
    """Can keep doing transactions even if not all secrets have been released."""
    number_of_transfers = 100
    balance_for_all_transfers = 11 * number_of_transfers

    lock_amounts = cycle([1, 3, 5, 7, 11])
    lock_secrets = [
        format(i, '>032').encode()
        for i in range(number_of_transfers)
    ]

    our_model, _ = create_model(70)
    partner_model, privkey2 = create_model(balance_for_all_transfers)
    channel_state = create_channel_from_models(our_model, partner_model)

    block_number = 1000
    nonce = 0
    transferred_amount = 0
    our_model_current = our_model
    partner_model_current = partner_model

    for i, (lock_amount, lock_secret) in enumerate(zip(lock_amounts, lock_secrets)):
        nonce += 1
        block_number += 1

        lock_expiration = block_number + channel_state.settle_timeout - 1
        lock_secrethash = sha3(lock_secret)
        lock = HashTimeLockState(
            lock_amount,
            lock_expiration,
            lock_secrethash,
        )

        merkletree_leaves = list(partner_model_current.merkletree_leaves)
        merkletree_leaves.append(lock.lockhash)

        partner_model_current = partner_model_current._replace(
            distributable=partner_model_current.distributable - lock_amount,
            amount_locked=partner_model_current.amount_locked + lock_amount,
            next_nonce=partner_model_current.next_nonce + 1,
            merkletree_leaves=merkletree_leaves,
        )

        receive_lockedtransfer = make_receive_transfer_mediated(
            channel_state,
            privkey2,
            nonce,
            transferred_amount,
            lock,
            merkletree_leaves=merkletree_leaves,
        )

        is_valid, msg = channel.handle_receive_lockedtransfer(
            channel_state,
            receive_lockedtransfer,
        )
        assert is_valid, msg

        assert_partner_state(
            channel_state.our_state,
            channel_state.partner_state,
            our_model_current,
        )
        assert_partner_state(
            channel_state.partner_state,
            channel_state.our_state,
            partner_model_current,
        )

        # claim a transaction at every other iteration, leaving the current one
        # in place
        if i % 2:
            # Update our model:
            # - Increase nonce because the secret is a new balance proof
            # - The lock is removed from the merkle tree, the balance proof must be updated
            #   - The locksroot must have unlocked lock removed
            #   - The transferred amount must be increased by the lock amount
            # - This changes the balance for both participants:
            #   - the sender balance and locked amount is decremented by the lock amount
            #   - the receiver balance and distributable is incremented by the lock amount
            nonce += 1
            transferred_amount += lock_amount

            merkletree_leaves = list(partner_model_current.merkletree_leaves)
            merkletree_leaves.remove(lock.lockhash)
            tree = compute_layers(merkletree_leaves)
            locksroot = tree[MERKLEROOT][0]

            partner_model_current = partner_model_current._replace(
                amount_locked=partner_model_current.amount_locked - lock_amount,
                balance=partner_model_current.balance - lock_amount,
                next_nonce=partner_model_current.next_nonce + 1,
                merkletree_leaves=merkletree_leaves,
            )

            our_model_current = our_model_current._replace(
                balance=our_model_current.balance + lock_amount,
                distributable=our_model_current.distributable + lock_amount,
            )

            message_identifier = random.randint(0, UINT64_MAX)
            secret_message = Secret(
                message_identifier=message_identifier,
                payment_identifier=nonce,
                nonce=nonce,
                channel=channel_state.identifier,
                transferred_amount=transferred_amount,
                locksroot=locksroot,
                secret=lock_secret,
            )
            secret_message.sign(privkey2, channel_state.partner_state.address)

            balance_proof = balanceproof_from_envelope(secret_message)
            unlock_state_change = ReceiveUnlock(
                lock_secret,
                balance_proof,
            )

            is_valid, msg = channel.handle_unlock(channel_state, unlock_state_change)
            assert is_valid, msg

            assert_partner_state(
                channel_state.our_state,
                channel_state.partner_state,
                our_model_current,
            )
            assert_partner_state(
                channel_state.partner_state,
                channel_state.our_state,
                partner_model_current,
            )
Example #13
0
def test_channelstate_receive_lockedtransfer():
    """Tests receiving a mediated transfer.

    The transfer is done in three steps:
        - a mediated transfer including a lock in its balance proof is sent
        - the secret is revealed
        - the unlocked balance proof is sent updating the transferred_amount
    """
    our_model1, _ = create_model(70)
    partner_model1, privkey2 = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)

    # Step 1: Simulate receiving a transfer
    # - The receiver end state doesnt change
    # - The lock must be registered with the sender end
    lock_amount = 30
    lock_expiration = 10
    lock_secret = sha3(b'test_end_state')
    lock_secrethash = sha3(lock_secret)
    lock = HashTimeLockState(
        lock_amount,
        lock_expiration,
        lock_secrethash,
    )

    nonce = 1
    transferred_amount = 0
    receive_lockedtransfer = make_receive_transfer_mediated(
        channel_state,
        privkey2,
        nonce,
        transferred_amount,
        lock,
    )

    is_valid, msg = channel.handle_receive_lockedtransfer(
        channel_state,
        receive_lockedtransfer,
    )
    assert is_valid, msg

    our_model2 = our_model1
    partner_model2 = partner_model1._replace(
        distributable=partner_model1.distributable - lock_amount,
        amount_locked=lock_amount,
        next_nonce=2,
        merkletree_leaves=[lock.lockhash],
    )
    assert_partner_state(channel_state.our_state, channel_state.partner_state, our_model2)
    assert_partner_state(channel_state.partner_state, channel_state.our_state, partner_model2)

    # Step 2: Simulate learning the secret
    # - Registers the secret, this must not change the balance/locked amount
    channel.register_secret(channel_state, lock_secret, lock_secrethash)

    assert_partner_state(channel_state.our_state, channel_state.partner_state, our_model2)
    assert_partner_state(channel_state.partner_state, channel_state.our_state, partner_model2)

    # Step 3: Simulate unlocking the lock
    # - Update the balances
    transferred_amount = 0
    message_identifier = random.randint(0, UINT64_MAX)
    secret_message = Secret(
        message_identifier=message_identifier,
        payment_identifier=1,
        nonce=2,
        channel=channel_state.identifier,
        transferred_amount=transferred_amount + lock_amount,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=lock_secret,
    )
    secret_message.sign(privkey2, channel_state.partner_state.address)

    balance_proof = balanceproof_from_envelope(secret_message)
    unlock_state_change = ReceiveUnlock(
        lock_secret,
        balance_proof,
    )

    is_valid, msg = channel.handle_unlock(channel_state, unlock_state_change)
    assert is_valid, msg

    our_model3 = our_model2._replace(
        balance=our_model2.balance + lock_amount,
        distributable=our_model2.balance + lock_amount,
    )
    partner_model3 = partner_model2._replace(
        balance=partner_model2.balance - lock_amount,
        amount_locked=0,
        next_nonce=3,
        merkletree_leaves=[],
    )

    assert_partner_state(channel_state.our_state, channel_state.partner_state, our_model3)
    assert_partner_state(channel_state.partner_state, channel_state.our_state, partner_model3)
Example #14
0
def assert_balance_proof(
    token_network_address: TokenNetworkAddress,
    app0: App,
    app1: App,
    saved_state0: SavedState,
    saved_state1: SavedState,
) -> None:
    """Assert app0 and app1 agree on the latest balance proof from app0.

    Notes:
        - The other direction of the channel does not have to be synchronized,
          it can be checked with another call.
        - It is important to do the validation on a fixed  state, that is why
          saved_state0 is used.
    """
    assert app0.raiden.wal
    assert app1.raiden.wal

    assert app0.raiden.address == saved_state0.state.our_address
    assert app1.raiden.address == saved_state1.state.our_address

    channel0 = views.get_channelstate_by_token_network_and_partner(
        saved_state0.state, token_network_address, app1.raiden.address)
    channel1 = views.get_channelstate_by_token_network_and_partner(
        saved_state1.state, token_network_address, app0.raiden.address)

    assert channel0
    assert channel1

    balanceproof0 = cast(BalanceProofUnsignedState,
                         channel0.our_state.balance_proof)
    balanceproof1 = cast(BalanceProofSignedState,
                         channel1.partner_state.balance_proof)

    if balanceproof0 is None:
        msg = "Bug detected. The sender does not have a balance proof, but the recipient does."
        assert balanceproof1 is None, msg

        # nothing to compare
        return

    # Handle the case when the recipient didn't receive the message yet.
    if balanceproof1 is not None:
        nonce1 = balanceproof1.nonce
    else:
        nonce1 = 0

    if balanceproof0.nonce < nonce1:
        msg = (
            "This is a bug, it should never happen. The nonce updates **always**  "
            "start with the owner of the channel's end. This means for a channel "
            "A-B, only A can increase its nonce, same thing with B. At this "
            "point, the assertion is failling because this rule was broken, and "
            "the partner node has a larger nonce than the sending partner.")
        raise AssertionError(msg)

    if balanceproof0.nonce > nonce1:
        # TODO: Only consider the records up to saved state's state_change_id.
        # ATM this has a race condition where this utility could be called
        # before the alarm task fetches the corresponding event but while it
        # runs it does fetch it.
        sent_balance_proof = get_event_with_balance_proof_by_balance_hash(
            storage=app0.raiden.wal.storage,
            canonical_identifier=balanceproof0.canonical_identifier,
            balance_hash=balanceproof0.balance_hash,
            recipient=app1.raiden.address,
        )
        received_balance_proof = get_state_change_with_balance_proof_by_locksroot(
            storage=app1.raiden.wal.storage,
            canonical_identifier=balanceproof0.canonical_identifier,
            locksroot=balanceproof0.locksroot,
            sender=app0.raiden.address,
        )

        if received_balance_proof is not None:
            if type(received_balance_proof) == ReceiveTransferRefund:
                msg = (
                    f"Node1 received a refund from node0 and rejected it. This "
                    f"is likely a Raiden bug. state_change={received_balance_proof}"
                )
            elif type(received_balance_proof) in (
                    ActionInitMediator,
                    ActionInitTarget,
                    ReceiveUnlock,
                    ReceiveLockExpired,
            ):
                if type(received_balance_proof) == ReceiveUnlock:
                    assert isinstance(received_balance_proof,
                                      ReceiveUnlock), MYPY_ANNOTATION
                    is_valid, _, innermsg = channel.handle_unlock(
                        channel_state=channel1, unlock=received_balance_proof)
                elif type(received_balance_proof) == ReceiveLockExpired:
                    assert isinstance(received_balance_proof,
                                      ReceiveLockExpired), MYPY_ANNOTATION
                    is_valid, innermsg, _ = channel.is_valid_lock_expired(
                        state_change=received_balance_proof,
                        channel_state=channel1,
                        sender_state=channel1.partner_state,
                        receiver_state=channel1.our_state,
                        block_number=saved_state1.state.block_number,
                    )
                else:
                    assert isinstance(received_balance_proof,
                                      (ActionInitMediator,
                                       ActionInitTarget)), MYPY_ANNOTATION
                    is_valid, _, innermsg = channel.handle_receive_lockedtransfer(
                        channel_state=channel1,
                        mediated_transfer=received_balance_proof.from_transfer,
                    )

                if not is_valid:
                    msg = (
                        f"Node1 received the node0's message but rejected it. This "
                        f"is likely a Raiden bug. reason={innermsg} "
                        f"state_change={received_balance_proof}")
                else:
                    msg = (
                        f"Node1 received the node0's message at that time it "
                        f"was rejected, this is likely a race condition, node1 "
                        f"has to process the message again. reason={innermsg} "
                        f"state_change={received_balance_proof}")
            else:
                msg = (
                    f"Node1 received the node0's message but rejected it. This "
                    f"is likely a Raiden bug. state_change={received_balance_proof}"
                )

        elif sent_balance_proof is None:
            msg = (
                "Node0 did not send a message with the latest balanceproof, "
                "this is likely a Raiden bug.")
        else:
            msg = (
                "Node0 sent the latest balanceproof but Node1 didn't receive, "
                "likely the test is missing proper synchronization amongst the "
                "nodes.")

        msg = (f"{msg}. "
               f"node1={to_checksum_address(app1.raiden.address)} "
               f"node0={to_checksum_address(app0.raiden.address)} "
               f"state_change_id0={saved_state0.state_change_id} "
               f"state_change_id1={saved_state1.state_change_id}.")

        raise AssertionError(msg)

    is_equal = (balanceproof0.nonce == balanceproof1.nonce
                and balanceproof0.transferred_amount
                == balanceproof1.transferred_amount
                and balanceproof0.locked_amount == balanceproof1.locked_amount
                and balanceproof0.locksroot == balanceproof1.locksroot
                and balanceproof0.canonical_identifier
                == balanceproof1.canonical_identifier
                and balanceproof0.balance_hash == balanceproof1.balance_hash)

    if not is_equal:
        msg = (
            f"The balance proof seems corrupted, the recipient has different "
            f"values than the sender. "
            f"node1={to_checksum_address(app1.raiden.address)} "
            f"node0={to_checksum_address(app0.raiden.address)} "
            f"state_change_id0={saved_state0.state_change_id} "
            f"state_change_id1={saved_state1.state_change_id}.")

        raise AssertionError(msg)