def test_join_invalid_discovery(
    local_matrix_servers,
    retry_interval_initial,
    retry_interval_max,
    retries_before_backoff,
    broadcast_rooms,
):
    """join_broadcast_room tries to join on all servers on available_servers config

    If any of the servers isn't reachable by synapse, it'll return a 500 response, which needs
    to be handled, and if no discovery room is found on any of the available_servers, one in
    our current server should be created
    """
    transport = MatrixTransport(
        config=MatrixTransportConfig(
            broadcast_rooms=broadcast_rooms,
            retries_before_backoff=retries_before_backoff,
            retry_interval_initial=retry_interval_initial,
            retry_interval_max=retry_interval_max,
            server=local_matrix_servers[0],
            available_servers=["http://invalid.server"],
        ),
        environment=Environment.DEVELOPMENT,
    )
    transport._client.api.retry_timeout = 0
    transport._send_raw = MagicMock()
    raiden_service = MockRaidenService(None)

    transport.start(raiden_service, [], None)
    transport.log = MagicMock()
    discovery_room_name = make_room_alias(transport.chain_id, "discovery")
    assert isinstance(transport._broadcast_rooms.get(discovery_room_name), Room)

    transport.stop()
    transport.greenlet.get()
def test_matrix_discovery_room_offline_server(
    local_matrix_servers,
    retries_before_backoff,
    retry_interval_initial,
    retry_interval_max,
    broadcast_rooms,
):

    transport = MatrixTransport(
        config=MatrixTransportConfig(
            broadcast_rooms=broadcast_rooms,
            retries_before_backoff=retries_before_backoff,
            retry_interval_initial=retry_interval_initial,
            retry_interval_max=retry_interval_max,
            server=local_matrix_servers[0],
            available_servers=[local_matrix_servers[0], "https://localhost:1"],
        ),
        environment=Environment.DEVELOPMENT,
    )
    transport.start(MockRaidenService(None), [], "")

    discovery_room_name = make_room_alias(transport.chain_id, "discovery")
    with gevent.Timeout(1):
        while not isinstance(transport._broadcast_rooms.get(discovery_room_name), Room):
            gevent.sleep(0.1)

    transport.stop()
    transport.greenlet.get()
Beispiel #3
0
def setup_matrix(
    transport_config: MatrixTransportConfig,
    services_config: ServiceConfig,
    environment_type: Environment,
    routing_mode: RoutingMode,
) -> MatrixTransport:
    if transport_config.server == MATRIX_AUTO_SELECT_SERVER:
        # fetch list of known servers from raiden-network/raiden-tranport repo
        available_servers_url = DEFAULT_MATRIX_KNOWN_SERVERS[environment_type]

        log.debug("Fetching available matrix servers")
        available_servers = get_matrix_servers(available_servers_url)
        log.debug("Available matrix servers", available_servers=available_servers)

        transport_config.available_servers = available_servers

    # Add PFS broadcast room when not in private mode
    if routing_mode != RoutingMode.PRIVATE:
        if PATH_FINDING_BROADCASTING_ROOM not in transport_config.broadcast_rooms:
            transport_config.broadcast_rooms.append(PATH_FINDING_BROADCASTING_ROOM)

    # Add monitoring service broadcast room if enabled
    if services_config.monitoring_enabled is True:
        transport_config.broadcast_rooms.append(MONITORING_BROADCASTING_ROOM)

    return MatrixTransport(config=transport_config, environment=environment_type)
Beispiel #4
0
def mock_matrix(monkeypatch, mock_raiden_service, retry_interval, retries_before_backoff):

    from raiden.network.transport.matrix.client import GMatrixClient
    from raiden.network.transport.matrix.utils import UserPresence
    from raiden.network.transport.matrix import transport as transport_module

    def make_client_monkey(
        handle_messages_callback, servers, *args, **kwargs
    ):  # pylint: disable=unused-argument
        return GMatrixClient(handle_messages_callback, servers[0])

    monkeypatch.setattr(User, "get_display_name", lambda _: "random_display_name")
    monkeypatch.setattr(transport_module, "make_client", make_client_monkey)

    def mock_get_room_ids_for_address(  # pylint: disable=unused-argument
        klass, address: Address
    ) -> List[str]:
        return ["!roomID:server"]

    def mock_set_room_id_for_address(  # pylint: disable=unused-argument
        self, address: Address, room_id: Optional[str]
    ):
        pass

    def mock_on_messages(messages):  # pylint: disable=unused-argument
        for message in messages:
            assert message
            assert message.sender

    def mock_get_user_presence(self, user_id: str):
        return UserPresence.ONLINE

    config = MatrixTransportConfig(
        broadcast_rooms=[],
        retries_before_backoff=retries_before_backoff,
        retry_interval=retry_interval,
        server="http://none",
        server_name="none",
        available_servers=[],
    )

    transport = MatrixTransport(config=config, environment=Environment.DEVELOPMENT)
    transport._raiden_service = mock_raiden_service
    transport._stop_event.clear()
    transport._address_mgr.add_userid_for_address(factories.HOP1, USERID1)
    transport._client.user_id = USERID0

    monkeypatch.setattr(
        MatrixTransport, "_get_room_ids_for_address", mock_get_room_ids_for_address
    )
    monkeypatch.setattr(MatrixTransport, "_set_room_id_for_address", mock_set_room_id_for_address)
    monkeypatch.setattr(transport._raiden_service, "on_messages", mock_on_messages)
    monkeypatch.setattr(GMatrixClient, "get_user_presence", mock_get_user_presence)

    monkeypatch.setattr(transport._client.api, "leave_room", lambda room_id: None)
    monkeypatch.setattr(transport._client, "sync_token", "already_synced")

    return transport
Beispiel #5
0
def fetch_available_matrix_servers(transport_config: MatrixTransportConfig,
                                   environment_type: Environment) -> None:
    """
    Fetches the list of known servers from raiden-network/raiden-tranport repo
    for the given environment.
    """
    available_servers_url = DEFAULT_MATRIX_KNOWN_SERVERS[environment_type]

    log.debug("Fetching available matrix servers")
    available_servers = get_matrix_servers(available_servers_url)
    log.debug("Available matrix servers", available_servers=available_servers)

    transport_config.available_servers = available_servers
Beispiel #6
0
def test_matrix_broadcast(
    local_matrix_servers,
    retries_before_backoff,
    retry_interval_initial,
    retry_interval_max,
    broadcast_rooms,
):
    transport = MatrixTransport(
        config=MatrixTransportConfig(
            broadcast_rooms=broadcast_rooms,
            retries_before_backoff=retries_before_backoff,
            retry_interval_initial=retry_interval_initial,
            retry_interval_max=retry_interval_max,
            server=local_matrix_servers[0],
            available_servers=[local_matrix_servers[0]],
        ),
        environment=Environment.DEVELOPMENT,
    )
    transport.start(MockRaidenService(None), [], "")
    gevent.idle()

    ms_room_name = make_room_alias(transport.chain_id,
                                   MONITORING_BROADCASTING_ROOM)
    ms_room = transport._broadcast_rooms.get(ms_room_name)
    assert isinstance(ms_room, Room)

    ms_room.send_text = MagicMock(spec=ms_room.send_text)

    for i in range(5):
        message = Processed(message_identifier=i, signature=EMPTY_SIGNATURE)
        transport._raiden_service.sign(message)
        transport.broadcast(MONITORING_BROADCASTING_ROOM, message)
    transport._schedule_new_greenlet(transport._broadcast_worker)

    gevent.idle()

    assert ms_room.send_text.call_count >= 1
    # messages could have been bundled
    call_args_str = " ".join(
        str(arg) for arg in ms_room.send_text.call_args_list)
    for i in range(5):
        assert f'"message_identifier": "{i}"' in call_args_str

    transport.stop()
    transport.greenlet.get()
Beispiel #7
0
def matrix_transports(
    local_matrix_servers: List[ParsedURL],
    retries_before_backoff: int,
    retry_interval_initial: float,
    retry_interval_max: float,
    number_of_transports: int,
    broadcast_rooms: List[str],
    matrix_sync_timeout: int,
    capabilities: CapabilitiesConfig,
) -> Iterable[List[MatrixTransport]]:
    transports = []
    local_matrix_servers_str = [str(server) for server in local_matrix_servers]

    for transport_index in range(number_of_transports):
        server = local_matrix_servers[transport_index %
                                      len(local_matrix_servers)]
        transports.append(
            MatrixTransport(
                config=MatrixTransportConfig(
                    broadcast_rooms=broadcast_rooms.copy(),
                    retries_before_backoff=retries_before_backoff,
                    retry_interval_initial=retry_interval_initial,
                    retry_interval_max=retry_interval_max,
                    server=server,
                    available_servers=local_matrix_servers_str,
                    sync_timeout=matrix_sync_timeout,
                    capabilities_config=capabilities,
                ),
                environment=Environment.DEVELOPMENT,
            ))

    yield transports

    for transport in transports:
        transport.stop()

    for transport in transports:
        # Calling `get()` on a never started Greenlet will block forever
        if transport._started:
            transport.greenlet.get()
def test_pfs_broadcast_messages(
    local_matrix_servers,
    retry_interval_initial,
    retry_interval_max,
    retries_before_backoff,
    monkeypatch,
    broadcast_rooms,
    route_mode,
):
    """
    Test that RaidenService broadcasts PFSCapacityUpdate messages to
    PATH_FINDING_BROADCASTING_ROOM room on newly received balance proofs.
    """
    transport = MatrixTransport(
        config=MatrixTransportConfig(
            broadcast_rooms=broadcast_rooms,
            retries_before_backoff=retries_before_backoff,
            retry_interval_initial=retry_interval_initial,
            retry_interval_max=retry_interval_max,
            server=local_matrix_servers[0],
            available_servers=[local_matrix_servers[0]],
        ),
        environment=Environment.DEVELOPMENT,
    )
    transport._client.api.retry_timeout = 0
    transport._send_raw = MagicMock()
    raiden_service = MockRaidenService(None)
    raiden_service.config.services.monitoring_enabled = True
    raiden_service.routing_mode = route_mode

    transport.start(raiden_service, [], None)

    pfs_room_name = make_room_alias(transport.chain_id, PATH_FINDING_BROADCASTING_ROOM)
    pfs_room = transport._broadcast_rooms.get(pfs_room_name)
    assert isinstance(pfs_room, Room)
    pfs_room.send_text = MagicMock(spec=pfs_room.send_text)

    raiden_service.transport = transport
    transport.log = MagicMock()

    # send PFSCapacityUpdate
    balance_proof = factories.create(HOP1_BALANCE_PROOF)
    channel_state = factories.create(factories.NettingChannelStateProperties())
    channel_state.our_state.balance_proof = balance_proof
    channel_state.partner_state.balance_proof = balance_proof
    monkeypatch.setattr(
        raiden.transfer.views,
        "get_channelstate_by_canonical_identifier",
        lambda *a, **kw: channel_state,
    )
    send_pfs_update(raiden=raiden_service, canonical_identifier=balance_proof.canonical_identifier)
    gevent.idle()
    with gevent.Timeout(2):
        while pfs_room.send_text.call_count < 1:
            gevent.idle()
    assert pfs_room.send_text.call_count == 1

    # send PFSFeeUpdate
    channel_state = factories.create(factories.NettingChannelStateProperties())
    fee_update = PFSFeeUpdate.from_channel_state(channel_state)
    fee_update.sign(raiden_service.signer)
    raiden_service.transport.broadcast(PATH_FINDING_BROADCASTING_ROOM, fee_update)
    with gevent.Timeout(2):
        while pfs_room.send_text.call_count < 2:
            gevent.idle()
    assert pfs_room.send_text.call_count == 2
    msg_data = json.loads(pfs_room.send_text.call_args[0][0])
    assert msg_data["type"] == "PFSFeeUpdate"

    transport.stop()
    transport.greenlet.get()
def test_monitoring_broadcast_messages(
    local_matrix_servers,
    retry_interval_initial,
    retry_interval_max,
    retries_before_backoff,
    monkeypatch,
    broadcast_rooms,
):
    """
    Test that RaidenService broadcast RequestMonitoring messages to
    MONITORING_BROADCASTING_ROOM room on newly received balance proofs.
    """
    transport = MatrixTransport(
        config=MatrixTransportConfig(
            broadcast_rooms=broadcast_rooms + [MONITORING_BROADCASTING_ROOM],
            retries_before_backoff=retries_before_backoff,
            retry_interval_initial=retry_interval_initial,
            retry_interval_max=retry_interval_max,
            server=local_matrix_servers[0],
            available_servers=[local_matrix_servers[0]],
        ),
        environment=Environment.DEVELOPMENT,
    )
    transport._client.api.retry_timeout = 0
    transport._send_raw = MagicMock()
    raiden_service = MockRaidenService(None)
    raiden_service.config = RaidenConfig(
        chain_id=1234,
        environment_type=Environment.DEVELOPMENT,
        services=ServiceConfig(monitoring_enabled=True),
    )

    transport.start(raiden_service, [], None)

    ms_room_name = make_room_alias(transport.chain_id, MONITORING_BROADCASTING_ROOM)
    ms_room = transport._broadcast_rooms.get(ms_room_name)
    assert isinstance(ms_room, Room)
    ms_room.send_text = MagicMock(spec=ms_room.send_text)

    raiden_service.transport = transport
    transport.log = MagicMock()

    balance_proof = factories.create(HOP1_BALANCE_PROOF)
    channel_state = factories.create(factories.NettingChannelStateProperties())
    channel_state.our_state.balance_proof = balance_proof
    channel_state.partner_state.balance_proof = balance_proof
    monkeypatch.setattr(
        raiden.transfer.views,
        "get_channelstate_by_canonical_identifier",
        lambda *a, **kw: channel_state,
    )
    monkeypatch.setattr(raiden.transfer.channel, "get_balance", lambda *a, **kw: 123)
    raiden_service.user_deposit.effective_balance.return_value = MONITORING_REWARD

    update_monitoring_service_from_balance_proof(
        raiden=raiden_service,
        chain_state=None,
        new_balance_proof=balance_proof,
        non_closing_participant=HOP1,
    )
    gevent.idle()

    with gevent.Timeout(2):
        while ms_room.send_text.call_count < 1:
            gevent.idle()
    assert ms_room.send_text.call_count == 1

    transport.stop()
    transport.greenlet.get()
def test_matrix_message_retry(
    local_matrix_servers,
    retry_interval_initial,
    retry_interval_max,
    retries_before_backoff,
    broadcast_rooms,
):
    """ Test the retry mechanism implemented into the matrix client.
    The test creates a transport and sends a message. Given that the
    receiver was online, the initial message is sent but the receiver
    doesn't respond in time and goes offline. The retrier should then
    wait for the `retry_interval` duration to pass and send the message
    again but this won't work because the receiver is offline. Once
    the receiver comes back again, the message should be sent again.
    """
    partner_address = factories.make_address()

    transport = MatrixTransport(
        config=MatrixTransportConfig(
            broadcast_rooms=broadcast_rooms,
            retries_before_backoff=retries_before_backoff,
            retry_interval_initial=retry_interval_initial,
            retry_interval_max=retry_interval_max,
            server=local_matrix_servers[0],
            available_servers=[local_matrix_servers[0]],
        ),
        environment=Environment.DEVELOPMENT,
    )
    transport._send_raw = MagicMock()
    raiden_service = MockRaidenService(None)

    transport.start(raiden_service, [], None)
    transport.log = MagicMock()

    # Receiver is online
    transport._address_mgr._address_to_reachabilitystate[partner_address] = ReachabilityState(
        AddressReachability.REACHABLE, datetime.now()
    )

    queueid = QueueIdentifier(
        recipient=partner_address, canonical_identifier=CANONICAL_IDENTIFIER_UNORDERED_QUEUE
    )
    chain_state = raiden_service.wal.state_manager.current_state

    retry_queue: _RetryQueue = transport._get_retrier(partner_address)
    assert bool(retry_queue), "retry_queue not running"

    # Send the initial message
    message = Processed(message_identifier=0, signature=EMPTY_SIGNATURE)
    transport._raiden_service.sign(message)
    chain_state.queueids_to_queues[queueid] = [message]
    retry_queue.enqueue_unordered(message)

    gevent.idle()
    assert transport._send_raw.call_count == 1

    # Receiver goes offline
    transport._address_mgr._address_to_reachabilitystate[partner_address] = ReachabilityState(
        AddressReachability.UNREACHABLE, datetime.now()
    )

    with gevent.Timeout(retry_interval_initial + 2):
        wait_assert(
            transport.log.debug.assert_called_with,
            "Partner not reachable. Skipping.",
            partner=to_checksum_address(partner_address),
            status=AddressReachability.UNREACHABLE,
        )

    # Retrier did not call send_raw given that the receiver is still offline
    assert transport._send_raw.call_count == 1

    # Receiver comes back online
    transport._address_mgr._address_to_reachabilitystate[partner_address] = ReachabilityState(
        AddressReachability.REACHABLE, datetime.now()
    )

    # Retrier should send the message again
    with gevent.Timeout(retry_interval_initial + 2):
        while transport._send_raw.call_count != 2:
            gevent.sleep(0.1)

    transport.stop()
    transport.greenlet.get()
Beispiel #11
0
def create_apps(
    chain_id: ChainID,
    contracts_path: Path,
    blockchain_services: BlockchainServices,
    token_network_registry_address: TokenNetworkRegistryAddress,
    one_to_n_address: Optional[OneToNAddress],
    secret_registry_address: SecretRegistryAddress,
    service_registry_address: Optional[ServiceRegistryAddress],
    user_deposit_address: Optional[UserDepositAddress],
    monitoring_service_contract_address: MonitoringServiceAddress,
    reveal_timeout: BlockTimeout,
    settle_timeout: BlockTimeout,
    database_basedir: str,
    retry_interval_initial: float,
    retry_interval_max: float,
    retries_before_backoff: int,
    environment_type: Environment,
    unrecoverable_error_should_crash: bool,
    local_matrix_url: Optional[ParsedURL],
    broadcast_rooms: List[str],
    routing_mode: RoutingMode,
    blockchain_query_interval: float,
    resolver_ports: List[Optional[int]],
    enable_rest_api: bool,
    port_generator: Iterator[Port],
    capabilities_config: CapabilitiesConfig,
) -> List[App]:
    """ Create the apps."""
    # pylint: disable=too-many-locals
    services = blockchain_services

    apps = []
    for idx, proxy_manager in enumerate(services):
        database_path = database_from_privatekey(base_dir=database_basedir,
                                                 app_number=idx)
        assert len(resolver_ports) > idx
        resolver_port = resolver_ports[idx]

        config = RaidenConfig(
            chain_id=chain_id,
            environment_type=environment_type,
            unrecoverable_error_should_crash=unrecoverable_error_should_crash,
            reveal_timeout=reveal_timeout,
            settle_timeout=settle_timeout,
            contracts_path=contracts_path,
            database_path=database_path,
            blockchain=BlockchainConfig(
                confirmation_blocks=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
                query_interval=blockchain_query_interval,
            ),
            mediation_fees=MediationFeeConfig(),
            services=ServiceConfig(monitoring_enabled=False),
            rest_api=RestApiConfig(rest_api_enabled=enable_rest_api,
                                   host=Host("localhost"),
                                   port=next(port_generator)),
            console=False,
            transport_type="matrix",
        )
        config.transport.capabilities_config = capabilities_config

        if local_matrix_url is not None:
            config.transport = MatrixTransportConfig(
                broadcast_rooms=broadcast_rooms,
                retries_before_backoff=retries_before_backoff,
                retry_interval_initial=retry_interval_initial,
                retry_interval_max=retry_interval_max,
                server=local_matrix_url,
                available_servers=[],
                capabilities_config=capabilities_config,
            )

        assert config.transport.capabilities_config is not None
        if resolver_port is not None:
            config.resolver_endpoint = f"http://localhost:{resolver_port}"

        registry = proxy_manager.token_network_registry(
            token_network_registry_address, block_identifier=BLOCK_ID_LATEST)
        secret_registry = proxy_manager.secret_registry(
            secret_registry_address, block_identifier=BLOCK_ID_LATEST)

        service_registry = None
        if service_registry_address:
            service_registry = proxy_manager.service_registry(
                service_registry_address, block_identifier=BLOCK_ID_LATEST)

        user_deposit = None
        if user_deposit_address:
            user_deposit = proxy_manager.user_deposit(
                user_deposit_address, block_identifier=BLOCK_ID_LATEST)

        # Use `TestMatrixTransport` that saves sent messages for assertions in tests
        assert config.transport.capabilities_config is not None
        transport = TestMatrixTransport(config=config.transport,
                                        environment=environment_type)

        raiden_event_handler = RaidenEventHandler()
        hold_handler = HoldRaidenEventHandler(raiden_event_handler)
        message_handler = WaitForMessage()

        api_server = None
        if enable_rest_api:
            api_server = start_api_server(rpc_client=proxy_manager.client,
                                          config=config.rest_api,
                                          eth_rpc_endpoint="bla")

        app = App(
            config=config,
            rpc_client=proxy_manager.client,
            proxy_manager=proxy_manager,
            query_start_block=BlockNumber(0),
            default_registry=registry,
            default_secret_registry=secret_registry,
            default_service_registry=service_registry,
            default_user_deposit=user_deposit,
            default_one_to_n_address=one_to_n_address,
            default_msc_address=monitoring_service_contract_address,
            transport=transport,
            raiden_event_handler=hold_handler,
            message_handler=message_handler,
            routing_mode=routing_mode,
            api_server=api_server,
        )
        apps.append(app)

    return apps