def setup_pfs_handler_test(
    set_feedback_token: bool,
) -> Tuple[RaidenService, PFSFeedbackEventHandler, TokenNetworkRegistryAddress,
           TokenNetworkAddress, List[Address], Optional[UUID], ]:
    channel_identifier = make_channel_identifier()
    token_network_registry_address = make_token_network_registry_address()
    token_network_address = make_token_network_address()
    participant = make_address()
    raiden = make_raiden_service_mock(
        token_network_registry_address=token_network_registry_address,
        token_network_address=token_network_address,
        channel_identifier=channel_identifier,
        partner=participant,
    )

    default_handler = RaidenEventHandler()
    pfs_handler = PFSFeedbackEventHandler(default_handler)

    route = [make_address(), make_address(), make_address()]

    # Set PFS config and feedback token
    pfs_config = True  # just a truthy value
    raiden.config.pfs_config = pfs_config

    feedback_uuid = None
    if set_feedback_token:
        feedback_uuid = uuid4()
        raiden.route_to_feedback_token[tuple(route)] = feedback_uuid

    return (
        raiden,
        pfs_handler,
        token_network_registry_address,
        token_network_address,
        route,
        feedback_uuid,
    )
def test_handle_contract_send_channelunlock_already_unlocked():
    """This is a test for the scenario where the onchain unlock has
    already happened when we get to handle our own send unlock
    transaction.

    Regression test for https://github.com/raiden-network/raiden/issues/3152
    """
    channel_identifier = 1
    payment_network_identifier = make_address()
    token_network_identifier = make_address()
    participant = make_address()
    raiden = make_raiden_service_mock(
        payment_network_identifier=payment_network_identifier,
        token_network_identifier=token_network_identifier,
        channel_identifier=channel_identifier,
        partner=participant,
    )

    channel_state = get_channelstate_by_token_network_and_partner(
        chain_state=state_from_raiden(raiden),
        token_network_id=token_network_identifier,
        partner_address=participant,
    )

    channel_state.our_state.onchain_locksroot = EMPTY_MERKLE_ROOT
    channel_state.partner_state.onchain_locksroot = EMPTY_MERKLE_ROOT

    def detail_participants(  # pylint: disable=unused-argument
            participant1, participant2, block_identifier, channel_identifier):
        transferred_amount = 1
        locked_amount = 1
        locksroot = make_32bytes()
        balance_hash = hash_balance_data(transferred_amount, locked_amount,
                                         locksroot)
        our_details = ParticipantDetails(
            address=raiden.address,
            deposit=5,
            withdrawn=0,
            is_closer=False,
            balance_hash=balance_hash,
            nonce=1,
            locksroot=locksroot,
            locked_amount=locked_amount,
        )

        transferred_amount = 1
        locked_amount = 1
        # Let's mock here that partner locksroot is 0x0
        balance_hash = hash_balance_data(transferred_amount, locked_amount,
                                         locksroot)
        partner_details = ParticipantDetails(
            address=participant,
            deposit=5,
            withdrawn=0,
            is_closer=True,
            balance_hash=balance_hash,
            nonce=1,
            locksroot=EMPTY_HASH,
            locked_amount=locked_amount,
        )
        return ParticipantsDetails(our_details, partner_details)

    # make sure detail_participants returns partner data with a locksroot of 0x0
    raiden.chain.token_network.detail_participants = detail_participants

    event = ContractSendChannelBatchUnlock(
        canonical_identifier=make_canonical_identifier(
            token_network_address=token_network_identifier,
            channel_identifier=channel_identifier),
        participant=participant,
        triggered_by_block_hash=make_block_hash(),
    )

    # This should not throw an unrecoverable error
    RaidenEventHandler().on_raiden_event(
        raiden=raiden,
        chain_state=raiden.wal.state_manager.current_state,
        event=event)
def test_handle_contract_send_channelunlock_already_unlocked():
    """This is a test for the scenario where the onchain unlock has
    already happened when we get to handle our own send unlock
    transaction.

    Regression test for https://github.com/raiden-network/raiden/issues/3152
    """
    channel_identifier = ChannelID(1)
    token_network_registry_address = make_token_network_registry_address()
    token_network_address = make_token_network_address()
    participant = make_address()
    raiden = make_raiden_service_mock(
        token_network_registry_address=token_network_registry_address,
        token_network_address=token_network_address,
        channel_identifier=channel_identifier,
        partner=participant,
    )

    channel_state = get_channelstate_by_token_network_and_partner(
        chain_state=state_from_raiden(raiden),
        token_network_address=token_network_address,
        partner_address=participant,
    )
    assert channel_state

    channel_state.our_state.onchain_locksroot = LOCKSROOT_OF_NO_LOCKS
    channel_state.partner_state.onchain_locksroot = LOCKSROOT_OF_NO_LOCKS

    def detail_participants(_participant1, _participant2, _block_identifier,
                            _channel_identifier):
        transferred_amount = TokenAmount(1)
        locked_amount = LockedAmount(1)
        locksroot = make_locksroot()
        balance_hash = hash_balance_data(transferred_amount, locked_amount,
                                         locksroot)
        our_details = ParticipantDetails(
            address=raiden.address,
            deposit=TokenAmount(5),
            withdrawn=WithdrawAmount(0),
            is_closer=False,
            balance_hash=balance_hash,
            nonce=Nonce(1),
            locksroot=locksroot,
            locked_amount=locked_amount,
        )

        transferred_amount = TokenAmount(1)
        locked_amount = LockedAmount(1)
        # Let's mock here that partner locksroot is 0x0
        balance_hash = hash_balance_data(transferred_amount, locked_amount,
                                         locksroot)
        partner_details = ParticipantDetails(
            address=participant,
            deposit=TokenAmount(5),
            withdrawn=WithdrawAmount(0),
            is_closer=True,
            balance_hash=balance_hash,
            nonce=Nonce(1),
            locksroot=LOCKSROOT_OF_NO_LOCKS,
            locked_amount=locked_amount,
        )
        return ParticipantsDetails(our_details, partner_details)

    # make sure detail_participants returns partner data with a locksroot of 0x0
    raiden.proxy_manager.token_network.detail_participants = detail_participants

    event = ContractSendChannelBatchUnlock(
        canonical_identifier=make_canonical_identifier(
            token_network_address=token_network_address,
            channel_identifier=channel_identifier),
        sender=participant,
        triggered_by_block_hash=make_block_hash(),
    )

    # This should not throw an unrecoverable error
    RaidenEventHandler().on_raiden_events(
        raiden=raiden,
        chain_state=raiden.wal.state_manager.current_state,
        events=[event])