コード例 #1
0
    def rebalance(self):
        if self.last_hop_channel:
            debug(("Sending {:,} satoshis to rebalance to channel with ID %d" %
                   self.last_hop_channel.chan_id).format(self.amount))
        else:
            debug("Sending {:,} satoshis.".format(self.amount))
        if self.channel_ratio != 0.5:
            debug("Channel ratio used is %d%%" % int(self.channel_ratio * 100))
        if self.first_hop_channel:
            debug("Forced first channel has ID %d" %
                  self.first_hop_channel.chan_id)

        payment_request = self.generate_invoice()
        routes = Routes(self.lnd, payment_request, self.first_hop_channel,
                        self.last_hop_channel)

        self.initialize_ignored_channels(routes)

        tried_routes = []
        while routes.has_next():
            route = routes.get_next()

            success = self.try_route(payment_request, route, routes,
                                     tried_routes)
            if success:
                return True
        debug("Could not find any suitable route")
        return False
コード例 #2
0
    def rebalance(self):
        debug("Sending %d satoshis to rebalance, remote pubkey: %s" %
              (self.amount, self.remote_pubkey))

        payment_request = self.generate_invoice()
        routes = Routes(self.lnd, payment_request, self.remote_pubkey)

        if not routes.has_next():
            debug("Could not find any suitable route")
            return None

        counter = 0
        while routes.has_next():
            counter += 1
            debug("Trying route #%d" % counter)

            route = routes.get_next()
            response = self.lnd.send_payment(payment_request, [route])
            is_successful = response.payment_error == ""

            if is_successful:
                fees_msat = response.payment_route.total_fees_msat
                fees_satoshi = round(float(fees_msat) / 1000.0, 3)
                debug("Success! Paid %d Satoshi in fees" % fees_satoshi)
                return response
            elif "TemporaryChannelFailure" in response.payment_error:
                debug("TemporaryChannelFailure (not enough funds along the route?)")
            else:
                debug("Error: %s" % response.payment_error)
        return None
コード例 #3
0
    def rebalance(self):
        first_hop_alias_formatted = ""
        last_hop_alias_formatted = ""
        first_channel_id = 0
        if self.first_hop_channel:
            first_hop_alias_formatted = format_alias(
                self.lnd.get_node_alias(self.first_hop_channel.remote_pubkey))
            first_channel_id = format_channel_id(
                self.first_hop_channel.chan_id)
        if self.last_hop_channel:
            last_hop_alias_formatted = format_alias(
                self.lnd.get_node_alias(self.last_hop_channel.remote_pubkey))
        amount_formatted = format_amount(self.amount)
        if self.first_hop_channel and self.last_hop_channel:
            self.output.print_line(
                f"Sending {amount_formatted} satoshis from channel {first_channel_id} with {first_hop_alias_formatted} "
                f"back through {last_hop_alias_formatted}.")
        elif self.last_hop_channel:
            self.output.print_line(
                f"Sending {amount_formatted} satoshis back through {last_hop_alias_formatted}."
            )
        else:
            self.output.print_line(
                f"Sending {self.amount:,} satoshis from channel {first_channel_id} with {first_hop_alias_formatted}."
            )

        fee_limit_msat = self.get_fee_limit_msat()
        payment_request = self.generate_invoice()
        min_fee_last_hop = None
        if self.first_hop_channel:
            fee_rate_first_hop = self.lnd.get_ppm_to(
                self.first_hop_channel.chan_id)
            policy_first_hop = self.lnd.get_policy_to(
                self.first_hop_channel.chan_id)
            min_fee_last_hop = self.compute_fee(self.amount,
                                                fee_rate_first_hop,
                                                policy_first_hop)
        routes = Routes(self.lnd, payment_request, self.first_hop_channel,
                        self.last_hop_channel, fee_limit_msat, self.output)

        self.initialize_ignored_channels(routes, fee_limit_msat,
                                         min_fee_last_hop)

        tried_routes = []
        while routes.has_next():
            route = routes.get_next()

            success = self.try_route(payment_request, route, routes,
                                     tried_routes)
            if success:
                return True
        self.output.print_line("Could not find any suitable route")
        self.lnd.cancel_invoice(payment_request.payment_hash)
        return False
コード例 #4
0
    def rebalance(self):
        debug(("Sending {:,} satoshis to rebalance to channel with ID %d"
               % self.last_hop_channel.chan_id).format(self.amount))
        if self.channel_ratio != 0.5:
            debug("Channel ratio used is %d%%" % int(self.channel_ratio * 100))
        if self.first_hop_channel_id:
            debug("Forced first channel has ID %d" % self.first_hop_channel_id)

        payment_request = self.generate_invoice()
        routes = Routes(self.lnd, payment_request, self.first_hop_channel_id, self.last_hop_channel)

        self.initialize_ignored_channels(routes)

        tried_routes = []
        while routes.has_next():
            route = routes.get_next()
            if self.route_is_invalid(route, routes):
                continue
            tried_routes.append(route)

            debug("")
            debug("Trying route #%d" % len(tried_routes))
            debug(Routes.print_route(route))

            response = self.lnd.send_payment(payment_request, route)
            is_successful = response.failure.code == 0

            if is_successful:
                debug("Success! Paid fees: %s sat (%s msat)" % (route.total_fees, route.total_fees_msat))
                debug("Successful route:")
                debug(Routes.print_route(route))
                debug("")
                debug("Tried routes:")
                debug("\n".join(Routes.print_route(route) for route in tried_routes))
                return
            else:
                code = response.failure.code
                failure_source_pubkey = self.bytes_to_hex_string(response.failure.failure_source_pubkey)
                if code == 15:
                    debugnobreak("Temporary channel failure, ")
                    routes.ignore_edge_on_route(failure_source_pubkey, route)
                elif code == 18:
                    debugnobreak("Unknown next peer, ")
                    routes.ignore_edge_on_route(failure_source_pubkey, route)
                elif code == 12:
                    debugnobreak("Fee insufficient, ")
                    routes.ignore_edge_on_route(failure_source_pubkey, route)
                else:
                    debug(repr(response))
                    debug("Unknown error code %s" % repr(code))
        debug("Could not find any suitable route")
        return None
コード例 #5
0
ファイル: logic.py プロジェクト: accumulator/rebalance-lnd
    def rebalance(self):
        if self.last_hop_channel:
            debug("Ⓘ Sending " + fmt.col_hi("{:,}".format(self.amount)) +
                  " satoshis to rebalance to channel with ID %s" %
                  fmt.col_lo(fmt.print_chanid(self.last_hop_channel.chan_id)))
        else:
            debug("Ⓘ Sending " + fmt.col_hi("{:,}".format(self.amount)) +
                  " satoshis.")
        if self.channel_ratio != 0.5:
            debug("Ⓘ Channel ratio used is " +
                  fmt.col_hi("%d%%" % int(self.channel_ratio * 100)))
        if self.first_hop_channel:
            debug("Ⓘ Forced first channel has ID %s" %
                  fmt.col_lo(fmt.print_chanid(self.first_hop_channel.chan_id)))

        payment_request = self.generate_invoice()

        if self.path:
            myroute = self.lnd.build_route(self.path, self.amount,
                                           self.first_hop_channel.chan_id)
            if isinstance(myroute, Exception):
                debug("")
                debug(fmt.col_err("✘ " + myroute.details()))
                return False
            try:
                success = self.try_route(payment_request, myroute, [myroute],
                                         [])
                if success:
                    return True
            except:
                # since we use --path, myroute isn't a real Routes object
                # assume fees too high
                debug(fmt.col_err("✘ fees too high"))
                return False

        else:
            routes = Routes(self.lnd, payment_request, self.first_hop_channel,
                            self.last_hop_channel, self.deep)

            self.initialize_ignored_channels(routes)

            tried_routes = []
            while routes.has_next():
                route = routes.get_next()

                success = self.try_route(payment_request, route, routes,
                                         tried_routes)
                if success:
                    return True
        debug("")
        debug(fmt.col_err("✘ Could not find any suitable route"))
        return False
コード例 #6
0
    def rebalance(self):
        debug(("Sending {:,} satoshis to rebalance to channel with ID %d" %
               self.last_hop_channel.chan_id).format(self.amount))
        if self.channel_ratio != 0.5:
            debug("Channel ratio used is %d%%" % int(self.channel_ratio * 100))
        if self.first_hop_channel_id:
            debug("Forced first channel has ID %d" % self.first_hop_channel_id)

        payment_request = self.generate_invoice()
        routes = Routes(self.rpc, payment_request, self.first_hop_channel_id,
                        self.last_hop_channel)

        if not routes.has_next():
            debug("Could not find any suitable route")
            return None

        tried_routes = []
        while routes.has_next():
            route = routes.get_next()
            if self.route_is_invalid(route):
                continue
            tried_routes.append(route)

            debug("Trying route #%d" % len(tried_routes))
            debug(Routes.print_route(route))

            response = self.rpc.send_payment_sync(payment_request, [route])
            is_successful = response.payment_error == ""

            if is_successful:
                fees_msat = response.payment_route.total_fees_msat
                fees_satoshi = round(float(fees_msat) / 1000.0, 3)
                debug("Success! Paid %d Satoshi in fees" % fees_satoshi)
                debug("Tried routes:")
                debug("\n".join(
                    Routes.print_route(route) for route in tried_routes))
                debug("Successful route:")
                debug(Routes.print_route(route))

                return response
            elif "TemporaryChannelFailure" in response.payment_error:
                debug(
                    "TemporaryChannelFailure (not enough funds along the route?)"
                )
            else:
                debug("Error: %s" % response.payment_error)
        return None
コード例 #7
0
    def rebalance(self):
        self.update_channels()
        if self.channels_balanced():
            debug("Done with rabalancing %d and %d"
                  % (self.first_hop_channel_id, self.last_hop_channel_id))
            return True
        if self.amount_too_big():
            debug("Amount %d is too big for current local and/or remote balance of first and/or last hop channel."
                  % self.amount)
            return False

        debug(("Sending {:,} satoshis to rebalance to channel with ID %d from channel with ID %d"
               % (self.last_hop_channel.chan_id, self.first_hop_channel.chan_id)).format(self.amount))

        payment_request = self.generate_invoice()
        routes = Routes(self.lnd,
                        payment_request,
                        self.first_hop_channel,
                        self.last_hop_channel,
                        self.max_routes_to_request)

        tried_routes = []
        while routes.has_next():
            route = routes.get_next()
            success = self.try_route(payment_request, route, routes, tried_routes)
            if success:
                self.last_hop_channel.local_balance += self.amount
                self.last_hop_channel.remote_balance -= self.amount
                self.last_hop_channel.local_balance -= (self.amount+route.total_fees_msat//1000)
                self.last_hop_channel.remote_balance += self.amount
                if self.channels_balanced():
                    debug("Done with rabalancing %d and %d"
                          % (self.first_hop_channel.chan_id, self.last_hop_channel.chan_id))
                    return True
                if self.amount_too_big():
                    debug(
                        "Amount %d is too big for current local and/or remote balance of first and/or last hop channel."
                        % self.amount)
                    return False
                return Logic(self.lnd,
                             self.first_hop_channel_id,
                             self.last_hop_channel_id,
                             self.from_ratio,
                             self.to_ratio,
                             self.amount,
                             self.max_amount_halvings,
                             self.max_fee_factor,
                             self.max_routes_to_request,
                             self.num_amount_halvings + 1).rebalance()
        debug("All routes exhausted.")
        if self.num_amount_halvings < self.max_amount_halvings:
            return Logic(self.lnd,
                         self.first_hop_channel_id,
                         self.last_hop_channel_id,
                         self.from_ratio,
                         self.to_ratio,
                         self.amount // 2,
                         self.max_amount_halvings,
                         self.max_fee_factor // 2,
                         self.max_routes_to_request,
                         self.num_amount_halvings + 1).rebalance()
        return False