From b54dbb40d5c81f7e6017bed96589c4322fac1e27 Mon Sep 17 00:00:00 2001 From: Evan Kaloudis Date: Thu, 24 Oct 2024 14:16:57 -0400 Subject: [PATCH 01/14] handle inbound fees on getchaninfo failures --- jobs.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jobs.py b/jobs.py index ecb4a3d4..d312b585 100644 --- a/jobs.py +++ b/jobs.py @@ -372,6 +372,10 @@ def update_channels(stub): db_channel.remote_disabled = False if db_channel.remote_disabled is None else db_channel.remote_disabled db_channel.remote_min_htlc_msat = -1 if db_channel.remote_min_htlc_msat is None else db_channel.remote_min_htlc_msat db_channel.remote_max_htlc_msat = -1 if db_channel.remote_max_htlc_msat is None else db_channel.remote_max_htlc_msat + db_channel.local_inbound_base_fee = -1 if db_channel.local_inbound_base_fee is None else db_channel.local_inbound_base_fee + db_channel.local_inbound_fee_rate = -1 if db_channel.local_inbound_fee_rate is None else db_channel.local_inbound_fee_rate + db_channel.remote_inbound_base_fee = -1 if db_channel.remote_inbound_base_fee is None else db_channel.remote_inbound_base_fee + db_channel.remote_inbound_fee_rate = -1 if db_channel.remote_inbound_fee_rate is None else db_channel.remote_inbound_fee_rate # Check for pending settings to be applied if pending_channel: if pending_channel.local_base_fee or pending_channel.local_fee_rate or pending_channel.local_cltv: From 8dd35de305aea76d1af93236e432a56f3ff8bb9f Mon Sep 17 00:00:00 2001 From: cryptosharks131 <38626122+cryptosharks131@users.noreply.github.com> Date: Sun, 27 Oct 2024 10:14:36 -0400 Subject: [PATCH 02/14] Update docker install command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 042590fe..ace31eb2 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ services: command: - sh - -c - - python initialize.py -net 'mainnet' -server '127.0.0.1:10009' -d && supervisord && python manage.py runserver 0.0.0.0:8889 + - python initialize.py -net 'mainnet' -rpc '127.0.0.1:10009' -wn && python controller.py runserver 0.0.0.0:8889 > /var/log/lndg-controller.log 2>&1 network_mode: "host" ``` ### Build and Deploy From 1f7096e3851db44c7263a4cc0a5484c088ed7ef7 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Thu, 25 Jan 2024 12:38:25 +0100 Subject: [PATCH 03/14] Minor fixes --- .dockerignore | 1 + Dockerfile | 8 ++++---- initialize.py | 4 ++-- justfile | 6 ++++++ 4 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 .dockerignore create mode 100644 justfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..1269488f --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +data diff --git a/Dockerfile b/Dockerfile index b3e04f34..896c6b0e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM python:3-alpine ENV PYTHONUNBUFFERED 1 -RUN apk add git g++ linux-headers && git clone https://github.com/cryptosharks131/lndg /app -WORKDIR /app -RUN git checkout "master" +# RUN git clone https://github.com/cryptosharks131/lndg.git /lndg +COPY . /lndg/ +WORKDIR /lndg RUN pip install -r requirements.txt -RUN pip install supervisor whitenoise \ No newline at end of file +RUN pip install supervisor whitenoise diff --git a/initialize.py b/initialize.py index b2ff07ec..4fe16406 100644 --- a/initialize.py +++ b/initialize.py @@ -253,7 +253,7 @@ def initialize_django(adminuser, adminpw): 'rest_framework', 'gui', ], - STATIC_URL = 'static/', + STATIC_URL = 'static/', STATIC_ROOT = os.path.join(BASE_DIR, 'gui/static/') ) django.setup() @@ -333,4 +333,4 @@ def main(): initialize_django(adminuser, adminpw) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/justfile b/justfile new file mode 100644 index 00000000..cbe2c7af --- /dev/null +++ b/justfile @@ -0,0 +1,6 @@ +build_image: + docker build -t chevdor/lndg . + docker images | grep lndg + +push_image: + docker push chevdor/lndg From 1079b8fa90ad01d6ece1997e7c6b0b3e15fbd7ca Mon Sep 17 00:00:00 2001 From: Chevdor Date: Thu, 25 Jan 2024 15:00:40 +0100 Subject: [PATCH 04/14] Fix dockerfile --- .dockerignore | 2 +- .gitignore | 2 +- Dockerfile | 4 +-- gui/templates/action_list.html | 2 +- gui/templates/addresses.html | 2 +- gui/templates/advanced.html | 2 +- gui/templates/channel.html | 8 +++--- gui/templates/channels.html | 2 +- gui/templates/fee_rates.html | 2 +- gui/templates/home.html | 38 ++++++++++++++--------------- gui/templates/income.html | 6 ++--- gui/templates/local_settings.html | 6 ++--- gui/templates/peers.html | 2 +- gui/templates/rebalances_table.html | 12 ++++----- gui/templates/rebalancing.html | 6 ++--- gui/templates/resolutions.html | 2 +- 16 files changed, 49 insertions(+), 49 deletions(-) mode change 100644 => 120000 .dockerignore diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 1269488f..00000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -data diff --git a/.dockerignore b/.dockerignore new file mode 120000 index 00000000..3e4e48b0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.gitignore \ No newline at end of file diff --git a/.gitignore b/.gitignore index 99dea3f7..68fb2954 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ lndg-admin.txt .vs gui/static/admin gui/static/rest_framework -data/ \ No newline at end of file +data/ diff --git a/Dockerfile b/Dockerfile index 896c6b0e..19217324 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM python:3-alpine +FROM python:3-slim ENV PYTHONUNBUFFERED 1 # RUN git clone https://github.com/cryptosharks131/lndg.git /lndg -COPY . /lndg/ WORKDIR /lndg +COPY . . RUN pip install -r requirements.txt RUN pip install supervisor whitenoise diff --git a/gui/templates/action_list.html b/gui/templates/action_list.html index 591036c9..1d0a822e 100644 --- a/gui/templates/action_list.html +++ b/gui/templates/action_list.html @@ -61,4 +61,4 @@

Suggested Action List

Nothing to see here! Great job!

{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/gui/templates/addresses.html b/gui/templates/addresses.html index 32dfa62e..24ed0b1c 100644 --- a/gui/templates/addresses.html +++ b/gui/templates/addresses.html @@ -27,4 +27,4 @@

{% if addresses.address_type == 1 %}Legacy{% elif addresses.address_type ==

You dont have any addresses yet.

{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/gui/templates/advanced.html b/gui/templates/advanced.html index f0431f9f..482884d0 100644 --- a/gui/templates/advanced.html +++ b/gui/templates/advanced.html @@ -265,4 +265,4 @@

Advanced Channel Settings

} }) -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/gui/templates/channel.html b/gui/templates/channel.html index bf9cb9b8..fa0e5ad6 100644 --- a/gui/templates/channel.html +++ b/gui/templates/channel.html @@ -8,14 +8,14 @@

{{ chan_id }} {{ channel.short_chan_id }}

- {% if peer_info %}📍{{ peer_info.address }} | - Channel Updates: {{ channel.num_updates|intcomma }} | + {% if peer_info %}📍{{ peer_info.address }} | + Channel Updates: {{ channel.num_updates|intcomma }} | {% if not channel.is_open %}❌ Closed:{% elif channel.is_active %}Uptime:{% else %}Downtime:{% endif %} {{ channel.last_update|naturaltime|slice:":-4" }} since {{ channel.last_update }}{% endif %} {%if channel.private %}🕶️{%else%}🌐{%endif%}
⛓️ Channel Point: {{ channel.funding_txid }}:{{ channel.output_index }} | - Opened In: {{ channel.open_block|intcomma }} | + Opened In: {{ channel.open_block|intcomma }} | Opener: {% if channel.initiator == True %}Local{% else %}Remote{% endif %}
@@ -570,7 +570,7 @@

Channel Notes

let next_failed_htlcs = (await failedhtlcs_task).results if(next_failed_htlcs.length<5){ byId("loadMoreFailedHTLCs").style.display = "none" - } + } if(next_failed_htlcs.length==0){ return } diff --git a/gui/templates/channels.html b/gui/templates/channels.html index d394b6e1..0ab519a3 100644 --- a/gui/templates/channels.html +++ b/gui/templates/channels.html @@ -56,4 +56,4 @@

Channel Performance

You dont have any channels to analyze yet!

{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/gui/templates/fee_rates.html b/gui/templates/fee_rates.html index c549b3cd..0ce4fc77 100644 --- a/gui/templates/fee_rates.html +++ b/gui/templates/fee_rates.html @@ -87,4 +87,4 @@

Suggested Fee Rates

{% if local_settings %} {% include 'local_settings.html' with settings=local_settings title='Auto-Fees' postURL='update_setting' %} {% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/gui/templates/home.html b/gui/templates/home.html index 0ecb7c70..a73b1946 100644 --- a/gui/templates/home.html +++ b/gui/templates/home.html @@ -45,7 +45,7 @@ - Addresses: + Addresses: {% for addr in node_info.uris %}
{{ addr }} @@ -138,10 +138,10 @@
\ No newline at end of file + diff --git a/gui/templates/peers.html b/gui/templates/peers.html index d9e0e138..e0a4f4cc 100644 --- a/gui/templates/peers.html +++ b/gui/templates/peers.html @@ -46,4 +46,4 @@

Peers List {% if status == 2 %}Successful{% elif status == 0 %}Pending{% elif status = const response = await POST('rebalancer', {body: new_rebal}) const table = input.parentElement.parentElement.parentElement table.prepend(use(transformations).render(response)) - } + } } else { input.innerHTML = "❌" - input.title="Cancel this request" + input.title="Cancel this request" input.onclick = async function(){ const response = await PUT(`rebalancer/${rebalance.id}`, {body: {status: 499}}) - + const table = input.parentElement.parentElement.parentElement const index = input.parentElement.parentElement.rowIndex -1 table.deleteRow(index) use(transformations).render(response, table.insertRow(index)) } - } + } return {innerHTML: input} - } + } }; async function buildTable(){ const res = await GET('rebalancer', {data: {limit: '{{count}}', status: '{{status}}', payment_hash: '{{payment_hash}}', last_hop_pubkey: '{% if last_hop_pubkey %}{{last_hop_pubkey}}{%else%}{{request.GET.last_hop_pubkey}}{%endif%}' }}) diff --git a/gui/templates/rebalancing.html b/gui/templates/rebalancing.html index dc981b72..82710752 100644 --- a/gui/templates/rebalancing.html +++ b/gui/templates/rebalancing.html @@ -71,7 +71,7 @@
Manual Rebalance R updateCols(['rebalance'], this, new_value) } }), - "ar_max_cost": ch => ({innerHTML: ``, + "ar_max_cost": ch => ({innerHTML: ``, changed: function(new_value){ updateCols(['ar_max_cost', 'fee_ratio'], this, new_value) } @@ -143,7 +143,7 @@
Manual Rebalance R ch.fee_check = parseInt(ch.fee_ratio*100/ch.ar_max_cost) ch.steps = parseInt(ch.inbound_can < 1 ? 0 : ((ch.percent_inbound - ch.ar_in_target)/(ch.ar_amt_target*100/ch.capacity)+0.999)) - ch.elegible = ch.inbound_can >= 1 && ch.fee_check < 100 && ch.auto_rebalance, + ch.elegible = ch.inbound_can >= 1 && ch.fee_check < 100 && ch.auto_rebalance, ch.available = ch.is_active && !ch.auto_rebalance && ch.percent_outbound / ch.ar_out_target >=1 return ch } @@ -174,7 +174,7 @@
Manual Rebalance R return ch1.percent_outbound - ch2.percent_outbound }) .forEach(ch => rebal_table.append(template.render(ch, 'chan_id'))) - + update_stats(await rebal_stats, rebal_table) }) function update_stats(stats, rebal_table){ diff --git a/gui/templates/resolutions.html b/gui/templates/resolutions.html index 123e2a48..f9c357e0 100644 --- a/gui/templates/resolutions.html +++ b/gui/templates/resolutions.html @@ -30,4 +30,4 @@

Resolutions For Channel: {{ chan_id }}

No resolutions were found for this channel!

{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} From a8e5f2f9fb3944ea48c1a5912d35891ee59e191b Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 26 Jan 2024 09:38:57 +0100 Subject: [PATCH 05/14] Move scripts to a scripts folder --- nginx.sh => scripts/nginx.sh | 0 systemd.sh => scripts/systemd.sh | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename nginx.sh => scripts/nginx.sh (100%) rename systemd.sh => scripts/systemd.sh (100%) diff --git a/nginx.sh b/scripts/nginx.sh similarity index 100% rename from nginx.sh rename to scripts/nginx.sh diff --git a/systemd.sh b/scripts/systemd.sh similarity index 100% rename from systemd.sh rename to scripts/systemd.sh From a2c043ec82da0298c7bf2ac6bf3bf96330856bc1 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 26 Jan 2024 09:39:41 +0100 Subject: [PATCH 06/14] Move doc to a doc folder --- postgres.md => doc/postgres.md | 0 quickstart.md => doc/quickstart.md | 0 systemd.md => doc/systemd.md | 14 +++++++------- 3 files changed, 7 insertions(+), 7 deletions(-) rename postgres.md => doc/postgres.md (100%) rename quickstart.md => doc/quickstart.md (100%) rename systemd.md => doc/systemd.md (78%) diff --git a/postgres.md b/doc/postgres.md similarity index 100% rename from postgres.md rename to doc/postgres.md diff --git a/quickstart.md b/doc/quickstart.md similarity index 100% rename from quickstart.md rename to doc/quickstart.md diff --git a/systemd.md b/doc/systemd.md similarity index 78% rename from systemd.md rename to doc/systemd.md index 4b4a52f1..12752dcd 100644 --- a/systemd.md +++ b/doc/systemd.md @@ -4,7 +4,7 @@ - **This assumes you have installed lndg on the home directory of the user. For example, user `mynode` will have a home directory of `/home/mynode/`.** ## Backend Controller Setup -Create a service file for `controller.py`, copying the contents below to the file and filling in the user you would like this to run under. +Create a service file for `controller.py`, copying the contents below to the file and filling in the user you would like this to run under. `nano /etc/systemd/system/lndg-controller.service` ``` [Unit] @@ -21,12 +21,12 @@ RestartSec=60s [Install] WantedBy=multi-user.target ``` -Enable and start the service to run the backend controller. -`sudo systemctl enable lndg-controller.service` +Enable and start the service to run the backend controller. +`sudo systemctl enable lndg-controller.service` `sudo systemctl start lndg-controller.service` ## Additional Commands -You can also check on the status, disable or stop the backend controller. -`sudo systemctl status lndg-controller.service` -`sudo systemctl disable lndg-controller.service` -`sudo systemctl stop lndg-controller.service` +You can also check on the status, disable or stop the backend controller. +`sudo systemctl status lndg-controller.service` +`sudo systemctl disable lndg-controller.service` +`sudo systemctl stop lndg-controller.service` From ef62cfee6cb35d00176718deacfce9310b0b7fa3 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 26 Jan 2024 12:14:38 +0100 Subject: [PATCH 07/14] Fix docker --- .dockerignore | 20 +++++++++++- .gitignore | 1 + Dockerfile | 7 ----- container/Dockerfile | 31 +++++++++++++++++++ .../docker-compose.yaml | 0 justfile | 2 +- scripts/entrypoint.sh | 18 +++++++++++ scripts/init.sh | 25 +++++++++++++++ scripts/suinit.sh | 18 +++++++++++ 9 files changed, 113 insertions(+), 9 deletions(-) mode change 120000 => 100644 .dockerignore delete mode 100644 Dockerfile create mode 100644 container/Dockerfile rename docker-compose.yaml => container/docker-compose.yaml (100%) create mode 100755 scripts/entrypoint.sh create mode 100755 scripts/init.sh create mode 100755 scripts/suinit.sh diff --git a/.dockerignore b/.dockerignore deleted file mode 120000 index 3e4e48b0..00000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -.gitignore \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..3bde5a7c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +__pycache__ +db.sqlite3 +lndg/settings.py +frontend +node_modules +lndg-admin.txt +.vscode +.vs +gui/static/admin +gui/static/rest_framework +data/ +container +doc +scripts +.github +.git +!scripts/entrypoint.sh +!scripts/init.sh +!scripts/suinit.sh diff --git a/.gitignore b/.gitignore index 68fb2954..9e8eb962 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ lndg-admin.txt gui/static/admin gui/static/rest_framework data/ +.DS_Store diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 19217324..00000000 --- a/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM python:3-slim -ENV PYTHONUNBUFFERED 1 -# RUN git clone https://github.com/cryptosharks131/lndg.git /lndg -WORKDIR /lndg -COPY . . -RUN pip install -r requirements.txt -RUN pip install supervisor whitenoise diff --git a/container/Dockerfile b/container/Dockerfile new file mode 100644 index 00000000..0f46a1b8 --- /dev/null +++ b/container/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3-slim + +ARG LNDG_PORT=8000 +ARG SUPERVISOR=1 +ENV PYTHONUNBUFFERED 1 + +# Add group abnd user to run rootless +RUN addgroup -gid 1000 lndg && \ + useradd -r -m -s /bin/bash -g lndg -u 1000 lndg + +WORKDIR /lndg + +COPY . . + +ENV LNDG_PORT=$LNDG_PORT +ENV LNDG_SUPERVISOR=$SUPERVISOR + +RUN echo "Install pip deps" && \ + pip install --upgrade pip && \ + pip install -r requirements.txt && \ + pip install whitenoise + +RUN scripts/suinit.sh + +EXPOSE $LNDG_PORT + +VOLUME [ "/lnd", "/lndg/data" ] + +USER lndg + +ENTRYPOINT [ "scripts/entrypoint.sh" ] diff --git a/docker-compose.yaml b/container/docker-compose.yaml similarity index 100% rename from docker-compose.yaml rename to container/docker-compose.yaml diff --git a/justfile b/justfile index cbe2c7af..27580966 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,5 @@ build_image: - docker build -t chevdor/lndg . + docker build -t chevdor/lndg -f container/Dockerfile . docker images | grep lndg push_image: diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh new file mode 100755 index 00000000..c03b9ea1 --- /dev/null +++ b/scripts/entrypoint.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e + +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} +LNDG_LISTEN=${LNDG_LISTEN:-0.0.0.0} +LNDG_PORT=${LNDG_PORT:-8000} + +scripts/init.sh + +if [ "$LNDG_SUPERVISOR" -eq "1" ]; then + echo "Starting supervisor" + supervisord +else + echo "Supervisor disabled, you need to setup an alternate method to run controller.py" +fi + +echo "Starting lndg server" +python manage.py runserver $LNDG_LISTEN:$LNDG_PORT diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100755 index 00000000..4bd6358e --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# This init script runs when the container start, as rootless + +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} +LNDG_NETWORK=${LNDG_NETWORK:-mainnet} +LNDG_SERVER=${LNDG_SERVER:-localhost:10009} + +echo "Initializing lndg for $LNDG_NETWORK network running on docker" + +if [ "$LNDG_SUPERVISOR" -eq "1" ]; then + echo "Initializing with supervisor running as lndg user" + python initialize.py \ + -net $LNDG_NETWORK \ + -server $LNDG_SERVER \ + --docker \ + --supervisord \ + --sduser lndg +else + echo "Initializing without supervisor" + python initialize.py \ + -net $LNDG_NETWORK \ + -server $LNDG_SERVER \ + --docker +fi diff --git a/scripts/suinit.sh b/scripts/suinit.sh new file mode 100755 index 00000000..29ce0d41 --- /dev/null +++ b/scripts/suinit.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} + +# This init script runs when the image is created, as root +touch /var/log/supervisord.log +chown lndg /var/log/supervisord.log + +mkdir -p /lndg/data/ +chown -R lndg /lndg + +if [ "$LNDG_SUPERVISOR" -eq "1" ]; then + pip install supervisor + chgrp lndg /usr/local/etc + chmod g+rw /usr/local/etc +else + echo "Supervisor disabled, you need to setup an alternate method to run controller.py" +fi From 82150562e09967c150a17337585d2d9d6cf0351b Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 26 Jan 2024 12:15:30 +0100 Subject: [PATCH 08/14] rootless fixes --- README.md | 61 +++++++++++++++++++++++++-------------------------- initialize.py | 2 +- p2p.py | 4 ++-- rebalancer.py | 10 ++++----- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index ace31eb2..b73f4649 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ services: lndg: build: . volumes: - - /home//.lnd:/root/.lnd:ro - - /home///lndg/data:/app/data:rw + - /home//.lnd:/lndg/.lnd:ro + - /home///lndg/data:/lndg/data:rw command: - sh - -c @@ -45,7 +45,7 @@ docker-compose up -d # Retrieve the admin password for login nano data/lndg-admin.txt ``` -- **This example configuration will host LNDg at http://0.0.0.0:8889. Use the machine IP to reach the LNDg instance.** +- **This example configuration will host LNDg at http://0.0.0.0:8889. Use the machine IP to reach the LNDg instance.** - **Log in to LNDg using the provided password and the username `lndg-admin`.** ### Updating @@ -121,7 +121,7 @@ To restart the uWSGI service, use the following command: ```bash sudo systemctl restart uwsgi.service -``` +``` ### Postgres Optionally, you may chose to run LNDg using a postgres database instead of the default sqlite3. @@ -173,7 +173,7 @@ LNDg will automatically act upon the suggestions it makes on the Suggests AR Act LNDg will listen for failure events in your htlc stream and record them to the dashboard when they occur. ### API Backend -The following data can be accessed at the /api endpoint: +The following data can be accessed at the /api endpoint: `payments` `paymenthops` `invoices` `forwards` `onchain` `peers` `channels` `rebalancer` `settings` `pendinghtlcs` `failedhtlcs` ### Peer Reconnection @@ -183,15 +183,15 @@ LNDg will automatically try to resolve any channels that are seen as inactive, n ### Here are some additional notes to help you get started using Auto-Fees (AF). LNDg can update your fees on a channel every 24 hours (default) if there is a suggestion listed on the fee rates page. You must make sure the `AF-Enabled` setting is set to `1` and that individual channels you want to be managed are also set to `enabled`. You can view a log of AF changes by opening the Autofees tab. -You can customize some settings of AF by updating the following settings: -`AF-FailedHTLCs` - The minimum daily failed HTLCs count in which we could trigger a fee increase (depending on flow) -`AF-Increment` - The increment size of our potential fee changes, all fee suggestions will be a multiple of this value -`AF-MaxRate` - The maximum fee rate in which we can adjust to -`AF-MinRate` - The minimum fee rate in which we can adjust to -`AF-Multiplier` - Multiplier to increase incremental movements, the larger the multiplier, the larger the incremental moves -`AF-UpdateHours` - Change the number of hours that must pass since the last fee rate change before AF may adjust the fee rate again -`AF-LowLiqLimit` - The liquidity (%) a channel must drop below before running the `Low Liquidity` fee algorithm -`AF-ExcessLimit` - The liquidity (%) a channel must go above before running the `Excess Liquidity` fee algorithm +You can customize some settings of AF by updating the following settings: +`AF-FailedHTLCs` - The minimum daily failed HTLCs count in which we could trigger a fee increase (depending on flow) +`AF-Increment` - The increment size of our potential fee changes, all fee suggestions will be a multiple of this value +`AF-MaxRate` - The maximum fee rate in which we can adjust to +`AF-MinRate` - The minimum fee rate in which we can adjust to +`AF-Multiplier` - Multiplier to increase incremental movements, the larger the multiplier, the larger the incremental moves +`AF-UpdateHours` - Change the number of hours that must pass since the last fee rate change before AF may adjust the fee rate again +`AF-LowLiqLimit` - The liquidity (%) a channel must drop below before running the `Low Liquidity` fee algorithm +`AF-ExcessLimit` - The liquidity (%) a channel must go above before running the `Excess Liquidity` fee algorithm AF Notes: 1. AF changes only trigger after `AF-UpdateHours` hours of no fee updates via LNDg @@ -225,20 +225,20 @@ Additional customization options: 6. `AR-Workers` - Define how many parallel rebalances to spin up at once. (default=1) #### Steps to start the Auto-Rebalancer: -1. Update Channel Specific Settings - a. Go to Active Channels section - b. Find the channels you would like to activate for rebalancing (this refills its outbound) - c. On far right column Click the Enable button to activate rebalancing - d. The dashboard will refresh and show AR-Target 100% - e. Adjust the AR-Target to desired % of liquidity you want to keep on remote INBOUND side. Example select 0.60 if you want 60% of the channel capacity on Remote/INBOUND side which would mean that there is 40% on Local/OUTBOUND side - f. Hit Enter - g. Dashboard will refresh in the browser - h. Make sure you enable all channels that are valuable outbound routes for you to ensure they are not used for filling up routes you have targeted (you can enable and target 100% in order to avoid any action on this channel from the rebalancer) - -2. Update Global Settings - a. Go to section Update Auto Rebalancer Settings - b. Select the global settings (sample below): - c. Click OK button to submit +1. Update Channel Specific Settings + a. Go to Active Channels section + b. Find the channels you would like to activate for rebalancing (this refills its outbound) + c. On far right column Click the Enable button to activate rebalancing + d. The dashboard will refresh and show AR-Target 100% + e. Adjust the AR-Target to desired % of liquidity you want to keep on remote INBOUND side. Example select 0.60 if you want 60% of the channel capacity on Remote/INBOUND side which would mean that there is 40% on Local/OUTBOUND side + f. Hit Enter + g. Dashboard will refresh in the browser + h. Make sure you enable all channels that are valuable outbound routes for you to ensure they are not used for filling up routes you have targeted (you can enable and target 100% in order to avoid any action on this channel from the rebalancer) + +2. Update Global Settings + a. Go to section Update Auto Rebalancer Settings + b. Select the global settings (sample below): + c. Click OK button to submit d. Once enabled is set to 1 in the global settings - the rebalancer will become active ``` Enabled: 1 @@ -248,9 +248,9 @@ Additional customization options: Global Max Fee Rate (ppm): 500 Max Cost (%): 0.6 ``` -3. Go to section Last 10 Rebalance Requests - that will show the list of the rebalancing queue and status. +3. Go to section Last 10 Rebalance Requests - that will show the list of the rebalancing queue and status. -If you want a channel not to be picked for rebalancing (i.e. it is already full with OUTBOUND capacity that you desire), enable the channel and set the AR-Target% to 100. The rebalancer will ignore the channel while selecting the channels for outbound candidates and since its INBOUND can never be above 100% it will never trigger a rebalance. +If you want a channel not to be picked for rebalancing (i.e. it is already full with OUTBOUND capacity that you desire), enable the channel and set the AR-Target% to 100. The rebalancer will ignore the channel while selecting the channels for outbound candidates and since its INBOUND can never be above 100% it will never trigger a rebalance. ## Preview Screens ### Main Dashboard @@ -283,4 +283,3 @@ If you want a channel not to be picked for rebalancing (i.e. it is already full ### View Keysend Messages (you can only receive these if you have `accept-keysend=true` in lnd.conf) ![image](https://user-images.githubusercontent.com/38626122/134045287-086d56e3-5959-4f5f-a06e-cb6d2ac4957c.png) - diff --git a/initialize.py b/initialize.py index 4fe16406..e1bbe384 100644 --- a/initialize.py +++ b/initialize.py @@ -290,7 +290,7 @@ def main(): parser.add_argument('-rpc', '--rpcserver', help = 'Server address to use for rpc communications with LND', default='localhost:10009') parser.add_argument('-maxmsg', '--maxmessage', help = 'Maximum message size for grpc communications (MB)', default='35') parser.add_argument('-sd', '--supervisord', help = 'Setup supervisord to run jobs/rebalancer background processes', action='store_true') - parser.add_argument('-sdu', '--sduser', help = 'Configure supervisord with a non-root user', default='root') + parser.add_argument('-sdu', '--sduser', help = 'Configure supervisord with a non-root user', default='lndg') parser.add_argument('-wn', '--whitenoise', help = 'Add whitenoise middleware (docker requirement for static files)', action='store_true') parser.add_argument('-d', '--docker', help = 'Single option for docker container setup (supervisord + whitenoise)', action='store_true') parser.add_argument('-dx', '--debug', help = 'Setup the django site in debug mode', action='store_true') diff --git a/p2p.py b/p2p.py index e09abe5e..69139305 100644 --- a/p2p.py +++ b/p2p.py @@ -43,8 +43,8 @@ def main(): finally: if 'p2p_thread' in locals() and p2p_thread.is_alive(): print(f"{datetime.now().strftime('%c')} : [P2P] : Removing any remaining processes...") - p2p_thread.terminate() + p2p_thread.terminate() sleep(20) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/rebalancer.py b/rebalancer.py index b7be43cb..e153aa4e 100644 --- a/rebalancer.py +++ b/rebalancer.py @@ -203,11 +203,11 @@ def auto_schedule() -> List[Rebalancer]: enabled = 0 if enabled == 0: return [] - + auto_rebalance_channels = Channels.objects.filter(is_active=True, is_open=True, private=False).annotate(percent_outbound=((Sum('local_balance')+Sum('pending_outbound'))*100)/Sum('capacity')).annotate(inbound_can=(((Sum('remote_balance')+Sum('pending_inbound'))*100)/Sum('capacity'))/Sum('ar_in_target')) if len(auto_rebalance_channels) == 0: return [] - + if not LocalSettings.objects.filter(key='AR-Outbound%').exists(): LocalSettings(key='AR-Outbound%', value='75').save() if not LocalSettings.objects.filter(key='AR-Inbound%').exists(): @@ -217,7 +217,7 @@ def auto_schedule() -> List[Rebalancer]: inbound_cans = auto_rebalance_channels.filter(auto_rebalance=True, inbound_can__gte=1).exclude(remote_pubkey__in=already_scheduled).order_by('-inbound_can') if len(inbound_cans) == 0 or len(outbound_cans) == 0: return [] - + if LocalSettings.objects.filter(key='AR-MaxFeeRate').exists(): max_fee_rate = int(LocalSettings.objects.filter(key='AR-MaxFeeRate')[0].value) else: @@ -244,7 +244,7 @@ def auto_schedule() -> List[Rebalancer]: target_fee = round(target_fee_rate*target_value*0.000001, 3) if target_fee_rate <= max_fee_rate else round(max_fee_rate*target_value*0.000001, 3) if target_fee == 0: continue - + if LocalSettings.objects.filter(key='AR-Time').exists(): target_time = int(LocalSettings.objects.filter(key='AR-Time')[0].value) else: @@ -354,7 +354,7 @@ async def async_queue_manager(rebalancer_queue): scheduled_rebalances.append(rebalance.id) await rebalancer_queue.put(rebalance) elif rebalancer_queue.qsize() == 0 and len(active_rebalances) == 0: - print(f"{datetime.now().strftime('%c')} : [Rebalancer] : Queue is still empty, stoping the rebalancer...") + print(f"{datetime.now().strftime('%c')} : [Rebalancer] : Queue is still empty, stopping the rebalancer...") shutdown_rebalancer = True return await asyncio.sleep(30) From da3a56f05f70e6f241aec935908865abb3cff7a1 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Thu, 25 Jan 2024 12:38:25 +0100 Subject: [PATCH 09/14] Remove old Dockerfile --- Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..6f6f47d6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3-alpine +ENV PYTHONUNBUFFERED 1 + +RUN apk add g++ linux-headers +COPY . /app/ +WORKDIR /app + +RUN pip install -r requirements.txt +RUN pip install supervisor whitenoise From 4eb196395f4531c35d547523e5d2892b3aaff809 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Tue, 19 Nov 2024 10:36:07 +0100 Subject: [PATCH 10/14] Fixes to follow the latest 1.9.0 --- container/Dockerfile | 2 +- justfile | 8 ++++++-- scripts/init.sh | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/container/Dockerfile b/container/Dockerfile index 0f46a1b8..cae8d9b9 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -26,6 +26,6 @@ EXPOSE $LNDG_PORT VOLUME [ "/lnd", "/lndg/data" ] -USER lndg +USER 1000 ENTRYPOINT [ "scripts/entrypoint.sh" ] diff --git a/justfile b/justfile index 27580966..e6bf1105 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,10 @@ +IMAGE := "gitea.k8s.chevdor.cc/chevdor/lndg" + build_image: - docker build -t chevdor/lndg -f container/Dockerfile . + #!/usr/bin/env bash + + docker build -t {{IMAGE}} --build-arg SUPERVISOR=0 -f container/Dockerfile . docker images | grep lndg push_image: - docker push chevdor/lndg + docker push {{IMAGE}} diff --git a/scripts/init.sh b/scripts/init.sh index 4bd6358e..b4052f87 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -12,7 +12,7 @@ if [ "$LNDG_SUPERVISOR" -eq "1" ]; then echo "Initializing with supervisor running as lndg user" python initialize.py \ -net $LNDG_NETWORK \ - -server $LNDG_SERVER \ + -rpc $LNDG_SERVER \ --docker \ --supervisord \ --sduser lndg @@ -20,6 +20,6 @@ else echo "Initializing without supervisor" python initialize.py \ -net $LNDG_NETWORK \ - -server $LNDG_SERVER \ + -rpc $LNDG_SERVER \ --docker fi From 62e50e2e794eab3ab27d27c0e1eef32259dcb6ac Mon Sep 17 00:00:00 2001 From: Chevdor Date: Tue, 19 Nov 2024 10:59:08 +0100 Subject: [PATCH 11/14] Fix justfile to extract version and let user configure image --- .env-example | 1 + .gitignore | 10 ++++++++++ Dockerfile | 9 --------- justfile | 21 +++++++++++++++++---- 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 .env-example delete mode 100644 Dockerfile diff --git a/.env-example b/.env-example new file mode 100644 index 00000000..58b74d5a --- /dev/null +++ b/.env-example @@ -0,0 +1 @@ +IMAGE=you/lndg diff --git a/.gitignore b/.gitignore index 9e8eb962..5acb1658 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.env* +!.env-example __pycache__ db.sqlite3 lndg/settings.py @@ -10,3 +12,11 @@ gui/static/admin gui/static/rest_framework data/ .DS_Store +container +doc +scripts +.github +.git +!scripts/entrypoint.sh +!scripts/init.sh +!scripts/suinit.sh diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 6f6f47d6..00000000 --- a/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM python:3-alpine -ENV PYTHONUNBUFFERED 1 - -RUN apk add g++ linux-headers -COPY . /app/ -WORKDIR /app - -RUN pip install -r requirements.txt -RUN pip install supervisor whitenoise diff --git a/justfile b/justfile index e6bf1105..da7ace7b 100644 --- a/justfile +++ b/justfile @@ -1,10 +1,23 @@ -IMAGE := "gitea.k8s.chevdor.cc/chevdor/lndg" - build_image: #!/usr/bin/env bash + IMAGE=${IMAGE:-cryptosharks131/lndg} + + # Hacky but the version does not seem to be extracted elsewhere... + VERSION=$(cat gui/templates/base.html | sed -nE 's/.*LNDg v([0-9]+\.[0-9]+\.[0-9]+).*/\1/p') + echo "Building image $IMAGE:$VERSION" - docker build -t {{IMAGE}} --build-arg SUPERVISOR=0 -f container/Dockerfile . + docker build \ + -t $IMAGE:$VERSION \ + -t $IMAGE:latest \ + --build-arg SUPERVISOR=0 \ + -f container/Dockerfile \ + . docker images | grep lndg push_image: - docker push {{IMAGE}} + #!/usr/bin/env bash + IMAGE=${IMAGE:-cryptosharks131/lndg} + # Hacky but the version does not seem to be extracted elsewhere... + VERSION=$(cat gui/templates/base.html | sed -nE 's/.*LNDg v([0-9]+\.[0-9]+\.[0-9]+).*/\1/p') + docker push $IMAGE:latest + docker push $IMAGE:$VERSION From 633c4b2ac73e0677e0f54ad3afb4d0a275ee6dbc Mon Sep 17 00:00:00 2001 From: Chevdor Date: Tue, 19 Nov 2024 11:32:06 +0100 Subject: [PATCH 12/14] Switch default to no supervisor --- container/Dockerfile | 2 +- scripts/entrypoint.sh | 2 +- scripts/init.sh | 2 +- scripts/suinit.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/container/Dockerfile b/container/Dockerfile index cae8d9b9..266b8fba 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -1,7 +1,7 @@ FROM python:3-slim ARG LNDG_PORT=8000 -ARG SUPERVISOR=1 +ARG SUPERVISOR=0 ENV PYTHONUNBUFFERED 1 # Add group abnd user to run rootless diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index c03b9ea1..32f26feb 100755 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-0} LNDG_LISTEN=${LNDG_LISTEN:-0.0.0.0} LNDG_PORT=${LNDG_PORT:-8000} diff --git a/scripts/init.sh b/scripts/init.sh index b4052f87..85f70582 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -2,7 +2,7 @@ # This init script runs when the container start, as rootless -LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-0} LNDG_NETWORK=${LNDG_NETWORK:-mainnet} LNDG_SERVER=${LNDG_SERVER:-localhost:10009} diff --git a/scripts/suinit.sh b/scripts/suinit.sh index 29ce0d41..f8154349 100755 --- a/scripts/suinit.sh +++ b/scripts/suinit.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-0} # This init script runs when the image is created, as root touch /var/log/supervisord.log From a25fc25dedd01578ad910ada7bd96eb0cf8af225 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Tue, 19 Nov 2024 12:06:52 +0100 Subject: [PATCH 13/14] Bring back LNDG_SUPERVISOR=1 as default --- container/Dockerfile | 2 +- initialize.py | 4 ++-- scripts/entrypoint.sh | 2 +- scripts/init.sh | 2 +- scripts/suinit.sh | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/container/Dockerfile b/container/Dockerfile index 266b8fba..cae8d9b9 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -1,7 +1,7 @@ FROM python:3-slim ARG LNDG_PORT=8000 -ARG SUPERVISOR=0 +ARG SUPERVISOR=1 ENV PYTHONUNBUFFERED 1 # Add group abnd user to run rootless diff --git a/initialize.py b/initialize.py index e1bbe384..b57f8a7f 100644 --- a/initialize.py +++ b/initialize.py @@ -218,11 +218,11 @@ def write_supervisord_settings(sduser): stdout_logfile_maxbytes = 150MB stdout_logfile_backups = 15 ''' % (sduser, supervisord_secret, supervisord_secret, BASE_DIR) - if Path("/usr/local/supervisord.conf").exists(): + if Path("supervisord.conf").exists(): print('A supervisord settings file already exist, skipping creation...') return try: - with open("/usr/local/supervisord.conf", "w") as f: + with open("supervisord.conf", "w") as f: f.write(supervisord_settings_file) except Exception as e: print('Error creating the settings file: ', str(e)) diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index 32f26feb..c03b9ea1 100755 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-0} +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} LNDG_LISTEN=${LNDG_LISTEN:-0.0.0.0} LNDG_PORT=${LNDG_PORT:-8000} diff --git a/scripts/init.sh b/scripts/init.sh index 85f70582..b4052f87 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -2,7 +2,7 @@ # This init script runs when the container start, as rootless -LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-0} +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} LNDG_NETWORK=${LNDG_NETWORK:-mainnet} LNDG_SERVER=${LNDG_SERVER:-localhost:10009} diff --git a/scripts/suinit.sh b/scripts/suinit.sh index f8154349..29ce0d41 100755 --- a/scripts/suinit.sh +++ b/scripts/suinit.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-0} +LNDG_SUPERVISOR=${LNDG_SUPERVISOR:-1} # This init script runs when the image is created, as root touch /var/log/supervisord.log From bc87e0084ef1ac8f658b1a19a09518c72884975b Mon Sep 17 00:00:00 2001 From: Chevdor Date: Wed, 20 Nov 2024 12:55:35 +0100 Subject: [PATCH 14/14] Add supervisor by default --- justfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/justfile b/justfile index da7ace7b..c096200a 100644 --- a/justfile +++ b/justfile @@ -7,9 +7,10 @@ build_image: echo "Building image $IMAGE:$VERSION" docker build \ + --progress=plain \ -t $IMAGE:$VERSION \ -t $IMAGE:latest \ - --build-arg SUPERVISOR=0 \ + --build-arg SUPERVISOR=1 \ -f container/Dockerfile \ . docker images | grep lndg