def test_capacity_check(
    token_network_model: TokenNetwork,
    reachability_state: SimpleReachabilityContainer,
    addresses: List[Address],
):
    """ Test that the mediation fees are included in the capacity check """
    # First get a path without mediation fees. This must return the shortest path: 4->1->0
    paths = token_network_model.get_paths(
        source=addresses[4],
        target=addresses[0],
        value=PaymentAmount(35),
        max_paths=1,
        reachability_state=reachability_state,
    )
    index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths]
    assert index_paths == [[4, 1, 0]]

    # New let's add mediation fees to the channel 0->1.
    model_with_fees = deepcopy(token_network_model)
    model_with_fees.G[addresses[1]][
        addresses[0]]["view"].fee_schedule_sender.flat = 1
    # The transfer from 4->1 must now include 1 Token for the mediation fee
    # which will be payed for the 1->0 channel in addition to the payment
    # value of 35. But 35 + 1 exceeds the capacity for channel 4->1, which is
    # 35. So we should now get the next best route instead.
    paths = model_with_fees.get_paths(
        source=addresses[4],
        target=addresses[0],
        value=PaymentAmount(35),
        max_paths=1,
        reachability_state=reachability_state,
        fee_penalty=0,
    )
    index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths]
    assert index_paths == [[4, 1, 2, 0]]
Example #2
0
def test_channel_withdraw(
    raiden_network: List[App],
    token_addresses: List[TokenAddress],
    deposit: TokenAmount,
    retry_timeout: float,
) -> None:
    """ Withdraw funds after a mediated transfer."""
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address
    )
    assert token_network_address

    token_proxy = bob_app.raiden.proxy_manager.token(token_address, BLOCK_ID_LATEST)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    message_handler = WaitForMessage()
    bob_app.raiden.message_handler = message_handler

    alice_to_bob_amount = PaymentAmount(10)
    identifier = PaymentID(1)
    target = TargetAddress(bob_app.raiden.address)
    secret = factories.make_secret()

    payment_status = alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=alice_to_bob_amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )
    wait_for_unlock = bob_app.raiden.message_handler.wait_for_message(
        Unlock, {"payment_identifier": identifier}
    )
    with block_offset_timeout(alice_app.raiden):
        wait_for_unlock.get()
        msg = (
            f"transfer from {to_checksum_address(alice_app.raiden.address)} "
            f"to {to_checksum_address(bob_app.raiden.address)} failed."
        )
        assert payment_status.payment_done.get(), msg

    total_withdraw = WithdrawAmount(deposit + alice_to_bob_amount)

    bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address)
    bob_app.raiden.withdraw(
        canonical_identifier=bob_alice_channel_state.canonical_identifier,
        total_withdraw=total_withdraw,
    )

    waiting.wait_for_withdraw_complete(
        raiden=bob_app.raiden,
        canonical_identifier=bob_alice_channel_state.canonical_identifier,
        total_withdraw=total_withdraw,
        retry_timeout=retry_timeout,
    )

    bob_balance_after_withdraw = token_proxy.balance_of(bob_app.raiden.address)
    assert bob_initial_balance + total_withdraw == bob_balance_after_withdraw
Example #3
0
def test_create_monitoring_request(raiden_network, token_addresses):
    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=chain_state,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
    )
    assert token_network_address

    payment_identifier = create_default_identifier()
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=PaymentAmount(1),
        identifier=payment_identifier,
    )
    chain_state = views.state_from_raiden(app0.raiden)
    channel_state = views.get_channelstate_by_token_network_and_partner(
        chain_state, token_network_address, app1.raiden.address)
    assert channel_state
    balance_proof = cast(BalanceProofSignedState,
                         channel_state.partner_state.balance_proof)
    api = RaidenAPI(app0.raiden)
    request = api.create_monitoring_request(balance_proof=balance_proof,
                                            reward_amount=TokenAmount(1))
    assert request
    as_dict = DictSerializer.serialize(request)
    from_dict = DictSerializer.deserialize(as_dict)
    assert DictSerializer.serialize(from_dict) == as_dict
Example #4
0
def test_close_regression(raiden_network, deposit, token_addresses):
    """ The python api was using the wrong balance proof to close the channel,
    thus the close was failing if a transfer was made.
    """
    app0, app1 = raiden_network
    token_address = token_addresses[0]

    api1 = RaidenAPI(app0.raiden)
    api2 = RaidenAPI(app1.raiden)

    registry_address = app0.raiden.default_registry.address
    channel_list = api1.get_channel_list(registry_address, token_address,
                                         app1.raiden.address)
    channel12 = channel_list[0]

    token_proxy = app0.raiden.proxy_manager.token(token_address,
                                                  BLOCK_ID_LATEST)
    node1_balance_before = token_proxy.balance_of(api1.address)
    node2_balance_before = token_proxy.balance_of(api2.address)

    # Initialize app2 balance proof and close the channel
    amount = PaymentAmount(10)
    identifier = PaymentID(42)
    secret, secrethash = factories.make_secret_with_hash()
    timeout = block_offset_timeout(app1.raiden, "Transfer timed out.")
    with watch_for_unlock_failures(*raiden_network), timeout:
        assert api1.transfer_and_wait(
            registry_address=registry_address,
            token_address=token_address,
            amount=amount,
            target=TargetAddress(api2.address),
            identifier=identifier,
            secret=secret,
        )
        timeout.exception_to_throw = ValueError(
            "Waiting for transfer received success in the WAL timed out.")
        result = waiting.wait_for_received_transfer_result(
            raiden=app1.raiden,
            payment_identifier=identifier,
            amount=amount,
            retry_timeout=app1.raiden.alarm.sleep_time,
            secrethash=secrethash,
        )

    msg = f"Unexpected transfer result: {str(result)}"
    assert result == waiting.TransferWaitResult.UNLOCKED, msg

    api2.channel_close(registry_address, token_address, api1.address)

    waiting.wait_for_settle(
        app0.raiden,
        app0.raiden.default_registry.address,
        token_address,
        [channel12.identifier],
        app0.raiden.alarm.sleep_time,
    )
    node1_expected_balance = node1_balance_before + deposit - amount
    node2_expected_balance = node2_balance_before + deposit + amount
    assert token_proxy.balance_of(api1.address) == node1_expected_balance
    assert token_proxy.balance_of(api2.address) == node2_expected_balance
Example #5
0
def test_regression_revealsecret_after_secret(
        raiden_network: List[App],
        token_addresses: List[TokenAddress]) -> None:
    """ A RevealSecret message received after a Unlock message must be cleanly
    handled.
    """
    app0, app1, app2 = raiden_network
    token = token_addresses[0]
    identifier = PaymentID(1)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), token_network_registry_address, token)
    assert token_network_address, "The fixtures must register the token"

    payment_status = app0.raiden.mediated_transfer_async(
        token_network_address,
        amount=PaymentAmount(1),
        target=TargetAddress(app2.raiden.address),
        identifier=identifier,
    )
    with watch_for_unlock_failures(*raiden_network):
        assert payment_status.payment_done.wait()

    assert app1.raiden.wal, "The fixtures must start the app."
    event = raiden_events_search_for_item(app1.raiden, SendSecretReveal, {})
    assert event

    reveal_secret = RevealSecret(
        message_identifier=make_message_identifier(),
        secret=event.secret,
        signature=EMPTY_SIGNATURE,
    )
    app2.raiden.sign(reveal_secret)
    app1.raiden.on_messages([reveal_secret])
Example #6
0
def test_regression_unfiltered_routes(raiden_network, token_addresses,
                                      settle_timeout, deposit):
    """ The transfer should proceed without triggering an assert.

    Transfers failed in networks where two or more paths to the destination are
    possible but they share same node as a first hop.
    """
    app0, app1, app2, app3, app4 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

    # Topology:
    #
    #  0 -> 1 -> 2 -> 4
    #       |         ^
    #       +--> 3 ---+
    app_channels = [(app0, app1), (app1, app2), (app1, app3), (app3, app4),
                    (app2, app4)]

    open_and_wait_for_channels(app_channels, registry_address, token, deposit,
                               settle_timeout)
    transfer(
        initiator_app=app0,
        target_app=app4,
        token_address=token,
        amount=PaymentAmount(1),
        identifier=PaymentID(1),
    )
def test_pfs_handler_handle_paymentsentsuccess_without_feedback_token():
    (
        raiden,
        pfs_handler,
        token_network_registry_address,
        token_network_address,
        route,
        _,
    ) = setup_pfs_handler_test(set_feedback_token=False)

    payment_id = make_payment_id()
    amount = PaymentAmount(123)
    target = TargetAddress(route[-1])
    raiden.targets_to_identifiers_to_statuses[target][payment_id] = Mock()

    route_failed_event = EventPaymentSentSuccess(
        token_network_registry_address=token_network_registry_address,
        token_network_address=token_network_address,
        identifier=payment_id,
        amount=amount,
        target=TargetAddress(target),
        secret=make_secret(),
        route=route,
    )

    with patch("raiden.raiden_event_handler.post_pfs_feedback"
               ) as pfs_feedback_handler:
        pfs_handler.on_raiden_events(
            raiden=raiden,
            chain_state=cast(
                ChainState,
                raiden.wal.state_manager.current_state),  # type: ignore
            events=[route_failed_event],
        )
    assert not pfs_feedback_handler.called
def test_receive_lockedtransfer_invalidnonce(raiden_network, number_of_nodes,
                                             deposit, token_addresses,
                                             reveal_timeout, network_wait):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token_address)
    assert token_network_address
    channel0 = get_channelstate(app0, app1, token_network_address)

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

    repeated_nonce = Nonce(1)
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_address,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=TokenAmount(amount),
        locked_amount=TokenAmount(amount),
        recipient=app1.raiden.address,
        locksroot=make_locksroot(),
        lock=Lock(amount=PaymentWithFeeAmount(amount),
                  expiration=expiration,
                  secrethash=UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        signature=EMPTY_SIGNATURE,
        metadata=Metadata(routes=[
            RouteMetadata(route=[app1.raiden.address, app2.raiden.address])
        ]),
    )

    sign_and_inject(mediated_transfer_message, app0.raiden.signer, app1)

    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )
Example #9
0
def test_api_channel_events(raiden_chain, token_addresses):
    app0, app1 = raiden_chain
    token_address = token_addresses[0]

    amount = PaymentAmount(30)
    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=PaymentID(1),
    )

    app0_events = RaidenAPI(app0.raiden).get_blockchain_events_channel(
        token_address, app1.raiden.address)

    assert must_have_event(app0_events, {"event": ChannelEvent.DEPOSIT})

    app0_events = app0.raiden.wal.storage.get_events()
    assert any(
        isinstance(event, EventPaymentSentSuccess) for event in app0_events)

    app1_events = app1.raiden.wal.storage.get_events()
    assert any(
        isinstance(event, EventPaymentReceivedSuccess)
        for event in app1_events)

    app1_events = RaidenAPI(app1.raiden).get_blockchain_events_channel(
        token_address, app0.raiden.address)
    assert must_have_event(app1_events, {"event": ChannelEvent.DEPOSIT})
Example #10
0
def test_mfee3():
    """ Unit test for the fee calculation in the mfee3_only_imbalance_fees scenario """
    amount = 500_000_000_000_000_000
    deposit = TokenAmount(1_000_000_000_000_000_000)
    imbalance_penalty = calculate_imbalance_fees(deposit, ProportionalFeeAmount(10_000))
    fee_schedule = FeeScheduleState(imbalance_penalty=imbalance_penalty, cap_fees=False)
    channels = make_channel_pair(fee_schedule, deposit)

    # How much do we need to send so that the target receives `amount`? PFS-like calculation.
    fee_calculation = get_initial_amount_for_amount_after_fees(
        amount_after_fees=PaymentAmount(amount), channels=[channels]
    )
    assert fee_calculation
    amount_with_margin = calculate_safe_amount_with_fee(
        fee_calculation.amount_without_fees, FeeAmount(sum(fee_calculation.mediation_fees))
    )
    assert amount_with_margin == 480_850_038_799_922_400

    # print values for scenario
    print("{:_} {:_}".format(deposit - amount_with_margin, amount_with_margin))
    for med_fee in running_sum(fee_calculation.mediation_fees):
        print(
            "{:_} {:_}".format(
                deposit - amount_with_margin + med_fee, amount_with_margin - med_fee
            )
        )
Example #11
0
    def is_valid(self) -> bool:
        """ Check capacity and settle timeout

        Capacity: The capacity for the last channel must be at least
        the payment value. The previous channel's capacity has to be larger
        than value + last channel's capacity, etc.

        Settle timeout: The raiden client will not forward payments if the
        channel over which they receive has a too low settle_timeout. So we
        should not use such routes. See
        https://github.com/raiden-network/raiden-services/issues/5.
        """
        log.debug("Checking path validity", nodes=self.nodes, value=self.value)
        if hasattr(self, "_is_valid"):
            return self._is_valid
        required_capacity = self.value
        edges = reversed(list(self.edge_attrs))
        fees = self.fees + [
            FeeAmount(0)
        ]  # The hop to the target does not incur mediation fees
        for edge, fee in zip(edges, fees):
            # check capacity
            if edge["view"].capacity < required_capacity:
                log.debug(
                    "Path invalid because of missing capacity",
                    edge=edge,
                    fee=fees,
                    available_capacity=edge["view"].capacity,
                    required_capacity=required_capacity,
                )
                return False
            required_capacity = PaymentAmount(required_capacity + fee)

            # check if settle_timeout / reveal_timeout >= default ratio
            ratio = edge["view"].settle_timeout / edge["view"].reveal_timeout
            if ratio < DEFAULT_SETTLE_TO_REVEAL_TIMEOUT_RATIO:
                log.debug(
                    "Path invalid because of too low reveal timeout ratio",
                    edge=edge,
                    fee=fees,
                    settle_timeout=edge["view"].settle_timeout,
                    reveal_timeout=edge["view"].reveal_timeout,
                    ratio=ratio,
                    required_ratio=DEFAULT_SETTLE_TO_REVEAL_TIMEOUT_RATIO,
                )
                return False

        # check node reachabilities
        for node in self.nodes:
            node_reachability = self.address_to_reachability.get(
                node, AddressReachability.UNKNOWN)
            if node_reachability != AddressReachability.REACHABLE:
                log.debug(
                    "Path invalid because of unavailable node",
                    node=node,
                    node_reachability=node_reachability,
                )
                return False

        return True
Example #12
0
def handle_unlock(
    target_state: TargetTransferState,
    state_change: ReceiveUnlock,
    channel_state: NettingChannelState,
) -> TransitionResult[Optional[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(
            token_network_registry_address=channel_state.token_network_registry_address,
            token_network_address=channel_state.token_network_address,
            identifier=transfer.payment_identifier,
            amount=PaymentAmount(transfer.lock.amount),
            initiator=transfer.initiator,
        )

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

        send_processed = SendProcessed(
            recipient=balance_proof_sender,
            message_identifier=state_change.message_identifier,
            canonical_identifier=CANONICAL_IDENTIFIER_UNORDERED_QUEUE,
        )

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

    return TransitionResult(next_target_state, events)
Example #13
0
def test_automatic_secret_registration(
    raiden_chain: List[App], token_addresses: List[TokenAddress]
) -> None:
    app0, app1 = raiden_chain
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address, token_address
    )
    assert token_network_address

    hold_event_handler = app1.raiden.raiden_event_handler
    message_handler = app1.raiden.message_handler

    msg = "hold event handler necessary to control messages"
    assert isinstance(hold_event_handler, HoldRaidenEventHandler), msg
    assert isinstance(message_handler, WaitForMessage), msg

    amount = PaymentAmount(100)
    identifier = factories.make_payment_id()

    target = TargetAddress(app1.raiden.address)
    (secret, secrethash) = factories.make_secret_with_hash()

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)
    locked_transfer_received = message_handler.wait_for_message(LockedTransfer, {})

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    # Wait for app1 to receive the locked transfer.
    locked_transfer_received.wait()

    # Stop app0 to avoid sending the unlock, this must be done after the locked
    # transfer is sent.
    app0.raiden.transport.stop()

    reveal_secret = RevealSecret(
        message_identifier=MessageID(random.randint(0, UINT64_MAX)),
        secret=secret,
        signature=EMPTY_SIGNATURE,
    )
    app0.raiden.sign(reveal_secret)
    message_handler.on_messages(app1.raiden, [reveal_secret])

    chain_state = views.state_from_app(app1)

    secrethash = sha256_secrethash(secret)
    target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash]
    lock_expiration = target_task.target_state.transfer.lock.expiration  # type: ignore
    app1.raiden.proxy_manager.client.wait_until_block(target_block_number=lock_expiration)

    assert app1.raiden.default_secret_registry.is_secret_registered(
        secrethash=secrethash, block_identifier=BLOCK_ID_LATEST
    )
Example #14
0
def test_event_filter_for_payments():
    secret = factories.make_secret()
    identifier = PaymentID(1)
    target = TargetAddress(factories.make_address())
    event1 = EventPaymentSentSuccess(
        token_network_registry_address=UNIT_TOKEN_NETWORK_REGISTRY_ADDRESS,
        token_network_address=UNIT_TOKEN_NETWORK_ADDRESS,
        identifier=identifier,
        amount=PaymentAmount(5),
        target=target,
        secret=secret,
        route=[],
    )
    assert event_filter_for_payments(event=event1, partner_address=None)
    assert event_filter_for_payments(event=event1,
                                     partner_address=Address(target))
    assert not event_filter_for_payments(
        event=event1, partner_address=factories.make_address())

    initiator = InitiatorAddress(factories.make_address())
    event2 = EventPaymentReceivedSuccess(
        token_network_registry_address=UNIT_TOKEN_NETWORK_REGISTRY_ADDRESS,
        token_network_address=UNIT_TOKEN_NETWORK_ADDRESS,
        identifier=identifier,
        amount=PaymentAmount(5),
        initiator=initiator,
    )
    assert event_filter_for_payments(event=event2, partner_address=None)
    assert event_filter_for_payments(event=event2,
                                     partner_address=Address(initiator))
    assert not event_filter_for_payments(
        event=event2, partner_address=factories.make_address())

    event3 = EventPaymentSentFailed(
        token_network_registry_address=UNIT_TOKEN_NETWORK_REGISTRY_ADDRESS,
        token_network_address=UNIT_TOKEN_NETWORK_ADDRESS,
        identifier=identifier,
        target=target,
        reason="whatever",
    )
    assert event_filter_for_payments(event=event3, partner_address=None)
    assert event_filter_for_payments(event=event3,
                                     partner_address=Address(target))
    assert not event_filter_for_payments(
        event=event3, partner_address=factories.make_address())
Example #15
0
def get_amount_for_sending_before_and_after_fees(
    amount_to_leave_initiator: PaymentAmount, channels: List[NettingChannelState]
) -> Optional[PaymentAmountCalculation]:
    """
    Calculates the amount needed to be sent by the initiator (before fees) in
    order for his balance to be reduced by `amount_to_leave_initiator`.

    Also returns the fees kept by the mediators.
    """
    amount_at_target = amount_to_leave_initiator
    while amount_at_target != 0:
        calculation = get_initial_payment_for_final_target_amount(
            final_amount=amount_at_target, channels=channels
        )
        if calculation is None:
            amount_at_target = PaymentAmount(amount_at_target - 1)
            continue

        total_amount_with_mediator_fees = calculation.total_amount
        mediation_fees = sum(calculation.mediation_fees)
        estimated_fee = max(
            mediation_fees, round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * amount_at_target)
        )
        estimated_total_amount_at_initiator = calculate_safe_amount_with_fee(
            payment_amount=amount_at_target, estimated_fee=FeeAmount(estimated_fee)
        )

        send_amount = min(
            estimated_total_amount_at_initiator, total_amount_with_mediator_fees - mediation_fees
        )
        send_amount_with_fees = max(
            estimated_total_amount_at_initiator, total_amount_with_mediator_fees
        )

        if send_amount_with_fees <= amount_to_leave_initiator:
            return PaymentAmountCalculation(
                amount_to_send=PaymentAmount(send_amount),
                mediation_fees=calculation.mediation_fees,
                amount_with_fees=send_amount_with_fees,
            )

        amount_at_target = PaymentAmount(amount_at_target - 1)

    return None
Example #16
0
 def from_dict(cls, data: Dict[str, Any]) -> "ReceiveSecretRequest":
     instance = cls(
         payment_identifier=PaymentID(int(data["payment_identifier"])),
         amount=PaymentAmount(int(data["amount"])),
         expiration=BlockExpiration(int(data["expiration"])),
         secrethash=SecretHash(deserialize_bytes(data["secrethash"])),
         sender=to_canonical_address(data["sender"]),
     )
     instance.revealsecret = data["revealsecret"]
     return instance
Example #17
0
 def from_dict(cls, data: Dict[str, Any]) -> 'ReceiveSecretRequest':
     instance = cls(
         payment_identifier=PaymentID(int(data['payment_identifier'])),
         amount=PaymentAmount(int(data['amount'])),
         expiration=BlockExpiration(int(data['expiration'])),
         secrethash=SecretHash(deserialize_bytes(data['secrethash'])),
         sender=to_canonical_address(data['sender']),
     )
     instance.revealsecret = data['revealsecret']
     return instance
def test_routing_in_direct_channel(happy_path_fixture, our_address,
                                   one_to_n_address):
    addresses, chain_state, channel_states, _, token_network_state = happy_path_fixture
    address1, _, _, _ = addresses
    channel_state1, _ = channel_states

    # with the transfer of 50 the direct channel should be returned,
    # so there must be not a pfs call
    with patch("raiden.routing.get_best_routes_pfs") as pfs_request:
        pfs_request.return_value = True, [], "feedback_token"
        routes, _ = get_best_routes(
            chain_state=chain_state,
            token_network_address=token_network_state.address,
            one_to_n_address=one_to_n_address,
            from_address=our_address,
            to_address=address1,
            amount=PaymentAmount(50),
            previous_address=None,
            config=CONFIG,
            privkey=PRIVKEY,
        )
        assert routes[0].next_hop_address == address1
        assert routes[0].forward_channel_id == channel_state1.identifier
        assert not pfs_request.called

    # with the transfer of 51 the direct channel should not be returned,
    # so there must be a pfs call
    with patch("raiden.routing.get_best_routes_pfs") as pfs_request:
        pfs_request.return_value = True, [], "feedback_token"
        get_best_routes(
            chain_state=chain_state,
            token_network_address=token_network_state.address,
            one_to_n_address=one_to_n_address,
            from_address=our_address,
            to_address=address1,
            amount=PaymentAmount(51),
            previous_address=None,
            config=CONFIG,
            privkey=PRIVKEY,
        )

        assert pfs_request.called
Example #19
0
def make_message(sign: bool = True) -> Message:
    message = SecretRequest(
        message_identifier=make_message_identifier(),
        payment_identifier=PaymentID(1),
        secrethash=factories.UNIT_SECRETHASH,
        amount=PaymentAmount(1),
        expiration=BlockExpiration(10),
        signature=EMPTY_SIGNATURE,
    )
    if sign:
        message.sign(LocalSigner(factories.HOP1_KEY))
    return message
Example #20
0
def test_fee_round_trip(flat_fee, prop_fee, imbalance_fee, amount):
    """ Tests mediation fee deduction. """
    balance = TokenAmount(100_000)
    prop_fee_per_channel = ppm_fee_per_channel(ProportionalFeeAmount(prop_fee))
    imbalance_fee = calculate_imbalance_fees(
        channel_capacity=balance,
        proportional_imbalance_fee=ProportionalFeeAmount(imbalance_fee))
    payer_channel = factories.create(
        NettingChannelStateProperties(
            our_state=NettingChannelEndStateProperties(balance=TokenAmount(0)),
            partner_state=NettingChannelEndStateProperties(balance=balance),
            fee_schedule=FeeScheduleState(
                flat=FeeAmount(flat_fee),
                proportional=prop_fee_per_channel,
                imbalance_penalty=imbalance_fee,
            ),
        ))
    payer_channel_backwards = factories.create(
        NettingChannelStateProperties(
            partner_state=NettingChannelEndStateProperties(
                balance=TokenAmount(0)),
            our_state=NettingChannelEndStateProperties(balance=balance),
            fee_schedule=FeeScheduleState(
                flat=FeeAmount(flat_fee),
                proportional=prop_fee_per_channel,
                imbalance_penalty=imbalance_fee,
            ),
        ))
    payee_channel = factories.create(
        NettingChannelStateProperties(
            our_state=NettingChannelEndStateProperties(balance=balance),
            partner_state=NettingChannelEndStateProperties(
                balance=TokenAmount(0)),
            fee_schedule=FeeScheduleState(
                flat=FeeAmount(flat_fee),
                proportional=prop_fee_per_channel,
                imbalance_penalty=imbalance_fee,
            ),
        ))

    fee_calculation = get_initial_payment_for_final_target_amount(
        final_amount=PaymentAmount(amount),
        channels=[payer_channel_backwards, payee_channel])
    assert fee_calculation

    amount_after_fees = get_lock_amount_after_fees(
        lock=make_hash_time_lock_state(amount=fee_calculation.total_amount),
        payer_channel=payer_channel,
        payee_channel=payee_channel,
    )
    assert amount_after_fees

    assert abs(amount - amount_after_fees) < 100
Example #21
0
def test_handle_insufficient_eth(raiden_network, token_addresses, caplog):
    app0, app1 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

    channel_state = views.get_channelstate_for(
        chain_state=views.state_from_raiden(app0.raiden),
        token_network_registry_address=registry_address,
        token_address=token,
        partner_address=app1.raiden.address,
    )
    assert isinstance(channel_state, NettingChannelState)
    channel_identifier = channel_state.identifier

    transfer(
        initiator_app=app0,
        target_app=app1,
        amount=PaymentAmount(1),
        token_address=token,
        identifier=PaymentID(1),
        timeout=60,
    )

    app1.raiden.stop()
    burn_eth(app1.raiden.rpc_client)
    app1.raiden.start()

    settle_block_timeout = BlockTimeout(
        exception_to_throw=RuntimeError("Settle did not happen."),
        raiden=app0.raiden,
        block_number=app0.raiden.get_block_number() + channel_state.settle_timeout * 2,
        retry_timeout=DEFAULT_RETRY_TIMEOUT,
    )

    with settle_block_timeout:
        RaidenAPI(app0.raiden).channel_close(
            registry_address=registry_address,
            token_address=token,
            partner_address=app1.raiden.address,
        )

        waiting.wait_for_settle(
            raiden=app0.raiden,
            token_network_registry_address=registry_address,
            token_address=token,
            channel_ids=[channel_identifier],
            retry_timeout=DEFAULT_RETRY_TIMEOUT,
        )

    assert any(
        "subtask died" in message and "insufficient ETH" in message for message in caplog.messages
    )
Example #22
0
def test_same_addresses_for_payment(raiden_network, token_addresses):
    app0, _ = raiden_network
    api0 = RaidenAPI(app0.raiden)
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]

    with pytest.raises(SamePeerAddress):
        api0.transfer(
            registry_address=registry_address,
            token_address=token_address,
            target=app0.raiden.address,
            amount=PaymentAmount(1),
        )
Example #23
0
    def from_dict(cls, data: Dict[str, Any]) -> 'TransferDescriptionWithSecretState':
        restored = cls(
            payment_network_identifier=to_canonical_address(data['payment_network_identifier']),
            payment_identifier=PaymentID(int(data['payment_identifier'])),
            amount=PaymentAmount(int(data['amount'])),
            allocated_fee=FeeAmount(int(data['allocated_fee'])),
            token_network_identifier=to_canonical_address(data['token_network_identifier']),
            initiator=to_canonical_address(data['initiator']),
            target=to_canonical_address(data['target']),
            secret=deserialize_secret(data['secret']),
        )

        return restored
Example #24
0
    def from_dict(cls, data: Dict[str, Any]) -> "TransferDescriptionWithSecretState":
        restored = cls(
            payment_network_identifier=to_canonical_address(data["payment_network_identifier"]),
            payment_identifier=PaymentID(int(data["payment_identifier"])),
            amount=PaymentAmount(int(data["amount"])),
            allocated_fee=FeeAmount(int(data["allocated_fee"])),
            token_network_identifier=to_canonical_address(data["token_network_identifier"]),
            initiator=to_canonical_address(data["initiator"]),
            target=to_canonical_address(data["target"]),
            secret=deserialize_secret(data["secret"]),
        )

        return restored
Example #25
0
def test_routing_simple(
    token_network_model: TokenNetwork,
    reachability_state: SimpleReachabilityContainer,
    addresses: List[Address],
):
    hex_addrs = [to_checksum_address(addr) for addr in addresses]
    view01: ChannelView = token_network_model.G[addresses[0]][
        addresses[1]]["view"]
    view10: ChannelView = token_network_model.G[addresses[1]][
        addresses[0]]["view"]

    assert view01.fee_schedule_sender.flat == 0
    assert view01.capacity == 90
    assert view10.capacity == 60

    # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used
    paths = token_network_model.get_paths(
        source=addresses[0],
        target=addresses[3],
        value=PaymentAmount(10),
        max_paths=1,
        reachability_state=reachability_state,
    )
    assert len(paths) == 1
    assert paths[0].to_dict()["path"] == [
        hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3]
    ]
    assert paths[0].to_dict()["estimated_fee"] == 0

    # Not connected.
    no_paths = token_network_model.get_paths(
        source=addresses[0],
        target=addresses[5],
        value=PaymentAmount(10),
        max_paths=1,
        reachability_state=reachability_state,
    )
    assert [] == no_paths
Example #26
0
def test_same_addresses_for_payment(raiden_network: List[RaidenService],
                                    token_addresses):
    app0, _ = raiden_network
    api0 = RaidenAPI(app0)
    registry_address = app0.default_registry.address
    token_address = token_addresses[0]

    with pytest.raises(SamePeerAddress):
        api0.transfer_and_wait(
            registry_address=registry_address,
            token_address=token_address,
            target=TargetAddress(app0.address),
            amount=PaymentAmount(1),
        )
Example #27
0
def test_regression_payment_complete_after_refund_to_the_initiator(
        raiden_network: List[RaidenService], token_addresses, settle_timeout,
        deposit):
    """Regression test for issue #3915"""
    app0, app1, app2, app3, app4 = raiden_network
    token = token_addresses[0]
    registry_address = app0.default_registry.address

    # Topology:
    #
    #  0 -> 1 -> 2
    #  |         ^
    #  v         |
    #  3 ------> 4

    app_channels = [(app0, app1), (app1, app2), (app0, app3), (app3, app4),
                    (app4, app2)]
    open_and_wait_for_channels(app_channels, registry_address, token, deposit,
                               settle_timeout)

    # Use all deposit from app1->app2 to force a refund
    transfer(
        initiator_app=app1,
        target_app=app2,
        token_address=token,
        amount=deposit,
        identifier=PaymentID(1),
        routes=[[app1.address, app2.address]],
    )

    # Send a transfer that will result in a refund app1->app0
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token,
        amount=PaymentAmount(50),
        identifier=PaymentID(2),
        timeout=20,
        expect_unlock_failures=True,
        routes=[
            [app0.address, app1.address, app2.address],
            [app0.address, app3.address, app4.address, app2.address],
        ],
    )

    assert raiden_state_changes_search_for_item(
        raiden=app0, item_type=ReceiveTransferCancelRoute, attributes={})
    assert raiden_events_search_for_item(raiden=app0,
                                         item_type=EventRouteFailed,
                                         attributes={})
Example #28
0
def test_routing_simple(
    token_network_model: TokenNetwork,
    address_to_reachability: Dict[Address, AddressReachability],
    addresses: List[Address],
):
    hex_addrs = [to_checksum_address(addr) for addr in addresses]
    view01: ChannelView = token_network_model.G[addresses[0]][addresses[1]]["view"]
    view10: ChannelView = token_network_model.G[addresses[1]][addresses[0]]["view"]

    assert view01.deposit == 100
    assert view01.fee_schedule_sender.flat == 0
    assert view01.capacity == 90
    assert view10.capacity == 60

    # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used
    paths = token_network_model.get_paths(
        source=addresses[0],
        target=addresses[3],
        value=PaymentAmount(10),
        max_paths=1,
        address_to_reachability=address_to_reachability,
    )
    assert len(paths) == 1
    assert paths[0] == {
        "path": [hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3]],
        "estimated_fee": 0,
    }

    # Not connected.
    with pytest.raises(NetworkXNoPath):
        token_network_model.get_paths(
            source=addresses[0],
            target=addresses[5],
            value=PaymentAmount(10),
            max_paths=1,
            address_to_reachability=address_to_reachability,
        )
Example #29
0
def test_transfer_with_invalid_address_type(raiden_network, token_addresses):
    app0, _ = raiden_network
    token_address = token_addresses[0]
    target_address = "\xf0\xef3\x01\xcd\xcfe\x0f4\x9c\xf6d\xa2\x01?X4\x84\xa9\xf1"

    # Enforce sandwich encoding. Calling `transfer` with a non binary address
    # raises an exception
    with pytest.raises(InvalidBinaryAddress):
        RaidenAPI(app0.raiden).transfer(
            app0.raiden.default_registry.address,
            token_address,
            PaymentAmount(10),
            target=target_address,  # type: ignore
            transfer_timeout=10,
        )
Example #30
0
def test_routing_result_order(
    token_network_model: TokenNetwork,
    address_to_reachability: Dict[Address, AddressReachability],
    addresses: List[Address],
):
    hex_addrs = [to_checksum_address(addr) for addr in addresses]
    paths = token_network_model.get_paths(
        addresses[0],
        addresses[2],
        value=PaymentAmount(10),
        max_paths=5,
        address_to_reachability=address_to_reachability,
    )
    # 5 paths requested, but only 1 is available
    assert len(paths) == 1
    assert paths[0] == {"path": [hex_addrs[0], hex_addrs[1], hex_addrs[2]], "estimated_fee": 0}