From bfe17d0ce1b59184927c2c9529e41206689b71ba Mon Sep 17 00:00:00 2001 From: ziggie Date: Sat, 14 Jan 2023 09:43:11 +0100 Subject: [PATCH 1/3] add the option to exclude channels by channelage --- README.md | 17 +++++++++-------- channels.go | 10 ++++++++++ info.go | 3 +++ main.go | 9 +++++++-- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8f7ded8..eb6a015 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ rebalance-lnd](https://github.com/accumulator/rebalance-lnd). - timeouts can be customized - JSON/TOML config file to set some defaults you prefer - optional route probing using binary search to rebalance a smaller amount -- optional rapid rebalancing using the same route for further rebalances +- optional rapid rebalancing using the same route for further rebalances unitl route is depleted in case a rebalance succeeds - data caching to speed up alias resolution, quickly skip failing channel pairs etc. @@ -62,8 +62,8 @@ in `~/go/bin/linux_arm`. ``` Config: - -f, --config config file path - + -f, --config config file path + Node Connection: -c, --connect connect to lnd using host:port -t, --tlscert path to tls.cert to connect @@ -88,6 +88,7 @@ Common: -e, --exclude-channel (DEPRECATED) don't use this channel at all (can be specified multiple times) -d, --exclude-node (DEPRECATED) don't use this node for routing (can be specified multiple times) --exclude don't use this node or your channel for routing (can be specified multiple times) + --exclude-channel-age channels with a lower channel age (in blocks) relative to the current blockheight are excluded when rebalancing --to try only this channel or node as target (should satisfy other constraints too; can be specified multiple times) --from try only this channel or node as source (should satisfy other constraints too; can be specified multiple times) --fail-tolerance a payment that differs from the prior attempt by this ppm will be cancelled @@ -198,9 +199,8 @@ continues. # Docker Setup In general its recommanded to run regolancer in a normal environment because it is -so easy to install as mentioned above. However if you want to run it in a docker -we also provide the Dockerfile and a docker-compose.yml so that you can easily -get started. +so easy to install as mentioned above. However if you want to run it in a docker +we also provide the Dockerfile so that you can easily get started. Build the container or pull it: @@ -224,7 +224,6 @@ alias regolancer="docker run --rm --network=umbrel_main_network -it -v /home/umb For older versions of Umbrel please use `/home/umbrel/umbrel/lnd` instead of `/home/umbrel/umbrel/app-data/lightning/data/lnd` - # What's wrong with the other rebalancers While I liked probing in `bos`, it has many downsides: gives up quickly on @@ -288,6 +287,7 @@ during route construction. You can also disable them (it only happens on your end so you'll be able to receive liquidity but not send it) but it hurts your score on various sites so better not to do it. Increase fees or lower max_htlc and you'll be good. You can set multiple brackets with multiple limits like: + - 20% local balance => set max_htlc to 0.1 of channel capacity (so it can process ≈2 payments max or more smaller payments) - 10% local balance => set max_htlc to 0.01 of channel capacity (small payments @@ -306,6 +306,7 @@ accept contributions and suggestions though! For now I implemented almost everything I needed, maybe except a couple of timeouts being configurable. But I don't see much need for that as of now. The main goals and motivation for this project were: + - make it reliable and robust so I don't have to babysit it (stop/restart if it hangs, crashes or gives up early) - make it fast and lightweight, don't stress `lnd` too much as it all should run @@ -318,4 +319,4 @@ project were: # Feedback and contact We have a Matrix room to discuss this program and solve issues, feel free to -join [#regolancer:matrix.org](https://matrix.to/#/#regolancer:matrix.org)! \ No newline at end of file +join [#regolancer:matrix.org](https://matrix.to/#/#regolancer:matrix.org)! diff --git a/channels.go b/channels.go index b9fbb30..242efec 100644 --- a/channels.go +++ b/channels.go @@ -64,6 +64,10 @@ func (r *regolancer) getChannelCandidates(fromPerc, toPerc, amount int64) error for _, c := range r.channels { + if params.ExcludeChannelAge != 0 && uint64(info.BlockHeight)-getChannelAge(c.ChanId) < params.ExcludeChannelAge { + continue + } + if _, ok := r.excludeBoth[c.ChanId]; ok { continue } @@ -200,6 +204,12 @@ func parseScid(chanId string) int64 { } +func getChannelAge(chanId uint64) uint64 { + shortChanId := lnwire.NewShortChanIDFromInt(chanId) + + return uint64(shortChanId.BlockHeight) +} + func (r *regolancer) getChannelForPeer(ctx context.Context, node []byte) []*lnrpc.Channel { channels, err := r.lnClient.ListChannels(ctx, &lnrpc.ListChannelsRequest{ActiveOnly: true, PublicOnly: true, Peer: node}) diff --git a/info.go b/info.go index 38ad861..3606f6b 100644 --- a/info.go +++ b/info.go @@ -79,6 +79,9 @@ func (r *regolancer) info(ctx context.Context) error { } } fmt.Println() + if params.ExcludeChannelAge != 0 { + fmt.Printf("ChannelAge needs to be >= than: %s blocks\n", hiWhiteColor(params.ExcludeChannelAge)) + } fmt.Printf("Fail tolerance: %s ppm\n", formatAmt(int64(params.FailTolerance))) printBooleanOption("Rapid rebalance", params.AllowRapidRebalance) printBooleanOption("Lost profit accounting", params.LostProfit) diff --git a/main.go b/main.go index 44a855e..bd1502d 100644 --- a/main.go +++ b/main.go @@ -45,6 +45,7 @@ type configParams struct { ExcludeChannels []string `short:"e" long:"exclude-channel" description:"(DEPRECATED) don't use this channel at all (can be specified multiple times)" json:"exclude_channels" toml:"exclude_channels"` ExcludeNodes []string `short:"d" long:"exclude-node" description:"(DEPRECATED) don't use this node for routing (can be specified multiple times)" json:"exclude_nodes" toml:"exclude_nodes"` Exclude []string `long:"exclude" description:"don't use this node or your channel for routing (can be specified multiple times)" json:"exclude" toml:"exclude"` + ExcludeChannelAge uint64 `long:"exclude-channel-age" description:"channels with a lower channel age (in blocks) relative to the current blockheight are excluded when rebalancing" json:"exclude_channel_age" toml:"exclude_channel_age"` To []string `long:"to" description:"try only this channel or node as target (should satisfy other constraints too; can be specified multiple times)" json:"to" toml:"to"` From []string `long:"from" description:"try only this channel or node as source (should satisfy other constraints too; can be specified multiple times)" json:"from" toml:"from"` FailTolerance int64 `long:"fail-tolerance" description:"a payment that differs from the prior attempt by this ppm will be cancelled" json:"fail_tolerance" toml:"fail_tolerance"` @@ -68,6 +69,7 @@ type configParams struct { } var params, cfgParams configParams +var info *lnrpc.GetInfoResponse type failedRoute struct { channelPair [2]*lnrpc.Channel @@ -104,7 +106,10 @@ type regolancer struct { } func loadConfig() { - flags.NewParser(&cfgParams, flags.None).Parse() + _, err := flags.NewParser(&cfgParams, flags.None).Parse() + if err != nil { + log.Fatalf("Error when parsing command line options: %s", err) + } if cfgParams.Config == "" { return @@ -313,7 +318,7 @@ func main() { defer mainCtxCancel() infoCtx, infoCtxCancel := context.WithTimeout(mainCtx, time.Second*time.Duration(params.TimeoutInfo)) defer infoCtxCancel() - info, err := r.lnClient.GetInfo(infoCtx, &lnrpc.GetInfoRequest{}) + info, err = r.lnClient.GetInfo(infoCtx, &lnrpc.GetInfoRequest{}) if err != nil { log.Fatal(err) } From ff679c977df24cf732d323bdb3d701b1d816a000 Mon Sep 17 00:00:00 2001 From: rkfg Date: Sat, 14 Jan 2023 20:27:02 +0300 Subject: [PATCH 2/3] Reword descriptions --- README.md | 3 +-- info.go | 2 +- main.go | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eb6a015..a47b9aa 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,7 @@ Common: -e, --exclude-channel (DEPRECATED) don't use this channel at all (can be specified multiple times) -d, --exclude-node (DEPRECATED) don't use this node for routing (can be specified multiple times) --exclude don't use this node or your channel for routing (can be specified multiple times) - --exclude-channel-age channels with a lower channel age (in blocks) relative to the current blockheight are excluded when rebalancing - --to try only this channel or node as target (should satisfy other constraints too; can be specified multiple times) + --exclude-channel-age don't use channels opened less than this number of blocks ago --to try only this channel or node as target (should satisfy other constraints too; can be specified multiple times) --from try only this channel or node as source (should satisfy other constraints too; can be specified multiple times) --fail-tolerance a payment that differs from the prior attempt by this ppm will be cancelled --allow-unbalance-from (DEPRECATED) let the source channel go below 50% local liquidity, use if you want to drain a channel; you should also set --pfrom to >50 diff --git a/info.go b/info.go index 3606f6b..8cead44 100644 --- a/info.go +++ b/info.go @@ -80,7 +80,7 @@ func (r *regolancer) info(ctx context.Context) error { } fmt.Println() if params.ExcludeChannelAge != 0 { - fmt.Printf("ChannelAge needs to be >= than: %s blocks\n", hiWhiteColor(params.ExcludeChannelAge)) + fmt.Printf("Channel age needs to be >= %s blocks\n", hiWhiteColor(params.ExcludeChannelAge)) } fmt.Printf("Fail tolerance: %s ppm\n", formatAmt(int64(params.FailTolerance))) printBooleanOption("Rapid rebalance", params.AllowRapidRebalance) diff --git a/main.go b/main.go index bd1502d..fb42822 100644 --- a/main.go +++ b/main.go @@ -45,7 +45,7 @@ type configParams struct { ExcludeChannels []string `short:"e" long:"exclude-channel" description:"(DEPRECATED) don't use this channel at all (can be specified multiple times)" json:"exclude_channels" toml:"exclude_channels"` ExcludeNodes []string `short:"d" long:"exclude-node" description:"(DEPRECATED) don't use this node for routing (can be specified multiple times)" json:"exclude_nodes" toml:"exclude_nodes"` Exclude []string `long:"exclude" description:"don't use this node or your channel for routing (can be specified multiple times)" json:"exclude" toml:"exclude"` - ExcludeChannelAge uint64 `long:"exclude-channel-age" description:"channels with a lower channel age (in blocks) relative to the current blockheight are excluded when rebalancing" json:"exclude_channel_age" toml:"exclude_channel_age"` + ExcludeChannelAge uint64 `long:"exclude-channel-age" description:"don't use channels opened less than this number of blocks ago" json:"exclude_channel_age" toml:"exclude_channel_age"` To []string `long:"to" description:"try only this channel or node as target (should satisfy other constraints too; can be specified multiple times)" json:"to" toml:"to"` From []string `long:"from" description:"try only this channel or node as source (should satisfy other constraints too; can be specified multiple times)" json:"from" toml:"from"` FailTolerance int64 `long:"fail-tolerance" description:"a payment that differs from the prior attempt by this ppm will be cancelled" json:"fail_tolerance" toml:"fail_tolerance"` From 00151033e9e735b06b3aa55aa0625cb51e980f3d Mon Sep 17 00:00:00 2001 From: rkfg Date: Sat, 14 Jan 2023 20:33:17 +0300 Subject: [PATCH 3/3] Get rid of global var --- channels.go | 2 +- main.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/channels.go b/channels.go index 242efec..a1d2311 100644 --- a/channels.go +++ b/channels.go @@ -64,7 +64,7 @@ func (r *regolancer) getChannelCandidates(fromPerc, toPerc, amount int64) error for _, c := range r.channels { - if params.ExcludeChannelAge != 0 && uint64(info.BlockHeight)-getChannelAge(c.ChanId) < params.ExcludeChannelAge { + if params.ExcludeChannelAge != 0 && uint64(r.blockHeight)-getChannelAge(c.ChanId) < params.ExcludeChannelAge { continue } diff --git a/main.go b/main.go index fb42822..3915301 100644 --- a/main.go +++ b/main.go @@ -69,7 +69,6 @@ type configParams struct { } var params, cfgParams configParams -var info *lnrpc.GetInfoResponse type failedRoute struct { channelPair [2]*lnrpc.Channel @@ -85,6 +84,7 @@ type regolancer struct { lnClient lnrpc.LightningClient routerClient routerrpc.RouterClient myPK string + blockHeight uint32 channels []*lnrpc.Channel fromChannels []*lnrpc.Channel fromChannelId map[uint64]struct{} @@ -318,11 +318,12 @@ func main() { defer mainCtxCancel() infoCtx, infoCtxCancel := context.WithTimeout(mainCtx, time.Second*time.Duration(params.TimeoutInfo)) defer infoCtxCancel() - info, err = r.lnClient.GetInfo(infoCtx, &lnrpc.GetInfoRequest{}) + info, err := r.lnClient.GetInfo(infoCtx, &lnrpc.GetInfoRequest{}) if err != nil { log.Fatal(err) } r.myPK = info.IdentityPubkey + r.blockHeight = info.BlockHeight err = r.getChannels(infoCtx) if err != nil { log.Fatal("Error listing own channels: ", err)