Browse Source

swapserver: throttle payments, handle exceptions in pay_pending_invoices

master
ThomasV 2 years ago
parent
commit
0083560ee6
  1. 51
      electrum/submarine_swaps.py

51
electrum/submarine_swaps.py

@ -4,6 +4,7 @@ import os
from typing import TYPE_CHECKING, Optional, Dict, Union from typing import TYPE_CHECKING, Optional, Dict, Union
from decimal import Decimal from decimal import Decimal
import math import math
import time
import attr import attr
import aiohttp import aiohttp
@ -124,6 +125,8 @@ class SwapServerError(Exception):
def __str__(self): def __str__(self):
return _("The swap server errored or is unreachable.") return _("The swap server errored or is unreachable.")
def now():
return int(time.time())
@stored_in('submarine_swaps') @stored_in('submarine_swaps')
@attr.s @attr.s
@ -217,28 +220,30 @@ class SwapManager(Logger):
asyncio.run_coroutine_threadsafe(network.taskgroup.spawn(coro), network.asyncio_loop) asyncio.run_coroutine_threadsafe(network.taskgroup.spawn(coro), network.asyncio_loop)
async def pay_pending_invoices(self): async def pay_pending_invoices(self):
# FIXME this method can raise, which is not properly handled...? self.invoices_to_pay = {}
self.invoices_to_pay = set()
while True: while True:
await asyncio.sleep(1) await asyncio.sleep(5)
for key in list(self.invoices_to_pay): for key, not_before in list(self.invoices_to_pay.items()):
if now() < not_before:
continue
swap = self.swaps.get(key) swap = self.swaps.get(key)
if not swap: if not swap:
continue continue
invoice = self.wallet.get_invoice(key) invoice = self.wallet.get_invoice(key)
if not invoice: if not invoice:
continue continue
current_height = self.network.get_local_height() self.logger.info(f'trying to pay invoice {key}')
delta = swap.locktime - current_height try:
if delta <= MIN_LOCKTIME_DELTA: success, log = await self.lnworker.pay_invoice(invoice.lightning_invoice, attempts=10)
# fixme: should consider cltv of ln payment except Exception as e:
self.logger.info(f'locktime too close {key}') success = False
continue if success:
success, log = await self.lnworker.pay_invoice(invoice.lightning_invoice, attempts=10) self.invoices_to_pay.pop(key)
if not success:
self.logger.info(f'failed to pay invoice {key}')
continue continue
self.invoices_to_pay.remove(key) # retry in 10 minutes
self.logger.info(f'failed to pay invoice {key}')
self.invoices_to_pay[key] = now() + 600
@log_exceptions @log_exceptions
async def _claim_swap(self, swap: SwapData) -> None: async def _claim_swap(self, swap: SwapData) -> None:
@ -296,14 +301,22 @@ class SwapManager(Logger):
# too early for refund # too early for refund
continue continue
else: else:
if swap.preimage is None:
swap.preimage = self.lnworker.get_preimage(swap.payment_hash)
if swap.preimage is None: if swap.preimage is None:
if funding_conf <= 0: if funding_conf <= 0:
continue continue
preimage = self.lnworker.get_preimage(swap.payment_hash) key = swap.payment_hash.hex()
if preimage is None: if -delta <= MIN_LOCKTIME_DELTA:
self.invoices_to_pay.add(swap.payment_hash.hex()) if key in self.invoices_to_pay:
# fixme: should consider cltv of ln payment
self.logger.info(f'locktime too close {key} {delta}')
self.invoices_to_pay.pop(key, None)
continue continue
swap.preimage = preimage if key not in self.invoices_to_pay:
self.invoices_to_pay[key] = 0
continue
if self.network.config.TEST_SWAPSERVER_REFUND: if self.network.config.TEST_SWAPSERVER_REFUND:
# for testing: do not create claim tx # for testing: do not create claim tx
continue continue
@ -502,7 +515,7 @@ class SwapManager(Logger):
swap = self.get_swap(payment_hash) swap = self.get_swap(payment_hash)
assert sha256(swap.preimage) == payment_hash assert sha256(swap.preimage) == payment_hash
assert swap.spending_txid is None assert swap.spending_txid is None
self.invoices_to_pay.add(key) self.invoices_to_pay[key] = 0
async def normal_swap( async def normal_swap(
self, self,

Loading…
Cancel
Save