Browse Source

lnpeer: more detailed logging in maybe_fulfill_htlc

patch-4
SomberNight 4 years ago
parent
commit
44059ec116
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 24
      electrum/lnpeer.py
  2. 2
      electrum/lnutil.py

24
electrum/lnpeer.py

@ -1471,10 +1471,14 @@ class Peer(Logger):
"""As a final recipient of an HTLC, decide if we should fulfill it. """As a final recipient of an HTLC, decide if we should fulfill it.
Returns the preimage if yes, or None. Returns the preimage if yes, or None.
""" """
def log_fail_reason(reason: str):
self.logger.info(f"maybe_fulfill_htlc. will FAIL HTLC: chan {chan.short_channel_id}. "
f"{reason}. htlc={str(htlc)}. onion_payload={processed_onion.hop_data.payload}")
try: try:
amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"] amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"]
except: except:
log_fail_reason(f"'amt_to_forward' missing from onion")
raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00') raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00')
# Check that our blockchain tip is sufficiently recent so that we have an approx idea of the height. # Check that our blockchain tip is sufficiently recent so that we have an approx idea of the height.
@ -1482,21 +1486,24 @@ class Peer(Logger):
# then they might try to force-close and it becomes a race. # then they might try to force-close and it becomes a race.
chain = self.network.blockchain() chain = self.network.blockchain()
if chain.is_tip_stale(): if chain.is_tip_stale():
log_fail_reason(f"our chain tip is stale")
raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_NODE_FAILURE, data=b'') raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_NODE_FAILURE, data=b'')
local_height = chain.height() local_height = chain.height()
exc_incorrect_or_unknown_pd = OnionRoutingFailure( exc_incorrect_or_unknown_pd = OnionRoutingFailure(
code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS,
data=amt_to_forward.to_bytes(8, byteorder="big") + local_height.to_bytes(4, byteorder="big")) data=amt_to_forward.to_bytes(8, byteorder="big") + local_height.to_bytes(4, byteorder="big"))
if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > htlc.cltv_expiry: if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > htlc.cltv_expiry:
self.logger.info('cltv expiry too soon') log_fail_reason(f"htlc.cltv_expiry is unreasonably close")
raise exc_incorrect_or_unknown_pd raise exc_incorrect_or_unknown_pd
try: try:
cltv_from_onion = processed_onion.hop_data.payload["outgoing_cltv_value"]["outgoing_cltv_value"] cltv_from_onion = processed_onion.hop_data.payload["outgoing_cltv_value"]["outgoing_cltv_value"]
except: except:
log_fail_reason(f"'outgoing_cltv_value' missing from onion")
raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00') raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00')
if not is_trampoline: if not is_trampoline:
if cltv_from_onion != htlc.cltv_expiry: if cltv_from_onion != htlc.cltv_expiry:
log_fail_reason(f"cltv_from_onion != htlc.cltv_expiry")
raise OnionRoutingFailure( raise OnionRoutingFailure(
code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY, code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY,
data=htlc.cltv_expiry.to_bytes(4, byteorder="big")) data=htlc.cltv_expiry.to_bytes(4, byteorder="big"))
@ -1506,6 +1513,7 @@ class Peer(Logger):
total_msat = amt_to_forward # fall back to "amt_to_forward" total_msat = amt_to_forward # fall back to "amt_to_forward"
if not is_trampoline and amt_to_forward != htlc.amount_msat: if not is_trampoline and amt_to_forward != htlc.amount_msat:
log_fail_reason(f"amt_to_forward != htlc.amount_msat")
raise OnionRoutingFailure( raise OnionRoutingFailure(
code=OnionFailureCode.FINAL_INCORRECT_HTLC_AMOUNT, code=OnionFailureCode.FINAL_INCORRECT_HTLC_AMOUNT,
data=htlc.amount_msat.to_bytes(8, byteorder="big")) data=htlc.amount_msat.to_bytes(8, byteorder="big"))
@ -1516,7 +1524,7 @@ class Peer(Logger):
info = self.lnworker.get_payment_info(htlc.payment_hash) info = self.lnworker.get_payment_info(htlc.payment_hash)
if info is None: if info is None:
self.logger.info('unknown payment hash') log_fail_reason(f"no payment_info found for RHASH {htlc.payment_hash.hex()}")
raise exc_incorrect_or_unknown_pd raise exc_incorrect_or_unknown_pd
preimage = self.lnworker.get_preimage(htlc.payment_hash) preimage = self.lnworker.get_preimage(htlc.payment_hash)
try: try:
@ -1524,21 +1532,23 @@ class Peer(Logger):
except: except:
if total_msat > amt_to_forward: if total_msat > amt_to_forward:
# payment_secret is required for MPP # payment_secret is required for MPP
self.logger.info('total_msat > amt to forward') log_fail_reason(f"'payment_secret' missing from onion")
raise exc_incorrect_or_unknown_pd raise exc_incorrect_or_unknown_pd
# TODO fail here if invoice has set PAYMENT_SECRET_REQ # TODO fail here if invoice has set PAYMENT_SECRET_REQ
else: else:
if payment_secret_from_onion != derive_payment_secret_from_payment_preimage(preimage): if payment_secret_from_onion != derive_payment_secret_from_payment_preimage(preimage):
self.logger.info(f'incorrect payment secret {payment_secret_from_onion.hex()} != {derive_payment_secret_from_payment_preimage(preimage).hex()}') log_fail_reason(f'incorrect payment secret {payment_secret_from_onion.hex()} != {derive_payment_secret_from_payment_preimage(preimage).hex()}')
raise exc_incorrect_or_unknown_pd raise exc_incorrect_or_unknown_pd
invoice_msat = info.amount_msat invoice_msat = info.amount_msat
if not (invoice_msat is None or invoice_msat <= total_msat <= 2 * invoice_msat): if not (invoice_msat is None or invoice_msat <= total_msat <= 2 * invoice_msat):
self.logger.info('incorrect total msat') log_fail_reason(f"total_msat={total_msat} too different from invoice_msat={invoice_msat}")
raise exc_incorrect_or_unknown_pd raise exc_incorrect_or_unknown_pd
mpp_status = self.lnworker.add_received_htlc(chan.short_channel_id, htlc, total_msat) mpp_status = self.lnworker.add_received_htlc(chan.short_channel_id, htlc, total_msat)
if mpp_status == True: if mpp_status is True:
self.logger.info(f"maybe_fulfill_htlc. will FULFILL HTLC: chan {chan.short_channel_id}. htlc={str(htlc)}")
return preimage return preimage
elif mpp_status == False: elif mpp_status is False:
log_fail_reason(f"MPP_TIMEOUT")
raise OnionRoutingFailure(code=OnionFailureCode.MPP_TIMEOUT, data=b'') raise OnionRoutingFailure(code=OnionFailureCode.MPP_TIMEOUT, data=b'')
else: else:
return None return None

2
electrum/lnutil.py

@ -1300,7 +1300,7 @@ def format_short_channel_id(short_channel_id: Optional[bytes]):
@attr.s(frozen=True) @attr.s(frozen=True)
class UpdateAddHtlc: class UpdateAddHtlc:
amount_msat = attr.ib(type=int, kw_only=True) amount_msat = attr.ib(type=int, kw_only=True)
payment_hash = attr.ib(type=bytes, kw_only=True, converter=hex_to_bytes) payment_hash = attr.ib(type=bytes, kw_only=True, converter=hex_to_bytes, repr=lambda val: val.hex())
cltv_expiry = attr.ib(type=int, kw_only=True) cltv_expiry = attr.ib(type=int, kw_only=True)
timestamp = attr.ib(type=int, kw_only=True) timestamp = attr.ib(type=int, kw_only=True)
htlc_id = attr.ib(type=int, kw_only=True, default=None) htlc_id = attr.ib(type=int, kw_only=True, default=None)

Loading…
Cancel
Save