Пример #1
0
 def test_unbalancedness_formula(self):
     self.assertAlmostEqual(
         channel_unbalancedness_and_commit_fee(500000, 1000000, 1000,
                                               False)[0], 0.0)
     self.assertAlmostEqual(
         channel_unbalancedness_and_commit_fee(500000, 1000000, 1000,
                                               True)[0], -0.002)
     self.assertAlmostEqual(
         channel_unbalancedness_and_commit_fee(600000, 1000000, 0,
                                               False)[0], -0.2)
Пример #2
0
    def rebalance_and_check(self,
                            test_channel_number,
                            target,
                            allow_unbalancing,
                            places=5):
        """
        Test function for rebalancing to a specific target unbalancedness and
        asserts afterwards that the target was reached.

        :param test_channel_number: channel id
        :type test_channel_number: int
        :param target: unbalancedness target
        :type target: float
        :param allow_unbalancing: if unbalancing should be allowed
        :type allow_unbalancing: bool
        :param places: accuracy of the comparison between expected and tested
            values
        :type places: int
        """
        rebalancer = Rebalancer(self.lndnode,
                                max_effective_fee_rate=50,
                                budget_sat=20)

        channel_id = self.testnet.channel_mapping[test_channel_number][
            'channel_id']

        try:
            fees_msat = rebalancer.rebalance(
                channel_id,
                dry=False,
                chunksize=1.0,
                target=target,
                allow_unbalancing=allow_unbalancing)
        except Exception as e:
            raise e

        # sleep a bit to let LNDs update their balances
        time.sleep(SLEEP_SEC_AFTER_REBALANCING)

        # check if graph has the desired channel balances
        graph = self.testnet.assemble_graph()
        channel_data = graph['A'][test_channel_number]
        listchannels = ListChannels(self.lndnode)
        listchannels.print_all_channels('rev_alias')

        channel_unbalancedness, _ = channel_unbalancedness_and_commit_fee(
            channel_data['local_balance'], channel_data['capacity'],
            channel_data['commit_fee'], channel_data['initiator'])

        self.assertAlmostEqual(target, channel_unbalancedness, places=places)

        return fees_msat
Пример #3
0
    def rebalance_and_check(self,
                            test_channel_number,
                            target,
                            allow_unbalancing,
                            places=5):
        """
        Test function for rebalancing to a specific target and assert after-
        wards that is was reached.

        :param test_channel_number: int
        :param target: float:
            unbalancedness target
        :param allow_unbalancing: bool:
            unbalancing should be allowed
        :param places: int
            number of digits the result should match to the requested
        :param should_fail: bool:
            indicates whether the rebalancing should fail as requested due to
            maybe unbalancing of other channels
        """
        rebalancer = Rebalancer(self.lndnode,
                                max_effective_fee_rate=50,
                                budget_sat=20)

        channel_id = self.testnet.channel_mapping[test_channel_number][
            'channel_id']
        try:
            fees_msat = rebalancer.rebalance(
                channel_id,
                dry=False,
                chunksize=1.0,
                target=target,
                allow_unbalancing=allow_unbalancing)
        except Exception as e:
            raise e

        time.sleep(SLEEP_SEC_AFTER_REBALANCING)
        graph = self.testnet.assemble_graph()
        channel_data = graph['A'][test_channel_number]
        listchannels = ListChannels(self.lndnode)
        listchannels.print_all_channels('rev_alias')

        channel_unbalancedness, _ = channel_unbalancedness_and_commit_fee(
            channel_data['local_balance'], channel_data['capacity'],
            channel_data['commit_fee'], channel_data['initiator'])

        self.assertAlmostEqual(target, channel_unbalancedness, places=places)

        return fees_msat
Пример #4
0
    def get_open_channels(self, active_only=False, public_only=False):
        """
        Fetches information (fee settings of the counterparty, channel
        capacity, balancedness) about this node's open channels and saves
        it into the channels dict attribute.

        :param active_only: only take active channels into
                            account (off by default)
        :type active_only: bool
        :param public_only: only take public channels into
                            account (off by default)
        :type public_only: bool

        :return: dict of channels sorted by remote pubkey
        :rtype: OrderedDict

        """
        raw_channels = self._rpc.ListChannels(
            lnd.ListChannelsRequest(active_only=active_only,
                                    public_only=public_only))
        try:
            channels_data = raw_channels.ListFields()[0][1]
        except IndexError:
            # If there are no channels, return.
            return OrderedDict({})

        channels = OrderedDict()

        for c in channels_data:
            # calculate age from blockheight
            blockheight, _, _ = convert_channel_id_to_short_channel_id(
                c.chan_id)
            age_days = (self.blockheight - blockheight) * 10 / (60 * 24)
            try:
                sent_received_per_week = int(
                    (c.total_satoshis_sent + c.total_satoshis_received) /
                    (age_days / 7))
            except ZeroDivisionError:
                # age could be zero right after channel becomes pending
                sent_received_per_week = 0

            # determine policy
            try:
                edge_info = self.network.edges[c.chan_id]
                # interested in node2
                if edge_info['node1_pub'] == self.pub_key:
                    policy_peer = edge_info['node2_policy']
                    policy_local = edge_info['node1_policy']
                else:  # interested in node1
                    policy_peer = edge_info['node1_policy']
                    policy_local = edge_info['node2_policy']
            except KeyError:
                # if channel is unknown in describegraph
                # we need to set the fees to some error value
                policy_peer = {
                    'fee_base_msat': float(-999),
                    'fee_rate_milli_msat': float(999)
                }
                policy_local = {
                    'fee_base_msat': float(-999),
                    'fee_rate_milli_msat': float(999)
                }

            # calculate last update (days ago)
            def convert_to_days_ago(timestamp):
                return (time.time() - timestamp) / (60 * 60 * 24)

            try:
                last_update = convert_to_days_ago(
                    self.network.edges[c.chan_id]['last_update'])
                last_update_local = convert_to_days_ago(
                    policy_local['last_update'])
                last_update_peer = convert_to_days_ago(
                    policy_peer['last_update'])
            except (TypeError, KeyError):
                last_update = float('nan')
                last_update_peer = float('nan')
                last_update_local = float('nan')

            # define unbalancedness |ub| large means very unbalanced
            channel_unbalancedness, our_commit_fee = \
                channel_unbalancedness_and_commit_fee(
                    c.local_balance, c.capacity, c.commit_fee, c.initiator)
            try:
                uptime_lifetime_ratio = c.uptime / c.lifetime
            except ZeroDivisionError:
                uptime_lifetime_ratio = 0

            channels[c.chan_id] = {
                'active':
                c.active,
                'age':
                age_days,
                'alias':
                self.network.node_alias(c.remote_pubkey),
                'amt_to_balanced':
                int(channel_unbalancedness * c.capacity / 2 - our_commit_fee),
                'capacity':
                c.capacity,
                'chan_id':
                c.chan_id,
                'channel_point':
                c.channel_point,
                'commit_fee':
                c.commit_fee,
                'fee_per_kw':
                c.fee_per_kw,
                'peer_base_fee':
                policy_peer['fee_base_msat'],
                'peer_fee_rate':
                policy_peer['fee_rate_milli_msat'],
                'local_base_fee':
                policy_local['fee_base_msat'],
                'local_fee_rate':
                policy_local['fee_rate_milli_msat'],
                'initiator':
                c.initiator,
                'last_update':
                last_update,
                'last_update_local':
                last_update_local,
                'last_update_peer':
                last_update_peer,
                'local_balance':
                c.local_balance,
                'num_updates':
                c.num_updates,
                'private':
                c.private,
                'remote_balance':
                c.remote_balance,
                'remote_pubkey':
                c.remote_pubkey,
                'sent_received_per_week':
                sent_received_per_week,
                'total_satoshis_sent':
                c.total_satoshis_sent,
                'total_satoshis_received':
                c.total_satoshis_received,
                'unbalancedness':
                channel_unbalancedness,
                'uptime':
                c.uptime,
                'lifetime':
                c.lifetime,
                'uptime_lifetime_ratio':
                uptime_lifetime_ratio,
            }
        sorted_dict = OrderedDict(
            sorted(channels.items(), key=lambda x: x[1]['alias']))
        return sorted_dict