Beispiel #1
0
 def get_balance(self, node, dst, edge_data):
     return balance_with_interests(
         get_balance(edge_data, node, dst),
         get_interest_rate(edge_data, node, dst),
         get_interest_rate(edge_data, dst, node),
         self.timestamp - get_mtime(edge_data),
     )
Beispiel #2
0
    def get_balances_along_path(self, path):
        balances = []

        for i in range(0, len(path) - 1):
            data = self.graph.get_edge_data(path[i], path[i + 1])
            balances.append(get_balance(data, path[i], path[i + 1]))

        return balances
Beispiel #3
0
    def total_cost_from_start_to_dst(
        self, cost_from_start_to_node, node, dst, edge_data
    ):
        if dst == self.ignore or node == self.ignore:
            return None
        if get_is_frozen(edge_data):
            return None

        sum_fees, num_hops = cost_from_start_to_node

        if num_hops + 1 > self.max_hops:
            return None

        # fee computation has been inlined here, since the comment in
        # Graph._get_fee suggests it should be as fast as possible. This means
        # we do have some code duplication, but I couldn't use some of the
        # methods in Graph anyway, because they don't take a timestamp argument
        # and rather use the current time.
        #
        # We should profile this at some point in time.
        #
        # We do the pathfinding in reverse, when the sender pays. In this
        # method this means that the payment is done from dst to node, i.e. the
        # order of arguments node and dst is reversed in the following code

        pre_balance = balance_with_interests(
            get_balance(edge_data, dst, node),
            get_interest_rate(edge_data, dst, node),
            get_interest_rate(edge_data, node, dst),
            self.timestamp - get_mtime(edge_data),
        )

        if num_hops == 0:
            fee = 0
        else:
            fee = calculate_fees_reverse(
                imbalance_generated=imbalance_generated(
                    value=self.value + sum_fees, balance=pre_balance
                ),
                capacity_imbalance_fee_divisor=self.capacity_imbalance_fee_divisor,
            )

        if sum_fees + fee > self.max_fees:
            return None

        # check that we don't exceed the creditline
        capacity = pre_balance + get_creditline(edge_data, node, dst)
        if self.value + sum_fees + fee > capacity:
            # creditline exceeded
            return None

        return self.Cost(fees=sum_fees + fee, num_hops=num_hops + 1)
Beispiel #4
0
    def total_cost_from_start_to_dst(
        self, cost_from_start_to_node: Cost, node, dst, edge_data
    ):
        if dst == self.ignore or node == self.ignore:
            return None
        if get_is_frozen(edge_data):
            return None

        # For this case the pathfinding is not done in reverse.
        #
        # we maintain the computed fee for the previous hop, since that is only
        # 'paid out' when we jump to the next hop The first element in this
        # tuple has to be the sum of the fees not including the fee for the
        # previous hop, since the graph finding algorithm needs to sort by that
        # and not by what would be paid out if there is another hop
        sum_fees, num_hops, previous_hop_fee = cost_from_start_to_node

        if num_hops + 1 > self.max_hops:
            return None

        pre_balance = balance_with_interests(
            get_balance(edge_data, node, dst),
            get_interest_rate(edge_data, node, dst),
            get_interest_rate(edge_data, dst, node),
            self.timestamp - get_mtime(edge_data),
        )

        fee = calculate_fees(
            imbalance_generated=imbalance_generated(
                value=self.value - sum_fees - previous_hop_fee, balance=pre_balance
            ),
            capacity_imbalance_fee_divisor=self.capacity_imbalance_fee_divisor,
        )

        if sum_fees + previous_hop_fee > self.max_fees:
            return None

        # check that we don't exceed the creditline
        capacity = pre_balance + get_creditline(edge_data, dst, node)
        if self.value - sum_fees - previous_hop_fee > capacity:
            # creditline exceeded
            return None

        return self.Cost(
            fees=sum_fees + previous_hop_fee,
            num_hops=num_hops + 1,
            previous_hop_fee=fee,
        )
Beispiel #5
0
    def transfer_path(self, path, value, expected_fees, timestamp=0):
        assert value > 0
        cost_accumulator = SenderPaysCostAccumulatorSnapshot(
            timestamp=timestamp,
            value=value,
            capacity_imbalance_fee_divisor=self.capacity_imbalance_fee_divisor,
        )
        cost = cost_accumulator.zero()

        path = list(reversed(path))
        for source, target in zip(path, path[1:]):
            edge_data = self.graph.get_edge_data(source, target)
            cost = cost_accumulator.total_cost_from_start_to_dst(
                cost, source, target, edge_data
            )
            if cost is None:
                raise nx.NetworkXNoPath("no path found")
            new_balance = get_balance(edge_data, target, source) - value - cost[0]
            set_balance(edge_data, target, source, new_balance)

        assert expected_fees == cost[0]
        return cost[0]
def test_balance(data):
    set_balance(data, a, b, 100)
    assert get_balance(data, a, b) == 100
    assert get_balance(data, b, a) == -100
Beispiel #7
0
 def balance(self) -> int:
     """Returns the balance without interests"""
     return get_balance(self.data, self.a, self.b)