commit 5663e598637d5cf8aba6b2be8c2b3ccc609fd692
parent d3d476f44c57cc9c545f9dabddf32897b84c784c
Author: ThomasV <thomasv@electrum.org>
Date: Sat, 6 Mar 2021 10:45:52 +0100
lnworker: fix amount_inflight.
(amount with routing fees were used on htlc failures)
Diffstat:
1 file changed, 27 insertions(+), 24 deletions(-)
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
@@ -601,7 +601,7 @@ class LNWallet(LNWorker):
self.sent_htlcs = defaultdict(asyncio.Queue) # type: Dict[bytes, asyncio.Queue[HtlcLog]]
self.sent_htlcs_routes = dict() # (RHASH, scid, htlc_id) -> route, payment_secret, amount_msat, bucket_msat
- self.sent_buckets = defaultdict(set)
+ self.sent_buckets = dict()
self.received_htlcs = dict() # RHASH -> mpp_status, htlc_set
self.swap_manager = SwapManager(wallet=self.wallet, lnworker=self)
@@ -1074,19 +1074,21 @@ class LNWallet(LNWorker):
use_two_trampolines=use_two_trampolines,
fwd_trampoline_onion=fwd_trampoline_onion))
# 2. send htlcs
- for route, amount_msat, total_msat, cltv_delta, bucket_payment_secret, trampoline_onion in routes:
+ for route, amount_msat, total_msat, amount_receiver_msat, cltv_delta, bucket_payment_secret, trampoline_onion in routes:
await self.pay_to_route(
route=route,
amount_msat=amount_msat,
total_msat=total_msat,
+ amount_receiver_msat=amount_receiver_msat,
payment_hash=payment_hash,
payment_secret=bucket_payment_secret,
min_cltv_expiry=cltv_delta,
trampoline_onion=trampoline_onion)
- amount_inflight += amount_msat
+ amount_inflight += amount_receiver_msat
assert amount_inflight <= amount_to_pay, f"amount_inflight {amount_inflight} > amount_to_pay {amount_to_pay}"
util.trigger_callback('invoice_status', self.wallet, payment_hash.hex())
# 3. await a queue
+ self.logger.info(f"amount inflight {amount_inflight}")
htlc_log = await self.sent_htlcs[payment_hash].get()
amount_inflight -= htlc_log.amount_msat
assert amount_inflight >= 0, f"amount_inflight={amount_inflight} < 0"
@@ -1124,6 +1126,7 @@ class LNWallet(LNWorker):
route: LNPaymentRoute,
amount_msat: int,
total_msat: int,
+ amount_receiver_msat:int,
payment_hash: bytes,
payment_secret: Optional[bytes],
min_cltv_expiry: int,
@@ -1147,11 +1150,12 @@ class LNWallet(LNWorker):
trampoline_onion=trampoline_onion)
key = (payment_hash, short_channel_id, htlc.htlc_id)
- self.sent_htlcs_routes[key] = route, payment_secret, amount_msat, total_msat
+ self.sent_htlcs_routes[key] = route, payment_secret, amount_msat, total_msat, amount_receiver_msat
# if we sent MPP to a trampoline, add item to sent_buckets
if not self.channel_db and amount_msat != total_msat:
if payment_secret not in self.sent_buckets:
- self.sent_buckets[payment_secret] = total_msat
+ self.sent_buckets[payment_secret] = 0
+ self.sent_buckets[payment_secret] += amount_receiver_msat
util.trigger_callback('htlc_added', chan, htlc, SENT)
@@ -1309,7 +1313,7 @@ class LNWallet(LNWorker):
continue
if chan.is_frozen_for_sending():
continue
- trampoline_onion, trampoline_fee, amount_with_fees, cltv_delta = create_trampoline_route_and_onion(
+ trampoline_onion, amount_with_fees, cltv_delta = create_trampoline_route_and_onion(
amount_msat=amount_msat,
total_msat=final_total_msat,
min_cltv_expiry=min_cltv_expiry,
@@ -1325,8 +1329,7 @@ class LNWallet(LNWorker):
trampoline_fee_level=trampoline_fee_level,
use_two_trampolines=use_two_trampolines)
trampoline_payment_secret = os.urandom(32)
- amount_to_send = amount_with_fees + trampoline_fee
- if chan.available_to_spend(LOCAL, strict=True) < amount_to_send:
+ if chan.available_to_spend(LOCAL, strict=True) < amount_with_fees:
continue
route = [
RouteEdge(
@@ -1338,7 +1341,7 @@ class LNWallet(LNWorker):
cltv_expiry_delta=0,
node_features=trampoline_features)
]
- routes = [(route, amount_to_send, amount_to_send, cltv_delta, trampoline_payment_secret, trampoline_onion)]
+ routes = [(route, amount_with_fees, amount_with_fees, amount_msat, cltv_delta, trampoline_payment_secret, trampoline_onion)]
break
else:
raise NoPathFound()
@@ -1350,7 +1353,7 @@ class LNWallet(LNWorker):
r_tags=r_tags, t_tags=t_tags,
invoice_features=invoice_features,
outgoing_channel=None, full_path=full_path)
- routes = [(route, amount_msat, final_total_msat, min_cltv_expiry, payment_secret, fwd_trampoline_onion)]
+ routes = [(route, amount_msat, final_total_msat, amount_msat, min_cltv_expiry, payment_secret, fwd_trampoline_onion)]
except NoPathFound:
if not invoice_features.supports(LnFeatures.BASIC_MPP_OPT):
raise
@@ -1374,7 +1377,7 @@ class LNWallet(LNWorker):
buckets[chan.node_id].append((chan_id, part_amount_msat))
for node_id, bucket in buckets.items():
bucket_amount_msat = sum([x[1] for x in bucket])
- trampoline_onion, trampoline_fee, bucket_amount_with_fees, bucket_cltv_delta = create_trampoline_route_and_onion(
+ trampoline_onion, bucket_amount_with_fees, bucket_cltv_delta = create_trampoline_route_and_onion(
amount_msat=bucket_amount_msat,
total_msat=final_total_msat,
min_cltv_expiry=min_cltv_expiry,
@@ -1389,15 +1392,16 @@ class LNWallet(LNWorker):
local_height=local_height,
trampoline_fee_level=trampoline_fee_level,
use_two_trampolines=use_two_trampolines)
- self.logger.info(f'trampoline fee {trampoline_fee}')
# node_features is only used to determine is_tlv
bucket_payment_secret = os.urandom(32)
+ bucket_fees = bucket_amount_with_fees - bucket_amount_msat
+ self.logger.info(f'bucket_fees {bucket_fees}')
for chan_id, part_amount_msat in bucket:
chan = self.channels[chan_id]
margin = chan.available_to_spend(LOCAL, strict=True) - part_amount_msat
- delta_fee = min(trampoline_fee, margin)
+ delta_fee = min(bucket_fees, margin) # fixme: we have to pay all trampolines
part_amount_msat_with_fees = part_amount_msat + delta_fee
- trampoline_fee -= delta_fee
+ bucket_fees -= delta_fee
route = [
RouteEdge(
start_node=self.node_keypair.pubkey,
@@ -1409,8 +1413,8 @@ class LNWallet(LNWorker):
node_features=trampoline_features)
]
self.logger.info(f'adding route {part_amount_msat} {delta_fee} {margin}')
- routes.append((route, part_amount_msat_with_fees, bucket_amount_with_fees, bucket_cltv_delta, bucket_payment_secret, trampoline_onion))
- if trampoline_fee > 0:
+ routes.append((route, part_amount_msat_with_fees, bucket_amount_with_fees, part_amount_msat, bucket_cltv_delta, bucket_payment_secret, trampoline_onion))
+ if bucket_fees != 0:
self.logger.info('not enough margin to pay trampoline fee')
raise NoPathFound()
else:
@@ -1424,7 +1428,7 @@ class LNWallet(LNWorker):
r_tags=r_tags, t_tags=t_tags,
invoice_features=invoice_features,
outgoing_channel=channel, full_path=None)
- routes.append((route, part_amount_msat, final_total_msat, min_cltv_expiry, payment_secret, fwd_trampoline_onion))
+ routes.append((route, part_amount_msat, final_total_msat, part_amount_msat, min_cltv_expiry, payment_secret, fwd_trampoline_onion))
self.logger.info(f"found acceptable split configuration: {list(s[0].values())} rating: {s[1]}")
break
except NoPathFound:
@@ -1660,11 +1664,11 @@ class LNWallet(LNWorker):
util.trigger_callback('htlc_fulfilled', payment_hash, chan.channel_id)
q = self.sent_htlcs.get(payment_hash)
if q:
- route, payment_secret, amount_msat, bucket_msat = self.sent_htlcs_routes[(payment_hash, chan.short_channel_id, htlc_id)]
+ route, payment_secret, amount_msat, bucket_msat, amount_receiver_msat = self.sent_htlcs_routes[(payment_hash, chan.short_channel_id, htlc_id)]
htlc_log = HtlcLog(
success=True,
route=route,
- amount_msat=amount_msat)
+ amount_msat=amount_receiver_msat)
q.put_nowait(htlc_log)
else:
key = payment_hash.hex()
@@ -1685,7 +1689,7 @@ class LNWallet(LNWorker):
# detect if it is part of a bucket
# if yes, wait until the bucket completely failed
key = (payment_hash, chan.short_channel_id, htlc_id)
- route, payment_secret, amount_msat, bucket_msat = self.sent_htlcs_routes[key]
+ route, payment_secret, amount_msat, bucket_msat, amount_receiver_msat = self.sent_htlcs_routes[key]
if error_bytes:
# TODO "decode_onion_error" might raise, catch and maybe blacklist/penalise someone?
try:
@@ -1701,16 +1705,15 @@ class LNWallet(LNWorker):
# check sent_buckets if we use trampoline
if self.channel_db is None and payment_secret in self.sent_buckets:
- self.sent_buckets[payment_secret] -= amount_msat
+ self.sent_buckets[payment_secret] -= amount_receiver_msat
if self.sent_buckets[payment_secret] > 0:
return
- else:
- amount_msat = bucket_msat
+ assert self.sent_buckets[payment_secret] == 0
htlc_log = HtlcLog(
success=False,
route=route,
- amount_msat=amount_msat,
+ amount_msat=amount_receiver_msat,
error_bytes=error_bytes,
failure_msg=failure_message,
sender_idx=sender_idx)