1
0

lnpeer: deduct jit channel fees from total amount

Deduct the just in time channel opening fees from the total amount so
htlcs don't get timed out if they come from a just in time channel with
opening fee.

Related: https://github.com/spesmilo/electrum/pull/9584
This commit is contained in:
f321x
2025-12-05 17:27:49 +01:00
committed by ThomasV
parent f8fc2b63e3
commit fb566eb59e
2 changed files with 22 additions and 8 deletions

View File

@@ -765,8 +765,15 @@ class Channel(AbstractChannel):
def __repr__(self):
return "Channel(%s)"%self.get_id_for_log()
def __init__(self, state: 'StoredDict', *, name=None, lnworker=None, initial_feerate=None, opening_fee=None):
self.opening_fee = opening_fee
def __init__(
self,
state: 'StoredDict', *,
name=None,
lnworker=None,
initial_feerate=None,
jit_opening_fee: Optional[int] = None,
):
self.jit_opening_fee = jit_opening_fee
self.name = name
self.channel_id = bfh(state["channel_id"])
self.short_channel_id = ShortChannelID.normalize(state["short_channel_id"])

View File

@@ -1316,9 +1316,12 @@ class Peer(Logger, EventListener):
# store the temp id now, so that it is recognized for e.g. 'error' messages
self.temp_id_to_id[temp_chan_id] = None
self._cleanup_temp_channelids()
channel_opening_fee = open_channel_tlvs.get('channel_opening_fee') if open_channel_tlvs else None
channel_opening_fee_tlv = open_channel_tlvs.get('channel_opening_fee', {})
channel_opening_fee = channel_opening_fee_tlv.get('channel_opening_fee')
if channel_opening_fee:
# todo check that the fee is reasonable
assert is_zeroconf
self.logger.info(f"just-in-time opening fee: {channel_opening_fee} msat")
pass
if self.use_anchors():
@@ -1433,7 +1436,7 @@ class Peer(Logger, EventListener):
chan_dict,
lnworker=self.lnworker,
initial_feerate=feerate,
opening_fee = channel_opening_fee,
jit_opening_fee = channel_opening_fee,
)
chan.storage['init_timestamp'] = int(time.time())
if isinstance(self.transport, LNTransport):
@@ -2115,8 +2118,8 @@ class Peer(Logger, EventListener):
log_fail_reason(f"'total_msat' missing from onion")
raise exc_incorrect_or_unknown_pd
if chan.opening_fee:
channel_opening_fee = chan.opening_fee['channel_opening_fee'] # type: int
if chan.jit_opening_fee:
channel_opening_fee = chan.jit_opening_fee
total_msat -= channel_opening_fee
amt_to_forward -= channel_opening_fee
else:
@@ -2281,7 +2284,7 @@ class Peer(Logger, EventListener):
self._fulfill_htlc(chan, htlc_id, preimage)
htlc_set.htlcs.remove(mpp_htlc)
# reset just-in-time opening fee of channel
chan.opening_fee = None
chan.jit_opening_fee = None
def _fulfill_htlc(self, chan: Channel, htlc_id: int, preimage: bytes):
assert chan.hm.is_htlc_irrevocably_added_yet(htlc_proposer=REMOTE, htlc_id=htlc_id)
@@ -3070,6 +3073,10 @@ class Peer(Logger, EventListener):
return OnionFailureCode.MPP_TIMEOUT, None, None
if mpp_set.resolution == RecvMPPResolution.WAITING:
# calculate the sum of just in time channel opening fees
htlc_channels = [self.lnworker.get_channel_by_short_id(scid) for scid in set(h.scid for h in mpp_set.htlcs)]
jit_opening_fees_msat = sum((c.jit_opening_fee or 0) for c in htlc_channels)
# check if set is first stage multi-trampoline payment to us
# first stage trampoline payment:
# is a trampoline payment + we_are_final + payment key is derived from outer onion's payment secret
@@ -3095,7 +3102,7 @@ class Peer(Logger, EventListener):
self.lnworker.received_mpp_htlcs[payment_key] = mpp_set._replace(
parent_set_key=trampoline_payment_key,
)
elif amount_msat >= total_msat:
elif amount_msat >= (total_msat - jit_opening_fees_msat):
# set mpp_set as completed as we have received the full total_msat
mpp_set = self.lnworker.set_mpp_resolution(
payment_key=payment_key,