rebalance: getroute update msatoshi by amount_msat

rebalance: getroute outdated msatoshi by amount_msat
This commit is contained in:
Michael Schmoock
2022-09-14 16:10:32 +02:00
parent 8ed6e3870b
commit 2322bf64a8
2 changed files with 38 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ from pyln.client import Plugin, Millisatoshi, RpcError
from threading import Thread, Lock from threading import Thread, Lock
from datetime import timedelta from datetime import timedelta
from functools import reduce from functools import reduce
import semver
import time import time
import uuid import uuid
@@ -10,18 +11,31 @@ plugin = Plugin()
plugin.rebalance_stop = False plugin.rebalance_stop = False
def setup_routing_fees(route, msatoshi): # The route msat helpers are needed because older versions of cln
# had different msat/msatoshi fields with different types Millisatoshi/int
def route_set_msat(obj, msat):
if plugin.rpcversion.major == 0 and plugin.rpcversion.minor < 12:
obj[plugin.msatfield] = msat.millisatoshis
obj['amount_msat'] = Millisatoshi(msat)
else:
obj[plugin.msatfield] = Millisatoshi(msat)
def route_get_msat(r):
return Millisatoshi(r[plugin.msatfield])
def setup_routing_fees(route, msat):
delay = plugin.cltv_final delay = plugin.cltv_final
for r in reversed(route): for r in reversed(route):
r['msatoshi'] = msatoshi.millisatoshis route_set_msat(r, msat)
r['amount_msat'] = msatoshi
r['delay'] = delay r['delay'] = delay
channels = plugin.rpc.listchannels(r['channel']) channels = plugin.rpc.listchannels(r['channel'])
ch = next(c for c in channels.get('channels') if c['destination'] == r['id']) ch = next(c for c in channels.get('channels') if c['destination'] == r['id'])
fee = Millisatoshi(ch['base_fee_millisatoshi']) fee = Millisatoshi(ch['base_fee_millisatoshi'])
# BOLT #7 requires fee >= fee_base_msat + ( amount_to_forward * fee_proportional_millionths / 1000000 ) # BOLT #7 requires fee >= fee_base_msat + ( amount_to_forward * fee_proportional_millionths / 1000000 )
fee += (msatoshi * ch['fee_per_millionth'] + 10**6 - 1) // 10**6 # integer math trick to round up fee += (msat * ch['fee_per_millionth'] + 10**6 - 1) // 10**6 # integer math trick to round up
msatoshi += fee msat += fee
delay += ch['delay'] delay += ch['delay']
@@ -65,9 +79,9 @@ def find_worst_channel(route):
return None return None
start_idx = 2 start_idx = 2
worst = route[start_idx] worst = route[start_idx]
worst_val = route[start_idx - 1]['msatoshi'] - route[start_idx]['msatoshi'] worst_val = route_get_msat(route[start_idx - 1]) - route_get_msat(worst)
for i in range(start_idx + 1, len(route) - 1): for i in range(start_idx + 1, len(route) - 1):
val = route[i - 1]['msatoshi'] - route[i]['msatoshi'] val = route_get_msat(route[i - 1]) - route_get_msat(route[i])
if val > worst_val: if val > worst_val:
worst = route[i] worst = route[i]
worst_val = val worst_val = val
@@ -221,7 +235,7 @@ def rebalance(plugin, outgoing_scid, incoming_scid, msatoshi: Millisatoshi = Non
"maxfeepercent": maxfeepercent, "maxfeepercent": maxfeepercent,
"exemptfee": exemptfee "exemptfee": exemptfee
} }
my_node_id = plugin.rpc.getinfo().get('id') my_node_id = plugin.getinfo.get('id')
outgoing_node_id = peer_from_scid(outgoing_scid, my_node_id, payload) outgoing_node_id = peer_from_scid(outgoing_scid, my_node_id, payload)
incoming_node_id = peer_from_scid(incoming_scid, my_node_id, payload) incoming_node_id = peer_from_scid(incoming_scid, my_node_id, payload)
get_channel(payload, outgoing_node_id, outgoing_scid, True) get_channel(payload, outgoing_node_id, outgoing_scid, True)
@@ -292,7 +306,7 @@ def rebalance(plugin, outgoing_scid, incoming_scid, msatoshi: Millisatoshi = Non
route_mid = r['route'] route_mid = r['route']
route = [route_out] + route_mid + [route_in] route = [route_out] + route_mid + [route_in]
setup_routing_fees(route, msatoshi) setup_routing_fees(route, msatoshi)
fees = route[0]['amount_msat'] - msatoshi fees = route_get_msat(route[0]) - msatoshi
# check fee and exclude worst channel the next time # check fee and exclude worst channel the next time
# NOTE: the int(msat) casts are just a workaround for outdated pylightning versions # NOTE: the int(msat) casts are just a workaround for outdated pylightning versions
@@ -318,7 +332,7 @@ def rebalance(plugin, outgoing_scid, incoming_scid, msatoshi: Millisatoshi = Non
full_route_str = "%s -> %s -> %s -> %s" % (get_node_alias(my_node_id), get_node_alias(outgoing_node_id), midroute_str, get_node_alias(my_node_id)) full_route_str = "%s -> %s -> %s -> %s" % (get_node_alias(my_node_id), get_node_alias(outgoing_node_id), midroute_str, get_node_alias(my_node_id))
plugin.log("%d hops and %s fees for %s along route: %s" % (len(route), fees.to_satoshi_str(), msatoshi.to_satoshi_str(), full_route_str)) plugin.log("%d hops and %s fees for %s along route: %s" % (len(route), fees.to_satoshi_str(), msatoshi.to_satoshi_str(), full_route_str))
for r in route: for r in route:
plugin.log(" - %s %14s %s" % (r['id'], r['channel'], r['amount_msat']), 'debug') plugin.log(" - %s %14s %s" % (r['id'], r['channel'], route_get_msat(r)), 'debug')
time_start = time.time() time_start = time.time()
count_sendpay += 1 count_sendpay += 1
@@ -796,6 +810,19 @@ def init(options, configuration, plugin):
plugin.getroute = getroute_switch(options.get("rebalance-getroute")) plugin.getroute = getroute_switch(options.get("rebalance-getroute"))
plugin.rebalanceall_msg = None plugin.rebalanceall_msg = None
# parse semver string to determine RPC version
# strip leading 'v' although semver should ignore it, but it doesn't.
plugin.getinfo = plugin.rpc.getinfo()
rpcversion = plugin.getinfo.get('version')
if rpcversion.startswith('v'):
rpcversion = rpcversion[1:]
plugin.rpcversion = semver.VersionInfo.parse(rpcversion)
# use getroute amount_msat/msatoshi field depending on version
plugin.msatfield = 'amount_msat'
if plugin.rpcversion.major == 0 and plugin.rpcversion.minor < 12:
plugin.msatfield = 'msatoshi'
plugin.log(f"Plugin rebalance initialized with {plugin.fee_base} base / {plugin.fee_ppm} ppm fee " plugin.log(f"Plugin rebalance initialized with {plugin.fee_base} base / {plugin.fee_ppm} ppm fee "
f"cltv_final:{plugin.cltv_final} " f"cltv_final:{plugin.cltv_final} "
f"maxhops:{plugin.maxhops} " f"maxhops:{plugin.maxhops} "

View File

@@ -1 +1,2 @@
pyln-client>=0.10.1 pyln-client>=0.10.1
semver==2.*