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