feeadjuster: set base fee for median strategy

This commit is contained in:
Michael Schmoock
2023-03-15 21:29:50 +01:00
parent a662b399c5
commit 79ea6c9aa1
2 changed files with 59 additions and 13 deletions

View File

@@ -120,8 +120,11 @@ def get_fees_median(plugin: Plugin, scid: str):
and ch['source'] != plugin.our_node_id]
if len(channels_to_peer) == 0:
return None
fees_ppm = [ch['fee_per_millionth'] for ch in channels_to_peer]
return {"base": plugin.adj_basefee, "ppm": statistics.median(fees_ppm) * plugin.median_multiplier}
# fees > ~5000 (base and ppm) are currently about top 2% of network fee extremists
fees_ppm = [ch['fee_per_millionth'] for ch in channels_to_peer if 0 < ch['fee_per_millionth'] < 5000]
fees_base = [ch['base_fee_millisatoshi'] for ch in channels_to_peer if 0 < ch['base_fee_millisatoshi'] < 5000]
return {"base": statistics.median(fees_base) * plugin.median_multiplier,
"ppm": statistics.median(fees_ppm) * plugin.median_multiplier}
def setchannelfee(plugin: Plugin, scid: str, base: int, ppm: int, min_htlc: int = None, max_htlc: int = None):
@@ -162,19 +165,19 @@ def maybe_adjust_fees(plugin: Plugin, scids: list):
our = plugin.adj_balances[scid]["our"]
total = plugin.adj_balances[scid]["total"]
percentage = our / total
base = plugin.adj_basefee
ppm = plugin.adj_ppmfee
base = int(plugin.adj_basefee)
ppm = int(plugin.adj_ppmfee)
# select ideal values per channel
fees = plugin.fee_strategy(plugin, scid)
if fees is not None:
base = fees['base']
ppm = fees['ppm']
base = int(fees['base'])
ppm = int(fees['ppm'])
# reset to normal fees if imbalance is not high enough
if (percentage > plugin.imbalance and percentage < 1 - plugin.imbalance):
if setchannelfee(plugin, scid, base, ppm):
plugin.log(f"Set default fees as imbalance is too low: {scid}")
plugin.log(f"Set default fees as imbalance is too low for {scid}: ppm {ppm} base {base}msat")
plugin.adj_balances[scid]["last_liquidity"] = our
channels_adjusted += 1
continue
@@ -189,8 +192,8 @@ def maybe_adjust_fees(plugin: Plugin, scids: list):
max_htlc = int(total * math.ceil(plugin.max_htlc_steps * percentage) / plugin.max_htlc_steps)
else:
max_htlc = None
if setchannelfee(plugin, scid, int(base), int(ppm * ratio), None, max_htlc):
plugin.log(f"Adjusted fees of {scid} with a ratio of {ratio}, set max_htlc to {max_htlc}")
if setchannelfee(plugin, scid, base, int(ppm * ratio), None, max_htlc):
plugin.log(f"Adjusted fees of {scid} with a ratio of {ratio}: ppm {int(ppm * ratio)} base {base}msat max_htlc {max_htlc}")
plugin.adj_balances[scid]["last_liquidity"] = our
channels_adjusted += 1
return channels_adjusted

View File

@@ -189,8 +189,8 @@ def test_feeadjuster_imbalance(node_factory):
amount = int(chan_total * 0.5)
pay(l1, l3, amount)
l2.daemon.wait_for_logs([
f'Set default fees as imbalance is too low: {scid_A}',
f'Set default fees as imbalance is too low: {scid_B}'
f'Set default fees as imbalance is too low for {scid_A}',
f'Set default fees as imbalance is too low for {scid_B}'
])
wait_for_fees(l2, scids, default_fees[0])
@@ -211,8 +211,8 @@ def test_feeadjuster_imbalance(node_factory):
# Bringing it back must cause default fees
pay(l3, l1, amount)
l2.daemon.wait_for_logs([
f'Set default fees as imbalance is too low: {scid_A}',
f'Set default fees as imbalance is too low: {scid_B}'
f'Set default fees as imbalance is too low for {scid_A}',
f'Set default fees as imbalance is too low for {scid_B}'
])
wait_for_fees(l2, scids, default_fees[0])
@@ -290,3 +290,46 @@ def test_feeadjuster_big_enough_liquidity(node_factory):
f"Adjusted fees.*{scid_B}"
])
wait_for_not_fees(l2, scids, default_fees[0])
@unittest.skipIf(not DEVELOPER, "Too slow without fast gossip")
def test_feeadjuster_median(node_factory):
"""
A rather simple network:
a b c
l1 <=======> l2 <=======> l3 <=======> l4
l2 will adjust its configuration-set base and proportional fees for
channels A and B as l1 and l3 exchange payments.
l4 is needed so l2 can make a median peers-of-peer calculation on l3.
"""
opts = {
"fee-base": 1337,
"fee-per-satoshi": 42,
}
l2_opts = {
"fee-base": 1000,
"fee-per-satoshi": 100,
"plugin": plugin_path,
"feeadjuster-deactivate-fuzz": None,
"feeadjuster-imbalance": 0.5,
"feeadjuster-feestrategy": "median"
}
l1, l2, l3, _ = node_factory.line_graph(4, opts=[opts, l2_opts, opts, opts],
wait_for_announce=True)
scid_a = l2.rpc.listpeerchannels(l1.info["id"])["channels"][0]["short_channel_id"]
scid_b = l2.rpc.listpeerchannels(l3.info["id"])["channels"][0]["short_channel_id"]
# we do a manual feeadjust
l2.rpc.feeadjust()
l2.daemon.wait_for_logs([
f"Adjusted fees.*{scid_a}",
f"Adjusted fees.*{scid_b}"
])
# since there is only l4 with channel c towards l3, l2 should take that value
chan_b = l2.rpc.listpeerchannels(l3.info['id'])['channels'][0]
assert chan_b['fee_base_msat'] == 1337
assert chan_b['fee_proportional_millionths'] < 42 # we could do the actual ratio math, but meh