electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

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:
Melectrum/lnworker.py | 51+++++++++++++++++++++++++++------------------------
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)