Exemple #1
0
class TestRouter(TestCase):
    def setUp(self):
        self.node = LndNode()
        self.router = Router(self.node)

    def test_get_routes_along_nodes(self):
        node_from = '000000000000000000000000000000000000000000000000000000000000000000'
        node_to = '000000000000000000000000000000000000000000000000000000000000000000'
        amt = 100
        routes = self.router.get_routes_from_to_nodes(node_from,
                                                      node_to,
                                                      amt,
                                                      number_of_routes=2)
        print(routes)

    def test_queryroute_external(self):
        node_from = '000000000000000000000000000000000000000000000000000000000000000000'
        node_to = '000000000000000000000000000000000000000000000000000000000000000000'
        amt = 100
        channel_route = self.node.queryroute_external(node_from, node_to, amt)
        print(channel_route)
        channel_route = self.node.queryroute_external(
            node_from, node_to, amt, ignored_channels=[000000000000000000])
        print(channel_route)

    def test_route(self):
        """
        to test a route, run
        $ lncli queryroutes source amt
        and copy-paste channel ids here and compare the results
        """

        route = Route(
            self.node, [000000000000000000, 000000000000000000],
            '000000000000000000000000000000000000000000000000000000000000000000',
            333000)
        route._debug_route()
        print('\nFinal route with reverse chain of fees:')
        print(self.node.lnd_route(route))

    def test_node_route_to_channel_route(self):
        hops = self.router._node_route_to_channel_route([
            '000000000000000000000000000000000000000000000000000000000000000000',
            '000000000000000000000000000000000000000000000000000000000000000000',
            '000000000000000000000000000000000000000000000000000000000000000000',
        ],
                                                        amt_msat=100)
        print(hops)

    def test_get_routes_for_advanced_rebalancing(self):
        self.router.get_routes_for_rebalancing(000000000000000000,
                                               000000000000000000, 100)
class TestRebalance(TestCase):
    def setUp(self):
        self.node = LndNode()

    def test_manual_rebalance(self):
        manual_rebalance(self.node, 000000000000000000, 000000000000000000, amt=141248, number_of_routes=5)

    def test_auto_rebalance(self):
        rebalancer = Rebalancer(self.node, max_effective_fee_rate=1, budget_sat=10)
        invoice_r_hash = self.node.get_rebalance_invoice(memo='autorebalance test')
        rebalancer.rebalance_two_channels(000000000000000000, 000000000000000000, amt_sat=1,
                                          invoice_r_hash=invoice_r_hash, budget_sat=10)

    def test_rebalance(self):
        rebalancer = Rebalancer(self.node, max_effective_fee_rate=0.0001, budget_sat=50)
        channel_id = 000000000000000000
        fee = rebalancer.rebalance(channel_id)
        print(fee)
Exemple #3
0
    def setUp(self):
        if self.network_definition is None:
            self.skipTest("This class doesn't represent a real test case.")
            raise NotImplementedError("A network definition path needs to be "
                                      "given.")

        # we delete previous test data
        try:
            shutil.rmtree(lndmanage_home)
        except FileNotFoundError:
            pass
        os.mkdir(lndmanage_home)

        self.testnet = Network(
            binary_folder=bin_dir,
            network_definition_location=self.network_definition,
            nodedata_folder=test_data_dir,
            node_limit='H',
            from_scratch=True)
        self.testnet.run_nocleanup()
        # to run the lightning network in the background and do some testing
        # here, run:
        # $ lnregtest --nodedata_folder /path/to/lndmanage/test/test_data/
        # self.testnet.run_from_background()

        # logger.info("Generated network information:")
        # logger.info(format_dict(self.testnet.node_mapping))
        # logger.info(format_dict(self.testnet.channel_mapping))
        # logger.info(format_dict(self.testnet.assemble_graph()))

        master_node_data_dir = self.testnet.master_node.data_dir
        master_node_port = self.testnet.master_node._grpc_port

        self.master_node_graph_view = self.testnet.master_node_graph_view()

        self.lndnode = LndNode(lnd_home=master_node_data_dir,
                               lnd_host='localhost:' + str(master_node_port),
                               regtest=True)
        self.graph_test()
Exemple #4
0
                    break
                else:
                    invoice_r_hash = self.node.get_rebalance_invoice(
                        memo=f"lndmanage: Rebalance of channel {channel_id}.")
            except NoRouteError:
                logger.error(
                    "There was no route cheap enough or with enough capacity.\n"
                )
            except DryRunException:
                logger.info(
                    "Would have tried this route now, but it was a dry run.\n")
            except RebalanceFailure:
                logger.error("Failed to rebalance with this channel.\n")
            except TooExpensive:
                logger.error("Too expensive.\n")

        return total_fees_msat


if __name__ == "__main__":
    import logging.config
    logging.config.dictConfig(_settings.logger_config)

    from lib.node import LndNode
    nd = LndNode()
    chan = 000000000000000000
    max_fee_rate = 0.0001
    rebalancer = Rebalancer(nd, max_fee_rate, budget_sat=20)
    fee = rebalancer.rebalance(chan)
    print(fee)
Exemple #5
0
import _settings
from lib.network_info import NetworkAnalysis
from lib.node import LndNode

import logging.config

logging.config.dictConfig(_settings.logger_config)
logger = logging.getLogger(__name__)

if __name__ == '__main__':
    node = LndNode()
    network_analysis = NetworkAnalysis(node)

    network_analysis.print_node_overview(node.pub_key)

    logger.info('-------- Nodes with highest capacity: --------')
    for n in network_analysis.get_sorted_nodes_by_property():
        logger.info(n)
    logger.info('-------- Nodes with highest degree: --------')
    for n in network_analysis.get_sorted_nodes_by_property(key='degree'):
        logger.info(n)
    logger.info('-------- Nodes with highest capacity/channel: --------')
    for n in network_analysis.get_sorted_nodes_by_property(
            key='capacity_per_channel', min_degree=10):
        logger.info(n)
    logger.info('-------- Nodes with lowest capacity/channel: --------')
    for n in network_analysis.get_sorted_nodes_by_property(
            key='capacity_per_channel', min_degree=20, decrementing=False):
        logger.info(n)
    logger.info('-------- Nodes with most user nodes: --------')
    for n in network_analysis.get_sorted_nodes_by_property(key='user_nodes',
Exemple #6
0
def main():
    parser = Parser()
    args = parser.parse_arguments()
    # print(args)

    if args.cmd is None:
        parser.parser.print_help()
        return 0

    # program execution
    if args.loglevel:
        # update the loglevel of the stdout handler to the user choice
        logger.handlers[0].setLevel(args.loglevel)

    node = LndNode()

    if args.cmd == 'status':
        node.print_status()

    elif args.cmd == 'listchannels':
        if not args.subcmd:
            print_channels_rebalance(node, unbalancedness_greater_than=0)
        if args.subcmd == 'rebalance':
            print_channels_rebalance(node, args.unbalancedness, sort_by='ub')
        elif args.subcmd == 'inactive':
            print_channels_hygiene(node)
        elif args.subcmd == 'forwardings':
            # convert time interval into unix timestamp
            time_from = time.time() - args.from_days_ago * 24 * 60 * 60
            time_to = time.time() - args.to_days_ago * 24 * 60 * 60
            print_channels_forwardings(node,
                                       sort_by=args.sort_by,
                                       time_interval_start=time_from,
                                       time_interval_end=time_to)

    elif args.cmd == 'rebalance':
        if args.target:
            logger.warning(
                "Warning: Target is set, this is still an experimental feature."
            )
        rebalancer = Rebalancer(node, args.max_fee_rate, args.max_fee_sat)
        try:
            rebalancer.rebalance(args.channel,
                                 dry=not args.reckless,
                                 chunksize=args.chunksize,
                                 target=args.target,
                                 allow_unbalancing=args.allow_unbalancing,
                                 strategy=args.strategy)
        except RebalanceFailure as e:
            logger.error(f"Error: {e}")

    elif args.cmd == 'circle':
        rebalancer = Rebalancer(node, args.max_fee_rate, args.max_fee_sat)
        invoice_r_hash = node.get_rebalance_invoice(memo='circular payment')
        try:
            rebalancer.rebalance_two_channels(args.channel_from,
                                              args.channel_to,
                                              args.amt_sats,
                                              invoice_r_hash,
                                              args.max_fee_sat,
                                              dry=not args.reckless)
        except DryRunException:
            logger.info("This was just a dry run.")
        except TooExpensive:
            logger.error(
                "Payment failed. This is likely due to a too low default --max-fee-rate."
            )
        except PaymentTimeOut:
            logger.error(
                "Payment failed because the payment timed out. This is an unresolved issue."
            )

    elif args.cmd == 'recommend-nodes':

        if not args.subcmd:
            parser.parser_recommend_nodes.print_help()
            return 0

        recommend_nodes = RecommendNodes(node,
                                         show_connected=args.show_connected,
                                         show_addresses=args.show_addresses)
        if args.subcmd == 'good-old':
            recommend_nodes.print_good_old(number_of_nodes=args.nnodes,
                                           sort_by=args.sort_by)
Exemple #7
0
        channels_in[f['chan_id_in']] += f['amt_in']

        total_amount += f['amt_in']
        total_fees += f['fee_msat']
        transactions += 1
        fee_rate += f['effective_fee']

    fee_rate /= transactions
    print("-------- Forwarding statistics --------")
    print("Number of forwardings: {}".format(transactions))
    print("Total forwardings [sats]: {}".format(total_amount))
    print("Total fees earned [sats]: {:.3f}".format(total_fees / 1000.))
    print("Average fee rate: {:.6f}".format(fee_rate))

    print("-------- Popular channels --------")
    print("Popular channels out:")
    for w in sorted(channels_out, key=channels_out.get, reverse=True)[:10]:
        print(w, channels_out[w])
    print("Popular channels in:")
    for w in sorted(channels_in, key=channels_in.get, reverse=True)[:10]:
        print(w, channels_in[w])


if __name__ == '__main__':
    node = LndNode()
    forwardings = node.get_forwarding_events()

    # plot_forwardings(forwardings)
    # plot_fees(forwardings)
    statistics_forwardings(forwardings)
import _settings
from lib.listchannels import print_channels_rebalance
from lib.node import LndNode

import logging.config

logging.config.dictConfig(_settings.logger_config)

if __name__ == '__main__':
    node = LndNode()
    node.print_status()
    print_channels_rebalance(
        node, unbalancedness_greater_than=_settings.UNBALANCED_CHANNEL)
 def setUp(self):
     self.node = LndNode()
Exemple #10
0
    @staticmethod
    def _sorting_order(sort_string):
        """
        Determines the sorting string and the sorting order.

        If sort_string starts with 'rev_', the sorting order is reversed.

        :param sort_string: str
        :return: bool
        """

        reverse_sorting = True
        if sort_string[:4] == 'rev_':
            reverse_sorting = False
            sort_string = sort_string[4:]

        sort_string = PRINT_CHANNELS_FORMAT[sort_string]['dict_key']

        return sort_string, reverse_sorting


if __name__ == '__main__':
    import logging.config

    from lib.node import LndNode
    import _settings
    logging.config.dictConfig(_settings.logger_config)

    node_instance = LndNode()
    listchannels = ListChannels(node_instance)
Exemple #11
0
 def setUp(self):
     self.node = LndNode()
     self.router = Router(self.node)