GithubHelp home page GithubHelp logo

accumulator / charge-lnd Goto Github PK

View Code? Open in Web Editor NEW
223.0 16.0 42.0 228 KB

charge-lnd is a simple policy based fee manager for LND. With this tool you can set fees to autobalance, recover channel open costs, use on-chain fees as reference, use channel activity to determine fees or just use static fees.

License: GNU General Public License v2.0

Python 99.41% Dockerfile 0.33% Shell 0.26%
bitcoin lightning-network

charge-lnd's Introduction

charge-lnd

This script matches your open Lightning channels against a number of customizable criteria and applies channel fees based on the matching policy.

Installation

See INSTALL.md

Usage

charge-lnd takes only a minimal set of parameters:

usage: charge-lnd [-h] [--lnddir LNDDIR] [--grpc GRPC] [--electrum-server ELECTRUM_SERVER]
                  [--dry-run] [--check] [-v] -c CONFIG

optional arguments:
  -h, --help            show this help message and exit
  --lnddir LNDDIR       (default ~/.lnd) lnd directory
  --tlscert TLS_CERT_PATH
                        (default [lnddir]/tls.cert) path to lnd TLS certificate
  --macaroon MACAROON_PATH
                        (default [lnddir]/data/chain/bitcoin/mainnet/charge-lnd.macaroon) path to lnd auth macaroons
  --grpc GRPC           (default localhost:10009) lnd gRPC endpoint
  --electrum-server ELECTRUM_SERVER
                        (optional, no default) electrum server host:port . Needed for
                        onchain_fee.
  --dry-run             Do not perform actions (for testing), print what we would do to
                        stdout
  --check               Do not perform actions, only check config file for valid syntax
  -v, --verbose         Be more verbose
  -c CONFIG, --config CONFIG
                        path to config file

All policies are defined using an INI style config file.

Each [policy-name] defined in the config file describes a policy. A single policy consists of;

  • a set of criteria to match against the channel and/or node (e.g. minimum channel capacity)
  • a fee strategy (how to calculate the new channel fees)

The defined criteria are compared against the open channels and their associated nodes. The fee strategy then executed to determine what the new channel fees should be.

There is a special [default] section, that will be used if none of the policies match a channel. The [default] section only contains a strategy, not any matching criteria.

All policies are evaluated top to bottom. The first matching policy is applied (except for the default policy).

A simple example:

[example-policy]
chan.min_capacity = 500000

strategy = static
base_fee_msat = 1000
fee_ppm = 10

This policy matches the channels against the chan.min_capacity criterium. Only channels with at least 500000 sats total capacity will match.

If a channel matches this policy, the static strategy is then used, which takes the base_fee_msat and fee_ppm properties defined in the policy and applies them to the channel.

Non-final policies

You can also define a 'non-final' policy. This is simply a policy without a strategy. It allows you to set default values for properties used by later policies, e.g. base_fee_msat, fee_ppm, min_fee_ppm_delta etc.

Processing continues after matching a non-final policy.

Example:

[mydefaults]
chan.max_capacity = 5_000_000
min_fee_ppm_delta = 10
base_fee_msat = 2000

[someotherpolicy]
chan.min_capacity = 500_000
strategy = static
fee_ppm = 50

This will, for channels that match mydefaults and after that someotherpolicy, set fees to 2 sat base fee and 50 ppm, and uses a minimum fee delta of 10 when applying a fee change for that channel.

More examples

Maintain a friends list with lower fees:

[friends]
node.id = file:///home/lnd/friends.list
strategy = static
base_fee_msat = 10
fee_ppm = 10

Use routing fees to nudge channel balances toward 50/50 channel ratios:

[discourage-routing-out-of-balance]
chan.max_ratio = 0.1
chan.min_capacity = 250000
strategy = static
base_fee_msat = 10000
fee_ppm = 500

[encourage-routing-to-balance]
chan.min_ratio = 0.9
chan.min_capacity = 250000
strategy = static
base_fee_msat = 1
fee_ppm = 2

More elaborate examples can be found in the examples folder.

Properties

Currently available properties:

Property Description Values
chan.id match on channel IDs - comma separated list of channel IDs and/or file references <channel ID|file url>[, <channel ID|file url>..]
chan.initiator match on initiator status, true if we are initiator true|false
chan.private match on channel private flag true|false
chan.min_capacity match on channel capacity # of sats
chan.max_capacity match on channel capacity # of sats
chan.min_age match on channel age # of blocks
chan.max_age match on channel age # of blocks
BALANCE
chan.max_ratio match on channel ratio 0..1
chan.min_ratio match on channel ratio 0..1
chan.min_local_balance match on channel local balance # of sats
chan.max_local_balance match on channel local balance # of sats
chan.min_remote_balance match on channel remote balance # of sats
chan.max_remote_balance match on channel remote balance # of sats
PEER
chan.min_base_fee_msat match on channel peer policy # of msats
chan.max_base_fee_msat match on channel peer policy # of msats
chan.min_fee_ppm match on channel peer policy 0..1000000 (parts per million)
chan.max_fee_ppm match on channel peer policy 0..1000000 (parts per million)
chan.disabled match on channel disabled by peer true|false
ACTIVITY
chan.activity_period define a time period for forwards #s seconds or #m minutes or #h hours or #d days
chan.activity_period_ignore_channel_age match on channel age less than activity_period true|false
chan.min_htlcs_in match on minimal amount of HTLCs arriving in channel during activity period # of htlcs
chan.max_htlcs_in match on maximum amount of HTLCs arriving in channel during activity period # of htlcs
chan.min_htlcs_out match on minimal amount of HTLCs departing from channel during activity period # of htlcs
chan.max_htlcs_out match on maximum amount of HTLCs departing from channel during activity period # of htlcs
chan.min_sats_in match on minimal amount of sats arriving in channel during activity period # of sats
chan.max_sats_in match on maximum amount of sats arriving in channel during activity period # of sats
chan.min_sats_out match on minimal amount of sats departing from channel during activity period # of sats
chan.max_sats_out match on maximum amount of sats departing from channel during activity period # of sats
chan.min_htlcs_ratio match on amount of HTLCs ratio arriving in channel during activity period 0..1
chan.max_htlcs_ratio match on amount of HTLCs ratio arriving in channel during activity period 0..1
chan.min_sats_ratio match on amount of sats ratio arriving in channel during activity period 0..1
chan.max_sats_ratio match on amount of sats ratio arriving in channel during activity period 0..1
NODE
node.id match on node pubkeys - comma separated list of node pubkeys and/or file references <node pubkey|file url>[, <node pubkey|file url>..]
node.min_channels match on number of channels the peer node has # of channels
node.max_channels match on number of channels the peer node has # of channels
node.min_shared_channels_active match on number of active channels the peer node has with us # of channels
node.max_shared_channels_active match on number of active channels the peer node has with us # of channels
node.min_shared_channels_inactive match on number of inactive channels the peer node has with us # of channels
node.max_shared_channels_inactive match on number of inactive channels the peer node has with us # of channels
node.min_capacity match on node total capacity # of sats
node.max_capacity match on node total capacity # of sats
node.min_shared_capacity_active match on node active shared capacity with us # of sats
node.max_shared_capacity_active match on node active shared capacity with us # of sats
node.min_shared_capacity_inactive match on node inactive shared capacity with us # of sats
node.max_shared_capacity_inactive match on node inactive shared capacity with us # of sats
node.max_shared_ratio match on channels ratio with us 0..1
node.min_shared_ratio match on channels ratio with us 0..1
node.max_shared_ratio_active match on active channels ratio with us 0..1
node.min_shared_ratio_active match on active channels ratio with us 0..1
node.max_shared_ratio_inactive match on inactive channels ratio with us 0..1
node.min_shared_ratio_inactive match on inactive channels ratio with us 0..1

File references should contain 1 item per line

Strategies

Available strategies:

Strategy Description Parameters
ignore ignores the channel completely
ignore_fees don't make any fee changes, only update htlc size limits and time_lock_delta
static sets fixed base fee and fee rate values. fee_ppm
match_peer sets the same base fee and fee rate values as the peer if base_fee_msat or fee_ppm are set the override the peer values
cost calculate cost for opening channel, and set ppm to cover cost when channel depletes. cost_factor
onchain_fee sets the fees to a % equivalent of a standard onchain payment (Requires --electrum-server to be specified.) onchain_fee_btc BTC
within onchain_fee_numblocks blocks.
proportional sets fee ppm according to balancedness. min_fee_ppm
max_fee_ppm
sum_peer_chans consider all channels with peer for balance calculations
disable disables the channel in the outgoing direction. Channel will be re-enabled again if it matches another policy (except when that policy uses an 'ignore' strategy).
use_config process channel according to rules defined in another config file. config_file

All strategies (except the ignore strategy) will apply the following properties if defined:

Property Description Values
base_fee_msat Base fee # msat
min_htlc_msat Minimum size (in msat) of HTLC to allow # msat
max_htlc_msat Maximum size (in msat) of HTLC to allow # msat
max_htlc_msat_ratio Maximum size of HTLC to allow as a fraction of total channel capacity 0..1
time_lock_delta Time Lock Delta # blocks
min_fee_ppm_delta Minimum change in fees (ppm) before updating channel ppm delta

Contributing

Contributions are highly welcome! Feel free to submit issues and pull requests. See development guide for help getting started.

Please also consider opening a channel with my node, or sending tips via keysend:

0266ad254117f16f16c3457e081e6207e91c5e414477a208cf4d9c633322799038@lightning.channels.zijn.cool:9735

charge-lnd's People

Contributors

aaronhayes avatar abellykens avatar accumulator avatar bhaagbosedk avatar bhoovd avatar dependabot[bot] avatar dmp1ce avatar glencooper avatar ibz avatar jorijn avatar jvrakor avatar keblek avatar mariaa144 avatar martinatime avatar microlancer avatar mmilata avatar ogunden avatar scissorstail avatar vilm3r avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

charge-lnd's Issues

Discount idle channels

Based on the assumption that a channel is not used because it is too expensive, it might help to reduce the fees for that channel. It'd be great to have this as a policy (possibly in addition to other policies?).

Channel X has fee rate 1000, but hasn't been used in 4 days. Reduce fee to 1000 - 0.9 * 4/30 (up to 90% discount for 30 days without forwardings).

I'm not sure if this should count consecutive days without forwardings, or just fractions (x out of the last y days).

Umbrel & docker documentation outdated

Since the upgrade to v0.2.9, the commands specified in https://github.com/accumulator/charge-lnd/blob/master/INSTALL.md#umbrel are no longer correct. What used to work in v0.2.8 no longer works in v0.2.9:

umbrel@umbrel:~ $ docker run --rm --network=umbrel_main_network -e GRPC_LOCATION=<IP> -e LND_DIR=/data/.lnd -e CONFIG_LOCATION=/app/charge.config -v /home/umbrel/umbrel/lnd:/data/.lnd -v /mnt/data/upgrades/charge-lnd:/app accumulator/charge-lnd:v0.2.9
usage: charge-lnd [-h] [--lnddir LNDDIR] [--tlscert TLS_CERT_PATH]
                  [--macaroon MACAROON_PATH] [--grpc GRPC]
                  [--electrum-server ELECTRUM_SERVER] [--dry-run] [--check]
                  [-v] -c CONFIG
charge-lnd: error: the following arguments are required: -c/--config

Issue installing on docker (Umbrel)

Hey all..
STILL working on getting this going on Umbrel (it's been a long journey)

I have the charge-lnd.config file at ~/umbrel/apps/charge-lnd/charge-lnd.config

Here's the command I'm running:

docker run --rm -it --network=umbrel_main_network \
  -e GRPC_LOCATION=lnd:10009 \
  -e LND_DIR=/data/.lnd \
  -e CONFIG_LOCATION=/app/charge.config \
  -v /home/umbrel/umbrel/lnd:/data/.lnd \
  -v /home/umbrel/umbrel/apps/charge-lnd/charge.config:/app/charge.config \
   accumulator/charge-lnd:latest

Here's the error I'm getting:

  File "/usr/local/bin/charge-lnd", line 5, in <module>
    from charge_lnd.charge_lnd import main
  File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 143, in <module>
    success = main()
  File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 39, in main
    lnd = Lnd(arguments.lnddir, arguments.grpc)
  File "/usr/local/lib/python3.9/site-packages/charge_lnd/lnd.py", line 33, in __init__
    self.feereport = self.get_feereport()
  File "/usr/local/lib/python3.9/site-packages/charge_lnd/lnd.py", line 53, in get_feereport
    feereport = self.stub.FeeReport(ln.FeeReportRequest())
  File "/usr/local/lib/python3.9/site-packages/grpc/_channel.py", line 946, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/usr/local/lib/python3.9/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
	status = StatusCode.UNAVAILABLE
	details = "failed to connect to all addresses"
	debug_error_string = "{"created":"@1627373607.142962053","description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":5420,"referenced_errors":[{"created":"@1627373607.142946924","description":"failed to connect to all addresses","file":"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc","file_line":398,"grpc_status":14}]}"
>```

I'm a beginner at this stuff, so I hope someone can help me see where I've gone wrong. 

Add toggle to prevent free zero base fee routing

To prevent free zero base fee routing, I manually edit my min_htlc_msat to minimally receive 1 msat.

I have tried to implement this in the proportional routing, but have not succeeded yet.

Is it possible to add a toggle property, for example min_htlc_msat_zerobase = true
to adjust the min_htlc_msat accordingly with proportional strategies?

An example of what I had in mind:

min_htlc_msat_zerobasefee=(
if fee_rate is 0: min_htlc_msat
elseif fee_rate is >1000000: 1
elseif min_htlc_msat is 0: (1000*(1000/fee_rate))
else: min_htlc_msat

AttributeError: 'str' object has no attribute 'lnd_dir'

Looking for help with charge-lnd

Just installed and getting this when trying to do anything with it:

bitcoin@raspberrypi:~ $ cd charge-lnd
bitcoin@raspberrypi:/charge-lnd $ charge-lnd -c charge.config --dry-run
Traceback (most recent call last):
File "/home/bitcoin/.local/bin/charge-lnd", line 5, in
from charge_lnd.charge_lnd import main
File "/home/bitcoin/.local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 165, in
success = main()
File "/home/bitcoin/.local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 39, in main
lnd = Lnd(arguments.lnddir)
File "/home/bitcoin/.local/lib/python3.9/site-packages/charge_lnd/lnd.py", line 23, in init
lnd_dir = expanduser(args.lnd_dir)
AttributeError: 'str' object has no attribute 'lnd_dir'
bitcoin@raspberrypi:
/charge-lnd $

Big newbie pleb here, so be easy on me. ;)

Thanks!

Feature Request: Continue Processing Strategy

I'm not certain if this is possible so I'm just throwing this out there.
Currently there is an ignore strategy where if the criteria match the channel is exempted from the other blocks. But what if there was another strategy such that if the criteria matches then only will the other blocks be considered.
Here is a simple example but maybe I'm missing some nuances:
I have a config where there is an ignore block for excluding my "friend" nodes.
I have a second config only for my "friend" nodes.
In order to deal with the second case I would have to add the channel/node matching to each block in the second file as opposed to a single block at the top of the config that would exclude everyone that was not in my friends list.

Error

Whenever I tried to run charge-ldn container, I receive this error:
Traceback (most recent call last):
File "/usr/local/bin/charge-lnd", line 5, in
from charge_lnd.charge_lnd import main
File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 146, in
success = main()
File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 30, in main
config = Config(arguments.config)
File "/usr/local/lib/python3.9/site-packages/charge_lnd/config.py", line 18, in init
with open(config_file, "r") as f:
IsADirectoryError: [Errno 21] Is a directory: '/app/charge.config'

Support for UpdateChanStatus

It would be great to have support for updatechanstatus

so to stop routing status can be set to Disable
to allow routing the status can be set to Enable.

This can be used with liquidity setting for example max.chan_ratio = 0.1, disbale channel.

Most people today use workaround to raise fees instead which has other issues.

Support for Chan.Min_Out_Amt, Max_Out_Amt, Min_In_Amt, Max_In_Amt

In addition to support for chan.max_ration/chan.min_ratio spport can be provided for absolute amount.

I would like to stop routing based on absolute amount below a certain liquidity level say 500_000_000 mSat because that is the average size through my node. However today I can only do it based on ratio < 0.1 which can be different for different channel size.

Multiple Channels with same peer are treated separately

If you have multiple channels with the same peer, they are treated separately. However lnd protocol treats multiple channels as one for routing purposes and therefore uses the highest fees for any of the multiple channel.

Therefore you may end up in a situation where CH1 is 100% local and has fee setup to encourage routing and CH2 is 100% remote and has fees setup to discourage routing, both CH1 and CH2 end up with discourage routing because network graph would show high fees (for discourage routing) is applied.

Solution - treat the local + remote for all channels with same peer together and apply the same fees for all channels with same peer.

Remote Node

Doesn't work as is on remote node (Voltage)? Is it possible to add flags for remote node? ex: --macaroon-path "" --tlscert-path "" --socket "". Looks like macaroon and cert path are relying on local running instance of LND.

chan.activity_period not working as expected

Have the following policy:

[idle-channel-2d]
chan.activity_period = 2d
chan.max_htlcs_out = 0
strategy = static
base_fee_msat = 0
fee_ppm = 350

Still the channel that had outgoing liquidity just 3 hours ago changed the fee based on this policy

Raspi 4.0 32-bit

Match on equal channel count

Looking for a way to match on equivalent number of channels. Basically, a channel to a node that cannot route. For example, I have 2 channels to node A, and A only has 2 channels. Use case is large deployments with root/leaf node structure.

Feature Request: MyNode Guide

it's great that you have both Raspiblitz and Umbrel guides but there area also many interested MyNode users that would love to use charge-lnd but are intimidated by the process.

Install process

I'm on a raspi4 and get the following msg after $ pip install -r requirements.txt .

ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
lndmanage 0.11.0 requires googleapis-common-protos==1.52.0, but you have googleapis-common-protos 1.53.0 which is incompatible.
lndmanage 0.11.0 requires grpcio==1.31.0, but you have grpcio 1.37.0 which is incompatible.
lndmanage 0.11.0 requires protobuf==3.12.4, but you have protobuf 3.15.8 which is incompatible.
Successfully installed aiorpcx-0.18.7 charge-lnd-0.1.0 colorama-0.4.4 googleapis-common-protos-1.53.0 grpcio-1.37.0 protobuf-3.15.8 termcolor-1.1.0
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv

Program seems to be working as expected. Should I try to remedy the above anyway?

disabling and enabling channels

With lnd 0.13 it is possible to disable channels
lncli updatechanstatus --funding_txid 123 --output_index 0 --action disable

It would be helpfull if one can disable and enable a channel then with charge-lnd too, e.g. when the outbound amount is very low. At the moment I raise fees in that case. But it has the sideeffect that the average fee of the node on amboss is raising too.

Feature Request: A simple GUI + Umbrel App on the Umbrel App Store!

Hey! I'm drooling over this awesome work, and really would love to see it added to Umbrel! Most Umbrel users are not SUPER technical, and even if they are, every upgrade would wipe out changes unless it was built into an Umbrel app via docker.

I'd love to see someone adapt this to Umbrel, so the many thousands of node operators running Umbrel OS could enjoy it!

match_peer strategy does not make the base_fee

One of my peer MasterYoda has base_fee 199 sat and base_fee_rate 0
I have created special section to match the peer
However the strategy always reduced the base_fee to 0 instead of matching to 199 (and even if I manually reset to 199 in the next run it is replaced by 0).

The configuration file is

[9-static]
#Match to channels which keep high static fees
#MasterYoda

node.id = 033dee9c6a0afc40ffd8f27d68ef260f3e5e1c19e59c6f9bb607fb04c1d497a809

strategy = match_peer

To correct this for now I changed to

[9-static]
#Match to channels which keep high static fees
#MasterYoda

node.id = 033dee9c6a0afc40ffd8f27d68ef260f3e5e1c19e59c6f9bb607fb04c1d497a809

strategy = match_peer
base_fee_msat = 199_000

But this would not be good if the peer base fee changes in future (because I will remain at 199).

Error after installing new version

Last version was running fine. When doing a dryrun following error appears:

Traceback (most recent call last):
File "/usr/local/bin/charge-lnd", line 6, in
from charge_lnd.charge_lnd import main
File "/usr/local/lib/python3.7/dist-packages/charge_lnd/charge_lnd.py", line 141, in
success = main()
File "/usr/local/lib/python3.7/dist-packages/charge_lnd/charge_lnd.py", line 51, in main
(new_base_fee_msat, new_fee_ppm, new_min_htlc, new_max_htlc, new_time_lock_delta) = policy.strategy.execute(channel)
AttributeError: 'NoneType' object has no attribute 'execute'

missing __init__.py

Hi, I think you need to put an empty init.py into the grpc_generated directory

at least that's what I needed for my install

docker sample config

I (and a lot of others I imagine) would like to run charge-lnd in docker. However since I'm no docker expert and don't know how the docker image is set up i would like a sample config for running the container and a sample config for compose, so i can set up a config file and have the built in systemd service or cronjob or whatever inside the container take care of the rest.

Error on my Umbrel node

I worked through jonathanalevi's guide (https://yalls.org/articles/97d67df1-d721-417d-a6c0-11d793739be9:0965AC5E-56CD-4870-9041-E69616660E6F/0d395aab-d85d-4039-a5cc-682950e89a9d) for my own Umbrel node, and I got it to work (although, I don't know that the crontab job was every repeating the command every hour, I suspect not). Now, though, I am getting the following error upon running the docker:

Here is the command:
docker run --rm -it --network=umbrel_main_network
-e GRPC_LOCATION=LND.IP.ADDRESS.GOES.HERE:10009
-e LND_DIR=/data/.lnd
-e CONFIG_LOCATION=/app/charge.config
-v /home/umbrel/umbrel/lnd:/data/.lnd
-v /home/umbrel/umbrel/apps/charge-lnd/charge.config:/app/charge.config
accumulator/charge-lnd:latest

Here is the output
Traceback (most recent call last):
File "/usr/local/bin/charge-lnd", line 5, in
from charge_lnd.charge_lnd import main
File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 146, in
success = main()
File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 30, in main
config = Config(arguments.config)
File "/usr/local/lib/python3.9/site-packages/charge_lnd/config.py", line 18, in init
with open(config_file, "r") as f:
IsADirectoryError: [Errno 21] Is a directory: '/app/charge.config'

Seems to not find the /app/charg.config. I'm not a developer... how do I fix this?

Disable -> Enable should be shown in output

Whenever a value changes charge lnd shows it in the output
for example if fee is changed from 300 to 250 it is shown as 300->250

when is channel is disabled as part of disable policy, it is shown as disabled.

but when it is renabeld it is not shown.

May be it can be shown as
enabled -> disabled
disabled -> enabled
on the respective state change.


696####x###0x0 [####|########]  
 policy:          default                                                                   
 strategy:        proportional                                                              
 base_fee_msat:   0                                                                         
 fee_ppm:         304                                                                       
 min_htlc_msat:   1000                                                                      
 max_htlc_msat:   1980000000                                                                
 time_lock_delta: 20                           
 disable -> enable                                             

Bug In Code? I don't know what else to title this

I just installed this and ran the following

$charge-lnd --dry-run -c charge.config.example
<REDACTED CHANNEL INFO>
  policy:          proportional
  strategy:        proportional
  base_fee_msat:   1000
Traceback (most recent call last):
  File "/usr/local/bin/charge-lnd", line 6, in <module>
    from charge_lnd.charge_lnd import main
  File "/usr/local/lib/python3.7/dist-packages/charge_lnd/charge_lnd.py", line 128, in <module>
    success = main()
  File "/usr/local/lib/python3.7/dist-packages/charge_lnd/charge_lnd.py", line 83, in main
    print("  fee_ppm:         %s%s" % (fmt.col_hi(current_fee_ppm), s) )
UnicodeEncodeError: 'latin-1' codec can't encode character '\u279c' in position 35: ordinal not in range(256)

Support for multi-arch (so that we can run it on Umbrel)

With some assistance from @Jorijn, I am working on creating an install guide for Umbrel users, allowing them to create a separate docker with charge-lnd (Because Umbrel is all dockerized, and I want to avoid it uninstalling and wiping out the changes every time users update).

I am trying to run this command:

docker run --platform linux/arm64/v8 --rm -it --network=umbrel_main_network -e GRPC_LOCATION=lnd:10009 -e LND_DIR=/data/.lnd -e CONFIG_LOCATION=/app/charge.config -v $(pwd)/umbrel/lnd:/data/.lnd -v $(pwd)/umbrel/apps/charge-lnd/charge.conf:/app/charge.config docker.pkg.github.com/accumulator/charge-lnd/charge-lnd:latest

However, I get this response:

docker: Error response from daemon: image with reference docker.pkg.github.com/accumulator/charge-lnd/charge-lnd:latest was found but does not match the specified platform: wanted linux/arm64v8, actual: linux/amd64.
See 'docker run --help'.

This is particularly confusing, because the Raspberry Pi 4B is 100% certainly ARM v8.

I cannot figure out how to get around this and get it to recognize the right platform in order to install, so I'm completely stuck.

Thanks for your help, all!

Wrong description in charge.config.example for zerobasefee-initiative

In the Example the following is described:

[zerobasefee-initiative]
#set base_fee_msat default to 0 if peer sets zero base fees
chan.max_fee_ppm = 0
base_fee_msat = 0

But in my understanding, this looks for the fee_rate of the peer, so in my view the should be something like:

chan.max_base_fee = 0

The above would mean if the peer has a feerate of 0 I will adjust my base_fee to 0 which is highly unlikely to happen.

Error Install charge-lnd

Hi,
im on Raspiblitz and i follow the instructions on: https://nullcount.com/install-charge-lnd-routing-fees-on-autopilot/
But when i enter the "pip install -r requirements.txt ."
i got this error msg:

Could not install packages due to an EnvironmentError: [('/home/bitcoin/charge-lnd/charge.config.save', '/tmp/pip-req-build-nqu2rchu/charge.config.save', "[Errno 13] Permission denied: '/home/bitcoin/charge-lnd/charge.config.save'")]
I'm a linux newbie and it would be great to get some help.

Bug while using verbose output and ignore strategy

While using verbose output I am getting the following error/stacktrace

Traceback (most recent call last):
  File "/usr/local/bin/charge-lnd", line 6, in <module>
    from charge_lnd.charge_lnd import main
  File "/usr/local/lib/python3.7/dist-packages/charge_lnd/charge_lnd.py", line 143, in <module>
    success = main()
  File "/usr/local/lib/python3.7/dist-packages/charge_lnd/charge_lnd.py", line 92, in main
    if min_fee_ppm_delta > abs(new_fee_ppm - current_fee_ppm):
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

The prior output is from a node that was in a file list of nodes with a strategy of ignore.

When I took the pubkey of a node above it in the output and added it to the file the error occurs that that node. So it seems to be an issue in the ignore strategy when verbose is on.

Everything seems to work fine when verbose is off.

Include a fee-change threshold for less updates

In routing nodes, many forwards can happen and this creates too many fee updates that take time to travel the network (which causes new forwards to fail due to different fee).

The current solution is to update fees less often, but this can have the issue of having your channels out of balance quicker.

A threshold (either in change percentage, or absolute sats change) could be taken into account. This would make changes only happen after the threshold has been reached after many channel forwards, and then issue a fee update. This would limit the micromanagement of fee rates, while still be able to check them quick and update when it is necessary.

chan.min_local_balance unknown property

I'm getting the following error message:

Error evaluating criteria for channel in policy '<charge_lnd.policy.Policy object at 0xb537a4d0>', ignoring channel. (Error=Unknown property 'chan.min_local_balance')

crash when peer node is down

Running when one of my peers is down, getting this error. Would be nice if charge continued with the other channels when this happens.

Failed to lookup <channel-id-redacted>
Traceback (most recent call last):
  File "/usr/local/bin/charge-lnd", line 5, in <module>
    from charge_lnd.charge_lnd import main
  File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 156, in <module>
    success = main()
  File "/usr/local/lib/python3.9/site-packages/charge_lnd/charge_lnd.py", line 60, in main
    my_policy = chan_info.node1_policy if chan_info.node1_pub == my_pubkey else chan_info.node2_policy
AttributeError: 'NoneType' object has no attribute 'node1_pub'

Strategy based on the period of channel activity

Channels often have only one flow direction.
For such channels, a strategy that increases or decreases fees based on activity could be useful.

Example:
[increase fee]
chan.activity_period = 1d
chan.max_htlcs_out = 3
strategy = increase
chan.current_fee = +0.1%

[decrease fee]
chan.activity_period = 1d
chan.max_htlcs_out = 1
strategy = decrease
chan.current_fee = -0.1%

set max_htlc_msat as a ratio of the capacity

Hey,
in the case of a very low balance score I'd like to change the max_htlc_msat to a lower amount. But because of different channelsizes it is difficult to choose a fixed amount which fits for all channels.
Because of this one should be able to configure it as a ratio of the capacity, e.g. with implentation of a new parameter max_htlc_msat_ratio.

Regards Steff

support for #9999BaseFee

First of all, thank you very much for this amazing tool. It is GodSend to manage fee and therefore routing efficiently and to achieve an efficient return on liquidity deployed.

Now, it is well known the network is choked today due to "TemporaryChannelFailures" which is mainly a result of channel with depleted liquidity coming up higher in the routing path and failing. This is akin to a driver who fails to move to the side when running out of fuel and therefore blocking the fast lane.

To resolve this and to not cause inconvenience to my peers routing through me, I have started using base fee as a switch
BaseFee = 0 when routing is on from my side -> peer
BaseFee = 9999_000 mSat when routing is off from my side -> peer if liquidity is depleted.

I do this by putting a stop routing policy very high in (after default and my default) as below


[1-stop_routing]
# if < 10% on local increase fees very high
chan.max_ratio = 0.1
strategy = static
base_fee_msat = 9999_000
fee_ppm = 0

The advantage of using base fee instead of fee rate is simply because
a) most explorers look for fee-rate, very high fee rate could impact the ranking or optics.
b) by using base fee simply as on-off switch it offers a predictability to the peers
c) by consistently using 9999 as base fee to signal routing off, it also starts establishing 9999 as a signal for routing off instead of a desire to claim a very high fee. i.e. it is a service to the network instead of charging very high fee. As you can see, there is no liquidity to charge that high fee anyway, the route will fail.

If many nodes are adopting this strategy, soon we can see a reduction in temporary channel failures and the network will flow smoothly through paths which have liquidity.

Since charge-lnd is most used tool for fee management, if such a configuration can be introduced in SampleConfiguration then it will really encourage the network to adopt this.

If you agree, I can create a pull request for your review in the sample configuration file.

no warnings in the case of empty lines or comments in a file-list

Hello,
In the case of an empty line (espacially in the case of an empty file) or a commented line in a list of node-ids, the tool prints a warning that the pubkey is invalid. This should be suppressed.

Having a commented line would be helpful to descripe the node in the list.

Regards Steff

--check does not check syntax errors

--check does not check syntax error.

for
[new section]
node.id = something

I had a - instead of _ mistake in
max.chan-ratio (instead of max.chan_ratio

Also I had spelling mistake

strategy = proportional

These were not caught during --check and instead they were caught in --dry-run

chan.id and reference to external file breaks in all formats tried so far

I'm trying to separate my channel segmentation into different files, with the goal to write into those dynamically.
I've been able to pull in
node.id = file:///home/lnd/.config/test.list
with test.list formatting just as

039cbc938e8a9095b60114143cdb301ae4d4d9bd1dca96763a494880863ac66055,
02868e12f320073cad0c2959c42559fbcfd1aa326fcb943492ed7f02c9820aa399

When trying to apply similar logic to channel-IDs, none of the following worked:
chan.id = file:///home/lnd/.config/test.list
in the main file, formatting of the pulled test.list with short channel IDs

717384x1380x2,
721770x2518x4

breaking with the following error:
Ignored: invalid channel id '717384x1380x2,' in 'file:///home/lnd/.config/test.list'

or with long channel IDs

763135836514680834,
784400391425949697,
795851805125050369

breaks with the following errors

Error evaluating criteria for channel 710983x401x1 in policy '<charge_lnd.policy.Policy object at 0x7f9c9e3a2be0>', ignoring channel. (Error=invalid literal for int() with base 10: 'chan.id = file')
Ignored: invalid channel id '763135836514680834,784400391425949697,795851805125050369' in 'file:///home/lnd/.config/test.list'

The policy section pulling it looks like this:

[1-Lowest-Normal]
chan.id = file:///home/lnd/.config/test.list
#chan.min_ratio = 0.05
strategy = proportional
min_fee_ppm = 30
max_fee_ppm = 90

Perhaps I'm using the wrong channel format, but lndmanage, lncli or LNDg which I'm using for exporting the long format.

Any way this is a bug, or I'm just using the wrong output for filtering the channel-ID?

Inverse proportional strategy

I was missing an inverse proportional setting as an addition to the encourage routing channels that have a high local balance.

Changing the ratio
from
ratio = channel.local_balance/(channel.local_balance + channel.remote_balance)
to
ratio = channel.remote_balance/(channel.local_balance + channel.remote_balance)
has the desired effect

I was not succesfull in implementing a new strategy in strategy.py, but could not find the issue.

How can I suggest a new strategy? Simply adding one in strategy.py did not work

AttributeError: 'NoneType' object has no attribute 'get'

Hello, I am trying to run the following:

# charge-lnd --lnddir /home/thorie/.lnd --dry-run -c ./charge.conf

But getting this result:

Traceback (most recent call last):
  File "/home/thorie/python/bin/charge-lnd", line 33, in <module>
    sys.exit(load_entry_point('charge-lnd==0.1.0', 'console_scripts', 'charge-lnd')())
  File "/home/thorie/python/lib/python3.6/site-packages/pkg_resources/__init__.py", line 474, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/home/thorie/python/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2846, in load_entry_point
    return ep.load()
  File "/home/thorie/python/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2450, in load
    return self.resolve()
  File "/home/thorie/python/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2456, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/home/thorie/python/lib/python3.6/site-packages/charge_lnd/charge_lnd.py", line 130, in <module>
    success = main()
  File "/home/thorie/python/lib/python3.6/site-packages/charge_lnd/charge_lnd.py", line 47, in main
    (new_base_fee_msat, new_fee_ppm, new_min_htlc, new_max_htlc, new_time_lock_delta) = policy.execute(channel)
  File "/home/thorie/python/lib/python3.6/site-packages/charge_lnd/policy.py", line 24, in execute
    strategy = self.config.get('strategy', 'ignore')
AttributeError: 'NoneType' object has no attribute 'get'

My config file looks like this:

[discourage-routing-out-of-balance]
chan.max_ratio = 0.1
chan.min_capacity = 25000
strategy = static
base_fee_msat = 10000
fee_ppm = 500

[encourage-routing-to-balance]
chan.min_ratio = 0.9
chan.min_capacity = 25000
strategy = static
base_fee_msat = 1
fee_ppm = 2

Any idea what is wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.