Ejemplo n.º 1
0
def get_network_to_broadcast_rooms(
        api: GMatrixHttpApi) -> Dict[str, List[RoomInfo]]:

    room_alias_fragments = [
        DISCOVERY_DEFAULT_ROOM,
        PATH_FINDING_BROADCASTING_ROOM,
        MONITORING_BROADCASTING_ROOM,
    ]

    server = urlparse(api.base_url).netloc
    network_to_broadcast: Dict[str, List[RoomInfo]] = dict()

    for network in Networks:
        broadcast_room_infos: List[RoomInfo] = list()
        network_to_broadcast[str(network.value)] = broadcast_room_infos
        for room_alias_fragment in room_alias_fragments:
            broadcast_room_alias = make_room_alias(ChainID(network.value),
                                                   room_alias_fragment)
            local_room_alias = f"#{broadcast_room_alias}:{server}"

            try:
                room_id = api.get_room_id(local_room_alias)
                broadcast_room_infos.append(
                    RoomInfo(room_id, broadcast_room_alias, server))
            except MatrixError as ex:
                click.secho(
                    f"Could not find room {broadcast_room_alias} with error {ex}"
                )

    return network_to_broadcast
Ejemplo n.º 2
0
def test_pfs_send_capacity_updates_on_deposit_and_withdraw(
        raiden_network: List[App],
        token_addresses: List[TokenAddress]) -> None:
    # We need to test if PFSCapacityUpdates and PFSFeeUpdates are being
    # sent after a deposit and withdraw.
    # Therefore, we create two Raiden nodes app0 and app1.
    # The nodes open a channel but do not deposit
    # a pfs matrix room is mocked to see what is sent to it

    app0, app1 = raiden_network
    transport0 = app0.raiden.transport

    pfs_room_name = make_room_alias(transport0.chain_id,
                                    PATH_FINDING_BROADCASTING_ROOM)
    pfs_room = transport0._broadcast_rooms.get(pfs_room_name)
    # need to assert for mypy that pfs_room is not None
    assert isinstance(pfs_room, Room)
    pfs_room.send_text = MagicMock(spec=pfs_room.send_text)

    api0 = RaidenAPI(app0.raiden)

    api0.channel_open(
        token_address=token_addresses[0],
        registry_address=app0.raiden.default_registry.address,
        partner_address=app1.raiden.address,
    )

    # the room should not have been called at channel opening
    assert pfs_room.send_text.call_count == 0

    api0.set_total_channel_deposit(
        token_address=token_addresses[0],
        registry_address=app0.raiden.default_registry.address,
        partner_address=app1.raiden.address,
        total_deposit=TokenAmount(10),
    )

    # now we expect the room to be called the 1st time with a PFSCapacityUpdate
    # and a PFSFeeUpdate after the deposit
    assert "PFSCapacityUpdate" in str(pfs_room.send_text.call_args_list[0])
    assert "PFSFeeUpdate" in str(pfs_room.send_text.call_args_list[0])

    api0.set_total_channel_withdraw(
        token_address=token_addresses[0],
        registry_address=app0.raiden.default_registry.address,
        partner_address=app1.raiden.address,
        total_withdraw=WithdrawAmount(5),
    )

    # now we expect the room to be called the 2nd time with a PFSCapacityUpdate
    # after the withdraw
    assert "PFSCapacityUpdate" in str(pfs_room.send_text.call_args_list[1])
    assert "PFSFeeUpdate" in str(pfs_room.send_text.call_args_list[1])
Ejemplo n.º 3
0
def get_discovery_room(api: GMatrixHttpApi,
                       network_value: int) -> Optional[RoomInfo]:

    server = urlparse(api.base_url).netloc
    discovery_room_alias = make_room_alias(ChainID(network_value),
                                           DISCOVERY_DEFAULT_ROOM)
    local_room_alias = f"#{discovery_room_alias}:{server}"

    try:
        room_id = api.get_room_id(local_room_alias)
        return RoomInfo(room_id, discovery_room_alias, server)
    except MatrixError as ex:
        click.secho(
            f"Could not find room {discovery_room_alias} with error {ex}")

    return None
Ejemplo n.º 4
0
def test_pfs_send_capacity_updates_during_mediated_transfer(
        raiden_network, number_of_nodes, deposit, token_addresses,
        network_wait):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state, token_network_registry_address, token_address)

    # Mock send_text on the PFS room
    transport0 = app0.raiden.transport
    pfs_room_name = make_room_alias(transport0.chain_id,
                                    PATH_FINDING_BROADCASTING_ROOM)
    pfs_room = transport0._broadcast_rooms.get(pfs_room_name)
    # need to assert for mypy that pfs_room is not None
    assert isinstance(pfs_room, Room)
    pfs_room.send_text = MagicMock(spec=pfs_room.send_text)

    amount = PaymentAmount(10)
    secrethash = transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=PaymentID(1),
        timeout=network_wait * number_of_nodes,
    )

    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_succeeding_transfer_invariants,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )

    # We expect one PFSCapacityUpdate when locking and one when unlocking
    assert pfs_room.send_text.call_count == 2
    assert "PFSCapacityUpdate" in str(pfs_room.send_text.call_args_list[0])
Ejemplo n.º 5
0
 def ensure_rooms(self) -> None:
     exceptions = {}
     for network in Networks:
         for alias_fragment in [
             DISCOVERY_DEFAULT_ROOM,
             MONITORING_BROADCASTING_ROOM,
             PATH_FINDING_BROADCASTING_ROOM,
         ]:
             try:
                 room_alias_prefix = make_room_alias(ChainID(network.value), alias_fragment)
                 self._first_server_actions(room_alias_prefix)
                 log.info(f"Ensuring {alias_fragment} room for {network.name}")
                 self._ensure_room_for_network(room_alias_prefix)
             except (MatrixError, EnsurerError) as ex:
                 log.exception(f"Error while ensuring room for {network.name}.")
                 exceptions[network] = ex
     if exceptions:
         log.error("Exceptions happened", exceptions=exceptions)
         raise MultipleErrors(exceptions)
Ejemplo n.º 6
0
    def _ensure_room_for_network(self, network: Networks,
                                 alias_fragment: str) -> None:
        log.info(f"Ensuring {alias_fragment} room for {network.name}")
        room_alias_prefix = make_room_alias(ChainID(network.value),
                                            alias_fragment)
        room_infos: Dict[str, Optional[RoomInfo]] = {
            server_name: self._get_room(server_name, room_alias_prefix)
            for server_name in self._known_servers.keys()
        }
        first_server_room_info = room_infos[self._first_server_name]

        if not first_server_room_info:
            log.warning("First server room missing")
            if self._is_first_server:
                log.info("Creating room", server_name=self._own_server_name)
                first_server_room_info = self._create_room(
                    self._own_server_name, room_alias_prefix)
                room_infos[self._first_server_name] = first_server_room_info
            else:
                raise EnsurerError("First server room missing.")

        are_all_rooms_the_same = all(
            room_info is not None
            and room_info.room_id == first_server_room_info.room_id
            for room_info in room_infos.values())
        if not are_all_rooms_the_same:
            log.warning(
                "Room id mismatch",
                alias_prefix=room_alias_prefix,
                expected=first_server_room_info.room_id,
                found={
                    server_name: room_info.room_id if room_info else None
                    for server_name, room_info in room_infos.items()
                },
            )
            own_server_room_info = room_infos.get(self._own_server_name)
            own_server_room_alias = f"#{room_alias_prefix}:{self._own_server_name}"
            first_server_room_alias = f"#{room_alias_prefix}:{self._first_server_name}"
            if not own_server_room_info:
                log.warning(
                    "Room missing on own server, adding alias",
                    server_name=self._own_server_name,
                    room_id=first_server_room_info.room_id,
                    new_room_alias=own_server_room_alias,
                )
                self._join_and_alias_room(first_server_room_alias,
                                          own_server_room_alias)
                log.info("Room alias set", alias=own_server_room_alias)
            elif own_server_room_info.room_id != first_server_room_info.room_id:
                log.warning(
                    "Conflicting local room, reassigning alias",
                    server_name=self._own_server_name,
                    expected_room_id=first_server_room_info.room_id,
                    current_room_id=own_server_room_info.room_id,
                )
                self._own_api.remove_room_alias(own_server_room_alias)
                self._join_and_alias_room(first_server_room_alias,
                                          own_server_room_alias)
                log.info(
                    "Room alias updated",
                    alias=own_server_room_alias,
                    room_id=first_server_room_info.room_id,
                )
            else:
                log.warning(
                    "Mismatching rooms on other servers. Doing nothing.")
        else:
            log.info(
                "Room state ok.",
                network=network,
                server_rooms={
                    server_name: room_info.room_id if room_info else None
                    for server_name, room_info in room_infos.items()
                },
            )
Ejemplo n.º 7
0
def run_raiden_service(
    address: Address,
    keystore_path: str,
    gas_price: Callable,
    eth_rpc_endpoint: str,
    user_deposit_contract_address: Optional[UserDepositAddress],
    api_address: Endpoint,
    rpc: bool,
    rpccorsdomain: str,
    sync_check: bool,
    console: bool,
    password_file: TextIO,
    web_ui: bool,
    datadir: Optional[str],
    matrix_server: str,
    chain_id: ChainID,
    environment_type: Environment,
    unrecoverable_error_should_crash: bool,
    pathfinding_service_address: str,
    pathfinding_max_paths: int,
    enable_monitoring: bool,
    resolver_endpoint: str,
    default_reveal_timeout: BlockTimeout,
    default_settle_timeout: BlockTimeout,
    routing_mode: RoutingMode,
    flat_fee: Tuple[Tuple[TokenAddress, FeeAmount], ...],
    proportional_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...],
    proportional_imbalance_fee: Tuple[Tuple[TokenAddress,
                                            ProportionalFeeAmount], ...],
    blockchain_query_interval: float,
    cap_mediation_fees: bool,
    **
    kwargs: Any,  # FIXME: not used here, but still receives stuff in smoketest
) -> RaidenService:
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument

    token_network_registry_deployed_at: Optional[BlockNumber]
    smart_contracts_start_at: BlockNumber

    if datadir is None:
        datadir = os.path.join(os.path.expanduser("~"), ".raiden")

    account_manager = AccountManager(keystore_path)
    web3 = Web3(HTTPProvider(rpc_normalized_endpoint(eth_rpc_endpoint)))

    check_sql_version()
    check_ethereum_has_accounts(account_manager)
    check_ethereum_chain_id(chain_id, web3)

    address, privatekey = get_account_and_private_key(account_manager, address,
                                                      password_file)

    api_host, api_port = split_endpoint(api_address)

    if not api_port:
        api_port = DEFAULT_HTTP_SERVER_PORT

    domain_list = []
    if rpccorsdomain:
        if "," in rpccorsdomain:
            for domain in rpccorsdomain.split(","):
                domain_list.append(str(domain))
        else:
            domain_list.append(str(rpccorsdomain))

    # Set up config
    fee_config = prepare_mediation_fee_config(
        cli_token_to_flat_fee=flat_fee,
        cli_token_to_proportional_fee=proportional_fee,
        cli_token_to_proportional_imbalance_fee=proportional_imbalance_fee,
        cli_cap_mediation_fees=cap_mediation_fees,
    )
    rest_api_config = RestApiConfig(
        rest_api_enabled=rpc,
        web_ui_enabled=rpc and web_ui,
        cors_domain_list=domain_list,
        eth_rpc_endpoint=eth_rpc_endpoint,
        host=api_host,
        port=api_port,
    )

    config = RaidenConfig(
        chain_id=chain_id,
        environment_type=environment_type,
        reveal_timeout=default_reveal_timeout,
        settle_timeout=default_settle_timeout,
        console=console,
        mediation_fees=fee_config,
        unrecoverable_error_should_crash=unrecoverable_error_should_crash,
        resolver_endpoint=resolver_endpoint,
        rest_api=rest_api_config,
    )
    config.blockchain.query_interval = blockchain_query_interval
    config.services.monitoring_enabled = enable_monitoring
    config.services.pathfinding_max_paths = pathfinding_max_paths
    config.transport.server = matrix_server

    contracts = load_deployed_contracts_data(config, chain_id)

    rpc_client = JSONRPCClient(
        web3=web3,
        privkey=privatekey,
        gas_price_strategy=gas_price,
        block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
    )

    token_network_registry_deployed_at = None
    if "TokenNetworkRegistry" in contracts:
        token_network_registry_deployed_at = BlockNumber(
            contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["block_number"])

    if token_network_registry_deployed_at is None:
        smart_contracts_start_at = get_smart_contracts_start_at(chain_id)
    else:
        smart_contracts_start_at = token_network_registry_deployed_at

    proxy_manager = ProxyManager(
        rpc_client=rpc_client,
        contract_manager=ContractManager(config.contracts_path),
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=
            token_network_registry_deployed_at,
            filters_start_at=smart_contracts_start_at,
        ),
    )

    api_server: Optional[APIServer] = None
    if config.rest_api.rest_api_enabled:
        api_server = start_api_server(rpc_client=rpc_client,
                                      config=config.rest_api,
                                      eth_rpc_endpoint=eth_rpc_endpoint)

    if sync_check:
        check_synced(rpc_client)

    # The user has the option to launch Raiden with a custom
    # user deposit contract address. This can be used to load
    # the addresses for the rest of the deployed contracts.
    # The steps done here make sure that if a UDC address is provided,
    # the address has to be valid and all the connected contracts
    # are configured properly.
    # If a UDC address was not provided, Raiden would fall back
    # to using the ones deployed and provided by the raiden-contracts package.
    if user_deposit_contract_address is not None:
        if not is_address(user_deposit_contract_address):
            raise RaidenError("The user deposit address is invalid")

        deployed_addresses = load_deployment_addresses_from_udc(
            proxy_manager=proxy_manager,
            user_deposit_address=user_deposit_contract_address,
            block_identifier=BLOCK_ID_LATEST,
        )
    else:
        deployed_addresses = load_deployment_addresses_from_contracts(
            contracts=contracts)

    # Load the available matrix servers when no matrix server is given
    # The list is used in a PFS check
    if config.transport.server == MATRIX_AUTO_SELECT_SERVER:
        fetch_available_matrix_servers(config.transport, environment_type)

    raiden_bundle = raiden_bundle_from_contracts_deployment(
        proxy_manager=proxy_manager,
        token_network_registry_address=deployed_addresses.
        token_network_registry_address,
        secret_registry_address=deployed_addresses.secret_registry_address,
    )

    services_bundle = services_bundle_from_contracts_deployment(
        config=config,
        deployed_addresses=deployed_addresses,
        proxy_manager=proxy_manager,
        routing_mode=routing_mode,
        pathfinding_service_address=pathfinding_service_address,
        enable_monitoring=enable_monitoring,
    )

    check_ethereum_confirmed_block_is_not_pruned(
        jsonrpc_client=rpc_client,
        secret_registry=raiden_bundle.secret_registry,
        confirmation_blocks=config.blockchain.confirmation_blocks,
    )

    database_path = Path(
        os.path.join(
            datadir,
            f"node_{pex(address)}",
            f"netid_{chain_id}",
            f"network_{pex(raiden_bundle.token_network_registry.address)}",
            f"v{RAIDEN_DB_VERSION}_log.db",
        ))
    config.database_path = database_path

    print(f"Raiden is running in {environment_type.value.lower()} mode")
    print("\nYou are connected to the '{}' network and the DB path is: {}".
          format(ID_TO_CHAINNAME.get(chain_id, chain_id), database_path))

    matrix_transport = setup_matrix(config.transport, config.services,
                                    environment_type, routing_mode)

    event_handler: EventHandler = RaidenEventHandler()

    # User should be told how to set fees, if using default fee settings
    log.debug("Fee Settings", fee_settings=fee_config)
    has_default_fees = (len(fee_config.token_to_flat_fee) == 0
                        and len(fee_config.token_to_proportional_fee) == 0
                        and len(fee_config.token_to_proportional_imbalance_fee)
                        == 0)
    if has_default_fees:
        click.secho(
            "Default fee settings are used. "
            "If you want use Raiden with mediation fees - flat, proportional and imbalance fees - "
            "see https://raiden-network.readthedocs.io/en/latest/overview_and_guide.html#firing-it-up",  # noqa: E501
            fg="yellow",
        )

    # Only send feedback when PFS is used
    if routing_mode == RoutingMode.PFS:
        event_handler = PFSFeedbackEventHandler(event_handler)

    message_handler = MessageHandler()

    raiden_service = RaidenService(
        config=config,
        rpc_client=rpc_client,
        proxy_manager=proxy_manager,
        query_start_block=smart_contracts_start_at,
        raiden_bundle=raiden_bundle,
        services_bundle=services_bundle,
        transport=matrix_transport,
        raiden_event_handler=event_handler,
        message_handler=message_handler,
        routing_mode=routing_mode,
        api_server=api_server,
    )

    raiden_service.start()

    if config.pfs_config is not None:
        # This has to be done down here since there is a circular dependency
        # between the PFS and Transport
        pfs_broadcast_room_key = make_room_alias(
            config.chain_id, PATH_FINDING_BROADCASTING_ROOM)
        check_pfs_transport_configuration(
            pfs_info=config.pfs_config.info,
            pfs_was_autoselected=(
                pathfinding_service_address == MATRIX_AUTO_SELECT_SERVER),
            transport_pfs_broadcast_room_id=matrix_transport.
            broadcast_rooms[pfs_broadcast_room_key].room_id,
            matrix_server_url=matrix_transport.server_url,
            matrix_server_was_autoselected=(
                config.transport.server == MATRIX_AUTO_SELECT_SERVER),
        )

    return raiden_service