Skip to content

Commit

Permalink
Merge pull request #171 from BhaagBoseDK/RapidFireUpDn
Browse files Browse the repository at this point in the history
Rapidfire up/down + prioritise remote balance for rebalance
  • Loading branch information
cryptosharks131 authored Nov 15, 2022
2 parents 99213d3 + 124ee53 commit 56a85a3
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
16 changes: 12 additions & 4 deletions jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ def update_payment(stub, payment, self_pubkey):
if hop_count == total_hops and hop.pub_key == self_pubkey and db_payment.rebal_chan is None:
db_payment.rebal_chan = hop.chan_id
db_payment.save()
adjust_ar_amt( payment, db_payment.rebal_chan )
try:
adjust_ar_amt( payment, db_payment.rebal_chan )
except Exception as e:
print (f"{datetime.now().strftime('%c')} : Error adjusting AR Amount {payment=} {db_payment.rebal_chan=} : {str(e)=}")

def adjust_ar_amt( payment, chan_id ):
if payment.status not in (2,3):
Expand Down Expand Up @@ -118,6 +121,7 @@ def adjust_ar_amt( payment, chan_id ):

if payment.status == 3:
estimated_liquidity = 0
attempt = None
for attempt in payment.htlcs:
total_hops=len(attempt.route.hops)
#Failure Codes https://github.com/lightningnetwork/lnd/blob/9f013f5058a7780075bca393acfa97aa0daec6a0/lnrpc/lightning.proto#L4200
Expand All @@ -128,9 +132,13 @@ def adjust_ar_amt( payment, chan_id ):
print (f"{datetime.now().strftime('%c')} : Liquidity Estimation {attempt.attempt_id=} {attempt.status=} {attempt.failure.code=} {chan_id=} {attempt.route.total_amt=} {payment.value_msat/1000=} {estimated_liquidity=} {payment.payment_hash=}")

if estimated_liquidity == 0:
#Could not estimate liquidity, reduce by half
estimated_liquidity = db_channel.ar_amt_target/2 if db_channel is not None else 0
print (f"{datetime.now().strftime('%c')} : Liquidity Estimation not possible, halving {attempt.attempt_id=} {attempt.status=} {attempt.failure.code=} {chan_id=} {attempt.route.total_amt=} {payment.value_msat/1000=} {estimated_liquidity=} {payment.payment_hash=}")
if attempt is not None:
#Could not estimate liquidity for valid attempts, reduce by half
estimated_liquidity = db_channel.ar_amt_target/2 if db_channel is not None else 0
print (f"{datetime.now().strftime('%c')} : Liquidity Estimation not possible, halving {attempt.attempt_id=} {attempt.status=} {attempt.failure.code=} {chan_id=} {attempt.route.total_amt=} {payment.value_msat/1000=} {estimated_liquidity=} {payment.payment_hash=}")
else:
#Mostly a case of NO ROUTE
print (f"{datetime.now().strftime('%c')} : Liquidity Estimation not performed {payment.payment_hash=} {payment.status=} {chan_id=} {estimated_liquidity=} {attempt=}")

if payment.value_msat/1000 >= lower_limit and estimated_liquidity <= payment.value_msat/1000 and estimated_liquidity > 0:
#Change AR amount. Ignore zero liquidity case which implies breakout from rapid fire AR
Expand Down
25 changes: 21 additions & 4 deletions rebalancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,35 @@ def run_rebalancer(rebalance):
finally:
rebalance.stop = datetime.now()
rebalance.save()
if rebalance.status == 2:
original_alias = rebalance.target_alias
inc=1.21
dec=2

if rebalance.status ==2:
update_channels(stub, rebalance.last_hop_pubkey, successful_out)
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'))
inbound_cans = auto_rebalance_channels.filter(remote_pubkey=rebalance.last_hop_pubkey).filter(auto_rebalance=True, inbound_can__gte=1)
outbound_cans = list(auto_rebalance_channels.filter(auto_rebalance=False, percent_outbound__gte=F('ar_out_target')).values_list('chan_id', flat=True))
outbound_cans = list(auto_rebalance_channels.filter(auto_rebalance=False, percent_outbound__gte=F('ar_out_target')).exclude(remote_pubkey=rebalance.last_hop_pubkey).values_list('chan_id', flat=True))

if len(inbound_cans) > 0 and len(outbound_cans) > 0:
next_rebalance = Rebalancer(value=int(rebalance.value*inc), fee_limit=int(rebalance.fee_limit*inc), outgoing_chan_ids=str(outbound_cans).replace('\'', ''), last_hop_pubkey=rebalance.last_hop_pubkey, target_alias=original_alias, duration=1)
next_rebalance.save()
print (f"{datetime.now().strftime('%c')} : RapidFire up {next_rebalance.target_alias=} {next_rebalance.value=} {rebalance.value=}")

else:
next_rebalance = None
elif rebalance.status > 2 and rebalance.duration <= 1 and rebalance.value > 69420:
#Previous Rapidfire with increased value failed, try with lower value up to 69420.
inbound_cans = auto_rebalance_channels.filter(remote_pubkey=rebalance.last_hop_pubkey).filter(auto_rebalance=True, inbound_can__gte=1)
if len(inbound_cans) > 0 and len(outbound_cans) > 0:
next_rebalance = Rebalancer(value=rebalance.value, fee_limit=rebalance.fee_limit, outgoing_chan_ids=str(outbound_cans).replace('\'', ''), last_hop_pubkey=rebalance.last_hop_pubkey, target_alias=rebalance.target_alias, duration=1)
next_rebalance = Rebalancer(value=int(rebalance.value/dec), fee_limit=int(rebalance.fee_limit/dec), outgoing_chan_ids=str(outbound_cans).replace('\'', ''), last_hop_pubkey=rebalance.last_hop_pubkey, target_alias=original_alias, duration=1)
next_rebalance.save()
print (f"{datetime.now().strftime('%c')} : RapidFire Down {next_rebalance.target_alias=} {next_rebalance.value=} {rebalance.value=}")
else:
next_rebalance = None
else:
next_rebalance = None

return next_rebalance

def update_channels(stub, incoming_channel, outgoing_channel):
Expand Down Expand Up @@ -120,7 +137,7 @@ def auto_schedule():
if not LocalSettings.objects.filter(key='AR-Inbound%').exists():
LocalSettings(key='AR-Inbound%', value='100').save()
outbound_cans = list(auto_rebalance_channels.filter(auto_rebalance=False, percent_outbound__gte=F('ar_out_target')).values_list('chan_id', flat=True))
inbound_cans = auto_rebalance_channels.filter(auto_rebalance=True, inbound_can__gte=1)
inbound_cans = auto_rebalance_channels.filter(auto_rebalance=True, inbound_can__gte=1).order_by('-remote_balance')
if len(inbound_cans) > 0 and len(outbound_cans) > 0:
if LocalSettings.objects.filter(key='AR-MaxFeeRate').exists():
max_fee_rate = int(LocalSettings.objects.filter(key='AR-MaxFeeRate')[0].value)
Expand Down

0 comments on commit 56a85a3

Please sign in to comment.