def get_capacity_update_message(  # pylint: disable=too-many-arguments
    updating_participant: Address,
    other_participant: Address,
    chain_id=ChainID(61),
    channel_identifier=DEFAULT_CHANNEL_ID,
    token_network_address: TokenNetworkAddress = DEFAULT_TOKEN_NETWORK_ADDRESS,
    updating_nonce=Nonce(1),
    other_nonce=Nonce(0),
    updating_capacity=TA(90),
    other_capacity=TA(110),
    reveal_timeout: BlockTimeout = BlockTimeout(2),
    privkey_signer: bytes = PRIVATE_KEY_1,
) -> PFSCapacityUpdate:
    updatepfs_message = PFSCapacityUpdate(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            channel_identifier=channel_identifier,
            token_network_address=token_network_address,
        ),
        updating_participant=updating_participant,
        other_participant=other_participant,
        updating_nonce=updating_nonce,
        other_nonce=other_nonce,
        updating_capacity=updating_capacity,
        other_capacity=other_capacity,
        reveal_timeout=reveal_timeout,
        signature=EMPTY_SIGNATURE,
    )

    updatepfs_message.sign(LocalSigner(privkey_signer))

    return updatepfs_message
def test_pfs_rejects_capacity_update_with_impossible_other_capacity(
    pathfinding_service_web3_mock: PathfindingService, ):
    setup_channel(pathfinding_service_web3_mock)

    message = get_capacity_update_message(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS,
        other_capacity=TA(UINT256_MAX),
        privkey_signer=PRIVATE_KEY_1,
    )
    message.other_capacity = TA(UINT256_MAX + 1)

    with pytest.raises(InvalidCapacityUpdate) as exinfo:
        pathfinding_service_web3_mock.on_capacity_update(message)
    assert "with impossible other_capacity" in str(exinfo.value)
Beispiel #3
0
    def __init__(self, channels: List[dict], default_capacity: TA = TA(1000)):
        super().__init__(
            token_network_address=TokenNetworkAddress(a(255)),
            settle_timeout=DEFAULT_TOKEN_NETWORK_SETTLE_TIMEOUT,
        )

        # open channels
        channel_ids = itertools.count(100)
        for chan in channels:
            self.handle_channel_opened_event(
                channel_identifier=ChannelID(next(channel_ids)),
                participant1=a(chan["participant1"]),
                participant2=a(chan["participant2"]),
            )

            cv1: ChannelView = self.G[a(chan["participant1"])][a(
                chan["participant2"])]["view"]
            cv1.capacity = chan.get("capacity1", default_capacity)
            cv2: ChannelView = self.G[a(chan["participant2"])][a(
                chan["participant1"])]["view"]
            cv2.capacity = chan.get("capacity2", default_capacity)

        # create reachability mapping for testing
        self.reachability_state = SimpleReachabilityContainer(
            {node: AddressReachability.REACHABLE
             for node in self.G.nodes})
Beispiel #4
0
def test_regression_issue_554():
    """Regression test for https://github.com/raiden-network/raiden-services/issues/554"""
    tn = TokenNetworkForTests(channels=[
        dict(participant1=1, participant2=2, capacity1=100, capacity2=0),
        dict(participant1=2, participant2=3, capacity1=100, capacity2=0),
    ])

    tn.set_fee(2, 1, imbalance_penalty=[(TA(0), FA(20)), (TA(100), FA(0))])
    assert tn.estimate_fee(1, 3) is not None

    capacity = TA(100_000)
    tn2 = TokenNetworkForTests(channels=[
        dict(participant1=1, participant2=2, capacity1=capacity, capacity2=0),
        dict(participant1=2, participant2=3, capacity1=capacity, capacity2=0),
    ])

    tn2.set_fee(2,
                1,
                imbalance_penalty=[(TA(0), FA(1000)), (capacity // 2, 0),
                                   (capacity, FA(1000))])
    assert tn2.estimate_fee(1, 3, value=PA(10_000)) is not None
def test_pfs_min_calculation_with_capacity_updates(
    pathfinding_service_web3_mock: PathfindingService, ):
    token_network = setup_channel(pathfinding_service_web3_mock)
    view_to_partner, view_from_partner = token_network.get_channel_views_for_partner(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS)

    message1 = get_capacity_update_message(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS,
        privkey_signer=PRIVATE_KEY_1,
        updating_capacity=TA(90),
        other_capacity=TA(110),
    )

    pathfinding_service_web3_mock.on_capacity_update(message1)

    # Now the channel capacities are set to 0, since only P1 sent an update
    assert view_to_partner.capacity == 0
    assert view_from_partner.capacity == 0

    # We need two Capacity Updates, one from each side to set the capacities due to min calculation
    message2 = get_capacity_update_message(
        updating_participant=PRIVATE_KEY_2_ADDRESS,
        other_participant=PRIVATE_KEY_1_ADDRESS,
        privkey_signer=PRIVATE_KEY_2,
        updating_capacity=TA(110),
        other_capacity=TA(90),
    )

    pathfinding_service_web3_mock.on_capacity_update(message2)

    # Now after both participants have sent Capacity Updates, we have the correct capacities
    assert view_to_partner.capacity == 90
    assert view_from_partner.capacity == 110

    # Now P1 sends the same update again, the capacities should not change (no need for nonces)
    pathfinding_service_web3_mock.on_capacity_update(message1)
    assert view_to_partner.capacity == 90
    assert view_from_partner.capacity == 110

    # Now P1 tries to cheat and lies about his own capacity (10000) to mediate more
    message3 = get_capacity_update_message(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS,
        privkey_signer=PRIVATE_KEY_1,
        updating_capacity=TA(10000),
        other_capacity=TA(110),
    )
    pathfinding_service_web3_mock.on_capacity_update(message3)

    # The capacities should be calculated out of the minimum of the two capacity updates,
    # so stay the same
    assert view_to_partner.capacity == 90
    assert view_from_partner.capacity == 110

    # Now P1 tries to cheat and lies about his partner's capacity (0) to block him
    message4 = get_capacity_update_message(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS,
        privkey_signer=PRIVATE_KEY_1,
        updating_capacity=TA(90),
        other_capacity=TA(0),
    )
    pathfinding_service_web3_mock.on_capacity_update(message4)

    # The capacities should be calculated out of the minimum of the two capacity updates,
    #  he can block his partner
    assert view_to_partner.capacity == 90
    assert view_from_partner.capacity == 0

    # Now P1 tries to cheat and lies about his partner's capacity (10000) for no obvious reason
    message4 = get_capacity_update_message(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS,
        privkey_signer=PRIVATE_KEY_1,
        updating_capacity=TA(90),
        other_capacity=TA(10000),
    )
    pathfinding_service_web3_mock.on_capacity_update(message4)

    # The capacities should be calculated out of the minimum of the two capacity updates
    assert view_to_partner.capacity == 90
    assert view_from_partner.capacity == 110
Beispiel #6
0
def test_fees_in_unbalanced_routing():  # pylint: disable=too-many-statements
    """Tests fee estimation in a network where only one participant has funds in a channel."""
    tn = TokenNetworkForTests(channels=[
        dict(participant1=1, participant2=2, capacity1=1000, capacity2=0),
        dict(participant1=2, participant2=3, capacity1=1000, capacity2=0),
    ])

    # Make sure that routing works and the default fees are zero
    assert tn.estimate_fee(1, 3) == 0

    # Fees for the initiator are ignored
    tn.set_fee(1, 2, flat=FA(1))
    assert tn.estimate_fee(1, 3) == 0

    # Node 2 demands fees for incoming transfers
    tn.set_fee(2, 1, flat=FA(1))
    assert tn.estimate_fee(1, 3) == 1

    # Node 2 demands fees for outgoing transfers
    tn.set_fee(2, 3, flat=FA(1))
    assert tn.estimate_fee(1, 3) == 2

    # No capacity in the opposite direction
    assert tn.estimate_fee(3, 1) is None

    # Reset fees to zero
    tn.set_fee(1, 2)
    tn.set_fee(2, 1)
    tn.set_fee(2, 3)

    # Let's try imbalance fees!
    # When approximation iterations matter, those are given as sums of the steps.

    # Incoming channel
    # Without fee capping
    tn.set_fee(2, 3, cap_fees=False)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(100))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 10 + 1
    assert tn.estimate_fee(3, 1) is None  # no balance in channel
    # With fee capping
    tn.set_fee(2, 3, cap_fees=True)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(100))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 10 + 1
    assert tn.estimate_fee(3, 1) is None  # no balance in channel

    # The opposite fee schedule should give opposite results, without fee capping
    tn.set_fee(2, 3, cap_fees=False)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(100)), (TA(1000), FA(0))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == -10 + 1
    assert tn.estimate_fee(3, 1) is None  # no balance in channel
    # Or zero with fee capping
    tn.set_fee(2, 3, cap_fees=True)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(100)), (TA(1000), FA(0))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) is None  # no balance in channel

    # Outgoing channel
    # Without fee capping
    tn.set_fee(2, 1, cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(100))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == -10
    assert tn.estimate_fee(3, 1) is None  # no balance in channel
    # With fee capping
    tn.set_fee(2, 1, cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(100))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) is None  # no balance in channel

    # The opposite fee schedule should give opposite results
    tn.set_fee(2, 3, imbalance_penalty=[(TA(0), FA(100)), (TA(1000), FA(0))])
    assert tn.estimate_fee(1, 3) == 10
    assert tn.estimate_fee(3, 1) is None  # no balance in channel

    # Combined fees cancel out
    # Works without fee capping
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(20))],
               cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(20))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) is None  # no balance in channel
    # With fee capping fees cancel out as well
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(20))],
               cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(1000), FA(20))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) is None  # no balance in channel

    # Works without fee capping
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(20)), (TA(1000), FA(0))],
               cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(20)), (TA(1000), FA(0))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) is None  # no balance in channel
    # With fee capping fees cancel out as well
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(20)), (TA(1000), FA(0))],
               cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(20)), (TA(1000), FA(0))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) is None  # no balance in channel

    # When the range covered by the imbalance_penalty does include the
    # necessary balance values, the route should be considered invalid.
    tn.set_fee(2, 3, imbalance_penalty=[(TA(0), FA(0)), (TA(80), FA(200))])
    assert tn.estimate_fee(1, 3) is None
Beispiel #7
0
def test_fees_in_balanced_routing():  # pylint: disable=too-many-statements
    """Tests fee estimation in a network where both participants have funds in a channel."""
    tn = TokenNetworkForTests(channels=[
        dict(participant1=1, participant2=2),
        dict(participant1=2, participant2=3)
    ])

    # Make sure that routing works and the default fees are zero
    assert tn.estimate_fee(1, 3) == 0

    # Fees for the initiator are ignored
    tn.set_fee(1, 2, flat=FA(1))
    assert tn.estimate_fee(1, 3) == 0

    # Node 2 demands fees for incoming transfers
    tn.set_fee(2, 1, flat=FA(1))
    assert tn.estimate_fee(1, 3) == 1

    # Node 2 demands fees for outgoing transfers
    tn.set_fee(2, 3, flat=FA(1))
    assert tn.estimate_fee(1, 3) == 2

    # Same fee in the opposite direction
    assert tn.estimate_fee(3, 1) == 2

    # Reset fees to zero
    tn.set_fee(1, 2)
    tn.set_fee(2, 1)
    tn.set_fee(2, 3)

    # Let's try imbalance fees
    # When the fees influence the amount strong that fee(amount) != fee(amount + fee)
    # the difference is given as an additional summand.

    # Incoming channel
    # Without fee capping
    tn.set_fee(2, 3, cap_fees=False)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(200))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 10 + 1
    assert tn.estimate_fee(3, 1) == -10
    # With fee capping
    tn.set_fee(2, 3, cap_fees=True)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(200))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 10 + 1
    assert tn.estimate_fee(3, 1) == 0

    # The opposite fee schedule should give opposite results
    # Without fee capping
    tn.set_fee(2, 3, cap_fees=False)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(200)), (TA(2000), FA(0))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == -10 + 1
    assert tn.estimate_fee(3, 1) == 10
    # With fee capping
    tn.set_fee(2, 3, cap_fees=True)
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(200)), (TA(2000), FA(0))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) == 10

    # Outgoing channel
    # Without fee capping
    tn.set_fee(2, 1, cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(200))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == -10
    assert tn.estimate_fee(3, 1) == 10 + 1
    # With fee capping
    tn.set_fee(2, 1, cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(200))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) == 10 + 1

    # The opposite fee schedule should give opposite results
    # Without fee capping
    tn.set_fee(2, 1, cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(200)), (TA(2000), FA(0))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 10
    assert tn.estimate_fee(3, 1) == -10 + 1
    # With fee capping
    tn.set_fee(2, 1, cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(200)), (TA(2000), FA(0))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 10
    assert tn.estimate_fee(3, 1) == 0

    # Combined fees cancel out
    # Works without fee capping
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(20))],
               cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(20))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) == 0
    # And with fee capping, as the amounts even out
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(20))],
               cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(0)), (TA(2000), FA(20))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) == 0

    # Works without fee capping
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(20)), (TA(2000), FA(0))],
               cap_fees=False)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(20)), (TA(2000), FA(0))],
               cap_fees=False)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) == 0
    # And with fee capping, as the amounts even out
    tn.set_fee(2,
               1,
               imbalance_penalty=[(TA(0), FA(20)), (TA(2000), FA(0))],
               cap_fees=True)
    tn.set_fee(2,
               3,
               imbalance_penalty=[(TA(0), FA(20)), (TA(2000), FA(0))],
               cap_fees=True)
    assert tn.estimate_fee(1, 3) == 0
    assert tn.estimate_fee(3, 1) == 0

    # When the range covered by the imbalance_penalty does include the
    # necessary balance values, the route should be considered invalid.
    tn.set_fee(2, 3, imbalance_penalty=[(TA(0), FA(0)), (TA(800), FA(200))])
    assert tn.estimate_fee(1, 3) is None