Home

Awesome

circular Tests GitHub

circular is a Core Lightning plugin that helps routing nodes rebalance their channels in the most efficient way possible.

It features a custom pathfinding algorithm that takes into account liquidity information and failed payments in order to optimize channel rebalancing. Circular is designed to be used by routing nodes who do not need reliability in their payments, and makes it easy to rebalance large amounts between channels.

:warning: circular needs allow-deprecated-apis=true in order to run, at least until glightning gets brought under the CLN repo. Also, it might not be feasible to run circular if your device is too weak. A good test is to see how long time lightning-cli listchannels > /dev/null takes to run: if it takes more than 60s circular won't be able to start.

Features

Endpoints

Detailed explanation of the endpoints follows in the Usage section.

Building

You can download the circular binary from the releases section. Alternatively, you can build the plugin on your own. You need Go 1.18 or higher to build this plugin.

git clone https://github.com/giovannizotta/circular.git
cd circular
go build -o circular cmd/circular/*.go
chmod +x circular

Running

This plugin is dynamic, meaning that you can start and stop it via the CLI. For general plugin installation instructions see How to install a plugin.

The executable that you have just built is called circular. The startup options are:

You can also set a preferred logging level. For example, with this startup command you would refresh the graph every 5 minutes, peers every 60 seconds, and reset liquidity on channels every 120 minutes. You would also not save stats and set the logging level to DEBUG.

⚠ This command is meant to be an example of how to use startup options. You should probably use a configuration file for CLN instead of starting it in this way.️

lightningd --plugin=/path/to/circularexecutable --circular-graph-refresh=5 --circular-peer-refresh=60 --circular-liquidity-refresh=120 --circular-save-stats=false --log-level=debug:plugin-circular

Usage

Rebalance one channel at a time

via Short Channel ID:

lightning-cli circular -k inscid=123456x1x1 outscid=345678x1x1 amount=200000 maxppm=10 attempts=1

via Node ID:

lightning-cli circular-node -k outnode=123abc innode=345def amount=200000 maxppm=10 attempts=1

Required parameters:

Optional parameters:

Pull liquidity into a channel from many sources in parallel

lightning-cli circular-pull -k inscid=123456x1x1 amount=500000 splits=5 splitamount=20000 maxppm=10 maxoutppm=50 attempts=1 maxhops=8 depleteuptopercent=0.5 depleteuptoamount=2000000

Required parameters:

Optional parameters:

cli circular-pull -k inscid=123456x1x1 outlist='["03700917a25f79a3e427fe86e49b5041b583c73dd223cfa9a87cd6be5076b7b7a5", "025614be3600e9899bc044d331ab58a9fe1ccf30e75ae35943cdd11218a0a55dba"]' amount=800000 splitamount=80000 splits=4 maxppm=5000

depleteuptopercent and depleteuptoamount are a bit special:

Example: you have a 10M channel and you set depleteuptopercent to 0.2 (20%) and depleteuptoamount to 1000000. The actual amount that will be left in that channel will be the minimum of 0.2 and 1000000. So in this case, at least 1000000 sats will be left in that channel.

Push liquidity out of a channel to many destinations in parallel

Symmetrical to circular-pull, but for pushing liquidity out of a channel.

lightning-cli circular-push -k outscid=123456x1x1 amount=500000 splits=5 splitamount=20000 maxppm=10 minoutppm=50 attempts=1 maxhops=8 filluptopercent=0.5 filluptoamount=2000000

Required parameters:

Optional parameters:

cli circular-push -k outscid=123456x1x1 inlist='["03700917a25f79a3e427fe86e49b5041b583c73dd223cfa9a87cd6be5076b7b7a5", "025614be3600e9899bc044d331ab58a9fe1ccf30e75ae35943cdd11218a0a55dba"]' amount=800000 splitamount=80000 splits=4 maxppm=5000

filluptopercent and filluptoamount are a bit special:

Example: you have a 10M channel and you set filluptopercent to 0.2 (20%) and filluptoamount to 1000000. The minimum amount of remote liquidity that will be left in that channel will be the minimum of 0.2 and 1000000. So in this case, at least 1000000 sats will be left in that channel.

Get stats about the usage of the plugin

lightning-cli circular-stats > stats.json

This command will return the following stats:

It's a good idea to pipe the output into a file, since it can be quite big. ⚠ To limit the size, circular will only keep the last 14 days of stats.

Benchmarks

Here is the performance of the pathfinding algorithm on the mainnet lightning network graph as of August 2022 (about 16000 nodes and 80000 channels). The benchmarks consist in finding a route between two random nodes and measuring the time it takes to find the route. Different values of maxhops are tested to show that shorter routes take less time to compute. Those routes are preferred by circular, since the longer the route, the most likely it is to fail.

On a laptop:

goos: linux
goarch: amd64
cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz

30 runs sampled
name                                 time/op
Graph_GetRoute/dijkstra_3_maxhops-8  2.44ms ± 2%
Graph_GetRoute/dijkstra_4_maxhops-8  3.25ms ± 5%
Graph_GetRoute/dijkstra_5_maxhops-8  6.57ms ± 5%
Graph_GetRoute/dijkstra_6_maxhops-8  10.6ms ± 5%
Graph_GetRoute/dijkstra_7_maxhops-8  14.6ms ±10%
Graph_GetRoute/dijkstra_8_maxhops-8  17.6ms ± 7%

On a Raspberry Pi 4:

goos: linux
goarch: arm64

30 runs sampled
name                                 time/op
Graph_GetRoute/dijkstra_3_maxhops-4  20.4ms ± 1%
Graph_GetRoute/dijkstra_4_maxhops-4  23.3ms ± 2%
Graph_GetRoute/dijkstra_5_maxhops-4  36.0ms ± 3%
Graph_GetRoute/dijkstra_6_maxhops-4  52.3ms ± 6%
Graph_GetRoute/dijkstra_7_maxhops-4  67.3ms ± 7%
Graph_GetRoute/dijkstra_8_maxhops-4  78.0ms ± 8%

To replicate these benchmarks on your own machine, you can use the following command:

cd graph
go test -bench=. -timeout 0 -count 30 | tee bench.txt

benchstat bench.txt

(you need benchstat installed)

Contributing

If you have any problems feel free to open an issue or join our Telegram group. Pull requests are welcome as well.

Special thanks to devzorLN🐸 for helping me test the plugin.