Skip to content

Commit

Permalink
factor out unwieldy tuple for channel parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
accumulator committed May 15, 2024
1 parent 14cb8a0 commit 9fed8d3
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 75 deletions.
69 changes: 38 additions & 31 deletions charge_lnd/charge_lnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from .lnd import Lnd
from .policy import Policies
from .strategy import is_defined
from .config import Config
from .electrum import Electrum
import charge_lnd.fmt as fmt
Expand Down Expand Up @@ -51,7 +52,7 @@ def main():
if not policy:
continue

(new_base_fee_msat, new_fee_ppm, new_inbound_base_fee_msat, new_inbound_fee_ppm, new_min_htlc, new_max_htlc, new_time_lock_delta, disable) = policy.strategy.execute(channel)
chp = policy.strategy.execute(channel)

if channel.chan_id in lnd.feereport:
(current_base_fee_msat, current_fee_ppm) = lnd.feereport[channel.chan_id]
Expand All @@ -60,26 +61,33 @@ def main():
if not chan_info:
print ("could not lookup channel info for " + fmt.print_chanid(channel.chan_id).ljust(14) + ", skipping")
continue

my_policy = chan_info.node1_policy if chan_info.node1_pub == my_pubkey else chan_info.node2_policy

min_fee_ppm_delta = policy.getint('min_fee_ppm_delta',0)

fee_ppm_changed = new_fee_ppm is not None and current_fee_ppm != new_fee_ppm and abs(current_fee_ppm - new_fee_ppm) >= min_fee_ppm_delta
inbound_fee_ppm_changed = new_inbound_fee_ppm is not None and my_policy.inbound_fee_rate_milli_msat != new_inbound_fee_ppm and \
abs(my_policy.inbound_fee_rate_milli_msat - new_inbound_fee_ppm) >= min_fee_ppm_delta
fee_ppm_changed = is_defined(chp.fee_ppm) and current_fee_ppm != chp.fee_ppm and abs(current_fee_ppm - chp.fee_ppm) >= min_fee_ppm_delta
base_fee_changed = is_defined(chp.base_fee_msat) and current_base_fee_msat != chp.base_fee_msat

inbound_fee_ppm_changed = lnd.supports_inbound_fees() \
and is_defined(chp.inbound_fee_ppm) \
and my_policy.inbound_fee_rate_milli_msat != chp.inbound_fee_ppm \
and abs(my_policy.inbound_fee_rate_milli_msat - chp.inbound_fee_ppm) >= min_fee_ppm_delta

inbound_base_fee_changed = lnd.supports_inbound_fees() \
and is_defined(chp.inbound_base_fee_msat) \
and my_policy.inbound_fee_base_msat != chp.inbound_base_fee_msat

base_fee_changed = new_base_fee_msat is not None and current_base_fee_msat != new_base_fee_msat
inbound_base_fee_changed = new_inbound_base_fee_msat is not None and my_policy.inbound_fee_base_msat != new_inbound_base_fee_msat
min_htlc_changed = new_min_htlc is not None and my_policy.min_htlc != new_min_htlc
max_htlc_changed = new_max_htlc is not None and my_policy.max_htlc_msat != new_max_htlc
time_lock_delta_changed = new_time_lock_delta is not None and my_policy.time_lock_delta != new_time_lock_delta
min_htlc_changed = is_defined(chp.min_htlc_msat) and my_policy.min_htlc != chp.min_htlc_msat
max_htlc_changed = is_defined(chp.max_htlc_msat) and my_policy.max_htlc_msat != chp.max_htlc_msat
time_lock_delta_changed = is_defined(chp.time_lock_delta) and my_policy.time_lock_delta != chp.time_lock_delta
is_changed = fee_ppm_changed or base_fee_changed or min_htlc_changed or max_htlc_changed or \
time_lock_delta_changed or inbound_base_fee_changed + inbound_fee_ppm_changed
time_lock_delta_changed or inbound_base_fee_changed or inbound_fee_ppm_changed

chan_status_changed = False
if lnd.min_version(0,13) and channel.active and disable != my_policy.disabled and policy.get('strategy') != 'ignore':
if lnd.min_version(0, 13) and channel.active and chp.disabled != my_policy.disabled and policy.get('strategy') != 'ignore':
if not arguments.dry_run:
lnd.update_chan_status(channel.chan_id, disable)
lnd.update_chan_status(channel.chan_id, chp.disabled)
chan_status_changed = True

if is_changed or chan_status_changed or arguments.verbose:
Expand All @@ -89,8 +97,7 @@ def main():
)

if is_changed and not arguments.dry_run:
lnd.update_chan_policy(channel.chan_id, new_base_fee_msat, new_fee_ppm, new_min_htlc,
new_max_htlc, new_time_lock_delta, new_inbound_base_fee_msat, new_inbound_fee_ppm)
lnd.update_chan_policy(channel.chan_id, chp)

if is_changed or chan_status_changed or arguments.verbose:
print(" policy: %s" % fmt.col_hi(policy.name) )
Expand All @@ -99,46 +106,46 @@ def main():
s = 'disabled' if my_policy.disabled else 'enabled'
if chan_status_changed:
s = s + ' ➜ '
s = s + 'disabled' if disable else 'enabled'
s = s + 'disabled' if chp.disabled else 'enabled'
print(" channel status: %s" % fmt.col_hi(s))
if new_base_fee_msat is not None or arguments.verbose:
if is_defined(chp.base_fee_msat) or arguments.verbose:
s = ''
if base_fee_changed:
s = ' ➜ ' + fmt.col_hi(new_base_fee_msat)
s = ' ➜ ' + fmt.col_hi(chp.base_fee_msat)
print(" base_fee_msat: %s%s" % (fmt.col_hi(current_base_fee_msat), s) )
if new_fee_ppm is not None or arguments.verbose:
if is_defined(chp.fee_ppm) or arguments.verbose:
s = ''
if fee_ppm_changed:
s = ' ➜ ' + fmt.col_hi(new_fee_ppm)
if min_fee_ppm_delta > abs(new_fee_ppm - current_fee_ppm):
s = ' ➜ ' + fmt.col_hi(chp.fee_ppm)
if min_fee_ppm_delta > abs(chp.fee_ppm - current_fee_ppm):
s = s + ' (min_fee_ppm_delta=%d)' % min_fee_ppm_delta
print(" fee_ppm: %s%s" % (fmt.col_hi(current_fee_ppm), s) )
if new_inbound_base_fee_msat is not None or arguments.verbose:
if is_defined(chp.inbound_base_fee_msat) or arguments.verbose:
s = ''
if inbound_base_fee_changed:
s = ' ➜ ' + fmt.col_hi(new_inbound_base_fee_msat)
s = ' ➜ ' + fmt.col_hi(chp.inbound_base_fee_msat)
print(" inbound_base_fee_msat: %s%s" % (fmt.col_hi(my_policy.inbound_fee_base_msat), s) )
if new_inbound_fee_ppm is not None or arguments.verbose:
if is_defined(chp.inbound_fee_ppm) or arguments.verbose:
s = ''
if inbound_fee_ppm_changed:
s = ' ➜ ' + fmt.col_hi(new_inbound_fee_ppm)
if min_fee_ppm_delta > abs(new_inbound_fee_ppm - my_policy.inbound_fee_rate_milli_msat):
s = ' ➜ ' + fmt.col_hi(chp.inbound_fee_ppm)
if min_fee_ppm_delta > abs(chp.inbound_fee_ppm - my_policy.inbound_fee_rate_milli_msat):
s = s + ' (min_fee_ppm_delta=%d)' % min_fee_ppm_delta
print(" inbound_fee_ppm: %s%s" % (fmt.col_hi(my_policy.inbound_fee_rate_milli_msat), s) )
if new_min_htlc is not None or arguments.verbose:
if is_defined(chp.min_htlc_msat) or arguments.verbose:
s = ''
if min_htlc_changed:
s = ' ➜ ' + fmt.col_hi(new_min_htlc)
s = ' ➜ ' + fmt.col_hi(chp.min_htlc_msat)
print(" min_htlc_msat: %s%s" % (fmt.col_hi(my_policy.min_htlc), s) )
if new_max_htlc is not None or arguments.verbose:
if is_defined(chp.max_htlc_msat) or arguments.verbose:
s = ''
if max_htlc_changed:
s = ' ➜ ' + fmt.col_hi(new_max_htlc)
s = ' ➜ ' + fmt.col_hi(chp.max_htlc_msat)
print(" max_htlc_msat: %s%s" % (fmt.col_hi(my_policy.max_htlc_msat), s) )
if new_time_lock_delta is not None or arguments.verbose:
if is_defined(chp.time_lock_delta) or arguments.verbose:
s = ''
if time_lock_delta_changed:
s = ' ➜ ' + fmt.col_hi(new_time_lock_delta)
s = ' ➜ ' + fmt.col_hi(chp.time_lock_delta)
print(" time_lock_delta: %s%s" % (fmt.col_hi(my_policy.time_lock_delta), s) )

return True
Expand Down
47 changes: 26 additions & 21 deletions charge_lnd/lnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from .grpc_generated import lightning_pb2_grpc as lnrpc, lightning_pb2 as ln
from .grpc_generated import router_pb2_grpc as routerrpc, router_pb2 as router

from .strategy import ChanParams, KEEP, DONTCARE

MESSAGE_SIZE_MB = 50 * 1024 * 1024


Expand All @@ -27,10 +29,11 @@ def __init__(self, lnd_dir, server, tls_cert_path=None, macaroon_path=None):
('grpc.max_receive_message_length', MESSAGE_SIZE_MB)
]
grpc_channel = grpc.secure_channel(server, combined_credentials, channel_options)
self.stub = lnrpc.LightningStub(grpc_channel)
self.lnstub = lnrpc.LightningStub(grpc_channel)
self.routerstub = routerrpc.RouterStub(grpc_channel)
self.graph = None
self.info = None
self.version = None
self.channels = None
self.node_info = {}
self.chan_info = {}
Expand Down Expand Up @@ -59,11 +62,14 @@ def get_credentials(lnd_dir, tls_cert_path, macaroon_path):

def get_info(self):
if self.info is None:
self.info = self.stub.GetInfo(ln.GetInfoRequest())
self.info = self.lnstub.GetInfo(ln.GetInfoRequest())
return self.info

def supports_inbound_fees(self):
return self.min_version(0, 18)

def get_feereport(self):
feereport = self.stub.FeeReport(ln.FeeReportRequest())
feereport = self.lnstub.FeeReport(ln.FeeReportRequest())
feedict = {}
for channel_fee in feereport.channel_fees:
feedict[channel_fee.chan_id] = (channel_fee.base_fee_msat, channel_fee.fee_per_mil)
Expand All @@ -82,7 +88,7 @@ def get_forward_history(self, chanid, seconds):
done = False
thishistory = {}
while not done:
forwards = self.stub.ForwardingHistory(ln.ForwardingHistoryRequest(
forwards = self.lnstub.ForwardingHistory(ln.ForwardingHistoryRequest(
start_time=start_time, end_time=last_time, index_offset=index_offset))
if forwards.forwarding_events:
for forward in forwards.forwarding_events:
Expand Down Expand Up @@ -128,20 +134,19 @@ def get_forward_history(self, chanid, seconds):

def get_node_info(self, nodepubkey):
if not nodepubkey in self.node_info:
self.node_info[nodepubkey] = self.stub.GetNodeInfo(ln.NodeInfoRequest(pub_key=nodepubkey))
self.node_info[nodepubkey] = self.lnstub.GetNodeInfo(ln.NodeInfoRequest(pub_key=nodepubkey))
return self.node_info[nodepubkey]

def get_chan_info(self, chanid):
if not chanid in self.chan_info:
try:
self.chan_info[chanid] = self.stub.GetChanInfo(ln.ChanInfoRequest(chan_id=chanid))
self.chan_info[chanid] = self.lnstub.GetChanInfo(ln.ChanInfoRequest(chan_id=chanid))
except:
print("Failed to lookup {}".format(chanid),file=sys.stderr)
return None
return self.chan_info[chanid]

def update_chan_policy(self, chanid, base_fee_msat, fee_ppm, min_htlc_msat, max_htlc_msat,
time_lock_delta, inbound_base_fee_msat, inbound_fee_ppm):
def update_chan_policy(self, chanid, chp: ChanParams):
chan_info = self.get_chan_info(chanid)
if not chan_info:
return None
Expand All @@ -150,27 +155,27 @@ def update_chan_policy(self, chanid, base_fee_msat, fee_ppm, min_htlc_msat, max_
output_index=int(chan_info.chan_point.split(':')[1])
)
my_policy = chan_info.node1_policy if chan_info.node1_pub == self.get_own_pubkey() else chan_info.node2_policy
return self.stub.UpdateChannelPolicy(ln.PolicyUpdateRequest(
return self.lnstub.UpdateChannelPolicy(ln.PolicyUpdateRequest(
chan_point=channel_point,
base_fee_msat=(base_fee_msat if base_fee_msat is not None else my_policy.fee_base_msat),
fee_rate=fee_ppm/1000000 if fee_ppm is not None else my_policy.fee_rate_milli_msat/1000000,
min_htlc_msat=(min_htlc_msat if min_htlc_msat is not None else my_policy.min_htlc),
min_htlc_msat_specified=min_htlc_msat is not None,
max_htlc_msat=(max_htlc_msat if max_htlc_msat is not None else my_policy.max_htlc_msat),
time_lock_delta=(time_lock_delta if time_lock_delta is not None else my_policy.time_lock_delta),
inbound_base_fee_msat=(inbound_base_fee_msat if inbound_base_fee_msat is not None else my_policy.inbound_fee_base_msat),
inbound_fee_rate_ppm=(inbound_fee_ppm if inbound_fee_ppm is not None else my_policy.inbound_fee_rate_milli_msat)
base_fee_msat=(chp.base_fee_msat if chp.base_fee_msat is not None else my_policy.fee_base_msat),
fee_rate=chp.fee_ppm/1000000 if chp.fee_ppm is not None else my_policy.fee_rate_milli_msat/1000000,
min_htlc_msat=(chp.min_htlc_msat if chp.min_htlc_msat is not None else my_policy.min_htlc),
min_htlc_msat_specified=chp.min_htlc_msat is not None,
max_htlc_msat=(chp.max_htlc_msat if chp.max_htlc_msat is not None else my_policy.max_htlc_msat),
time_lock_delta=(chp.time_lock_delta if chp.time_lock_delta is not None else my_policy.time_lock_delta),
inbound_base_fee_msat=(chp.inbound_base_fee_msat if chp.inbound_base_fee_msat is not None else my_policy.inbound_fee_base_msat),
inbound_fee_rate_ppm=(chp.inbound_fee_ppm if chp.inbound_fee_ppm is not None else my_policy.inbound_fee_rate_milli_msat)
))

def get_txns(self, start_height = None, end_height = None):
return self.stub.GetTransactions(ln.GetTransactionsRequest(
return self.lnstub.GetTransactions(ln.GetTransactionsRequest(
start_height=start_height,
end_height=end_height
))

def get_graph(self):
if self.graph is None:
self.graph = self.stub.DescribeGraph(ln.ChannelGraphRequest(include_unannounced=True))
self.graph = self.lnstub.DescribeGraph(ln.ChannelGraphRequest(include_unannounced=True))
return self.graph

def get_own_pubkey(self):
Expand All @@ -182,7 +187,7 @@ def get_edges(self):
def get_channels(self):
if self.channels is None:
request = ln.ListChannelsRequest()
self.channels = self.stub.ListChannels(request).channels
self.channels = self.lnstub.ListChannels(request).channels
return self.channels

# Get all channels shared with a node
Expand All @@ -191,7 +196,7 @@ def get_shared_channels(self, peerid):
byte_peerid=bytes.fromhex(peerid)
if peerid not in self.peer_channels:
request = ln.ListChannelsRequest(peer=byte_peerid)
self.peer_channels[peerid] = self.stub.ListChannels(request).channels
self.peer_channels[peerid] = self.lnstub.ListChannels(request).channels
return self.peer_channels[peerid]

def min_version(self, major, minor, patch=0):
Expand Down
2 changes: 1 addition & 1 deletion charge_lnd/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import sys
import re
import time
from .strategy import StrategyDelegate
from .strategy import StrategyDelegate, DONTCARE
from . import fmt

def debug(message):
Expand Down
Loading

0 comments on commit 9fed8d3

Please sign in to comment.